- commit
- cc0c322c9cb565d56428c3b1fc1c29e0469dc340
- parent
- 308c2d4e65c990aeab5843f19aee97dd5f352a0a
- author
- Dami <dami.etoile@gmail.com>
No content changes.
No content changes.
No content changes.
No content changes.
@@ -0,0 +1,127 @@
1+# level-schema-boundary Specification2+3+## Purpose4+TBD - created by archiving change consolidate-level-schema-boundary. Update Purpose after archive.5+## Requirements6+### Requirement: Level inputs SHALL cross one canonical normalization boundary7+8+The host SHALL expose one pure level normalization and validation boundary for9+standalone engine levels, trusted CommonJS levels, and data-only shared levels.10+The boundary SHALL clone caller data before normalization, SHALL not execute11+code or access presentation state, and SHALL return canonical level data with12+explicit object kinds, uppercase word and noun tokens, and explicit automaton13+action objects. A context profile MAY add pack identity and size limits, but it14+SHALL reuse the same structural checks and canonical output.15+16+#### Scenario: Direct and pack paths produce equivalent canonical data17+18+- **WHEN** the same valid level is passed to direct engine creation and to a19+ CommonJS pack preview20+- **THEN** both paths use equivalent canonical gameplay fields, including21+ inferred kinds, token casing, IDs, and automaton actions22+23+#### Scenario: Input is not mutated24+25+- **WHEN** a caller supplies lowercase tokens, omitted kinds, or shorthand26+ automaton steps and then mutates the original input after normalization27+- **THEN** the canonical level and the active game remain unchanged and the28+ original input retains its original values29+30+### Requirement: Legacy level shorthand SHALL be normalized at input31+32+During the compatibility window, the boundary SHALL accept omitted object33+`kind` when `text` or `noun` makes the kind unambiguous, case-insensitive word34+and noun tokens, and automaton pattern strings `U`, `D`, `L`, `R`, and `W`.35+Canonical output SHALL materialize these as `kind: 'word'` or `kind: 'object'`,36+uppercase tokens, and `{ action: 'move', dx, dy }` or `{ action: 'wait' }`.37+Unknown shorthand, non-cardinal vectors, and unsupported action fields SHALL38+remain errors. The boundary SHALL not emit new shorthand in CommonJS exports39+or shared payloads.40+41+#### Scenario: Legacy automaton shorthand survives a share round trip42+43+- **WHEN** a valid level uses `['L', 'W', 'R']` in an automaton pattern and is44+ exported to CommonJS or encoded as a shared pack45+- **THEN** loading or decoding succeeds, the normalized pattern contains three46+ explicit action objects, and a game created from the result has the same47+ next transitions as the source game48+49+#### Scenario: Ambiguous shorthand fails consistently50+51+- **WHEN** a level contains an unsupported pattern string or a diagonal52+ `{ action: 'move', dx: 1, dy: 1 }`53+- **THEN** direct engine creation, CommonJS preview, and shared decoding all54+ reject the same structural issue before play or installation55+56+### Requirement: Pack-only policy SHALL be an explicit adapter57+58+The pack profile SHALL require a stable lowercase level ID, enforce the59+documented pack-level and pack-count bounds, and retain duplicate-ID checks.60+The standalone engine profile MAY omit pack-only identity fields and SHALL not61+silently inherit pack limits. Pack policy errors SHALL preserve the canonical62+field path and SHALL occur before catalog registration.63+64+#### Scenario: A standalone fixture remains playable without a pack ID65+66+- **WHEN** a valid direct engine fixture has width, height, and objects but no67+ `id`68+- **THEN** direct game creation succeeds with canonical gameplay data69+70+#### Scenario: Pack identity is required before installation71+72+- **WHEN** a CommonJS pack contains a level without a stable lowercase `id`73+- **THEN** preview reports the level path, rejects the pack atomically, and74+ leaves existing catalog content unchanged75+76+### Requirement: Error adapters SHALL preserve canonical issue identity77+78+The shared boundary SHALL report stable issue codes and source paths. The79+engine adapter SHALL retain its level-labeled `TypeError`/`RangeError` style;80+the CommonJS adapter SHALL retain `ModValidationError` paths and source81+context; and the shared decoder SHALL retain its player-readable invalid-pack82+error. Adapters MAY add filename, pack, or level labels but SHALL not duplicate83+structural validation or alter issue severity.84+85+#### Scenario: One malformed object has equivalent diagnostics86+87+- **WHEN** `objects[0]` has an invalid coordinate type through all three input88+ paths89+- **THEN** each path reports the same structural issue code and object index,90+ while retaining its existing caller-specific error envelope91+92+### Requirement: Canonical data SHALL round-trip through sharing and export93+94+CommonJS export and data-only shared encoding SHALL serialize canonical level95+data only. Decoding or loading SHALL revalidate through the boundary before96+returning normalized data. A valid canonical level SHALL preserve gameplay97+fields through CommonJS export/import and share encode/decode, including98+automata metadata and optional authored level metadata.99+100+#### Scenario: Export/share parity preserves gameplay101+102+- **WHEN** a pack with words, objects, automata, and level metadata is exported103+ and shared, then imported through both supported paths104+- **THEN** both results compare equal on canonical gameplay data and create105+ games with matching initial snapshots and first accepted transitions106+107+#### Scenario: Invalid shared data cannot bypass the boundary108+109+- **WHEN** a shared payload contains malformed level data or unsupported110+ metadata111+- **THEN** decoding fails before catalog installation and does not execute112+ CommonJS or leave partial content registered113+114+### Requirement: Boundary parity SHALL be a release gate115+116+The project SHALL maintain focused fixtures covering canonical valid levels,117+legacy shorthand, invalid coordinates, duplicate IDs, invalid tokens,118+automaton action errors, and share/export round trips. The gate SHALL run the119+direct engine, CommonJS loader, and data-only sharing paths against those120+fixtures, followed by the full Node suite and production build.121+122+#### Scenario: Parity fixtures catch validator drift123+124+- **WHEN** one path accepts or normalizes a fixture differently from the125+ canonical boundary126+- **THEN** the focused parity test fails with the path and issue difference127+ before the change can be marked complete