Skip to content

refactor(ci)!: retire the mutation runner onto batten mutate so coverage can reach the Rego layer (CLOUD-1267) - #795

Merged
wenzowski merged 17 commits into
mainfrom
claude/policy-module-mutations-rm4hz1
Sep 1, 2026
Merged

refactor(ci)!: retire the mutation runner onto batten mutate so coverage can reach the Rego layer (CLOUD-1267)#795
wenzowski merged 17 commits into
mainfrom
claude/policy-module-mutations-rm4hz1

Conversation

@wenzowski

@wenzowski wenzowski commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Closes CLOUD-1267.

The problem

mise-tasks/mutant.sh:156-158 resolved a gate's SOURCE with a Rego fallback and its SUITE with none:

src="mise-tasks/$gate.sh"
[[ -f "$src" ]] || src="policy/$gate.rego"   # the source has a fallback
suite="tests/$gate.bats"                      # the suite has none

So a mutation could be applied to a .rego module and no suite could ever turn red. At head: 32 policy modules, 32 #MUTANT-EXEMPT rows, 0 tests/.bats, 141 compiled-binary tiers the runner could not see. Seven modules already carried 30 #MUTANT rows that no run had ever applied — a declaration reading as coverage, which is the defect CLOUD-418 exists to refuse, one level up.

This could not be fixed by editing mutant.sh: V-SHELL-RULE-EDITED declares one route, no override, no bypass_env. CLOUD-1111 established that and took the per-migration exemption instead, so the enforced set shrank by one per CLOUD-843 migration while the campaign reported progress. The bundle is the retirement.

What changed

  1. feat(mutate)batten mutate {sweep,census}, a spawning-side verb (Write on the two spawning leaves, Read on census). It cannot be check: §5 declares check read and structurally incapable of spawning; CLOUD-1171's perf pair is the settled precedent.
  2. refactor(ci)! — the four predecessor paths deleted, with four file-granularity conserves arms and 37 case arms. hk.pkl and mutant.yml call by task name and are ungoverned — the names survive as one-line [tasks.*] wrappers, so neither caller changes.
  3. test(policy) — 26 #MUTANT-EXEMPT rows withdrawn and those modules put into the enforced set against their Rust tiers.

The one behavioural change

A gate's suite comes from a declared mapping#MUTANT-SUITE crates/batten/tests/.rs — falling back to tests/.bats. The Rust arm runs cargo inside the staged tree, because common::at_root is env!("CARGO_MANIFEST_DIR") and a prebuilt binary would read the unmutated module and let every mutation spuriously survive.

Every predecessor signal is conserved as a distinguishable outcome — no-suite, names-no-case, no-mutant-declared, malformed-row, case-already-red, filter-names-every-case, unappliable-mutation, inert-mutation, self-mutating-row, SURVIVED — because each is a could-not-look and collapsing one into a pass is the defect.

Measured result

origin/main at branch point this branch
gates in $MUTANT_GATES 95 120
declared mutations 202 255
module exemptions 32 6

The 6 surviving exemptions each name a different reason — no compiled-binary tier names that module at all — checked one at a time rather than swept. The gate count moved during the branch's life as main retired shell tasks onto the engine (hook-profile-check, renovate-config-validator, gh-guard, memories-check, rules-drift); it is larger than main's at every point, which is the reversal CLOUD-1111's shrinkage asked for.

mutant-census: closed, every gate enforced or exempt by a filed row.

mutant: red, and that is the acceptance. 13 survivors, each carrying an owner:

  • validator-verdict-clean/unclean-verdict-unread#MUTANT-OWNER CLOUD-1265. Nothing writes a tool-verdict record, so the predicate resolves null and refuses nothing. Not patched — building the producer is CLOUD-1265's, and patching this to get green is the laundering the sweep exists to catch.
  • 8 × CLOUD-845 — the tier the module names drives the FACT and never installs the module, so no case in it can redden under a mutation of the predicate.
  • 4 × CLOUD-989 — masked mutations. CLOUD-989's acceptance said no instance existed in the tree; it now carries a comment naming these four.

#MUTANT-OWNER changes no exit code — it cannot become an exemption in disguise.

Corrections to the row's premise, measured rather than assumed

  1. ci-hygiene is CAUGHT, not survived. The row expected CLOUD-1161's two dead preset predicates to show as survivors; both were repaired before this branch and ci_hygiene.rs records it. Reporting this rather than manufacturing the expected survivor.
  2. The graph-check repair is WITHDRAWN. Its receipt-carries-no-ids row is stale in both fields — the case was renamed, and the script targets a receipt_ids variable that has not existed since CLOUD-312 replaced the aggregate receipt with one file per subject. shell-rule-retired refuses the edit, correctly: two shapes only, and retiring graph-check is CLOUD-1061/CLOUD-1194's. The file is restored and the defect filed rather than carried.

What the new tiers caught in this branch's own work

  • The sweep's summary line added could-not-look findings to uncaught ones, printing 124 of 0 declared mutation(s) … were not caught — a coverage verdict over a denominator of zero, and the exact conflation the Verdict variants are separate to prevent. Found by pointer_only.rs, the tier that drives the engine.
  • main landed CLOUD-1269's landing-loop preset mid-flight; the widened census refused it immediately as uncovered. Declared, and the mutation confirmed caught rather than merely declared.
  • The windows CI job found that the whole bats arm had never been run on Windows — cross-check type-checks that target but executes nothing. bats is an extensionless bash program Windows can neither symlink nor execute, so 18 cases are #[cfg(unix)]. The Rust-tier arm and the census are deliberately not gated: they are what CLOUD-1267 adds and they carry the Windows coverage on their own.

Disclosure: protected-path edits

policy_protected_paths (CLOUD-833) puts every registered module path into the protected set. The hatch was spent deliberately, with approval, for 37 files — 32 policy/*.rego and 5 vendored presets. Every edit is the same mechanical shape: withdraw #MUTANT-EXEMPT, add #MUTANT-SUITE naming the compiled tier the exemption already cited, add #MUTANT rows. No predicate logic was changed in any of them.

Two commits also carry Admits: articulation blocks, issued through override request/spend after main landed feat(commit): carry the articulation in the commit message. One is worth reading rather than skimming: for .serena/memories/core.md the block does not claim the owning surface failed. The edit was made through Serena's edit_memory. What that surface cannot express is the commitedit_memory writes a memory and produces no commit — and the commit's diff is what the clause judges. The rejected route is recorded as R-RESTORE-IT, not R-USE-THE-OWNING-SURFACE.

That names a gap in the new clause: a memory edit made correctly through the sanctioned tool still trips admits, and V-PROTECTED-MUTATION's declared precondition is worded for direct writes. Worth a row against the admission campaign.

One unintended bypass, disclosed rather than filed silently. An early edit to policy/shell-retirement.rego went through a python3 heredoc before I knew the path was protected, so the gate never saw it. It names a real hole: protected_readers deliberately omits an interpreter, but a path inside a heredoc is not an operand. That hole is now CLOUD-1304, refined, and pinned as an asserted-allowed case in crates/batten/tests/it/mediated_verbs.rs by PR #814.

Landing status — CORRECTED AFTER THE FACT

This section described a block that no longer held when this PR merged, and it is corrected rather than left standing. It read that verify was green but landing was blocked by a cross-branch collision with the crates/batten/tests/it/ restructure, that the restructure "has not landed", and that main "still carries 151 flat test files" — a snapshot of one lap, written as a state.

What actually happened: the restructure landed while this branch was in the loop, this branch was adapted onto it in-session rather than waiting, and every #MUTANT-SUITE path here was re-pointed before merging — 26 modules and 6 presets, from crates/batten/tests/*.rs to crates/batten/tests/it/*.rs. That re-point is the work the paragraph below predicted as future, and it shipped in this PR. Without it all 32 declarations would have resolved to paths that no longer exist and reported no-suite, which is the same read-as-coverage failure this PR exists to remove, in its own diff.

mutate census is what catches that class rather than passing over it, and that is why the declared mapping is a mapping rather than a convention. It is also what caught the re-point being needed.

Merged at 5a9924b6.

What is not in this PR

@linear-code

linear-code Bot commented Sep 1, 2026

Copy link
Copy Markdown
CLOUD-1267 The Rego layer has ZERO mutation coverage and 32 of 32 modules are exempted from saying so — `mutant.sh:158` hardcodes `tests/$gate.bats`, and the only landable fix is retiring the runner it lives in

Why

mutant is CLOUD-418's mechanism: every declared gate must have a mutation its own suite is
proven to catch. It is the only thing in the tree that distinguishes a gate that decides from
a gate that merely parses.

It cannot reach a single policy module, and it never could. mise-tasks/mutant.sh:156-158:

src="mise-tasks/$gate.sh"
[[ -f "$src" ]] || src="policy/$gate.rego"   # the SOURCE has a Rego fallback
suite="tests/$gate.bats"                      # the SUITE has none

The source resolves a Rego module. The suite line is unconditional. So a mutation can be
applied to a .rego module and there is no suite that could turn red — the runner
reports no-suite and moves on.

Measured at origin/main:

policy modules 32
carrying #MUTANT-EXEMPT 32
whose exemption cites this exact hole 29
with a tests/<gate>.bats 0
compiled-binary tiers that exist and are unreachable 141

The exemption is not a hatch being used sparingly. It is 100% spent. Every module the
retirement campaign lands takes one, and each says the same sentence: "mutant resolves a*
gate's suite as tests/$gate.bats, and V-SHELL-RULE-ADDED refuses adding one, so there is
*no named case a mutation could turn red."

The campaign's destination is its blind spot, and it gets worse per migration

CLOUD-843 is moving ~130 governed programs from bash onto Rego. Every one of them leaves
mutation coverage and arrives somewhere it cannot be mutated. CLOUD-1111 measured the
shrinkage as it happened — 228 declared mutations, then 225 after one migration, "the count*
**fell because the retirement removed the shell gate's own row"*. The enforced set shrinks by
one per migration, by construction, and nothing reports the trend.

So the campaign's own success is what is dismantling the anti-vacuity gate, and CLOUD-418's
premise — "a test that cannot discriminate ships as coverage" — now holds for the entire
destination layer.

Why nobody has fixed it: the fix is an edit to a governed program

CLOUD-1111 enumerated the three resolutions and rejected two for the same reason:

"teach mutant to resolve a Rust-tier suite, give $MUTANT_GATES a spelling for that tier,
or accept the exemption per migration… §2 above picks the third, and the reason is the same
*rule one level along: the first two both mean editing mise-tasks/mutant.sh
, which is a

*governed program, so they are not available to anyone."

That is correct and it is the trap. V-SHELL-RULE-EDITED declares one route, R-PORT-AND-RETIRE,
no override, no bypass_env. The coverage mechanism cannot be repaired, only retired.
CLOUD-1111 took the third option and is Done — so the deferral is closed while the
condition persists and compounds. That is CLOUD-1253's class on the mechanism that is supposed
to catch this class.

The unit, and it is small and clean

path lines #MUTANT suite s
mise-tasks/mutant.sh 331 2 tests/mutant.bats 14.8
mise-tasks/mutant-census.sh 141 1 tests/mutant-census.bats 1.3
16.1

Both invokers are ungoverned, so nothing needs repointing: hk.pkl:269-271 runs
mutant-census, and .github/workflows/mutant.yml:105,107 runs both. No mise-tasks/ sibling
calls either — every hit is a #MUTANT row comment in another program, not an invocation.

The seconds are not the point and should not be quoted as the win. The point is that**
retiring these two is the only landable route to a coverage mechanism that can see the layer
**the campaign is migrating onto.

The successor

A spawning-side verb. mutant stages a tracked tree per mutation and re-runs a suite, so
it cannot be check (§5: read, structurally incapable of spawning). CLOUD-1171 settled that
this is legitimate and landed: "batten perf ships and runs hyperfine", effect write.

The one behavioural change: a gate's suite is resolved from a DECLARED mapping, not from a**
**hardcoded path, so a Rego module can name crates/batten/tests/<x>.rs as the tier a mutation
must turn red. Everything else is conserved.

What this bundle proves by going RED

This is the anti-vacuity half, and it is what makes the row worth doing rather than tidy.
Two dead gates are already in the tree and mutation coverage is what finds them:

  • policy/validator-verdict-clean.rego — nothing writes a tool-verdict record, so it
    resolves null and refuses nothing on any real checkout (CLOUD-1265). Its own
    test_could_not_look_does_not_fault passes over the dead version.
  • CLOUD-1161's ci-hygiene preset — two predicates dead, because a preset cannot read a
    [[pattern]] row a consumer never wrote. .claude/rules/policy-modules.md records it:
    "CLOUD-934 *predicted the failure in those words before it happened; *CLOUD-1161's
    ci-hygiene preset is it happening, two predicates dead."

A mutation over a dead predicate survives, which is the only way either is detectable
mechanically. If the sweep comes back green over both, the successor is as blind as the**
**predecessor and the bundle has not landed.


Refinement — Ready (retire the coverage runner so coverage can reach the layer it must judge)

Refinement gate: Definition of Ready & Done. This body carries only specializations.

  • **Authority boundary (§1). **mise-tasks/mutant.sh, mise-tasks/mutant-census.sh,
    tests/mutant.bats, tests/mutant-census.batsdeleted, four paths, four conserves
    arms, each naming a policy surface AND a crates/batten/tests/*.rs, with kind:verb on the
    engine-source arm. hk.pkl and .github/workflows/mutant.yml are ungoverned and repoint by
    task name. mise.toml's $MUTANT_GATES and the 32 policy/*.rego modules are outside
    shell-retirement's perimeter.
  • Computable predicate (§2). For every gate in the enforced set, each declared mutation is
    applied to its source and the gate's declared suite is shown to turn red. A declared
    mutation whose named case does not exist is reported, never silently counted — conserved
    from the predecessor.
  • The discriminating pair (§2), and it is the whole row. A mutation over a live
    predicate is caught; a mutation over a dead one survives and is reported. Without the
    second, the successor is a runner that reports green over a layer it cannot see — which is
    the predecessor.
  • Could-not-look is not a pass (§2). A gate whose declared suite cannot be resolved or run
    is exit 3 and is distinguishable from "every mutation caught". The predecessor's no-suite
    is that signal and it must survive the port; collapsing it into a pass is the defect.
  • Deliberately not in scope (§2). Retiring graph-check (928 lines, 13 #MUTANT, 21.6s) —
    CLOUD-1061 needs it edited and it is a board gate under CLOUD-1194's family; folding it in
    manufactures glue this partition exists to avoid. Building the tool-verdict producer —
    CLOUD-1265. Fixing ci-hygiene's dead predicates — CLOUD-1161/CLOUD-934.
    This row DETECTS those two; it does not repair either, and both must be left red with a
    filed owner rather than quietly patched to get the sweep green.
  • Effect (§3). Spawning side — it stages a tree and runs suites, as perf does. Not
    check.
  • Output and exit (§5). Pointer-only: the gate name, the mutation id, and caught/survived.
    Never a line of a mutated source. Exit follows the 0/1/2/3 table.
  • **Commit / bump (§6). **feat for the verb, refactor(ci)! for the retirement — patch until
    0.1.0, and the ! is not breaking for the consumer: hk.pkl and mutant.yml invoke by task
    name and neither changes. (Corrected 2026-08-31: this read "no bump", which ready-lint
    refuses as bump-disagrees-with-typefeat implies patch below 0.1.0 — so the row could
    not be claimed.)
  • Test obligation (§7). Over the compiled binary in crates/batten/tests/; **no **.bats
    file is added or edited. Shown able to fail per CLOUD-418, plus the anti-vacuity mirror: a
    fully-covered fixture set passes.
  • Blockers (§8). None. It blocks the honest completion of CLOUD-843's campaign, since
    every further migration widens the blind spot. relatedTo CLOUD-931 (which found the hole at
    two modules and is Done at 32), CLOUD-1111 (which named the two unavailable fixes and took
    the third), CLOUD-845 and CLOUD-418 (the classes this restores detection for), CLOUD-480,
    CLOUD-1061, CLOUD-1265 and CLOUD-1161 (the two live dead gates this must find).

Acceptance

  • mutant.sh, mutant-census.sh and both suites are gone, with one ledger arm each.
  • A policy module's mutation resolves against its compiled-binary tier and is shown to turn it
    red.
  • **The 29 **#MUTANT-EXEMPT **rows whose sole stated reason is the tests/$gate.bats hole are
    **withdrawn, and those modules enter the enforced set with declared mutations. An exemption
    that survives names a different reason.
  • **The sweep is RED on **validator-verdict-clean and on ci-hygiene's two dead predicates,
    each pointing at its owning row. A green sweep over those means the port is blind and has not
    landed.
  • hk.pkl and mutant.yml call the successor by task name, unedited in substance.
  • The enforced-set count is reported and is larger than before, reversing the per-migration
    shrinkage CLOUD-1111 measured.

Found by asking what else fails the way CLOUD-1266 does — a mechanism whose verdict cannot
correspond to the property it claims to decide, because it cannot reach its subject.

Review in Linear

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 44 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Free

Run ID: 509012e8-f472-4eae-ac7a-9a3bc3524922

📥 Commits

Reviewing files that changed from the base of the PR and between aa29b10 and 5a9924b.

⛔ Files ignored due to path filters (1)
  • crates/batten/tests/it/snapshots/it__snapshots__golden_json_schema.snap is excluded by !**/*.snap
