# Rules Engine and Authoritative RNG Contract - **Status:** `complete` - **Outcome:** `pass` - **Started:** 2026-07-25 - **Updated:** 2026-07-25 - **Research ID:** `2026-07-25-rules-engine-authoritative-rng` ## Проверяемый вопрос Можно ли задать rules-engine boundary, который принимает только validated typed commands, проверяет idempotency и expected state version, использует только server RNG и создаёт полностью аудируемый roll record до state transition? ## Почему решение нужно сейчас PRD запрещает narrator/LLM определять исход броска или применять state change. Rules and randomness contract нужен до production reducer/event API, иначе formula, modifier order, rule version, retries и concurrency будут иметь несколько несовместимых источников истины. ## Scope - Rules input as a schema-valid typed command. - Deterministic preconditions and effects around an injected server RNG port. - Auditable roll evidence: raw result, formula, modifiers, rule version and enclosing stored event reference. - Idempotency key and expected state version checks before RNG/event/state work. - Original genre-neutral shared profile inspired by attributed Knave 1.0 mechanical principles, without Knave wording, content or compatibility claim. - Executable behavioral tests against the shared vertical-slice engine, event-log, state and authoritative fixture. ## Non-goals - Production reducer, durable event store, distributed idempotency store or deployment topology. - Full combat, character creation, bestiary, items, spells or adventure content. - Cryptographic fairness/provably-fair protocol or statistical RNG-quality measurement. - Knave/D&D text, setting, product name or compatibility. - Balance, fun, throughput or latency claims. ## Критерии успеха | ID | Обязательный критерий | Порог или ожидаемое поведение | Способ проверки | |---|---|---|---| | AC-01 | Accepted roll is fully auditable | Every committed roll record contains raw roll value(s), canonical formula, ordered modifier, rules profile/version and event reference | Execute both registered roll-producing command kinds with fixed RNG; compare every roll field to worked literal values and resolve the committed event by command ID | | AC-02 | RNG authority is server-side | Client/LLM cannot supply or overwrite accepted raw result; rules engine consumes only injected server RNG output and commits no success before that result exists | Submit a fabricated `raw`/`success` payload, then a valid command against a controlled server RNG; inspect rejection, RNG calls, stored events and accepted raw/source | | AC-03 | Invalid command stops before randomness or mutation | `100%` labelled schema-invalid state-changing fixtures return structured rejection/clarification with zero RNG calls and unchanged event/state snapshot | Submit null, missing-field and ill-typed fixtures; compare RNG calls, event count and state hash | | AC-04 | Idempotency prevents double application | Repeating a command with the same idempotency key returns the original committed result or structured duplicate response and appends no second event/state effect | Execute the same command twice and compare event ID, event count, state hash and RNG calls | | AC-05 | Expected-version conflict fails closed | Command whose expected state version differs from authoritative version returns structured conflict before RNG/event/state mutation | Submit a stale-version command and inspect conflict code/state version, RNG calls, event count and state hash | | AC-06 | Mechanical profile is attributed and original | Fixture names Knave 1.0/Ben Milton/official URL/CC BY 4.0 as inspiration, while executable design is genre-neutral and contains no Knave/D&D branding | Load the shared Game Contract fixture and assert attribution, source URL, versioned profile data and unbranded executable fields | The PRD supplies the `100%` invalid-command gate and “every roll” completeness requirement. No latency, throughput, distribution-quality or fairness number is invented here. Criteria did not change after implementation began. ## Рабочие гипотезы - **Hypothesis H-01:** checking idempotency and expected version before consuming RNG makes duplicate/retry/concurrency behavior deterministic; the registered duplicate and stale-version cases consumed no second/new roll or effect. - **Hypothesis H-02:** a declarative, versioned rules profile separates original game design from the engine and prevents LLM mechanics improvisation; the shared fixture passed attribution/originality assertions without a local profile copy. ## Материалы - [Исследование и evidence log](RESEARCH.md) - [Техническое решение и запуск](SOLUTION.md) - [Проверка и итог](VALIDATION.md) - [`prototype/`](prototype/) — six executable AC tests - [Shared authoritative Game Contract/rules profile](../2026-07-25-ai-gm-vertical-slice/prototype/fixtures/game-contract.json) - [Official primary source: Questing Beast — Knave](https://questingbeast.itch.io/knave) ## Итог Локальный Node.js `v24.14.0` прогон завершился `6/6` passing tests, без failures, skips или TODO. AC-01–AC-06 выполнены: roll evidence complete for the registered check/attack paths, fabricated client rolls rejected, invalid commands stop before RNG/state, duplicate and stale-version commands fail closed, and the shared profile is attributed/original. Root `npm run typecheck` также завершился успешно. Подробности находятся в [`VALIDATION.md`](VALIDATION.md). ## Ограничения - Fixed RNG verifies authority and calculation, not entropy quality, distribution or cryptographic fairness. - In-memory sequential tests do not prove distributed idempotency, durable transactionality or multi-process conflict handling. - Shared profile values are research design choices, not validated product balance. - The official Knave page supports the attributed high-level inspiration and license statement, not product demand, suitability or legal clearance. ## Следующее решение `GO` для использования проверенного ordering/authority contract в production design: validation, idempotency and expected-version checks must stay before RNG consumption; accepted rolls must remain server-sourced and attached to a stored event. Production promotion separately requires a durable transactional store, RNG threat/entropy decision, concurrent-writer tests and balance validation.