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 gap
A level-crossing LocationEnteredEvent (location_kind="level") is emitted identically for stairs_down and stairs_up: _relocate reports the destination (location_id = dungeon id, level_number) and, since 1.5.0, a gate's narrative success beat — but not how the party got there. The emission site knows (it is executing one command or the other); the event does not say.
Why it matters downstream
A renderer that wants direction in its line — "The party descends to level 2." — has to guess or track prior level in render state. osr-web guessed: its line hard-codes "descends", so the bundled adventure's up-stair (level 2 back to level 1 at (18,1)) currently renders "The party descends to level 1." while the party climbs. Tracking prior level downstream instead is fragile across whole-log re-renders and mid-dungeon restores, and it re-derives at render time a fact the engine had in hand at emission.
The same field would serve trap-transition relocations (slides) and any future transition kind — each reads differently at the table, and today they are indistinguishable on the event.
What downstream needs
An additive field on the level-crossing event naming the means — e.g. via: "stairs_down" | "stairs_up" | "trap" (naming and domain this repo's call), defaulting None so old logs still parse, always filled by the engine at emission.
Downstream in the interim
osr-web moves to the neutral "The party comes to level N." — always true, direction restored when the engine states it. No prior-level tracking will be built in the interim.
https://claude.ai/code/session_01GSYzXCjpPnVDLTC2rpmhTZ
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 gap
A level-crossing
LocationEnteredEvent(location_kind="level") is emitted identically forstairs_downandstairs_up:_relocatereports the destination (location_id= dungeon id,level_number) and, since 1.5.0, a gate'snarrativesuccess beat — but not how the party got there. The emission site knows (it is executing one command or the other); the event does not say.Why it matters downstream
A renderer that wants direction in its line — "The party descends to level 2." — has to guess or track prior level in render state. osr-web guessed: its line hard-codes "descends", so the bundled adventure's up-stair (level 2 back to level 1 at (18,1)) currently renders "The party descends to level 1." while the party climbs. Tracking prior level downstream instead is fragile across whole-log re-renders and mid-dungeon restores, and it re-derives at render time a fact the engine had in hand at emission.
The same field would serve trap-
transitionrelocations (slides) and any future transition kind — each reads differently at the table, and today they are indistinguishable on the event.What downstream needs
An additive field on the level-crossing event naming the means — e.g.
via: "stairs_down" | "stairs_up" | "trap"(naming and domain this repo's call), defaultingNoneso old logs still parse, always filled by the engine at emission.Downstream in the interim
osr-web moves to the neutral "The party comes to level N." — always true, direction restored when the engine states it. No prior-level tracking will be built in the interim.
https://claude.ai/code/session_01GSYzXCjpPnVDLTC2rpmhTZ