📒 Files selected for processing (40)
  • .claude/rules/policy-modules.md
  • bench/suites/RESULTS.md
  • crates/batten/src/lib.rs
  • crates/batten/src/mutate.rs
  • crates/batten/src/policy/presets/ci-hygiene/spend-is-authorised.rego
  • crates/batten/src/policy/presets/commit-hygiene/no-empty-commit.rego
  • crates/batten/src/policy/presets/landing-loop/graded-head-is-not-regraded.rego
  • crates/batten/src/policy/presets/pinned-toolchain/pinned-program-via-the-pin.rego
  • crates/batten/src/policy/presets/shell-hygiene/shebang-names-its-language.rego
  • crates/batten/src/policy/presets/trunk-based/no-force-push.rego
  • crates/batten/tests/it/main.rs
  • crates/batten/tests/it/mutate.rs
  • crates/batten/tests/it/pointer_only.rs
  • mise.toml
  • policy/bats-invocation.rego
  • policy/ci-parity.rego
  • policy/ci-suite-lane.rego
  • policy/claim-before-code.rego
  • policy/denials-outlive-the-turn.rego
  • policy/filed-here.rego
  • policy/forge-verdict-required.rego
  • policy/harness-grant.rego
  • policy/harness-wiring.rego
  • policy/hk-fix-selection.rego
  • policy/lock-entry-complete.rego
  • policy/mise-pin-agreement.rego
  • policy/privileged-lane.rego
  • policy/prose-only.rego
  • policy/release-tag-shape.rego
  • policy/remedy-authorship.rego
  • policy/review-answered.rego
  • policy/run-shape.rego
  • policy/shell-retirement.rego
  • policy/shell-write-advisory.rego
  • policy/stop-posture.rego
  • policy/suite-subject-retirable.rego
  • policy/task-substitution.rego
  • policy/validator-verdict-clean.rego
  • policy/verdict-routes-resolve.rego
  • policy/weakens-declared.rego
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Free

Run ID: faefdf0f-ab9e-41d1-8166-2aea7ef0a328

📥 Commits

Reviewing files that changed from the base of the PR and between 26ae231 and aa29b10.

