Skip to content

A door-edge trap find doesn't say which door: the search token carries no bearing #67

Description

@mmacy

Surfaced by adversarial review of osr-web's phase-1 authored-layer adoption (mmacy/osr-web#44). Filed engine-first per the standing rule: the renderer needs a fact only the engine knows at emission time, so the engine states it — no downstream reconstruction.

The gap

1.5.0 widened room_traps searches to door edges: _reveal (src/osrlib/crawl/exploration.py) walks the searched cell's door edges and reports an open-trigger trap in the area beyond, guarded so an undiscovered secret door stays blank wall. But the report it emits is the token room_trap:{area_id} on SearchCompletedEvent, whose only other facts are character_id, kind, and found — no position, no bearing. At the moment _reveal appends the token it knows exactly which door edge earned the find; the event does not say.

Why downstream cannot reconstruct it

osr-web's phase 1 tried to name the door at render time by re-deriving the walk from session.dungeon_state.location. Review refuted it three ways, each fundamental rather than a bug in the attempt:

  • Whole-log re-renders fabricate history. The transcript re-renders on page reload, member rename, and save restore, resolving every historical search against wherever the party stands now. Reproduced on the bundled document: a trap found by standing inside its area ("a hidden trap") re-rendered from one cell away as "a trap rigged to the south door" — a bearing the engine never produced, and one _reveal cannot produce for an enter-trigger trap.
  • It leaks hidden geometry unless it re-implements the engine's guards. The walk must skip undiscovered secret doors and non-open triggers — exactly _reveal's guarded logic — or it tells the player a door exists where the projection renders wall. Duplicating that walk downstream is rule re-implementation, which the adoption spec forbids.
  • The event is the contract. Everything else the renderer says resolves off event-carried facts; this would be the one line derived from mutable session state instead.

What downstream needs

The bearing stated at emission, the same shape as every other resolved-at-emission fact (osrlib#65's display names, gate narrative on the command's event). Two candidate forms, this repo's call:

  • the token grows a segment for door-edge finds — room_trap:{area_id}:{direction} — with the bare two-segment form remaining the in-area find, or
  • found stays as-is and the event gains a structured companion field carrying {token, direction} entries.

Either is additive within schema 3 for freshly emitted events; old logs keep formatting since the bare token remains valid.

Downstream in the interim

osr-web renders every room_trap find as "a hidden trap" with no bearing — the spec's door-naming clause is amended to record this decision (render only what the data states) and to point here. No workaround will be built in the interim.

https://claude.ai/code/session_01GSYzXCjpPnVDLTC2rpmhTZ

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions