The Ruleset Engine — The Complete Picture
This page teaches the whole system from zero: what is being built, how a rule will change at runtime without a deploy, how the design is being hardened before a line of code exists, how decisions are made and recorded, and every gate that can say no along the way. Diagrams first, then the detail. Sources are at the bottom; every number here traces to a committed file.
0. The end-to-end process, one picture
The whole effort has four stages. A design is attacked until it stops breaking; every decision found on the way becomes an ADR that only Mohamed can flip; when a full attack round finds nothing, the design becomes a spec and implementation begins — traced, gated, and merged only by Mohamed. Gates (the flag-shaped nodes) attach where they bite.
Reading the picture. Stage 2 is a loop: each round either finds real defects (fold them, run again) or finds none (exit). Stage 3 runs continuously beside the loop — decisions surface mid-round and are recorded immediately; the loop never waits on a ruling unless the fix itself needs one. Stage 4 is bound by F13, the ratified traceability contract: nothing lands untraced.
1. What is being built, in plain terms
The problem. Today, changing an enforcement rule means editing code and deploying. Mohamed's requirement, verbatim: "I want to be able to change and edit the rules at runtime without having to create a whole new deploy." And later: everything free-threaded and async, no blocking waits, and "if the rule is violated the gate fails" — rules are law, and law must fail closed.
The shape of the answer.
- Rules are data, not code. They live in rulesets — one per surface (a surface = one enforcement domain, e.g. test-purity or commit-hygiene).
- Every edit creates a new immutable version. A
RulesetVersionis a content-addressed tree (rules + tests + vendored detectors + params). Nothing is ever edited in place; versions are pinned against garbage collection. - What actually runs is a named composition. A
Compositionpins each surface to one version; a name (likeprod-gates) points at a composition. Names are the operational handle — activation, rollback, and denial all target names. (This shape is decision ADR-0041 — eight consecutive review rounds READY, awaiting Mohamed.) - Four signing authorities, strictly separated.
ratify— Mohamed's key, the only one that can change law.adjudicate— the queue's key, for review verdicts.prove— the admission host's key, for proofs.admit— the projector's key, for admission records. No key can do another's job; a machine key alone can never change what serves. - Engines are processes-per-version. Each ruleset version runs in its own supervised process; switching versions is spawning the new beside the old, self-testing, and atomically flipping the name — never mutating a live process.
- Everything fails closed. An unevaluable check is INVALID, never a silent pass;
a name with no valid law serves
deny_allwith a stamped reason, never lawlessness.
2. How a rule change flows at runtime
The walk, step by step — what each stage exists to guarantee.
- Edit. Anyone authorized drafts a candidate rule tree. It costs nothing and blocks nobody: minting a lineage reserves nothing, so submissions can never deadlock each other (this was a hard-won round-15/16 result — an earlier design gated at mint and two honest submitters could deadlock; the gate moved to presentation, where Mohamed's override is actually reachable).
- Lineage. The queue mints an amendment lineage and hands the submitter a bearer token — the continuity credential for resubmissions. Review history is permanent: a FAIL is resolved only by a later PASS in the same lineage or by Mohamed — never by waiting. Silence sheds nothing, by mechanism.
- Machine checks. Load check, rule tests, scope diff, meta-lint, and cross-rule consistency are re-derived by the queue — the second factor that keeps a compromised prover honest.
- Reviews. Where a rule's bindings demand judgment, adjudications run and are recorded as durable acts (PASS / FAIL / INVALID / never-ran — four distinguishable states; INVALID blocks exactly like FAIL).
- Proof. The admission pipeline loads the candidate in throwaway validator children (all must agree on the same candidate tree AND the same engine build — a rolling deploy mid-proof is refused, not straddled) and shadow-replays recent real decisions against the new rules: Mohamed sees what would have changed before it is live. A rule change whose shadow was never exercised is blocked from Proven unless he explicitly overrides.
- Presentation → one word. Everything lands in Mohamed's session: the law diff, proof verdicts, shadow flips, rejection/review history including other lineages touching the same surfaces. He says approve — the harness signs with the ratify key held in his context; he never touches key material. Or reject — a durable, ratify-signed no that every future resubmission surfaces. (This interface is ratified contract F13; its description is being corrected to target-vs-current semantics under proposed ADR-0050.)
- Admission. The projector checks tip-currency (no signing over a stale view of the world) and the six tri-state act-checks, and attaches an AdmissionRecord — the artifact every reader verifies forever after. An entry without its admission record is refused everywhere.
- Activation. Engine hosts spawn the new version's process beside the old, self-test it, then atomically flip the name. In-flight decisions complete under the rules they started with; the next decision uses the new law. Total time from Mohamed's word: seconds to minutes, every stage deadline-bounded.
- Rollback is first-class. Any of the last N generations can be restored by a
ratification alone — grandfathered, needing no fresh proof — which is exactly
what makes it the emergency escape when something bad is live or a fleet is in
deny_all.
3. How the design is being hardened — the adversarial loop
The design is 1,400+ lines of contracts, failure tables, and concurrency obligations. Before any code, it is attacked — round after round — by fresh reviewer agents that inherit no conversation context and treat all prior rounds as claims to re-test.
Why two lenses? Concurrency/distributed-state hunts interleavings, races, ABA bugs, unbounded queues, and blocking waits; lifecycle/proof-binding/authority hunts authority leaks, forgeable records, retroactivity holes, and fail-open paths. Each CONFIRMED finding must carry a numbered interleaving or scenario — vague unease doesn't count; a reproducible failure story does.
Why a fold-verifier? Because the author folding findings is the weakest link. The verifier mechanically re-checks every claimed fix: citations resolve, every failure-table row has a live mechanism, budget lists close in both directions, every new artifact names its producer + executing task + channel + wait + authority root, and deletions never orphan prior conclusions. It has caught the author claiming a fix a version early — twice — and both times the ledger now records the false claim by name.
The discipline was earned, not designed. Eight revision rules exist because each one's absence caused a real fold failure: fold from files, never summaries (round 12 left 9 of 24 defects uncorrected off a summary); never compress mechanism away; walk the concurrency tables rather than asserting them; re-grade everything a deletion touched, same round; per-id ledger entries, never "ALL"; and rule 8's three clauses — every new field names who produces it, what executes it, and who authorizes it.
The trajectory (confirmed findings per round):
| Round | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Confirmed | 26 | 16 | 22 | 19 | 16 | 20 | 15 | 22 | 22 | 20 | 21 | 14 | 14 | 14 | 11 | 15 |
How to read it. Plateaus happen when a fold invents new machinery — the new mechanism arrives carrying the gaps of its novelty. The surface-lease chain ate three rounds of redesign then converged from ten findings to one loose end in a single round; the silence machinery was found rotten five independent ways and was deleted rather than repaired (minting is now ungated; history is permanent; the gate sits at presentation). Round 16's rise is localized: F13, ratified text added outside the loop, took its first review and yielded four of five HIGHs — the strongest argument the loop has produced for its own necessity: nothing skips review, including the reviewers' owner's own ratified prose.
4. Decisions — the ADR system
The law, and where it came from. Three rulings, all Mohamed's, all this week:
ADR-0046 — every ADR lives in three synchronized homes (docs file, wiki entry,
graph node); it isn't done until the drift gate says OK in sync. ADR-0047 — the
project had two colliding ADR series (a factory series in docs and a project series
on the wiki, reusing the same integers for different decisions — 38 gate violations,
with the graph silently preferring the wiki's); the fix: ids are zero-padded
strings in two named registers — ADR-0001 and ADR-001 are different ids —
and nothing was renumbered, so every existing citation stayed valid.
ADR-0048 (proposed) — a ratified ADR is itself sufficient design authority for
bounded implementation, so executing a decision doesn't require restating it as a
contract file.
The tooling. A decision skill (deployed in the repo, shipped in the orchestrata
plugin) carries the whole procedure; a word-trigger hook fires it whenever a prompt
mentions decision / decide / ADR / ratify / ruling — the discipline is injected
before action, not remembered after. Rulings are executed the same turn they're
given, with commit shas shown: a ruling is not recorded until it is in the artifact
and committed.
The current register (ruleset series):
| ADR | Decision | Status |
|---|---|---|
| 0039 | One commit per design version (F12) | Accepted |
| 0040 | Traceability contract + one-word approval (F13) | Accepted |
| 0041 | Per-surface versions + named compositions (F1) | Proposed — READY 8 rounds; ruling conditioned on round 16, now satisfiable |
| 0042 | Wiring-gate supersession (F4) | Proposed — READY 8 rounds |
| 0043 | Rollback window + CAP arithmetic (F8-cap) | Proposed — READY 8 rounds |
| 0044 | Registry entries self-admit | Proposed |
| 0045 | Per-lineage bearer token | Proposed |
| 0046 | ADRs live in three homes | Accepted |
| 0047 | Two registers, string-significant ids | Accepted |
| 0048 | Ratified ADR = design authority | Proposed |
| 0049 | Review evidence three homes | Proposed |
| 0050 | Amend F13(D): target semantics + full payload | Proposed — unblocks four §11 items |
5. Every gate that can say no
A gate here means: a mechanical check with a command, a failure behavior, and no discretion. The system's honesty lives in these.
The full gate population is larger than this table: 24 registered battery gates
(the scripts/gates.py registry plus its __ast__ pre-step, verified against
.cache/gates.json 2026-08-29) plus three families — the suite preflight gates,
the 32 .claude/hooks/*.sh session guards, and the process-level gates below. Every
gate now has its own detailed page:
Gates — Master Index.
Process-level gates
| # | Gate | What it refuses | How it runs |
|---|---|---|---|
| 1 | Briefs-before-dispatch | any reviewer working from undocumented instructions | briefs committed to plans/briefs/; the agent's prompt IS the committed file |
| 2 | Evidence-on-landing | review data living only in volatile storage | every report committed to plans/reviews/ruleset/ the turn it lands |
| 3 | Author sweep | half-propagated folds (a term retired in one place, alive in another) | grep of every retired term must return zero live hits before commit |
| 4 | Per-id ledger | fold claims hiding behind "all fixed" | the design's own §12 bans bare quantifiers; every finding id gets its own disposition |
| 5 | Fold-verifier | false fold claims, inert mechanisms, orphaned deletions | independent auditor, 8 mechanical checks per version; its file is folded, never its summary |
| 6 | RUL-007 attribution | AI attribution in commits (Mohamed is sole author) | runs on every git commit, both repos |
| 7 | ADR drift | any ADR differing across docs/wiki/graph | uv run python scripts/check_adr_graph_sync.py → every id must read OK in sync |
| 8 | Ruling authority | anyone but Mohamed flipping a decision; unrecorded rulings | process law: one decision at a time, data in the ADR first, same-turn recording with shas |
| 9 | RUL-022 design-before-build | implementation with no design authority | PreToolUse hook blocks builder dispatch without a contract or an Accepted-ADR waiver |
| 10 | F13's traceability battery | untraced or drifting SPEC-115 code | check-traces + trace-audit (review battery), trace_intel orphans/untraced-reqs (exhaustive Prolog), evidence-graded RTM, feature-loss (pre-commit), spec-authority, req-format, factory conformance — all blocking |
| 11 | Suite | red tests; false-green runs | python scripts/run_tests.py — the gRPC kernel is REQUIRED (a run that skips it is invalid), no mocks, no xdist, real infra |
| 12 | Plugin currency | skills/hooks missing from the delivery path | python3 claude/scripts/gen_plugin.py --check |
| 13 | Session honesty | guessing ("likely"), "pre-existing" as an excuse, claims without verification | RUL-017 / RUL-024 stop-hooks + deception audits on every reply |
| 14 | Mohamed | everything above him | ratification sessions and the merge gate — no branch reaches master without his word |
6. Where everything lives
| Artifact | Home |
|---|---|
| The design (v16.1, ~1,408 lines) | plans/ruleset-runtime-design.md, branch architecture/domain-model — one commit per version |
| Review evidence, rounds 1–16 | plans/reviews/ruleset/ — 41 committed files |
| Reviewer briefs (verbatim, pre-dispatch) | plans/briefs/ |
| Status (refreshed per round) | plans/ruleset-review-status.md |
| ADRs | docs/adr/ + this wiki's decisions page + ArchitectureDecision graph nodes |
| The decision skill + trigger | .claude/skills/decision/, .claude/hooks/decision-adr-trigger.sh, shipped in plugins/orchestrata/ |
| Detailed round-16 state | the companion page Ruleset Design — Adversarial Review Lifecycle & State |
This page is regenerated as the process evolves; its facts are under the same adversarial review as everything else — a hostile fact-checker's findings are folded into it the turn they land.