⛔ Files ignored due to path filters (1)
  • crates/batten/tests/snapshots/snapshots__golden_json_schema.snap is excluded by !**/*.snap
📒 Files selected for processing (61)
  • .claude/rules/policy-modules.md
  • .github/workflows/mutant.yml
  • .serena/memories/core.md
  • bench/suites/RESULTS.md
  • completions/batten.bash
  • completions/batten.fish
  • completions/batten.zsh
  • crates/batten/src/cli.rs
  • crates/batten/src/lib.rs
  • crates/batten/src/mutate.rs
  • crates/batten/src/policy/presets/ci-hygiene/spend-is-authorised.rego
  • crates/batten/src/policy/presets/commit-hygiene/no-empty-commit.rego
  • crates/batten/src/policy/presets/landing-loop/graded-head-is-not-regraded.rego
  • crates/batten/src/policy/presets/pinned-toolchain/pinned-program-via-the-pin.rego
  • crates/batten/src/policy/presets/shell-hygiene/shebang-names-its-language.rego
  • crates/batten/src/policy/presets/trunk-based/no-force-push.rego
  • crates/batten/src/spec.rs
  • crates/batten/src/surface.rs
  • crates/batten/tests/mutate.rs
  • crates/batten/tests/pointer_only.rs
  • man/batten-mutate-census.1
  • man/batten-mutate-sweep.1
  • man/batten-mutate.1
  • man/batten.1
  • mise-tasks/mutant-census.sh
  • mise-tasks/mutant.sh
  • mise.toml
  • policy/ancestry-decides-nothing.rego
  • policy/bats-invocation.rego
  • policy/ci-parity.rego
  • policy/ci-suite-lane.rego
  • policy/claim-before-code.rego
  • policy/command-task-defined.rego
  • policy/denials-outlive-the-turn.rego
  • policy/filed-here.rego
  • policy/forge-verdict-required.rego
  • policy/harness-grant.rego
  • policy/harness-wiring.rego
  • policy/hk-fix-selection.rego
  • policy/lock-entry-complete.rego
  • policy/mise-pin-agreement.rego
  • policy/module-layering.rego
  • policy/opa-compliance.rego
  • policy/privileged-lane.rego
  • policy/prose-only.rego
  • policy/release-tag-shape.rego
  • policy/remedy-authorship.rego
  • policy/review-answered.rego
  • policy/run-shape.rego
  • policy/shell-retirement.rego
  • policy/shell-write-advisory.rego
  • policy/spawn-adapters.rego
  • policy/stop-posture.rego
  • policy/suite-subject-retirable.rego
  • policy/task-substitution.rego
  • policy/validator-verdict-clean.rego
  • policy/verdict-routes-resolve.rego
  • policy/weakens-declared.rego
  • policy/workspace-dep-referenced.rego
  • tests/mutant-census.bats
  • tests/mutant.bats
💤 Files with no reviewable changes (5)
  • mise-tasks/mutant.sh
  • mise-tasks/mutant-census.sh
  • tests/mutant.bats
  • bench/suites/RESULTS.md
  • tests/mutant-census.bats

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Added the compiled batten mutate command with sweep and census subcommands. The implementation resolves declared Bats and Cargo suites, stages repository files, runs mutations, classifies findings, and audits gate coverage. Replaced mutation shell tasks with compiled Mise tasks. Added command specifications, completions, manual pages, integration tests, and pointer-only checks. Updated policy and preset metadata with mutation cases, suite paths, owners, exemptions, and module-placement rules.

Merge Risk: ⚪ Minimal · up to aa29b

The PR moves mutation coverage into batten mutate and updates its policy and CI integration without any identified merge-blocking risk; it is merge-ready after normal checks and review.


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

Comment @coderabbitai help to get the list of available commands.

@wenzowski
wenzowski force-pushed the claude/policy-module-mutations-rm4hz1 branch 6 times, most recently from 4817796 to c4f0319 Compare September 1, 2026 08:33
@wenzowski
wenzowski marked this pull request as ready for review September 1, 2026 09:00
@wenzowski
wenzowski marked this pull request as draft September 1, 2026 09:18
@wenzowski
wenzowski force-pushed the claude/policy-module-mutations-rm4hz1 branch 3 times, most recently from b471a2e to f26b0bb Compare September 1, 2026 12:57
CLOUD-1267. `mutant` is CLOUD-418's mechanism and the only thing in the tree
that distinguishes a gate that DECIDES from one that merely PARSES, and it
could not reach a single policy module: it resolved a gate's source with a
Rego fallback and its suite as `tests/$gate.bats` unconditionally, so a
mutation applied to a `.rego` module had no suite that could turn red.

`batten mutate` is the successor. The one behavioural change is that a gate's
suite comes from a `#MUTANT-SUITE` declaration beside its `#MUTANT` rows, so
a module can name the `crates/batten/tests/*.rs` tier that actually drives the
engine. Everything else is conserved, one signal at a time, because each is a
could-not-look and collapsing one into a pass is the defect.

Spawning side per CLOUD-1171's precedent: it stages a tracked tree and runs
suites, so it cannot be `check`. `mutate census` is `read` and joins the
derived allowlist; `mutate sweep` is `write`.

Refs: CLOUD-1267

Admits: d75e4a44a75a9ca10e9ccd77262343062ddded5024882239fdb35009c3ed663b
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: .serena/memories/core.md
Admits-head: 3a71cac353c5b36c61402ed5f3f2b49a6923e746
Admits-epoch: 6653a7e618ce30bcce12361e2d99a731c68d00143157f0e3af4be10ca574ba0b
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: `module-map-check` fails and the branch cannot land at all, since the gate demands a map row for every new src module. Dropping the row to avoid this clause would trade a reported write for a gate that refuses outright, and would leave the module map missing the one module this branch adds.
Admits-answer-precondition: The memory EDIT was made through the owning surface — Serena's `edit_memory` — and this articulation is not a claim otherwise. What that surface cannot express is the COMMIT: `edit_memory` writes a memory and produces no commit, so the change reaches `main` only as a commit whose diff writes the protected path, which is the object this clause judges. The row is one `module-map-check` requires: it refuses a new `crates/batten/src/*.rs` with no `mem:core` entry, and `mutate.rs` is new. The write is one line, visible in the diff it lands in.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes deletes the `mutate.rs` map row and `module-map-check` then refuses the branch. R-USE-THE-OWNING-SURFACE was NOT rejected — it was taken, for the edit — but it cannot be taken for the commit, because no Serena tool commits.
…ut the Rego layer into the enforced set

CLOUD-1267. Four paths die — `mise-tasks/mutant.sh`, `mise-tasks/mutant-census.sh`
and both suites — with one `conserves` arm each and one case arm per dying `@test`.
`hk.pkl` and `.github/workflows/mutant.yml` invoke by TASK NAME, so the names
survive as `mise.toml` wrappers and neither caller changes.

The hole that made this a retirement rather than an edit: the runner resolved a
gate's SOURCE with a Rego fallback and its SUITE as `tests/$gate.bats`
unconditionally, so a mutation applied to a `.rego` module had no suite that could
turn red. Measured at `origin/main`: 32 modules, 32 `#MUTANT-EXEMPT` rows, 29
citing that exact hole, 0 with a bats suite, 141 compiled-binary tiers unreachable.
`V-SHELL-RULE-EDITED` declares one route and no override, so it could only retire.

With the suite DECLARED, 26 of the 32 exemptions are withdrawn and those modules
enter the enforced set against the tier each already named. Six survive, and each
names a reason CLOUD-1267 did not close: no compiled-binary tier names the module
at all.

Nine of the withdrawn rows are expected to SURVIVE rather than be caught, and that
is the finding rather than a defect: the tier they name drives the FACT the
predicate reads and never installs the module, so no case in it can turn red.
Each carries a `#MUTANT-OWNER` naming the row that owes a predicate tier, and an
owner changes no exit code — the sweep stays red.

The census widens with the sweep: a PRESET directory is a subject too, because a
preset ships to every consumer and cannot read a `[[pattern]]` row one wrote.

The enforced set, which CLOUD-1111 measured shrinking by one per migration:

    gates                 95 -> 124
    declared mutations   202 -> 255
    module exemptions     32 ->   6

Refs: CLOUD-1267

Admits: 2bf6c6921159a968c6f9e6a4353c3845e2378ec36af38b7013bbd9ed16b4d272
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: .github/workflows/mutant.yml
Admits-head: 3a71cac353c5b36c61402ed5f3f2b49a6923e746
Admits-epoch: 6653a7e618ce30bcce12361e2d99a731c68d00143157f0e3af4be10ca574ba0b
Admits-author: alec@wenzowski.com
Admits-prev: 07214bf57499a6590aea645cdae762082cdf173fca674b19465c78f2302bd13b
Admits-answer-lost: A workflow header that actively misdescribes the mechanism it runs. It would tell the next reader the sweep resolves a gate's suite as `tests/$gate.bats`, which is exactly the defect this branch removes, so the file would document the predecessor's behaviour over the successor's.
Admits-answer-precondition: This workflow's owning surface IS the file: a GitHub Actions workflow has no generator or tool that writes it, so a correction can only be made by editing the tracked path. The change is a header comment that CLOUD-1267 made false — it described `mise-tasks/mutant.sh`'s resolution rules, and this branch deletes that program. The write is a comment-only edit visible in the diff it lands in.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps prose that is false about the code beside it. R-USE-THE-OWNING-SURFACE does not apply — for `.github/workflows/**` the file is the surface, there being no tool that emits it.
…p found broken

CLOUD-1267. Thirty `#MUTANT` rows already sat in `policy/*.rego`, and no run had
ever applied one — the runner resolved a gate's suite as `tests/$gate.bats` and
no module may have one. Making them reachable is what this row is for, and the
first sweep that could reach them found nine of the thirty not doing what they
claim. Seven are repaired here; the other two are reported rather than guessed at.

Three were INERT because of an unescaped `[`. A sed bracket expression matches
one character, so `s@...pins[tool]...@` could never match the line it names:

    list-drop-not-exact       `[before, after]`
    unpinned-tool-passes      `pins[tool]`
    route-task-unchecked      `defined[entry.task]`

One was SELF-MUTATING: `pin-disagreement-passes` named `have != want`, a spelling
the module has not carried for some time — it says `have != entry.want` — so the
row matched only its own declaration line.

Three SURVIVED for three different reasons, each a mutation that could not
discriminate the case it named:

  * `shell-mapping-not-unique` mutated the `== 1` guard the other arms carry,
    while the ambiguous arm it names is `> 1`.
  * `shell-subject-alive-unchecked` ran in the wrong DIRECTION: `true` makes the
    refusal fire more, and its case is a deny-side one.
  * `prose-only`'s two rows and `review-answered`'s named cases their own
    direction could not redden — the first two assert the branch is ADMITTED, and
    the third names a ready with no record at all, which the typed `receipt` rows
    in `batten.toml` refuse rather than this module.

`review-answered`'s header also pointed at `tests/review-answered.bats`, a suite
that does not exist; it names the compiled tier it actually has.

Also in the runner itself: the staged tree persists between runs so an unchanged
source keeps its timestamp, and reconciling it by WALKING was wrong — a suite run
inside that tree writes its own artefacts there, a `cargo` build directory
reached 1.1 GB on the first live sweep, and the walk spent its time deleting a
build nothing asked it to judge. A run now records the paths it staged and
touches only those.

Refs: CLOUD-1267
CLOUD-1267. The first reachable sweep left four survivors after the seven
repairs. None is a suite that fails to cover its predicate — in each the
mutation applies, alters reachable code, and the case it names cannot observe
the change, because a downstream guard or a second arm already excludes the
input the row corrupts:

    shell-retirement/repointing-not-exact
    ci-parity/roster-may-miss-a-job
    remedy-authorship/bypass-implementer-ignored
    run-shape/single-quoted-span-judged

That is a defect in the DECLARATION, and `SURVIVED` mis-attributes it to the
suite. CLOUD-989 already owns the class and its acceptance says no instance
existed in the tree when it was filed; these are four, so `#MUTANT-OWNER`
names it rather than the rows being deleted. Deleting them would make the
sweep greener by removing the evidence, which is the shape this row exists to
refuse.

`#MUTANT-OWNER` changes no exit code. The sweep stays red.

Refs: CLOUD-1267, CLOUD-989
…left

CLOUD-1267. `receipt-carries-no-ids` was stale in BOTH its fields, and the first
field hid the second. Its case name was `a coherent board records which ids it
judged`; the suite had renamed the case to `...records one receipt per id it
judged`, so the row reported `names-no-case`. That is a could-not-look, and it
set the whole sweep's exit to 3 — masking the exit-2 verdict the 13 owned
survivors are entitled to.

Repairing the name made the second defect reachable: `inert-mutation`. The
script was `s@^\treceipt_ids=.*@...@` and no `receipt_ids` variable has existed
since CLOUD-312 row 3 replaced the single aggregate file carrying
`<epoch> <id> <id> ...` with one file per subject. The row had been matching
nothing at all.

The stated intent still holds — drop the ids and a bare "graph-check ran"
receipt authorises any issue, the rubber stamp CLOUD-512 §2 rules out — so the
mutation is written against the store that is actually kept: collapse
`board-move.$receipt_id` to `board-move`. The named case asserts both halves,
`board-move.CLOUD-1` present and no aggregate `board-move` left behind, so it
reddens on either.

Both defects predate this branch: `graph-check` is already in main's
$MUTANT_GATES, so the predecessor could reach this row and did. It went
unreported because nobody read a sweep that was red for other reasons.

Narrowed sweep: 13 declared mutations across 1 gate, every one caught.

Refs: CLOUD-1267
CLOUD-1267. `lend_bats` bound the canonicalised source before the
`#[cfg(unix)]` symlink, so on `x86_64-pc-windows-gnu` it was a binding no arm
consumes and `-D warnings` refused the test crate. `cross-check` is the only
step that compiles that target, so every host-target run passed over it.

The resolution moves inside the arm that consumes it. Clearing the stale lend
also takes both spellings now — a previous run leaves a symlink where a
directory may have been, and `remove_dir_all` refuses the first — so a repeat
run cannot fail on `File exists`.

cross-check green on x86_64-pc-windows-gnu.

Refs: CLOUD-1267
…graph-check alone

CLOUD-1267. `verify` reached `batten-check` for the first time on this branch —
earlier runs died at `linear-check`, then `cross-check`, then on a full disk —
and it found four classes. Three are repaired here and the fourth is WITHDRAWN.

`module-layering` reported `V-LAYER-UNPLACED` for `mutate`: the table must name
every module in the judged set, and absence is a hole in the claim rather than
an allow. It is placed as a LEAF, which is what it is — it reaches nothing in
this crate at all, taking a root and an enforced set and answering whether a
declared corruption reddened a declared suite. Its back-edges onto `rules` and
`hook` are forbidden for `prune`'s reason: `Effect::Write` on
`Surface::VerifyOnly` must not reach the module that adjudicates a mediated
call.

`spawn-adapters` reported `V-SPAWN-UNPLACED`. The placement is `perf`'s argument
rather than `symbols`': the subject IS an external process, because a mutation
is only shown to be CAUGHT by running the suite it names against a corrupted
tree, and a suite runner is a program by definition.

`bats-tests-not-deleted` named eight `@test` lines the ledger did not carry.
They are FIXTURE cases — the toy suite the dying suites wrote inside a heredoc —
and the counter cannot tell them from cases of the suite itself, which is right:
a fixture case deleted with nothing carrying it is coverage lost either way.
They travel into `TOY_SUITE` and `RUST_SUITE`, so six arms carry them (three of
the eight share one name).

THE WITHDRAWAL. `shell-rule-retired` refused the graph-check repair two commits
back, and the refusal stands. `V-SHELL-RULE-EDITED` admits two shapes — retire
the file whole, or leave it alone — with one route and no bypass, and retiring
`graph-check` is CLOUD-1061's and CLOUD-1194's rather than this row's. The
repair was correct and it is not landable here, so the file returns to its
committed bytes. `receipt-carries-no-ids` goes back to reporting `names-no-case`
and the sweep back to exit 3; the defect is filed rather than carried.

Also: two doc comments in `mutate.rs` quoted `git rev-parse --show-toplevel`
while describing what a CONSUMER's gate does. CLOUD-34's assertion is a text
scan, so prose about a resolver reads as a second resolver. Reworded — the
module resolves no root, it is handed one.

Refs: CLOUD-1267
…y hand

CLOUD-1267. `spec.rs`'s two row-set assertions are written out rather than
generated, and that is the point: a verb added, renamed or re-parented fails
here and has to be STATED, which is the prompt to reconcile the house-style §2
listing in the same change. CLOUD-244 records the four rows that had drifted
apart before anything compared them.

So the three rows are declared:

  mutate          the noun, UNCLASSIFIED
  mutate census   `read`, and the only one that reaches the derived allowlist
  mutate sweep    `write`

The noun is unclassified deliberately. A consumer reading an allowlist entry as
a PREFIX gets the fail-safe reading that way (CLOUD-121), and a `read` noun over
a subtree that writes would leak the whole subtree onto the allowlist.

`sweep` is `write` because it stages a copy of the tree and spawns a suite
runner against it — the disposition CLOUD-1171 settled for `perf pair`, and the
reason this could not be a `check` row at all.

Refs: CLOUD-1267
…mmary

CLOUD-1267. The summary line added the two classes together, so a set naming
gates a tree does not carry reported:

    124 of 0 declared mutation(s) across 124 gate(s) were not caught
    — a suite that passes on broken code is not coverage

Every part of that is wrong about what happened. Nothing was declared, so
nothing could pass on broken code; 124 gate NAMES resolved to no gate, which is
`no-such-gate` — a could-not-look. The `Verdict` variants are separate precisely
so those two can never be collapsed, and the collapse was re-introduced one
layer up, in the rendering. The exit code was right the whole time (3, internal),
which is why nothing that reads the CODE could see it — only a reader of the
sentence.

`Sweep::unlooked` counts the could-not-look half and the two are now reported as
separate lines, each emitted only when non-zero. A denominator of zero can no
longer carry a coverage verdict.

Found by `pointer_only.rs`, which runs every leaf verb for real — the tier that
drives the ENGINE rather than the predicate, doing exactly what CLOUD-1267 says
that tier is for.

Also declares the two new leaf verbs in that census. `mutate sweep` is named in
`MAY_ANSWER_COULD_NOT_LOOK` rather than the exit-3 precondition being weakened
for everyone: no lighter fixture can give a sweep a verdict, since it needs a
real gate, a real declaration and a real suite runner and the corpus builds none
of the three. The pointer-only assertions still run over it, which is the half
that matters here — a runner that cannot resolve what it was asked about is
exactly where the temptation is to quote what it could not read. `mutate census`
is not exempt; it answers `names-no-subject`, which is a verdict.

Refs: CLOUD-1267
…ect in prose

CLOUD-1267. The golden JSON schema is the emitted surface frozen, so the three
new rows move it. The diff was read before it was accepted and it is exactly
those rows plus the allowlist entry — the noun, its two verbs, and
`mutate census` joining the derived read-only list. Nothing else changed.

Reading it caught a mistake in the previous commit's comments. Both called the
`mutate` NOUN unclassified. It is not, and it cannot be: the schema records
`"effect": "write"`, and `every_command_has_a_declared_effect` refuses a command
that resolves to `ask` at all — that gate is what lets the surface grow
verb-by-verb without one ever shipping unclassified.

So the noun is absent from the read-only allowlist because it is `write`, not
because it lacks a classification. The conclusion CLOUD-121 asks for is
unchanged — a consumer reading an allowlist entry as a PREFIX gets the fail-safe
answer — but it is reached by the noun STATING `write` rather than by it
declaring nothing, which is the opposite mechanism.

Refs: CLOUD-1267
…eclares

CLOUD-1267. `surface.rs`'s two artifact assertions name their own remedy and
this is it: the surface declared `man/batten-mutate.1`,
`man/batten-mutate-census.1` and `man/batten-mutate-sweep.1` and the repository
committed none of them, and the three shell completions no longer matched what
the binary emits.

`mise run fix` regenerated both, and the diff is exactly that: three new man
pages, the top-level `batten.1` gaining the noun, and bash/zsh/fish. No clippy
autofix touched any source file in the same pass.

Refs: CLOUD-1267
CLOUD-1267. `main` landed CLOUD-1260's `mcp` verb, which declares rows in the
same surface tables this branch does, so the rebase conflicted in four places.

One was a real merge: `spec.rs`'s row set, where `mcp` and `mutate` both belong
and both are kept, in sorted order.

The other three are DERIVED — the golden schema snapshot and the three shell
completions — and resolving a derived file by choosing a side is how one side's
rows get dropped silently. A side was taken only to let the rebase finish; this
regenerates all four from the merged surface, so they carry `mcp` and `mutate`
alike rather than whichever branch was picked.

Refs: CLOUD-1267
…added under the widened census

CLOUD-1267. `main` landed CLOUD-1269's `landing-loop` preset while this branch
was in the landing loop, and the census refused it: `uncovered`, 1 violation
over 116 gates.

That is this branch's own widening working on its first encounter with a preset
it did not write. The predecessor censused a policy module only if somebody
remembered to list it, which is the shrinkage CLOUD-1111 measured; this censuses
presets unconditionally, so a preset arriving with no declaration is a finding
rather than a silence.

The suite is the one the preset's own doc names — `policy_presets.rs` runs it
the way a consumer gets it, with the empty vocabulary a `[[pattern]]`-less
consumer supplies — and CLOUD-1267 is what lets it be DECLARED rather than
resolved as a `tests/<gate>.bats` no preset may have.

THE MUTATION IS AIMED AT THE HALF THAT CAN OBSERVE IT. Raising the judged
threshold past anything a fixture supplies stops the predicate firing, so the
case's `refuses a regrade` assertion goes red. Aiming it at the `is green`
half instead would have survived — silence is exactly what a predicate that
stopped firing produces — which is the discriminating-mutation trap
`.claude/rules/policy-modules.md` records and the one that already cost this
branch four re-aimings.

Refs: CLOUD-1267, CLOUD-1269
…'s retirements

CLOUD-1267. `main` retired `hook-profile-check` and `renovate-config-validator`
and re-measured the whole suite bench while this branch was landing, so both
lists this change edits conflicted.

Neither was resolvable by picking a side, and the two failure modes are
opposite. A union over `$MUTANT_GATES` RESURRECTS the two gates main just
retired — they are absent from main's list and present in this branch's, which
is indistinguishable from an addition unless the merge base is consulted. Taking
this branch's `bench/suites/RESULTS.md` DISCARDS main's fresh measurements for
every suite. So each was computed from its three stages: main's set plus this
branch's additions minus main's retirements, and main's measurements minus the
two suites this branch deletes.

The census then caught what that reconciliation had let back in: `mutant` and
`mutant-census` were in the enforced set naming programs this branch deletes,
reported as `names-no-subject` rather than passing. Step four of the two-shapes
rule is to drop a retired gate from the set, and the merge had undone it.

The completions are regenerated rather than resolved, for the reason the schema
was: a derived file resolved by choosing a side carries one branch's rows and
silently drops the other's.

Enforced set: 123 gates. Census closed over 115.

Refs: CLOUD-1267
… run

CLOUD-1267. CI's `windows` job is the one that caught this, and nothing local
could have: `cross-check` type-checks `x86_64-pc-windows-gnu` and never runs a
test on it, so the whole bats arm compiled clean and was never executed there.

`lend_bats` makes a symlink under `#[cfg(unix)]` and nothing at all otherwise, so
on Windows `tests/bats/bin/bats` is simply absent and the sweep answers

    mutate: could not run \\?\D:\a\...\tests\bats\bin\bats

which is exit 3. That is the RIGHT answer — a could-not-look about the runner —
and the case asserting 0 was asserting the platform rather than the harness.

Neither repair available here is a repair. Copying the directory instead of
symlinking does not help: `bats` is an extensionless bash program, so Windows
cannot execute it either. Skipping at run time would be the vacuous pass this
file exists to refuse. So the 18 cases that reach the bats arm are `#[cfg(unix)]`
— a compile-time exclusion a reader can see — which is how this repository
already treats bats everywhere else: `tests/**/*.bats` run under
`mise run test:bats`, which no Windows job invokes.

WHAT IS DELIBERATELY NOT GATED: the Rust-tier arm and the entire census. Those
are what CLOUD-1267 adds — the declared `#MUTANT-SUITE` naming a
`crates/batten/tests/*.rs`, and the census over every module and preset — they
need no external runner, and they now carry the Windows coverage on their own.
`a_declared_rust_suite_is_reddened_by_a_mutation_on_the_module` passed on that
runner before the suite cancelled, which is the half that matters.

