The dossier

Six incident classes, extracted from a real production codebase run under a mechanically enforced zero-false-pass rule across 48 days of history (evidence: source repo's first commit 2026-07-18 to the pinned commit 2026-09-04). Every one of them still produced a green check that meant nothing.


The scanner that could skip

Class

A guard wrapped its own execution in a check for an optional dependency, and treated the dependency's absence as permission to pass rather than a reason to refuse.

What faked green

A pre-commit secret-scan hook shipped wrapped in if command -v gitleaks; then ... fi. On the machine that needed it, gitleaks was never installed. Every commit skipped the scan and the commit still succeeded, indistinguishable from a commit that had actually been scanned and found clean. The record's own description of the shape: "the check reports green for the case where it did not run" (evidence: CLAUDE.md:1078). The hole was closed only when an incident forced the question: a committed acceptance artifact carried a live-shaped credential straight through the silent scan and onto the remote.

How long it lived

18 days (evidence: af7bb1d 2026-07-24 to f9a1b55 2026-08-11). The source's own phrase: "18 days of commits that skipped the scan and succeeded looking clean" (evidence: CLAUDE.md:620-621, repeated at CLAUDE.md:1078-1079).

Source-repo commits

  • af7bb1d -- 2026-07-24 -- PR #170 -- "sec: pre-commit secret-scan guard (recurrence prevention, PART A #5)" -- introduced the hook, wrapped in the command -v gitleaks check that later made it silent.
  • f9a1b55 -- 2026-08-11 -- PR #609 -- "chore(security): the pre-commit secret guard was a silent no-op, and there was no push-time net" -- found and fixed both halves of the incident: the silent hook, and the absence of any push-time net for what gitleaks structurally cannot see (low-entropy values such as a six-digit invite code).

The mechanical fix that now exists

Both the pre-commit and pre-push hooks now fail closed: no gitleaks binary means no commit and no push, with one loud, named override rather than a silent pass. The pre-push hook adds a second, independent check -- a shape check for the class of credential an entropy scanner cannot see by construction -- because gitleaks catching one half of the 2026-08-11 incident and missing the other (a six-digit code with no entropy to flag) is what made the fix two checks, not one. Installed per clone by scripts/install_git_hooks.sh, which points core.hooksPath at the tracked hook files rather than copying them, specifically so the hooks cannot drift from the repo that defines them. The fix is honest about what it still does not cover on a standing basis: a branch that never opens a pull request and never merges is never scanned by CI at all, a gap the source repo measured directly (1,227 of 1,348 branches, unmerged and unscanned) rather than estimated, and states plainly that closing it needs a separate scheduled job it does not yet run.

Which Corund check closes the class

C2 (skip audit). A guard whose own execution depends on an unstated precondition is exactly the shape C2 exists to catch: a silent skip removing a guard from the pipeline that is supposed to enforce it. Corund's rule is structural rather than case-by-case -- a skip must be loud or it is a failure -- so the "wrap a check in a tool-presence test" pattern cannot recur unnoticed the way it did here for 18 days (evidence: CLAUDE.md:620-621).

Evidence paths in the source repo

  • CLAUDE.md:605-621 (the pattern named alongside two sibling instances of the same shape)
  • CLAUDE.md:1070-1105 (the full incident writeup, both halves, and the 2026-09-03 correction to its own blast-radius claim)
  • .githooks/pre-commit, .githooks/pre-push (the fixed hooks, fail-closed)
  • scripts/install_git_hooks.sh (the install path that keeps hooks versioned rather than copied)

Vacuous green

Class

A full test suite exits 0 while individual tests inside it silently skip the exact assertions that were supposed to gate the pipeline -- and the skip is invisible unless someone runs a census, because the suite's own summary line does not distinguish "skipped for a stated, load-bearing reason" from "skipped because the guard it carries never got to run."

What faked green

A full-suite run at a real commit reported "11993 passed, 82 skipped, 105 xfailed" and exited 0 (evidence: a full-suite run record, 2026-09-01, pytest -q invocation). A systematic classification of every skip in that run -- not a spot check -- sorted 103 distinct skip signatures into buckets by why each one fires, and found seven of them, across five files, hiding a guard from CI entirely: an environment variable never set in CI, an optional dependency CI never installs, and a binary CI never provides, each guarding an assertion that therefore has run zero times in continuous integration. The classification's own label for that bucket: "HIDES-A-GUARD- FROM-CI" (evidence: a skip census's classification output, 2026-09-01).

