Research: Game Contract and Canonical State Boundary
Baseline#
Fact: At study start the repository had PRD and research requirements but no
shared executable Game Contract/state API. During the same R&D series, the
2026-07-25-ai-gm-vertical-slice study introduced public contract, validator,
engine, event-log, state, projection and orchestrator modules plus shared JSON
fixtures. This study therefore moved from pre-registered ports to executable
cross-study contract tests without creating a second implementation or fixture.
Метод#
- Извлечь только canonical invariants и существующие numerical gates из PRD.
- Разделить untrusted generative data, validated command, authoritative state и participant projection как отдельные capabilities.
- Зафиксировать positive/negative fixtures for schema, mutation boundary and visibility before connecting the implementation.
- Import the shared vertical-slice public APIs and load its authoritative
fixture through
loadFixtureBundle(). - Run invalid-command, adversarial narration, version-conformance and projection allow-list cases with fresh in-memory state/event contexts.
- Compare RNG call counts, event counts, canonical hashes, state versions, replayed state and structured validation issues.
- Run the root TypeScript compiler after the behavior suite.
Controlled inputs are the shared 1.0.0 Game Contract, fixed synthetic
participants/facts, a deterministic RNG stub and fresh state per case. The
number of cases is reported as observed evidence, not as an invented
production-quality threshold.
Реестр доказательств#
| ID | Тип | Описание | Источник, путь или команда | Дата или версия |
|---|---|---|---|---|
| E-001 | Fact | PRD requires schema-invalid or ambiguous state-changing commands to stop before roll/commit; narrator receives confirmed outcome and does not mutate state; split-party facts stay in scope | ../../docs/prd/2026-07-22-global-party-ai-rpg.md, FR-05/FR-08/FR-10 |
PRD Draft, 2026-07-22 |
| E-002 | Fact | Component contract separates proposal, rules, authoritative state, context and narration; generative steps cannot independently change canon | ../../docs/prd/2026-07-22-global-party-ai-rpg.md |
PRD Draft, 2026-07-22 |
| E-003 | Fact | Canonical PRD guardrails set 100% clarification before commit and 0 branch privacy leaks |
../../docs/prd/2026-07-22-global-party-ai-rpg.md |
PRD Draft, 2026-07-22 |
| E-004 | Fact | Server-side authorization and pre/post-retrieval visibility filtering are Technical Context requirements | ../../docs/prd/2026-07-22-global-party-ai-rpg.md |
PRD Draft, 2026-07-22 |
| E-005 | Fact | Research architecture defines state service authority and enumerates participant visibility scopes | ../../research/06-product-mvp-and-ai-gm.md |
2026-07-21 research pack |
| E-006 | Fact | The executable suite imports shared contracts, engine, event log, fixture loader, hash, orchestrator, projection, state and validators rather than duplicating them | prototype/game-contract.verification.test.ts; shared source directory |
2026-07-25 |
| E-007 | Fact | loadFixtureBundle() loads the authoritative game-contract.json; it declares contract/state version 1.0.0, supported state versions ["1.0.0"] and unknownVersion: "reject" |
../2026-07-25-ai-gm-vertical-slice/prototype/src/fixtures.ts; ../2026-07-25-ai-gm-vertical-slice/prototype/fixtures/game-contract.json |
2026-07-25 |
| E-008 | Measurement | Boundary suite completed with 5 tests, 5 pass, 0 fail, 0 skipped and 0 TODO on Node.js v24.14.0 |
node --test RnD/technical/2026-07-25-game-contract-canonical-state/prototype/game-contract.verification.test.ts from repository root |
2026-07-25T01:37:39+07:00 rerun |
| E-009 | Measurement | Unsupported contractVersion and stateVersion values 999.0.0 each produced a structured schema_const issue at /game/contractVersion and /game/stateVersion respectively |
AC-03 assertions in prototype/game-contract.verification.test.ts |
2026-07-25 |
| E-010 | Measurement | Root strict TypeScript compilation completed with exit code 0 | npm run typecheck; root tsconfig.json |
2026-07-25 final rerun |
| E-011 | Unknown | Production persistence, distributed concurrency and downstream UI/retrieval/TTS/image privacy have not been measured by this study | Scope boundary and VALIDATION.md |
2026-07-25 |
Журнал экспериментов#
| Время | Изменение или попытка | Наблюдение | Artifact или evidence ID | Вывод |
|---|---|---|---|---|
| 2026-07-25T01:04:02+07:00 | PRD invariant extraction and test-port pre-registration | Exact schema, authority and visibility behavior could be stated without choosing a shared API | Historical initial test manifest; E-001–E-005 | Criteria registered before implementation |
| 2026-07-25T01:07:08+07:00 | Initial stub run under the then-active Node.js v22.14.0 |
Plain node --test failed with ERR_UNKNOWN_FILE_EXTENSION; the experimental strip-types flag executed one manifest check and four TODO tests |
Historical command output retained from the study start | This was stub evidence only and is superseded by the final Node.js v24.14.0 behavior run |
| 2026-07-25 | Connected all pre-registered cases to the shared vertical-slice implementation | Invalid command, narrator mutation, version and visibility paths became executable through public shared APIs | E-006–E-009 | No study-local core implementation was needed |
| 2026-07-25 | First root typecheck of the adversarial narrator | TypeScript rejected a direct NarrationResult object literal containing the deliberately forbidden extra statePatch property |
npm run typecheck; test edit history |
Return was changed to an inferred structural value that still carries statePatch at runtime; the adversarial case remained intact |
| 2026-07-25 | First unsupported-version characterization | validateBundle accepted contractVersion/stateVersion 999.0.0 despite the fixture’s rejection policy |
Earlier AC-03 characterization run | Shared validator/schema needed an explicit supported-version check before final acceptance |
| 2026-07-25 | Added supported-version validation and reran AC-03 | Both unsupported versions now return structured schema_const issues at their exact game paths |
E-007, E-009 | AC-03 now passes |
| 2026-07-25T01:37:39+07:00 | Final behavior and compiler rerun on Node.js v24.14.0 |
Game suite: 5/5 pass, no fail/skip/TODO; root typecheck exit 0 | E-008, E-010 | All AC pass; outcome is pass |
Выводы#
- Fact: All five executable boundary tests pass on the recorded final
environment. Основание:
E-008. - Fact: The shared validator now rejects missing, ill-typed and unsupported
contract/state versions with structured issues. Основание:
E-007,E-009. - Fact: Adversarial narrator output retained an extra mutation-shaped field
at runtime, yet canonical state matched authoritative replay and the stored
event remained authoritative. Основание:
E-006,E-008. - Inference: Capability separation plus schema validation and deterministic
projection is sufficient for the tested local Game Contract boundary.
Основание:
E-001–E-010. - Unknown: The same guarantees across persistent/distributed adapters and
downstream media surfaces require separate integration evidence. Основание:
E-011.
Рассмотренные альтернативы#
| Подход | Что проверили | Почему не выбран | Evidence |
|---|---|---|---|
| LLM returns arbitrary canonical state patch | Executed a narrator that mutates its projection and returns statePatch |
Generative output remains untrusted and cannot replace authoritative replay/state | E-002, E-006, E-008 |
| Prompt-only secrecy | Compared with explicit visibility metadata and participant allow-lists | Cannot provide deterministic access control or an executable adversarial oracle | E-003–E-005, E-008 |
| Study-local contract/profile copy | Compared with shared loader and fixture | Would create a second source of truth; the shared fixture already supplies all tested data | E-006, E-007 |
| Accept any syntactically valid semantic version | Tested 999.0.0 against the declared migration policy |
Contradicts supportedStateVersions and unknownVersion: "reject" |
E-007, E-009 |
Неизвестные#
- Unknown: canonical serialization/hash compatibility across future language runtimes; close with cross-runtime golden fixtures if a second runtime is introduced.
- Unknown: migration compatibility window beyond
1.0.0; close when the first real migration is designed. - Unknown: persistence and concurrent-writer behavior; close with the event-store study and multi-process integration tests.
- Unknown: end-to-end privacy after projection data reaches retrieval, summaries, TTS or images; close with downstream adapter adversarial tests.