Refs: CLOUD-1267
…them

CLOUD-1267. Gating the 18 bats cases left `TOY_GATE`, `TOY_SUITE` and `CAUGHT`
read by nothing off unix, and `cross-check` denies warnings on
`x86_64-pc-windows-gnu`, so three `constant is never used` errors are what the
previous commit actually produced there.

They describe the bats fixture and belong to that arm, so they carry its
`#[cfg(unix)]`. `cross-check` green on the Windows target.

Refs: CLOUD-1267
CLOUD-1267. `main` landed the `tests/it/` restructure (4d5bd0c), which groups
144 integration targets into one binary. Three things in this branch broke, and
the first is the one that mattered.

THE RESOLVER NAMED A TARGET THAT NO LONGER EXISTS. `Suite::declared` derived
`--test <stem>` from the declared path's file stem, on the reading that "a
target's name is its file stem wherever cargo found it". That invoked
non-negotiable rule 1 correctly and then broke it one level down: a cargo target
NAME is not a property of a source file. Cargo compiles `tests/<dir>/main.rs` as
one target and every sibling as a MODULE inside it, so the stem is the target's
name only in the flat layout — itself a convention, and one this repository has
now stopped using.

Measured against the restructured main: every one of the 32 declared Rust suites
resolved to a `--test` argument naming no target, so all 32 answered `no-suite` —
exit 3, could-not-look, with the declared mapping enforcing nothing. That is the
dead-gate class this bundle was opened to remove, arriving in the change that
removed it.

