2026-10-02 — Meta-rule change: promote kahn's gate-and-evidence rules to fleet MRs (MR-18, MR-19; MR-20/MR-21 for the operator to rule)
rank: decision outranks: []
Section titled “rank: decision outranks: []”2026-10-02 — Meta-rule change: promote kahn’s gate-and-evidence rules to fleet MRs (MR-18, MR-19; MR-20/MR-21 for the operator to rule)
Section titled “2026-10-02 — Meta-rule change: promote kahn’s gate-and-evidence rules to fleet MRs (MR-18, MR-19; MR-20/MR-21 for the operator to rule)”Date: 2026-10-02 Status: closed Supersedes: none Superseded-by: none — current MR-compliance: MR-4, MR-7, MR-8, MR-9
Context
Section titled “Context”On 2026-10-02 kahn (kahn-tools/kahn, registry slug kahn-hq) adopted four
KAHN-local rules by operator ruling, numbered KMR-3 … KMR-6. The ruling is
kahn decision
docs/decisions/2026-10-02-meta-rule-namespace-and-gate-evidence-rules.md.
It lands via kahn-tools/kahn#114, which renames kahn’s local MR-13/MR-14 to
KMR-1/KMR-2 and adds KMR-3…KMR-6. This doc cites it by path and does not
quote it. The rules come
from kahn’s two Phase 12 verification rounds:
docs/findings/20260812-1500-phase-12-verify-round.md(first round, FF-n items)docs/findings/20260812-1800-phase-12-verify-round-second-reader.md(independent second reader, SF-n items)
The four rules, and the incidents behind them:
- (a) A gate may not reference an artefact created by the action it gates.
A gate whose evidence cannot yet exist refuses the tick. kahn Phase 12 PA-3
read “
make e2ereturns 0 failed on the Phase-12 close commit”. That commit cannot exist until the phase closes, which is the action PA-3 permits. It was ticked[x]on assertion (second reader SF-2). The first round had already diagnosed the gate as “unsatisfiable locally, tautological in CI” (FF-5) and still recorded PASS-with-deviation. Meanwhiledocs-invariantswas red on kahnmainfor 17 consecutive runs, 2026-05-13 → 2026-09-23. Observed 2026-10-02 withgh run list -R kahn-tools/kahn --workflow docs-invariants.yml --branch main: the first red run is25788367666(feb2019), the last is35850050095(79861e5), and the first green is36854996324on 2026-10-01. The cause was one malformed tag (AGENTS.xml:28-31). The job died at XML parse before it reached any of its checks. - (b) A friction item or claim about a workflow or job cites an observed run
ID, not the workflow’s source. kahn FF-3 said
docs-invariants.yml“only checks IDs inAGENTS.xml”. The job never reached that check. The claim describes the YAML, and was written while the last 15 runs were “onegh run listaway” (SF-3). That is the direct reason SF-1 survived the first round. The same thing happens elsewhere in the fleet:erid-tech/rockye2e.ymlhas never passed. The workflow was created 2026-07-02. All 5 runs on record failed, from28579849318(2026-07-02) to36903860891(2026-10-01), observed 2026-10-02 withgh run list -R erid-tech/rocky --workflow e2e.yml. Its YAML reads correctly. Only the runs say it doesn’t work.- eva-hq’s fleet trap register
(
.claude/skills/operating-the-eva-fleet/references/traps.md:55) records that “pulse cites an old CI failure as current”. The health guard read an unscopedgh run list -L 5across workflows. The fix it records is to confirm on the commit (gh run list --commit <sha>). An observation also has to be scoped, or it observes the wrong run.
- (c) A measured FAIL states the exact command and reconciles it against the
scope the source document names, before filing. kahn’s Phase 11 round
filed AC-6 as “FAIL-unevaluable at 178 sites”. The inline-style tally is
pinned at 176. The extra two came from the round’s own method drift: it
widened the glob from
frontend/src/{views,components}/*.ts(the scope DESIGN.md names) to all offrontend/src. kahn’s Phase 12 first round (FF-1) calls this “the most serious item in this round”. A round that invents a FAIL spends the next phase’s budget on a milestone that did not need to exist. - (d) A negative assertion has a positive precondition in the same test.
kahn’s M11.1 route rename left two
default-routespa-e2e tests passing for three months against a 404 page. Their only assertion wasexpect(url).not.toContain("#/agents")(first round FF-4). M12.2 fixed the instance, but nothing fixed the class.
What petrova already says, and why that wasn’t enough
Section titled “What petrova already says, and why that wasn’t enough”petrova already has half of (a), at the wrong layer.
skills/petrova-verify-round/SKILL.md Part A says: “No gate may be evaluated
on assertion. A gate you cannot evaluate is a FAIL with reason
‘unevaluable’”. docs/decisions/2026-08-13-acceptance-gate-waiver-shape.md
forbids waiving an unevaluable gate. Both rules act at round time, and only in
repos that run petrova’s verify-round skill. kahn’s first round knew the
unevaluable-gate rule and still passed PA-3. Nothing applies when a gate is
written or when a box is ticked, and those are the two moments where
PA-3 went wrong. A meta-rule applies at all three moments, in every consumer.
The playbook deposits it there (MR-17).
petrova has already hit (d)‘s class in its own tooling, twice:
docs/findings/20260826-1230-a-green-that-cannot-tell-nothing-to-report-from-nothing-reported.md(PTV-FND-0063): a checker exited green, “every recorded campaign is citable”, over a zero-byte artefact.docs/findings/20260828-1500-a-citation-over-an-empty-artefact.md: a citation resolved against an empty artefact.
Decision
Section titled “Decision”Proposed. Nothing here takes effect until a human countersigns. Agents may open a meta-rule change, but cannot ratify one (META-RULES “Updating these rules”, step 3).
-
Promote (a) and (b) to fleet meta-rules. The highest MR assigned today is MR-17. That is true in the canonical
META-RULES.md(v1.3), inhost/src/sources/audit.tsALL_MRS, and in the generated site pages. MR-18 and MR-19 are not used anywhere in petrova-codes or eva-hq. The one exception is a code comment indashboard/src/pages/console/governance.astrothat says “MR-1 .. MR-19” while describing sort order. It assigns nothing. Proposed wording:MR-18 — A gate’s evidence must be able to exist before its tick. An acceptance gate may not name, as its evidence, an artefact created by the action it gates. Examples are the close commit, the merge, and the tag being released. A gate whose evidence cannot yet exist is unevaluable, and an unevaluable gate refuses the tick. It is a FAIL with reason “unevaluable” and a finding about how the gate was written. It is never a PASS-with-deviation, never waived, and never ticked on assertion. Write the gate against evidence that comes before the action, such as CI at the candidate commit, named by SHA and run ID.
MR-19 — Claims about a workflow cite an observed run. A finding, friction item, gate verdict or status line that says what a workflow, job or check does cites the run ID(s) it observed, and the commit they ran on. A workflow’s source says what it is meant to do. Only its runs say what it does. Scope the observation to the subject: by commit, or by workflow and branch. An unscoped run listing mixes in stale runs from other workflows.
-
(c) and (d): the operator decides at countersign. The recommendation and reasoning follow. The countersign line asks for an explicit ruling on each.
-
(d) Recommend fleet-wide, as MR-20. The class shows up in more than one repo: kahn’s spa-e2e against a 404, and petrova’s own PTV-FND-0063 and empty-artefact citation, which are the same shape in a checker instead of a test. It doesn’t depend on any one stack, because “asserts absence, so it passes on nothing” applies equally to Playwright, a CI checker, or an audit row. It also complements MR-19: MR-19 asks whether you looked at the run, and MR-20 asks whether the run looked at anything. Proposed wording:
MR-20 — A negative assertion carries a positive precondition. A test or check that asserts absence (“no error”, “URL does not contain”, “zero violations”) also asserts, in the same test, something positive that proves it observed its subject: the page rendered, the input is non-empty, the checker read N > 0 records. Otherwise it passes on a 404, an empty file, or a server that isn’t running.
-
(c) Recommend it stays repo-local (kahn KMR) for now. The rule is sound, but the fleet has only kahn’s 178-vs-176 incident behind it, and the incident needs a pinned count with a stated scope, which few repos have. Its general core is that a measurement must be reproducible from what the record states. The petrova verify-round skill already requires that (“cite the specific evidence”), and MR-19 already requires it for CI. Promoting (c) now would add a rule with one incident behind it. MR-9 discourages that for invariants, and the same reasoning applies here. If the operator rules it fleet-wide anyway, it takes MR-21 with kahn’s wording.
-
-
Numbering is assigned at ratification, in this order. MR-18 is (a). MR-19 is (b). MR-20 is (d), if ruled fleet-wide. MR-21 is (c), if ruled fleet-wide. If (d) is rejected, MR-20 stays unassigned: nothing outside this doc may cite MR-20 or MR-21 until a countersign assigns them. If (d) is rejected and (c) accepted, (c) takes MR-20. Once a number is ratified it is stable (MR-8).
-
Namespace rule for repo-local meta-rules. Bare
MR-Nis reserved for the petrova playbook’sMETA-RULES.md. A repo that adopts its own meta-rules prefixes them with a repo code, following kahn’s precedent:KMR-N. kahn’s earlier local MR-13 (“invariants need test enforcement”) and MR-14 (“cross-runner baselines come from the canonical runner”) collided with petrova MR-13/MR-14. GreppingMR-13in kahn returned two different rules (second reader SF-6). The kahn ruling resolves this by renumbering intoKMR-. This doc adopts the prefix convention fleet-wide but does not choose prefixes for other repos. When a local rule is promoted to a fleet MR, the repo marks its local number “promoted to MR-N” and does not reuse it (MR-8 applied to local numbering). For kahn, if this doc is countersigned as written, KMR-3 and KMR-4 become “promoted to MR-18 / MR-19”, KMR-6 becomes “promoted to MR-20” if (d) is ruled fleet-wide, and KMR-5 stays local.
Not decided here: any audit implementation, and the eva-hq prose edit. Both are follow-ups (see Consequences). This PR is doc-only.
Alternatives considered
Section titled “Alternatives considered”- Leave all four rules KAHN-local. Rejected. (a) and (b) failed in a repo that already had petrova’s verify-round rule, and (b) shows up in rocky and in the eva-hq fleet tooling. Leaving them local means each repo learns them again from its own incident.
- Fold (a) into the verify-round skill only, with stronger wording. Rejected. The skill acts at round time. PA-3 went wrong when it was written and when it was ticked, and the skill isn’t present at either moment. A meta-rule reaches every agent that loads the playbook preamble.
- Promote all four at once. Not recommended, because of (c)‘s evidence base (Decision 2). The operator can still choose this at countersign.
- Absorb (a) into MR-10 (“the verification round is mandatory”) as a
sub-clause. Rejected for the same reason MR-16 was not folded into MR-1
(
docs/decisions/2026-05-13-meta-rules-mr16-mr17.md). MR-10 says a round must happen. MR-18 says what a gate may cite. Merging them would lose the difference between the two citations.
Consequences
Section titled “Consequences”For code (follow-up PRs after countersign, not in this PR):
- Authoring home is eva-hq, not here.
core/playbook/META-RULES.mdis a mirror ofeva-hq/prompts/_shared/petrova/META-RULES.md, kept in sync by.github/workflows/sync-playbook-from-eva.yml(eva-hq has been canonical since 2026-05-14). The two are byte-identical at the time of writing. The MR prose, the version bump 1.3 → 1.4 and the changelog entry land in eva-hq. The mirror PR then lands here. Also: the file header says 1.3, but the changelog stops at 1.2, so the follow-up should backfill the 1.3 entry. The text “almost always one of these seventeen” needs updating too. core/playbook/schemas/progress.schema.jsonrejects new MRs.petrova_invariants_violateditems match^MR-(1[0-5]|[1-9])$. An agent that halts on MR-18 cannot emit a valid progress signal. This defect already exists, since MR-16 and MR-17 fail the same pattern. The follow-up should widen it to^MR-[1-9][0-9]*$, matchingspec/verbs/_common.schema.json.core/playbook/partials/mr-preamble.xmllists headline rules only up to MR-15. It needs MR-16 … MR-19 (and MR-20 if ratified).host/src/sources/audit.ts.ALL_MRSlists only MRs with an audit function. MR-2, MR-6, MR-9 and MR-11 are prose-only and are not in it. MR-18 and MR-19 start the same way: noALL_MRSentry, no/console/governancecolumn, until someone writes an audit. Possible audits, not committed to here: for MR-18, flag ticked gates in a consumer’sMILESTONES.mdwhose text names “the close commit” or “the merge”. For MR-19, flag findings that name a.github/workflows/*.ymlwithout a run-ID-shaped citation. Both are heuristic, and a heuristic audit should bewarn, neverfail. If an audit is added, updateALL_MRSand the “MR coverage” header comment together.skills/petrova-verify-round/SKILL.md. Part A should cite MR-18, and Part B should require MR-19 run IDs for any CI claim.docs/site/generated/meta-rules/*regenerates throughsync-docs. No hand edits.
For consumers (vendoring):
petrova_install_playbookdepositsMETA-RULES.md,mr-preamble.xmlandprogress.schema.jsoninto each consumer’s.petrova/playbook/. kahn’s copy at.petrova/playbook/META-RULES.mdmatches canonical v1.3 apart from the install-time placeholder rewrite. Every consumer atrole: productionorexperimentalgets the new rules only when the playbook is re-deposited. MR-17 checks that the playbook is present, not that it is current, so a consumer can keep v1.3 indefinitely and still pass audit. Rollout therefore needs either a re-run of the install verb across the fleet, or a separate freshness check. Neither is decided here.- eva.consumption.v1 is not changed.
contracts/vendor/eva-consumption.v1.jsoncarries no MR identifiers, so its shape is unchanged. The downstream surface this changes is the playbook boot kit that eva-hq authors. Under eva-hq’sCLAUDE.md(“changes affecting downstream consumers need the fleet to ratify”), this doc is that ratification vehicle. The eva-hq follow-up should cite it.
For in-flight phases:
- kahn Phase 13 (M13.2, gate-and-evidence doctrine and namespace) is the local counterpart. It doesn’t wait on this doc, because KMR-3 … KMR-6 are already in force locally.
- Once MR-18 is ratified, any open phase in any consumer with a gate citing its own close artefact has an unevaluable gate. This doc does not audit for those gates.
For invariants:
- Adds MR-18 and MR-19. Conditionally adds MR-20 (d) and/or MR-21 (c). No MR is modified or repealed.
- Adopts the repo-prefix convention (
KMR-N) for local meta-rules. BareMR-Nis reserved for the playbook. - Pre-existing defect, recorded here because this doc adds numbers to the
same space:
host/src/sources/audit.tslabels two audits with numbers whose playbook meaning differs.:453“MR-14 — Onboarding-complete signal” vscore/playbook/META-RULES.md:220“MR-14 — Probes never auto-promote, only auto-demote”, and:493“MR-15 — Workflow drift” vs:235“MR-15 — The schema is the source of bootstrap questions”. MR-13 (:429/:206) and MR-17 (:684/:265) agree. Follow-up, not in this doc: either re-key those audits to the rules they enforce, or record that they are audits of MR-14/MR-15 under a reading the playbook text does not give. Until then afailrow labelled MR-14 or MR-15 does not mean what the playbook says.
References
Section titled “References”- kahn decision (in parallel, may be in review):
kahn-tools/kahn:docs/decisions/2026-10-02-meta-rule-namespace-and-gate-evidence-rules.md - kahn findings:
docs/findings/20260812-1500-phase-12-verify-round.md(FF-1, FF-3, FF-4, FF-5) anddocs/findings/20260812-1800-phase-12-verify-round-second-reader.md(SF-1, SF-2, SF-3, SF-6) - kahn
docs-invariantsruns:25788367666(first red, 2026-05-13) …35850050095(last red, 2026-09-23),36854996324(first green, 2026-10-01) - erid-tech/rocky
e2e.ymlruns:28579849318(2026-07-02) …36903860891(2026-10-01), allfailure - eva-hq
.claude/skills/operating-the-eva-fleet/references/traps.md:55 - petrova:
skills/petrova-verify-round/SKILL.md(Part A);docs/decisions/2026-08-13-acceptance-gate-waiver-shape.md;docs/findings/20260826-1230-a-green-that-cannot-tell-nothing-to-report-from-nothing-reported.md;docs/findings/20260828-1500-a-citation-over-an-empty-artefact.md - Shape precedent:
docs/decisions/2026-05-13-meta-rules-mr16-mr17.md,docs/decisions/2026-04-30-integration-spine-meta-rules.md - Playbook mirror:
.github/workflows/sync-playbook-from-eva.yml;cli/src/verbs/petrova_install_playbook.ts
Sign-off
Section titled “Sign-off”- Subagent: Claude Opus 5.5, 2026-10-02 (drafted; run IDs above observed
2026-10-02 with
gh run list; petrova state read ate5f695cd) - Human: flight@arno.host — that MR-18 (a) and MR-19 (b) join META-RULES.md as
worded above; a ruling on (d) → MR-20 (recommended: yes) and on (c) → MR-21
(recommended: no, stays KMR-local); and that bare
MR-Nis reserved for the playbook, with repo-local meta-rules prefixed (KMR-Nprecedent)
Countersigned by human:flight@arno.host on 2026-10-02 — box ticked in commit
8e68899c, authored by the human. The tick was given without amending the
box’s two pending rulings, so it is read as accepting both stated
recommendations: (d) → MR-20, fleet-wide; (c) not promoted, stays
KAHN-local as KMR-5 (MR-21 unassigned). That commit wrote Status: approved; the scribe commit after it normalises this to closed, which is the
vocabulary petrova validate (MR-7) accepts. Status flipped on 2026-10-02 by
an agent as scribe (MR-7).