# Research: Rules Engine and Authoritative RNG Contract ## Baseline **Fact:** At study start the repository had PRD/research rules and RNG invariants but no shared executable engine, randomness port, idempotency store or expected-version handler. The parallel `2026-07-25-ai-gm-vertical-slice` study then supplied a shared engine, event log, state model, fixture loader and authoritative Game Contract/rules profile. This study connected its pre-registered authority cases to those public modules instead of keeping a duplicate engine or profile. The mechanical baseline is not a product implementation. Knave 1.0 is used only as an attributed source of high-level rules-light principles: classless characters, d20 ability-driven resolution and equipment-defined roles. The shared executable profile uses original genre-neutral names and contains no Knave setting, items, spells, prose or compatibility claim. ## Метод 1. Extract roll completeness, invalid-command, recovery, idempotency and version requirements from canonical PRD/research. 2. Record the official Knave 1.0 page, access date, version indicator, license statement and only the high-level principles stated there. 3. Keep one original declarative profile in the shared Game Contract fixture. 4. Import the shared `executeProposal`, `InMemoryEventLog`, `loadFixtureBundle`, `stateHash` and `createInitialState` APIs. 5. Execute controlled fixed-RNG, fabricated-result, invalid-command, duplicate and stale-version cases with fresh state/event contexts. 6. Compare roll fields with independently worked literals and inspect RNG call count, event count/reference, state hash/version and structured errors. 7. Run the root strict TypeScript compiler after the behavior suite. No statistical RNG-quality gate is set. Distribution, entropy, concurrency and latency are separate production measurements and are not inferred from fixed test values. ## Реестр доказательств | ID | Тип | Описание | Источник, путь или команда | Дата или версия | |---|---|---|---|---| | E-001 | Fact | FR-05 prevents roll/commit for schema-invalid commands; FR-06 requires raw result, formula, modifiers, rule version and event reference; FR-12 prevents reconnect duplication | [`../../docs/prd/2026-07-22-global-party-ai-rpg.md`](../../docs/prd/2026-07-22-global-party-ai-rpg.md) | PRD Draft, 2026-07-22 | | E-002 | Fact | Technical Context requires append-only events, materialized state, expected state version, idempotency keys and logged server RNG | [`../../docs/prd/2026-07-22-global-party-ai-rpg.md`](../../docs/prd/2026-07-22-global-party-ai-rpg.md) | PRD Draft, 2026-07-22 | | E-003 | Fact | Research specifies server-generated logged RNG and checking idempotency/expected version before a new event after slow AI/STT work | [`../../research/06-product-mvp-and-ai-gm.md`](../../research/06-product-mvp-and-ai-gm.md) | 2026-07-21 research pack | | E-004 | Fact | Pilot criteria require every roll to retain reproducible formula/modifiers/event reference and reconnect not to duplicate an action | [`../../research/06-product-mvp-and-ai-gm.md`](../../research/06-product-mvp-and-ai-gm.md) | 2026-07-21 research pack | | E-005 | Fact | Official author page lists Knave 1.0 files, classless play, d20 rolls using abilities, equipment-defined roles and CC BY 4.0 adaptation with attribution | [Questing Beast — Knave](https://questingbeast.itch.io/knave) | Accessed 2026-07-25; downloadable version shown as Knave 1.0 | | E-006 | Fact | `loadFixtureBundle()` loads the single shared `game-contract.json`; its `quick-kit` rules profile contains Knave 1e/Ben Milton/CC BY 4.0/official URL attribution and original executable fields | [`../2026-07-25-ai-gm-vertical-slice/prototype/src/fixtures.ts`](../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-ai-gm-vertical-slice/prototype/fixtures/game-contract.json) | 2026-07-25 | | E-007 | Fact | Rules tests import the shared contracts, engine, event log, fixture loader, hash and state modules; the former study-local profile duplicate is absent | [`prototype/rules-engine.verification.test.ts`](prototype/rules-engine.verification.test.ts); `rg --files RnD/technical/2026-07-25-rules-engine-authoritative-rng` | 2026-07-25 | | E-008 | Measurement | Behavior suite completed with 6 tests, 6 pass, 0 fail, 0 skipped and 0 TODO on Node.js `v24.14.0` | `node --test RnD/technical/2026-07-25-rules-engine-authoritative-rng/prototype/rules-engine.verification.test.ts` from repository root | 2026-07-25 final rerun | | E-009 | Measurement | Root strict TypeScript compilation completed with exit code 0 | `npm run typecheck`; root `tsconfig.json` | 2026-07-25 final rerun | | E-010 | Unknown | Production entropy quality, distributed idempotency, concurrent persistence and mechanical balance have not been measured | Scope boundary and `VALIDATION.md` | 2026-07-25 | ## Журнал экспериментов | Время | Изменение или попытка | Наблюдение | Artifact или evidence ID | Вывод | |---|---|---|---|---| | 2026-07-25T01:04:02+07:00 | Read the official Knave page and canonical PRD/research requirements | Version 1.0 and licensed high-level mechanical inspiration are attributable; product-specific text/content is unnecessary | E-001–E-006 | Proceed with an original genre-neutral profile | | 2026-07-25T01:10:14+07:00 | Initial manifest-only run | Historical suite reported 7 tests: 2 manifest/profile checks passed and 5 behavior cases were TODO | Historical test output retained from study start | This pre-registration did not verify rules/RNG behavior and is superseded by the final executable suite | | 2026-07-25 | Connected AC-01–AC-06 to shared vertical-slice public APIs and removed the local duplicate profile | All tests now use `loadFixtureBundle()` and the shared `game-contract.json` | E-006, E-007 | Shared fixture is the authoritative rules-profile source | | 2026-07-25 | First executable Node.js `v24.14.0` behavior run | Failed with `ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX` because `FixedRandomSource` used a TypeScript constructor parameter property, which built-in strip mode cannot erase | Initial command output; test edit history | Replace the parameter property with an ordinary class field plus constructor assignment | | 2026-07-25 | Re-ran after the erasable-syntax fix | Six AC tests passed with no fail, skip or TODO | E-008 | AC-01–AC-06 pass | | 2026-07-25 | Ran the root strict compiler | `tsc --project tsconfig.json --noEmit` exited successfully | E-009 | Shared imports and test types compile | ## Выводы - **Fact:** All six executable acceptance tests pass on the recorded final environment. Основание: `E-008`. - **Fact:** Fabricated client roll fields are schema-rejected before RNG; valid commands store only the injected server result. Основание: `E-007`, `E-008`. - **Fact:** Duplicate and stale-version commands return before a second/new RNG call, event append or state mutation in the registered cases. Основание: `E-007`, `E-008`. - **Fact:** The shared authoritative profile preserves official attribution while its executable fields remain original and genre-neutral. Основание: `E-005`, `E-006`, `E-008`. - **Inference:** The tested ordering and capability boundary is suitable as the reference contract for a production rules/event implementation. Основание: `E-001`–`E-009`. - **Unknown:** Fixed in-memory tests do not establish production entropy, durability, distributed concurrency or balance. Основание: `E-010`. ## Рассмотренные альтернативы | Подход | Что проверили | Почему не выбран | Evidence | |---|---|---|---| | LLM chooses roll/outcome | Submitted fabricated raw/success fields | Payload is rejected and cannot become canonical randomness | `E-001`–`E-004`, `E-008` | | Consume RNG before idempotency/version checks | Compared duplicate and stale-version call counts | Would waste/change randomness and risk duplicate effects; tested ordering consumes no extra roll | `E-002`–`E-004`, `E-008` | | Keep a study-local rules profile | Compared local study contents with the shared loader/fixture | Creates divergent sources of truth; the duplicate was removed | `E-006`, `E-007` | | Copy Knave text/content into the profile | Compared with actual executable needs | Unnecessary; original profile uses only attributed high-level inspiration | `E-005`, `E-006` | | Select a production RNG dependency now | Compared with the authority question | Fixed port proves source authority/order but provides no entropy or threat-model evidence for a dependency decision | `E-008`, `E-010` | ## Неизвестные - **Unknown:** deterministic PRNG versus system entropy policy and seed disclosure; close through a dedicated fairness/threat decision. - **Unknown:** idempotency retention, partition key and transactional persistence; close when the room/event store is selected. - **Unknown:** behavior under actual concurrent writers and reconnect storms; close with multi-process integration/chaos cases. - **Unknown:** modifier ordering and rounding beyond the current original profile; close with worked balance fixtures. - **Unknown:** throughput/latency under concurrent commands; measure against an approved product gate after a durable implementation exists.