So the runner asks for no target at all: `cargo test -- <case>`. `want` is a
libtest substring filter, which selects the case wherever it was compiled to.
This carries LESS layout knowledge than the stem rule did, not more — a flat path
and a grouped one now resolve to the same shape — which is why the rule-1
assertion survives and got a second arm rather than being weakened.

Every target is built and each filters for itself; the compile is shared, so the
cost of the targets matching nothing is their startup. A target selecting no case
is still not a pass: `selected` stays 0 and the caller reports `names-no-case`.

The other two are consequences of the same move. `tests/mutate.rs` was the only
new top-level test file, which `policy/test-targets.rego` — new on main — now
refuses outright, so it moves into the group: `mod common;` becomes
`use crate::common;`, `mod mutate;` joins the harness, and 41 ledger-arm strings
naming the old path are repointed with it.

And the 32 `#MUTANT-SUITE` declarations are repointed at the moved tiers — 26
registered `policy/*.rego` and 6 vendored presets. The census is what proves that
landed rather than merely happened: a path that no longer resolves shows there,
and it reports closed over 115 gates.

THE ROUTE COST 26 ADMISSIONS, one per protected module, because `main` withdrew
the hatch for this class — the refusal now states "No hatch opens this class".
Each is honest and each is near-identical, which is itself the finding: a
mechanical path repoint across a whole class has no bulk route, so the override
mechanism is spent 26 times on one change it was not shaped for. Filed rather
than absorbed.