A second finding in the same investigation was sharper: the pipeline's own shared-write allowlist guard -- the one that is supposed to assert every allowlisted table was actually observed being written to during the run -- took the silent branch on the exact invocation used to run "the full suite" locally, and printed nothing. A 12,075-item run exited 0 with the guard's own comparison never evaluated. The fix's own description of the defect: "green because it did not run" (evidence: the fix's commit message, 9fa6742).

How long it lived

The seven skip sites were census-verified live on 2026-09-01. Independently re-checked line by line against the source repo's pinned commit (2026-09-04): all seven skip statements are present, byte-for-byte unchanged, and the two CI conditions that would silence them -- installing the optional [ingest] dependency, or installing the gitleaks binary inside the test job -- are still absent from that job's own setup steps. That is at least 3 days measured (2026-09-01 to 2026-09-04, evidence: census file dated 2026-09-01, re-check performed directly against the pinned tree) with no upper bound recorded, because no commit between those two dates touches any of the seven files. The allowlist guard's own self-skip is a separate, narrower defect and was fixed within 2 days (evidence: 9fa6742 2026-09-03, following the census dated 2026-09-01).

Source-repo commits

  • 9fa6742 -- 2026-09-03 -- PR #1633 -- "fix(tests): full suite green -- the allowlist guard runs on pytest tests and says so; a PWA destination assertion stops depending on the invoice sequence; skip census" -- fixed the allowlist guard's self-skip (it now states which branch it took on every run) and an unrelated database-sequence-dependent skip found in the same investigation. It does not touch any of the seven HIDES-A-GUARD-FROM-CI sites the same investigation's census identified.

The mechanical fix that now exists

The allowlist guard now distinguishes a full run from a filtered run by comparing the invocation's path argument against the project's own configured test paths, and prints one of two named lines on every run: "checked -- N entries, every one observed" or "NOT checked -- filtered run" -- so a run that could not have evaluated the guard can never be mistaken for one that did. That fix is honest about its own scope: it repairs the guard's self-skip, not the seven-site census. The seven-site finding itself was filed and left open in the source repo's own handoff record, which names it plainly as unresolved rather than folding it into an adjacent fix: "Five CI skip-sites hiding guards ... fix parked as PR #1633 -- whose head has MOVED since the finding ... so re-verify before trusting it" (evidence: a project handoff document, section (j), item 5). Re- verifying, as this dossier did, shows the parked fix never reached any of the seven sites.

Which Corund check closes the class

C2 (skip audit). The census that found these seven sites is exactly the sweep C2 runs on every gated pull request, continuously, rather than as a one-time investigation: every skip must be loud, on a committed allowlist naming why, or the check fails. A guard whose own comparison can be silently bypassed by an invocation shape -- the shared-write allowlist's defect -- is the same class C2's own self-audit is built to refuse: a check that exits 0 without stating whether it compared anything is not a pass.

Evidence paths in the source repo

  • A skip-census classification file, dated 2026-09-01, listing 103 skip signatures in seven buckets, with the seven HIDES-A-GUARD-FROM-CI sites named by file and line.
  • A full-suite run record, same date, showing the allowlist guard's silent branch on a clean-tree invocation.
  • A project handoff document, section (j) item 5, recording the finding as still open at the time it was written.
  • tests/test_ingest_ocr.py:75, tests/test_pre_push_secret_scan.py:135, tests/test_report_pdf.py:97, tests/test_spreadsheet_ingest_none_bbox.py:116,136,137, tests/test_upload_and_render_hardening.py:120 in the source repo -- the seven sites, independently re-checked against the pinned commit.

