Stream name constants are split across the layer boundary: eight *_STREAM constants live in core (effects, npc_party, combat, monster_spawn, magic, treasure, character_creation, advancement) and five in crawl/session.py (wandering, encounter, exploration, monster_action, adjudication). Core functions draw from crawl-named streams by string literal at eight call sites (streams.get("encounter") and the like), so the rule that core never imports crawl holds only because a string is not an import. The docstring pass had to link EXPLORATION_STREAM from core docstrings as a docs cross-reference while the examples spelled the string out to avoid the import.
Proposal: one StrEnum of stream names in core/rng.py, every module importing from there, and docs/reference/rng-streams.md generated from it so the published list cannot drift. The determinism contract does not change, since the string values stay the same and stream order is unaffected. Acceptance: a test that no source file outside core/rng.py contains a stream name as a string literal, and the golden files unchanged.
Stream name constants are split across the layer boundary: eight
*_STREAMconstants live in core (effects,npc_party,combat,monster_spawn,magic,treasure,character_creation,advancement) and five incrawl/session.py(wandering,encounter,exploration,monster_action,adjudication). Core functions draw from crawl-named streams by string literal at eight call sites (streams.get("encounter")and the like), so the rule that core never imports crawl holds only because a string is not an import. The docstring pass had to linkEXPLORATION_STREAMfrom core docstrings as a docs cross-reference while the examples spelled the string out to avoid the import.Proposal: one
StrEnumof stream names incore/rng.py, every module importing from there, anddocs/reference/rng-streams.mdgenerated from it so the published list cannot drift. The determinism contract does not change, since the string values stay the same and stream order is unaffected. Acceptance: a test that no source file outsidecore/rng.pycontains a stream name as a string literal, and the golden files unchanged.