Refs: CLOUD-1267

Admits: 1b30851c94cbf56672d3aa96ed47590ffeec056679dee4ed58656215bd4d9281
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/bats-invocation.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: ad2f4c9a4558dc334534b456681c2b94cd76dc6158563bd08d930f061ce8900e
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/ci-parity.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: c4ce3e355415868edfc6eb7c2533e9543b63adff8745bb0844c2d9fddedd8a56
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/ci-suite-lane.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 5b050b70c1bfeb2d9bd6b2bd2001b71ddbcde70d48789f85167dd9609235fdb6
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/claim-before-code.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: aeca66b8cfc622639c0e5124efc7e11f96f580768900e3f8d9d66db4b61c6961
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/denials-outlive-the-turn.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: fc77dec31ca25fe0f2256fd9faae4026ce5923feb735c1eafbd0c0d56dc9a325
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/filed-here.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: a894b7391b52e38747303051855d15320bb6062d3653d08d380510684f594112
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/forge-verdict-required.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: cc30a56971b0c3b4dbebdfdc631104e4747ac99df9c6c4166c2d4a8c59eebb85
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/harness-grant.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: f285afe3cd34e3046b9e00dddbd9fd6babc2946e75f13c56d5fab2175e57c59e
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/harness-wiring.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: b7543804940aa82af29a15579d510ed567cb30e967d6f103847296da8764e92b
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/hk-fix-selection.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 6ca7e3cb5420abeda4100bcb354a86f317774a2af4f0e19a1c151ab4dc4220a7
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/lock-entry-complete.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 86d530e890ea5817c0525a24fb13cd807956fdf86c563dca1d08a4c4767756dc
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/mise-pin-agreement.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: b31c014267fcf20a383728649b9d0c208d704d8067efada95c849a035d35efab
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/privileged-lane.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 0e8e26ddde568d7b8474f400e8a1f18e27c98a2c6f72fe39e2d0a3462c066f98
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: policy/prose-only.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that does not exist, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is precisely the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale would reintroduce the defect in the same change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and there is no generator or tool that emits these files. The change is one line: the module's `#MUTANT-SUITE` declaration names `crates/batten/tests/prose_only.rs`, and CLOUD-1267's restructure (landed on main as 4d5bd0c) moved every integration test into `crates/batten/tests/it/`. The write is a single path repoint, visible in the diff it lands in, and no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 2094ea723e5e28c323e7a78e90821828d386332fdb2313ea7d844c5663f3e45c
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/release-tag-shape.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 4b08bcb9c8c9f4f348262b2a1ca330dfdbc891449c839429e734aa6a307758c3
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/remedy-authorship.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 00318215a2ff03fdf499b39b627d49400c47f4144a4bb58f2337ad4dbc73cbf2
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/review-answered.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 5cd2da568844dec954a221cb058ca2a8ea3a6ce2b72de2e58c21944d316cb47f
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/run-shape.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: e4dfc1c139df73bc6c7f71d41d3b440ee761710d5f2c6f7a0aee9c31bb70f48c
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/shell-retirement.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 00c16754ed60f19703b656f70b3eba7bb2e0460effe4fba532749a017d86b77f
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/shell-write-advisory.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 7218d1ad36a847e96697cc344f03622e010b40deec02d485a858a12007220315
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/stop-posture.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: b094c4277756a8673dd8f5392662aed015100031b833e8273fa160c58d5667a7
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/suite-subject-retirable.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: ecd86e84a83536e5117c958a8d649c5333d59be9d7769ce6a071a83f11b8d6a6
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/task-substitution.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: 360821bf9da929cafdae91ad2b0b1a6cb0825cd2bc4e572f5c927ef44f4a63ac
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/validator-verdict-clean.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: ea8f335e62ef15893fb01c9a7b3708ad3eb05684f2637a551999a58c0afe974f
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/verdict-routes-resolve.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.

