# Game Contract and Canonical State Boundary - **Status:** `complete` - **Outcome:** `pass` - **Started:** 2026-07-25 - **Updated:** 2026-07-25 - **Research ID:** `2026-07-25-game-contract-canonical-state` ## Проверяемый вопрос Можно ли выразить минимальный versioned Game Contract и canonical state boundary так, чтобы schema-invalid команды и generative output не могли изменить каноническое состояние, а каждая participant projection соблюдала visibility scope? ## Почему решение нужно сейчас PRD делает authoritative state измеримым отличием продукта и требует, чтобы clarification, rules validation и state transition завершались до narration. Контракт нужен до production-реализации rules engine, event store и LLM adapters, иначе каждый слой сможет неявно определить собственную несовместимую форму канона. ## Scope - Versioned envelope для Game Contract, command proposal и canonical state. - Граница между недоверенным LLM proposal/narration и state service. - Schema validation до RNG, event append и state mutation. - Canonical state fields для персонажей, inventory, statuses, location, initiative, chronology, state version и event sequence. - Visibility scopes `public`, `party`, `branch`, `player` и `GM` как часть данных, а не prompt-only правило. - Executable contract tests against the shared vertical-slice public modules and authoritative fixture. ## Non-goals - Production API, database, distributed event store or deployment topology. - Выбор новой schema-validation библиотеки или canonical serialization format. - Сюжет, карта, NPC content и UI. - Копирование текста, контента или branded compatibility Knave/D&D. - Доказательство production reliability, downstream media privacy или multi-process concurrency одним локальным прогоном. ## Критерии успеха Критерии были зафиксированы до подключения executable shared implementation. Числовые gates взяты только из канонического PRD; остальные строки задают точное поведение без придуманного процентного порога. | ID | Обязательный критерий | Порог или ожидаемое поведение | Способ проверки | |---|---|---|---| | AC-01 | Schema-invalid state-changing command останавливается на boundary | `100%` labelled schema-invalid fixtures требуют structured rejection/clarification до RNG или commit; state hash, state version и event count не меняются | Submit invalid, missing, ill-typed and forbidden-extra-field payloads through `executeProposal`; compare RNG calls, event count, state hash and version | | AC-02 | LLM не имеет mutation capability | Proposal и narration adapters возвращают только typed data/text; попытка передать state patch, HP/inventory/location/status mutation или fabricated event отклоняется, canonical state остаётся byte-for-byte/hash-equivalent исходному | Run a narrator that mutates its projection and returns an extra `statePatch`; compare canonical state with authoritative event replay | | AC-03 | Game Contract и state имеют явную версию и однозначную schema boundary | Valid fixture проходит executable schema validator; missing, unknown-version and ill-typed fixtures return structured errors before state service | Validate the shared fixture plus missing, numeric and unsupported `999.0.0` contract/state versions; inspect structured issue paths/codes | | AC-04 | Visibility является обязательным свойством canonical facts/projections | `0` unauthorized branch facts в adversarial projections; fact outside actor scope is absent from the participant projection | Build explicit allow-lists for three participants and exercise player, GM, branch and public visibility through `projectState` | Изменений критериев после старта не было. ## Рабочие гипотезы - **Hypothesis H-01:** capability boundary, в которой generative adapters не получают state write port, делает прямую LLM mutation структурно невозможной; executable mutation attempt не изменила canonical state или stored event. - **Hypothesis H-02:** visibility metadata на canonical fact/event, а не только в prompt, позволяет строить детерминированные participant projections; explicit allow-list checks прошли для всех зарегистрированных scope cases. ## Материалы - [Исследование и evidence log](RESEARCH.md) - [Техническое решение и запуск](SOLUTION.md) - [Проверка и итог](VALIDATION.md) - [`prototype/`](prototype/) — 5 executable boundary tests against the shared vertical slice - [Shared authoritative Game Contract fixture](../2026-07-25-ai-gm-vertical-slice/prototype/fixtures/game-contract.json) ## Итог Локальный прогон на Node.js `v24.14.0` завершился `5/5` passing tests, без failures, skips или TODO. AC-01–AC-04 выполнены: invalid commands не достигли RNG/event/state, malicious narration не изменила canonical state, missing, ill-typed и unsupported versions получили structured rejection, а participant projections совпали с explicit allow-lists. Root `npm run typecheck` также завершился успешно. Evidence и точные команды записаны в [`VALIDATION.md`](VALIDATION.md). ## Ограничения - Это один локальный deterministic прогон с synthetic fixtures, а не reliability или load measurement. - In-memory event log и current projection boundary не доказывают multi-process storage safety или отсутствие утечек в ещё не подключённых UI, retrieval, summary, TTS и image adapters. - Passing contract tests не выбирают production schema migration window, serialization/hash format или database. ## Следующее решение `GO` для переноса проверенной boundary-модели в production design: сохранять shared fixture/API как единый источник истины, запрещать generative adapters state/event write capability и запускать эти contract tests при изменениях validators, orchestrator, state или projection. Production promotion отдельно требует persistent event store, authorization/threat review и downstream privacy integration tests.