Context
The engine already deduplicates semantic rules so simulation does not apply the same subject IS predicate more than once. The designer's sentence bars need a different view: every physical sentence on the board, including exact duplicates and stacked-word paths. E3 has been implemented in the engine and tests; this change records that landed contract before the implementation is committed.
Goals / Non-Goals
Goals:
- Expose
state.sentences: [{ ids, axis }]for presentation consumers. - Preserve one semantic rule per unique sentence meaning in
state.rules. - Keep exact duplicate physical runs, stacked-word paths, and horizontal/vertical axes deterministic.
- Drop strict subset spans when a longer span exists on the same axis.
Non-Goals:
- Changing rule semantics, movement, transformations, contact effects, or event payloads.
- Drawing sentence bars or choosing their visual placement.
- Adding new vocabulary or changing the parser beyond the physical span projection.
Decisions
1. Keep semantic rules and physical spans as separate projections
The parser discovers candidate source paths once. It emits every physical path into state.sentences, while the existing semantic map keeps only the first deterministic source for each rule text. A renderer uses spans for bars and rules for behavior.
2. Store only source IDs and axis in spans
The span contract is intentionally small: ids preserves the source word entity order and axis is h or v. Positions and text remain available from state objects, avoiding a second mutable representation that could drift from the board.
3. Filter strict subsets by axis and source membership
After candidates are collected, remove a span when another candidate on the same axis has more source IDs and contains every ID in the shorter span. Exact duplicates are retained because they are distinct candidate records and have equal length. This matches the prototype parser's maximal-span behavior.
4. Recompute spans with rules
state.sentences is rebuilt whenever rules are refreshed, including reset, word movement, undo restoration, and transformations that trigger a re-scan. It is derived state and is not independently edited by mods or renderers.
Risks / Trade-offs
- [ID membership can mistake disjoint spans for subsets] → Require same-axis and strict-length comparisons while retaining candidate order; fixtures cover horizontal, vertical, stacked, and duplicate cases.
- [Consumers assume semantic rule count equals bar count] → Document
state.sentencesas the physical source and keepstate.rulesas the semantic source of truth. - [Parser changes alter bar order] → Preserve deterministic discovery order and assert exact ordered spans in engine tests.
Migration Plan
- Keep existing
state.rulesconsumers unchanged. - Read
state.sentencesin sentence-bar rendering when that separate presentation change lands. - Archive this change after the engine implementation and tests are committed.
Open Questions
None for the E3 data contract.