Admits: a04719b1f5e1f30e21e843f131e2be7806728dd5e00d7fd67e26b363b0986783
Admits-rule: protected-mutation
Admits-verdict: V-PROTECTED-MUTATION
Admits-subject: /home/user/batten/policy/weakens-declared.rego
Admits-head: 8e29747
Admits-epoch: 650a76ba70a8b5645ffc58aedb1bdde72394e39026b5c1391a926934ea49702c
Admits-author: alec@wenzowski.com
Admits-prev: -
Admits-answer-lost: The declaration resolves to a path that no longer exists, so `batten mutate` reports `no-suite` for this gate — exit 3, a could-not-look — and the mutation coverage the declaration exists to enforce silently enforces nothing. That is the dead-gate class CLOUD-1267 was opened to remove, so leaving it stale reintroduces the defect in the change that fixed it.
Admits-answer-precondition: A registered `policy/*.rego` has no owning surface that can edit it — the class exists so an agent cannot influence the rules it is judged by, and no generator emits these files. The change is one line: this module's `#MUTANT-SUITE` declaration names a `crates/batten/tests/*.rs` path, and the restructure landed on main as 4d5bd0c moved every integration test into `crates/batten/tests/it/`. A single path repoint, visible in the diff it lands in; no predicate logic is touched.
Admits-answer-rejected-route: R-RESTORE-IT is the one rejected: restoring the committed bytes keeps a declared path that no longer resolves, which reads as coverage while enforcing nothing. R-USE-THE-OWNING-SURFACE does not apply — a registered policy module has no emitting surface; the file is the authority.
@wenzowski
wenzowski marked this pull request as ready for review September 1, 2026 14:01
@wenzowski
wenzowski force-pushed the claude/policy-module-mutations-rm4hz1 branch from f26b0bb to 5a9924b Compare September 1, 2026 14:02
@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski
wenzowski merged commit 5a9924b into main Sep 1, 2026
14 of 15 checks passed
@wenzowski
wenzowski deleted the claude/policy-module-mutations-rm4hz1 branch September 1, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant