Files
stack/docs/remediation/AC-RM02-HARDENING.md
T
mos-dt-0andClaude Opus 5 72b577eb85 docs(remediation): pre-register the RM-02 hardening re-review — attack the FIX, not the original bug
Registered at 32b490a7 before any reviewer read the diff. I verified three of the four attacks are dead
by re-running them myself: injecting activationCommit=HEAD now yields "author-controlled
activationCommit is forbidden; history boundary is derived from the registry introduction"; the
misspelled outputPatern is rejected as an unknown field by the recursive schema; the global
cross-commit duplicate check is present. The three criteria are registered with caseRefs 1/3/3.

So the AC set does not spend itself re-checking what I already reproduced. Every round on this mission
the remediation introduced the next hole — the commit-binding fix shipped a type confusion, the
type-strict fix was clean but the registry around it had four defeats — so the value is in whether the
NEW mechanism is defeatable.

Blocker 1's fix replaced an author-settable field with a derivation, and a derivation has inputs. H1
asks who controls them: can an author move the derived boundary by adding, renaming, deleting-and-
recreating or symlinking gates/gates.manifest.json, or by planting a second manifest earlier in
history? If so, blocker 1 is relocated rather than fixed. H2-H4 ask what first-parent traversal,
shallow clones, and path deletion do — fail closed or silently derive a wrong boundary.

S1 asks whether the schema closure is complete or merely enumerated: find a nested object the author
did not list and inject an unknown key there. C2 asks whether the new criteria express D-38 and D-40
generally or only their originating instances — a clause that covers only the instance that produced it
is not a clause.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-01 11:32:35 -05:00

9.5 KiB

RM-02 / PR #1030 — PRE-REGISTERED RE-REVIEW: the four-blocker hardening pass

Subject head (exact): 32b490a712a5e8e77f13c40c60099b51feb38994 Supersedes: the NO-GO at 83d2ecb2 (D-44, four silent-defeat paths). That verdict is VOID. Registered by: mos-remediation before any reviewer read the diff. Reviewer: rev-974.

Framing — attack the FIX, not the original bug

Every round on this mission, the remediation introduced the next hole: the commit-binding fix shipped a type confusion; the type-strict fix was clean but the registry around it had four defeats. So the highest-value checks here are not "was each blocker fixed" — the orchestrator already reproduced three of the four attacks as dead — but "is the NEW mechanism itself defeatable?"

Blocker 1's fix replaced an author-settable field with a derivation. A derivation has inputs. The question is who controls them.

H — the new derivation (highest value)

id check
H1 deriveHistoryBoundary = parent of the first first-parent commit introducing gates/gates.manifest.json. Are its inputs author-controlled? Can a PR author influence the derived value by adding, moving, renaming, deleting-and-recreating, or symlinking that path — or by adding a SECOND manifest earlier in history? If the derivation is gameable, blocker 1 is not fixed, only relocated.
H2 First-parent traversal: what happens on a merge commit, an octopus merge, a squash, a rebase that reorders, or a branch where the introducing commit is not on the first-parent chain? Does the boundary silently move, or fail closed?
H3 Shallow/partial clone: the branch previously needed an unshallow fix (e8959975 "unshallow gate replay history"). If history is shallow, does the derivation fail CLOSED or silently derive a wrong/empty boundary?
H4 Path deletion: if gates/gates.manifest.json is absent at HEAD, or was deleted and re-added, what is derived? Fail closed, or a boundary that excludes the deletion window?
H5 Are the three registered seam controls (HEAD, HEAD^, introduction) genuinely RED-FIRST — do they fail against the PRE-fix code for their own stated reason? A control that was always green is a regression guard, not a must-fail control (D-8).

S — the recursive schema closure

id check
S1 Is closure COMPLETE or enumerated? The author lists the objects they closed. Find one they did not — any nested object anywhere in the manifest — and inject an unknown key there. If it is accepted, the fix covers instances, not the class.
S2 Wrong-type, not just unknown-key: outputPattern as a number/array/object/null rather than misspelled. Does the closed schema type-check values, or only key names?
S3 Empty/degenerate values: outputPattern: "" — does an empty regex match everything and silently neuter the assertion the same way a typo did? The author claims an empty-pattern control; verify it is bound.
S4 Confirm the registered typo/wrong-type/empty-pattern controls are genuine red-first against pre-fix code, and that anything labelled a regression guard is honestly labelled as one.

E — provider evidence (blocker 4)

id check
E1 Global validation runs before per-commit filtering on every path, including the HEAD-only path the author calls out. Is there any code path that reaches per-commit assessment without it?
E2 Duplicate identity by another key: the fix makes pipeline NUMBER globally unique. Can two records still collide on a different identity dimension — same commit + different number, same URL, same step-id — and certify the wrong subject?
E3 "Exactly one gate-verify step per record" — what if a record has zero, or two with different outcomes? Fail closed?

C — clauses, integrity, CI

id check
C1 The three new criteria (RM02-EVIDENCE-SUBJECT-BINDING, RM02-TYPE-STRICT-SCHEMA, RM02-HISTORY-BOUNDARY) are checked criteria with bidirectionally bound cases, not prose. Orchestrator observed caseRefs 1 / 3 / 3 — verify the bindings actually run and can fail.
C2 B1/B2 satisfied in substance: does RM02-EVIDENCE-SUBJECT-BINDING express D-38 generally ("does this gate bind its evidence to its subject?") or only the one pipeline-number instance? Same for D-40 vs the one typo instance. A clause that only covers its originating instance is not a clause.
C3 Nothing weakened: diff 83d2ecb232b490a7 removes/relaxes no existing case, test, or assertion.
C4 Exact-head CI terminal-green, full -f json, counts stated including clone; machine-checked with verify-terminal-green.py --expect-commit 32b490a712a5e8e77f13c40c60099b51feb38994.
C5 Closes #1029 still present (D-38c).

Reviewer instruction

Verdict bound to 32b490a712a5e8e77f13c40c60099b51feb38994, evidence enumerated, posted durably under your own identity. If a check is unrunnable, say so — never substitute a passing variant.

H1 and S1 are the two I most want answered, because they ask whether each fix closed a class or an instance. Attack outside this set: four of the last five blockers on this PR came from mutating something nobody had registered.

Environment note: pnpm gate:verify fails on checkout-preflight with outcome 42 (bubblewrap class) in at least one worktree. If you hit it, report it as an environment limitation — do not treat it as a finding, and do not let it mask one.

No one dispatching this review may state a conclusion on an open check (D-39).