The check that could not see

Class

A required CI job reported green while the specific tests it was relied on to run had never actually executed, because the checkout underneath them was too shallow for those tests to see what they needed to see -- and the job's own summary line could not tell the difference.

What faked green

Three tests exist specifically to check that a release-notes generator agrees with a fresh regeneration of itself against real git history. They were given a skip condition for exactly one situation: a shallow checkout, where there isn't enough history for the comparison to mean anything. The CI job that was supposed to run them checked out with the default depth (one commit), so --check-stale always returned "unknown" and all three tests skipped, silently, on every single run, for six days, before a fetch-depth fix landed. The fix's own description of what a green run had actually been worth: "the exact mechanism that let a wrong ... attribution survive four days" in the project's own rules file, because "the rule said 'trust the CI green,' and that green was a skip" (evidence: commit 0a99b1c's message).

Two days after that fix landed, the same shallow-checkout defect reappeared -- not because the fix was wrong, but because a second, separate workflow (a nightly regression run) had its own independent checkout step, at the default depth, that the daytime CI fix never touched. The same three tests failed loudly this time, because by then a GITHUB_ACTIONS-gated fail-instead-of-skip had been added -- but nothing in that second workflow's own alerting named which job or which tests had failed; the failure was invisible inside a generic run-failed notification until someone read the raw log.

How long it lived

6 days for the original defect (evidence: b3812d2 2026-08-25 to 0a99b1c 2026-08-31, both dates from the source repo's own commit history). The recurrence in the second workflow was found and fixed within 2 days of the first fix (evidence: 0a99b1c 2026-08-31 to c45abe5 2026-09-02).

Source-repo commits

  • b3812d2 -- 2026-08-25 -- PR #1276 -- "test(releases): live-git tests skip on shallow history" -- added the shallow-history skip condition to the two live-git tests, correctly, for the reason stated, but did not check whether CI's own checkout was shallow enough to trigger it on every run.
  • 0a99b1c -- 2026-08-31 -- PR #1519 -- "batch(final-four)" -- fixed the underlying checkout (fetch-depth: 0, matching a sibling job that already needed real history for the same reason) and made the shallow-history skip fail loudly under GITHUB_ACTIONS instead of skipping quietly, so a future depth regression could not go green again unnoticed.
  • c45abe5 -- 2026-09-02 -- PR #1591 -- "fix(ci): nightly alert names WHICH job(s) failed" -- mirrored the same fetch-depth: 0 fix onto the nightly workflow's own checkout (the one job the first fix never reached) and added a named, derived-from-job-results attribution step so a future failure states which job broke instead of relying on a generic notification.

The mechanical fix that now exists

CI's primary test job now checks out full history rather than the default single commit, matching the depth another guard in the same pipeline already required for the identical reason: judging anything about git history needs the history to be there. The shallow-history skip condition itself was changed from a silent pytest.skip to an explicit failure whenever GITHUB_ACTIONS is set, naming the shallow-history condition in the failure message -- so a future regression in checkout depth produces a loud, specific failure instead of three tests quietly not running. The nightly workflow received the identical fetch-depth fix, and a new attribution step derives, from every other job's own result, the list of jobs that did not succeed and names them by job name rather than leaving a failure to read as generic. The fix does not claim to close every shape of "a check that cannot see because of how it was invoked" -- it closes this specific checkout-depth instance in the two workflows it touched, and is explicit that the underlying shallow-history skip condition is still a skip, not a failure, everywhere it is NOT running inside GitHub Actions (a local pytest run with a shallow clone still skips quietly, by design, since the condition is gated on GITHUB_ACTIONS specifically).

Which Corund check closes the class

C3 (gate-fold). C3's requirement -- every test file in a diff must be tracked and inside the required, branch-protected path, checked out with enough history for the check to mean anything -- is aimed directly at this class: a test that exists and is even collected is not evidence of anything if the environment it runs in cannot see what it needs to see. C2 (skip audit) also applies to the first half: the shallow-history skip, before it was converted to a loud CI failure, was itself a silent skip removing a guard from every CI run.

Evidence paths in the source repo

  • .github/workflows/ci.yml, the tests job's checkout step (comment naming the fetch-depth-0 requirement and the three tests it protects)
  • .github/workflows/nightly_regression.yml, the suite job's checkout step and the new nightly_attribution job
  • tests/test_gen_releases.py, the three tests gated by _skip_if_shallow_history()
  • Commit 0a99b1c's own message, which documents the RED (shallow, skip) / RED-loud (shallow, fail) / GREEN (full history, pass) verification it ran before shipping the fix

The guard with no true-positive path

Class

A guard shipped to catch a specific dangerous shape, was believed to be catching it for weeks on the strength of it firing, and turned out -- once measured against a deliberately constructed positive case -- to have never had a way to fire for the right reason. Every alarm it had ever raised was the same false shape, and it had a 0% detection rate on the shape it existed for.

What faked green

A revert guard was written to stop a silent revert: a branch whose merge lands and quietly drops lines that reached the base branch after the branch started. For weeks, the guard compared a branch's own diff against the *current* base branch rather than against the branch's own merge-base. The effect: any branch that was simply behind showed the base's newer lines as if the branch had deleted them -- a false positive that grows with how far behind the branch is, not with anything the branch actually did. Measured directly: 71 of 76 open pull requests failed the guard, with reported "deletions" ranging from 2,969 to 147,611 lines, a spread the investigation itself called "monotone in how far behind they are" -- the signature of a guard measuring branch age, not reverts. Three branches that the guard's own founding incident named as reverting real work were re-checked against the actual objects and were, in every case, merely stale: zero file overlap with the work they were accused of reverting, clean three-way merges, one of them merged the same night with every line intact.

The owner's own ruling, quoted directly in the investigation's evidence: "the guard has been reporting false silent-reverts for as long as this algorithm has been in place, proportional to main's movement. Every 'revert_guard failed' I've been told was the behind-main class was actually this. That includes the 38 reopened PRs and the whole overnight batch" (evidence: a revert-guard investigation record, section on the owner's 2026-09-01 ruling).

The one-line fix the owner ordered -- diff against the branch's own merge-base instead of the current base -- removed every one of those false positives (71 of 76 open PRs, down to 9, whose remaining hits were textual coincidences in generic tokens like pass or return out in unrelated files). But the same investigation was required to prove the fix could still detect a *genuine* revert, by constructing one in a throwaway repository. It could not. Diffing against the branch's own merge-base is structurally blind to the one shape the guard was named for: a rebase that resolves a conflict by silently keeping the branch's side and dropping the base's newer line. After such a rebase, the merge-base *is* the base's own head, so the set of "lines the base added since the merge-base" is empty by construction -- there is nothing left for the comparison to find, on either the old algorithm or the new one. The investigation's own verdict: "the current guard never detected one either ... this is not a weakening, there was no detection to lose; it is a guard with no true-positive path" (evidence: the same investigation record, verdict paragraph).

How long it lived

23 days for the phantom false-positive behavior (evidence: eaa1771 2026-08-10 to 122b944 2026-09-02, both dates from the source repo's own commit history). The guard's inability to detect a genuine rebase-took-my-side revert is a design limitation rather than a bug with a lifespan, and remains open at the time this dossier was written: it is pinned in the guard's own test suite as xfail(strict=True), specifically so the test suite fails loudly -- rather than silently passing -- on the day a version of the guard exists that can catch it.

Source-repo commits

  • eaa1771 -- 2026-08-10 -- PR #591 -- "fix(extract): guard round 2 -- narrow the transposed branch, close a live false pass" -- the version of the guard whose base-vs-current-main comparison produced the 23-day phantom.
  • 122b944 -- 2026-09-02 -- PR #1638 -- "fix(revert_guard): #1612 -- diff against the branch's own merge-base; the phantom-deletion class closed, the guard's real reach stated" -- landed the owner's one-line fix, rewrote the guard's header to state exactly what it measures and what it cannot see, un-pinned three tests that had encoded the phantom behavior as correct, and added the rebased-resolution gap as an xfail(strict=True) test rather than leaving it undocumented.

The mechanical fix that now exists

The guard now diffs a branch's deletions against its own merge-base rather than against the current base branch, closing the phantom entirely: 0 false positives on the three previously- flagged branches, 0 of 76 open pull requests after the fix (down from 71). The early-exit path for a current branch was removed, so an "OK" result is now a measured zero-of-zero rather than a short-circuit that never compared anything, and the guard's own output states both numbers it compared. What the fix is explicit about *not* covering: a rebase whose conflict resolution silently keeps the branch's side and drops the base's line is structurally invisible to a merge-base-keyed comparison, because after such a rebase the merge-base and the base's own head are the same commit. The guard's own passing output names this gap by class on every clean run, and a dedicated test (test_the_guard_names_the_rebased_resolution_it_cannot_see) asserts that the naming actually happens rather than trusting that it does. A companion test (test_a_rebased_conflict_resolution_that_dropped_mains_line_is_caught) is marked xfail(strict=True) specifically so it fails the suite -- loudly, not silently -- the day someone ships a guard that can see this shape, forcing that test to be rewritten around the guard that finally catches it rather than left quietly green. A candidate design that closes even this gap (keying on file, not merge-base window; counting line copies, not text) was prototyped and measured at 8 of 8 constructed scenarios and 0 of 76 false positives on open pull requests, but was not shipped -- it remains a proposal, not a fix, at the time this dossier was written.

Which Corund check closes the class

C1 (red-on-revert). Corund's own answer to "does this guard have a true-positive path" is not a constructed fixture written once and trusted -- it is C1 running on every gated pull request: the diff is actually reverted, the new tests are actually required to fail, and only then is the fix restored and required to pass again. A guard that can only ever report the same false shape would be caught by C1's own requirement that a check prove it can fail before its pass is trusted.

Evidence paths in the source repo

  • A revert-guard investigation record, dated 2026-09-01, containing the owner's ruling verbatim, the three re-measured branches, the eight constructed scenarios, the 76-PR sweep, and the drafted CLAUDE.md corrections
  • tests/test_no_silent_revert_guard.py:283-300 (the xfail(strict=True) test and its honest companion, test_the_guard_names_the_rebased_resolution_it_cannot_see)
  • scripts/check_no_silent_revert.sh (the fixed guard)
  • CLAUDE.md:405-425 (the corrected description of the guard's mechanism and reach, edited in place rather than appended)

The label that lied

Class

A deploy pipeline stamped a build label naming the commit it intended to ship, and a race in the deploy process itself let an older build finish and start serving traffic under that newer label -- so the one field an operator would check to know what was live named a commit that was not, in fact, what was running.

What faked green

The first instance: two overlapping deploy invocations could each trigger a platform deploy call; harmless if they carried the same commit, but if they raced with different commits, production would end up running whichever build happened to finish last -- while the deploy script's own success output still reported the commit it had *intended* to ship. The second instance, weeks later: a failed attempt to set the build-label variable left the *previous* successful deploy's label in place rather than clearing it, so the health endpoint reported a real, plausible-looking previous commit as current while the actual code fingerprint proved something newer was already live -- a label that lied by being stale rather than wrong. The third and largest instance: measured directly against production, the platform's own deploy semantics meant the label-setting step could fire a redeploy of the *old*, not-yet-registered source, which then won the race the platform ran internally -- production ended up serving a commit eight commits behind the one its own build_sha label named, and four behind that same label's own most recent successful deploy. The investigation's own description of what made this find-able at all: "the two-leg verify refused for 30 polls but could never converge," because the deploy script's health check was comparing against a build that had already lost.

How long it lived

The class recurred across 39 days before its third and (at the time of writing) final instance was found and fixed the same day it was found (evidence: bf2b9ea 2026-07-24 to e170f37 2026-09-01, both dates from the source repo's own commit history). The specific instance measured live in production was resolved within hours of discovery: the fix, the re-derivation of the correct commit's fingerprint, and the queued redeploy all landed on 2026-09-01.

Source-repo commits

  • bf2b9ea -- 2026-07-24 -- PR #169 -- "fix(deploy): single-flight prod deploy + build-marker verification (duplicate-deploy race)" -- closed the first instance: two overlapping deploy processes racing to ship different commits. Added a single-flight lock and a marker-verify step that polls the live service until it reports the intended commit, rather than trusting the deploy call's own exit code.
  • 3b3b037 -- 2026-08-27 -- PR #1334 -- "fix(deploy): a failed build-label set is cleared to 'unknown', never left stale" -- closed the second instance: a failed attempt to set the label used to leave the previous deploy's label in place, reading as a real, current, and wrong answer instead of an honest unknown.
  • e170f37 -- 2026-09-01 -- PR #1617 -- "fix(deploy): wait for the upload's own deployment to reach SUCCESS before stamping the build label (closes the marker race)" -- closed the third instance: the platform-level race between an upload's own deployment succeeding and a label-triggered redeploy of stale source, measured live against the production incident it fixed.
  • 6b81707 -- 2026-09-01 -- PR #1542 -- "fix(deploy): an interpreter that cannot import the application's own database module now refuses before a deploy" -- a related same-day hardening of the same deploy path, refusing before any deploy attempt rather than failing partway through one.

The mechanical fix that now exists

The deploy script now baselines the platform's own deployment list before triggering an upload, polls until that specific upload's own deployment reaches a real success state (never inferring success from the newest deployment in the list, which is exactly what let the race win before), and only then stamps the build label -- so the label-triggered redeploy that follows is guaranteed to rebuild the source that was actually just registered, not whatever source happened to be newest a moment earlier. A failed label-set is actively cleared to an honest "unknown" rather than left holding a stale, plausible-looking value. The fix is proven against a scripted stand-in for the deploy platform's command-line tool, never against the real service, with a decisive before/after pair: the same race scenario loses under the old ordering and wins under the new one, on one state machine, with every platform command intercepted. What the fix does not claim: it does not remove the two-leg fingerprint verification that is described elsewhere as "the trust anchor" -- it keeps that as the final arbiter and adds the ordering fix in front of it, on the reasoning that a race this narrow should not be allowed to happen even though the fingerprint check would eventually catch it downstream.

Which Corund check closes the class

C4 (approval binding). C4's rule -- a label or an approval must be bound to the exact commit it names, verified by content, not by trusting that a deploy or a merge call's own success message means what it says -- is the direct answer to a label that can drift from the code actually running. Where C4 binds an approval to a SHA and verifies the landed content matches it, the same discipline applied to a deploy pipeline is a two-leg build-label-plus-code-fingerprint verification, which is what closed the third and largest instance of this class.

Evidence paths in the source repo

  • scripts/deploy_prod.sh, scripts/deploy_lib.sh (the fixed deploy ordering and the two-leg build-label/fingerprint verify)
  • A project handoff document, section (a), containing the re-derived fingerprint comparison that caught the third instance live: the label named one commit, the served code matched a different one, eight commits behind main
  • tests/test_deploy_marker_race.py (the red-before / green-after pairwise test against the scripted deploy-platform stand-in)
  • CLAUDE.md, the deploy-path entry describing all three instances as one recurring class

Stale word

Class

An owner's approval to merge or deploy was given for an exact commit, the branch it named was rebased afterward without anyone announcing it, and the approval kept being treated as current for a commit it had never actually seen.

What faked green

The project's own standing rule states plainly what an approval means: "a merge/deploy word binds to a SHA, not a PR. An owner 'merge' / 'deploy on green' authorizes the EXACT commit it was given for; ANY new commit to the branch VOIDS that word until all required gates re-green on the new SHA" (evidence: CLAUDE.md:424-427). The rule exists because it was violated for real: two branches carrying live approvals were silently rebased, and both approvals kept being treated as valid against commits the approving read had never covered. The record: "two worded branches ... were silently rebased, voiding their words until patch-id proofs restored them a day later" (evidence: CLAUDE.md:166-168). The only reason those two approvals were caught rather than simply carried forward on a false premise was that a separate mechanism -- a patch-id comparison between the pre-rebase and post-rebase content -- was run and found the rewritten commits were, in that case, byte-for-byte identical in patch content to what had actually been approved. Where that comparison does not hold (any real conflict resolution during the rebase), the rule states plainly that the approval must be treated as void and re-earned, not carried.

How long it lived

Approximately 1 day (evidence: CLAUDE.md:167-168, "Lived 2026-09-02 ... restored ... a day later"), stated in the source's own record rather than derived from separate commit timestamps.

Source-repo commits

  • 4836f7b -- 2026-07-30 -- PR #309 -- "docs(CLAUDE.md): standing rule -- a merge/deploy word binds to a SHA, not a PR" -- established the underlying rule this incident violated, citing an earlier instance (a merge word given on one commit that a follow-up commit silently moved past) as the reason the rule exists at all.
  • 59c6981 -- 2026-09-03 -- PR #1709 -- includes "the silent-rebase rule -- a rebase of a worded branch announces itself (owner-approved 2026-09-03)" -- added the specific rule this incident produced: a rebase of an approved branch must post its old and new commit plus a patch-id verdict at push time, so a silent rebase is treated as an incident rather than a routine update.
  • 3ad38b8 -- 2026-09-03 -- PR #1712 -- "fix(instruments): verify_merge zero-file path verifies tree identity + payload trailers, never head-ancestry -- CANT-VERIFY is a distinct verdict, not a mismatch" -- landed the same day, hardening the general content-verification mechanism (used after every merge, independent of this specific incident) to stop reporting a real inability to verify as if it were a real mismatch.

The mechanical fix that now exists

Two mechanical pieces already existed and remain the backbone of the fix: merges are made with an explicit head-commit pin (gh pr merge --match-head-commit <sha>) so a race cannot swap the head underneath an approval, and a merge-verification script runs immediately after every merge to confirm the landed content actually matches the approved head -- content, not merely a successful merge call. What did not exist mechanically, and still does not: the specific promise that "a rebase of a worded branch announces itself" -- posting the old commit, the new commit, and a patch-id verdict at push time -- is recorded as an owner-approved rule in the project's own rules file, not as a script that runs on every push. The dossier's source is explicit that this half of the fix is a rule, not code: no push-time hook, workflow step, or script anywhere in the repository implements the "post old SHA, new SHA, and a patch-id verdict" behavior the rule describes. The mechanical half that does exist -- content verification after merge -- is a backstop that catches a bad landing after the fact; it does not, by itself, prevent an approval from being silently treated as current against a branch that moved underneath it before the merge ever happens.

Which Corund check closes the class

C4 (approval binding). This is the class C4 exists for by name: a human approval must be bound to an exact commit SHA, and any new commit -- including a rebase that leaves the visible diff unchanged -- voids that binding until the gates re-run against the new SHA. Where the source repo's own fix for the general problem is a merge-time content check plus a written rule about rebases announcing themselves, Corund's C4 makes the binding itself mechanical and continuous rather than a policy enforced by a human noticing: the approval simply does not carry to a different commit, checked in the pipeline, not in a rules document.

Evidence paths in the source repo

  • CLAUDE.md:165-168 (the silent-rebase incident and rule, added 2026-09-03)
  • CLAUDE.md:424-427 (the underlying word-binds-to-a-SHA rule, added 2026-07-30, naming its own founding incident)
  • scripts/merge_pr.sh (the --match-head-commit merge call)
  • scripts/verify_merge.sh (the post-merge content verification, hardened 2026-09-03 for its zero-file-diff path)