Skip to content

✅ test(audit): pin the AUD2 remediations behind a PR-visible exit gate (AUD2-S05) - #82

Merged
konih merged 10 commits into
mainfrom
lane/aud2-s05-integrate
Aug 19, 2026
Merged

✅ test(audit): pin the AUD2 remediations behind a PR-visible exit gate (AUD2-S05)#82
konih merged 10 commits into
mainfrom
lane/aud2-s05-integrate

Conversation

@konih

@konih konih commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

AUD2-S05 — the P5-AUD2 epic exit gate

Closes the P5-AUD2 epic. Adds hack/audit/aud2_exitgate_test.sh (2121 lines), which
asserts the four 2026-08-18 audit remediations landed by S01–S04 are still present, and
wires it PR-visibly as the 19th task check stage.

The four remediations it pins

Finding Story How it is held closed
REL-01 / REL-02 AUD2-S01 source pins over CallExec (bounded stdout at MaxResponseBytes, cmd.WaitDelay)
REL-07 AUD2-S01 behavioural mutation run — the revert is applied to a throwaway tree copy and TestExecStderrFoldedIntoError must FAIL against it
REL-03 AUD2-S02 behavioural mutation run over two named resolveRunFacts tests
SEC-03 AUD2-S03 source pin over hack/install.sh + no drift from SECURITY.md
TEST-02 AUD2-S04 its named unit case, TestClassifyStricterInterventionAddedChallengeEffect

The mutation runs are indifferent both to how a production revert is spelled and to how a
test might be hollowed out (t.Skip, a no-op body, a deleted assertion all redden it).
38 mutation controls run, floor-asserted, each red for its own stated reason.

Why it is in verify, not only release-exitgate

release-exitgate carries if: github.event_name != 'pull_request' (RELSE-08), so a gate
wired only there is invisible to every PR — exactly how AUD-S18's stale CHECK_STAGES pin
survived four merges. This gate is a task check stage and the same commit adds it to
CHECK_STAGES (now 19).

Step position in verify.yaml is load-bearing: it sits below actions/setup-go,
because the gate runs go build/go test against reverted tree copies and go.mod pins
toolchain go1.26.6.

Verification on this head

  • task check exit 0; 19/19 unique stage banners observed in the transcript.
  • bash hack/audit/aud2_exitgate_test.sh exit 0 (full mode); --text-only exit 0.
  • bash hack/audit/exitgate_test.sh --text-only exit 0 — the AUD-S18 grader confirms
    "Taskfile check: runs exactly the 19 pinned stages". task ci-audit-test exit 0.
  • git diff origin/main...HEAD over internal/provider/transport.go,
    cmd/assent/provider_host.go, internal/compare/, hack/install.sh, SECURITY.md is
    empty — this lane modifies none of the remediations it grades.
  • No agent-context/ committed.

Integrator-owned commits

CHANGELOG.md regenerated with task changelog-write after the rebase (a no-op — the
lane was already based on 07b44db) and amended into the tip, alongside
openspec/specs/backlog.md's AUD2 status line (AUTONOMOUS COMPLETE, AUD2-F01 left
explicitly OPEN as a follow-up, not an AUD2 story, per D-152).

Branch note

The changelog amend rewrote SHAs already published on lane/aud2-s05, and force-push is not
authorized (AGENTS.md rule 2) — so this PR comes from a new branch. lane/aud2-s05 stays on
origin at d1c8096 as the pre-rebase review record.

Independent review: APPROVE after seven implementation rounds and eight reviews; no P0/P1
outstanding. This branch has never had a CI run (lane branches get no Actions here), so this
PR is the first time the gate executes on a real runner.

konih added 10 commits August 19, 2026 01:57
REQ-AUD2-S05-01..05. hack/audit/aud2_exitgate_test.sh asserts, per 2026-08-18
audit finding, that all four AUD2 remediations are still present:

  REL-01/02/07 (S01) CallExec bounds stdout at MaxResponseBytes, sets
               cmd.WaitDelay, and folds a bounded stderr into its error;
  REL-03       (S02) resolveRunFacts skips only on forge.ErrNotFound;
  SEC-03       (S03) hack/install.sh pins the cosign identity + OIDC issuer,
               byte-identically with SECURITY.md;
  TEST-02      (S04) isStricterInterventionEffect keeps EffectChallenge and
               the named unit case defends it.

Three of the four have a decoy occurrence in the very same file (CallHTTP's
MaxResponseBytes, loadResourceOwnerRegistry's D-130 errors.Is guard, the
compare tests' EffectChallenge), so every assertion reads a function body
extracted by name, with a positive control on a known-present anchor and a
scoping control refusing the neighbouring decoy function. 14 mutation
controls on temp copies prove each assertion goes red, and red for its own
stated reason (REQ-AUD2-S05-02); the REL-03 mutant deliberately leaves the
D-130 guard intact, so a file-level grep stays green on it.

Wiring, in this same commit because the AUD-S18 pin exists to force exactly
that: `- task: audit-aud2-exitgate-test` in Taskfile check: (19th stage) and
the matching CHECK_STAGES entry in hack/audit/exitgate_test.sh. A stale pin
here is the AUD-S18/RELSE-08 incident that reddened main for four merges.

REQ-AUD2-S05-05: the gate runs as an early step of verify.yaml's `verify`
job, which fires on pull_request — not only in release-exitgate, whose
`if: github.event_name != 'pull_request'` is RELSE-08 itself. The gate
asserts that placement and reds if the step is deleted or the job grows a
push-only condition. What stays out of tree is recorded in the spec: making
`verify` a required check is branch protection, and the `task check` stage
still does not run on PRs. Also corrects verify.yaml's stale "all 14 task
check stages" comment (19 now).

Spec hygiene surfaced by AUD2-S03's re-review, all in the AUD2 spec:
REQ-AUD2-S03-06 promotes the real-SAN fixture assertion (D-153's "assertion
that would have caught the defect") from a Definition-of-done bullet to an
annotated requirement pinning install_cosign_pin_test.sh §4c/§4d; the Paths
owned table now records S03's SECURITY.md and CHECK_STAGES writes and S05's
actual footprint; and the Problem section's line numbers are dated to
b4f5054 with the SECURITY.md range corrected to that same era.
REQ-AUD2-S05-05. check_pr_wiring proved the `verify` job carries no job-level
`if:`, but nothing read the workflow's own `on:` block — so deleting the
`pull_request:` trigger removed the gate's entire pull-request reach for every
job at once while every assertion stayed green. That is the same class of hole
the REQ exists to close (RELSE-08 by another route), so it is now asserted,
with a mutation control that keeps the step wired and only drops the trigger.

Mutation-control floor raised 12 -> 15 to match.

Verified identically green under GNU coreutils
(debian:stable-slim), not only macOS BSD sed/awk/grep — this gate now runs on
every PR on ubuntu-latest, and awk -v escape handling already bit once here.
Independent review, P1. check_notfound_discrimination's second assertion
grepped the whole resolveRunFacts body for `^\s*return nil, nil, fmt.Errorf(`.
That function has THREE such returns — the guard's own, the LoadProviderConfig
path and the provider-call path — so the pattern was satisfied on every
possible tree, including a broken one. The reviewer proved it with a
compiling, gofmt-clean half-revert (guard kept, its body downgraded to
`continue`, i.e. REL-03 fully restored) that this gate passed. An assertion
that cannot fail is the exact defect class this epic exists to close, and its
presence made the gate's own "every assertion can fail" banner untrue.

The assertion now reads only the guard BLOCK — from `if !errors.Is(err,
forge.ErrNotFound)` to the `}` at the same indentation, brace-matched on
gofmt's indentation guarantee — over a comment-stripped view, because the
guard's own prose names both LoadProviderConfig and the `continue` it
replaced. Three controls keep the isolation honest: the region must start with
the guard line, must not contain the LoadProviderConfig statement, and must be
strictly smaller than the body.

Adds the missing mutation control (16th): guard kept, first
`return nil, nil, fmt.Errorf(` downgraded to `continue` at the same
indentation. It asserts the guard line survives AND that two sibling returns
survive, so the mutant is one a body-wide grep stays green on — that survival
is the proof the assertion is scoped. Verified end-to-end: the mutated file is
gofmt-clean, `go build ./cmd/assent` succeeds, and the gate reds naming REL-03.

Also (F3) widens the REL-02 wait-forever defence: `[[ "$rhs" == "0" ]]`
accepted `time.Duration(0)` and `0 * time.Second`, both of which are Go's wait
forever. The rule is now "digits present and all of them zero", with a control
for the typed spelling and a reverse control proving `30 * time.Second` is
still accepted.

MUTATIONS_PROVED 15 -> 17; the floor moves with it.

Same file, same review round:
- F2: the wiring section ran its mutants BEFORE its real-tree greens, so a
  genuine revert of the `check:` line / CHECK_STAGES entry / verify.yaml step
  surfaced as the harness's own "mutation did not land" instead of a REQ-named
  message. Green now runs first, as in sections 1-4.
- F5: two of the three body_of over-extraction guards named a function ABOVE
  their target, and extract_func only reads downward, so they could never fire
  — the same species as F1. CallExec's now names execFailure (the function
  below it); isStricterInterventionEffect is the last function in its file and
  passes none. A direction-independent `^func ` count is the live backstop in
  every case.
…F4, F6)

F4 — hack/audit/README.md had no entry for the 800-line AUD2 exit gate, and
its exitgate_test.sh table still read "all 14 pinned stages", the identical
stale number already corrected at verify.yaml:156. Both fixed: the count is 19,
and aud2_exitgate_test.sh now has its own section covering what it asserts, why
every assertion is scoped to a function body (three of the four remediations
have a same-file decoy), why the REL-03 branch assertion reads only the guard
block, the anti-vacuity discipline and mutation-control floor, the GNU/BSD
portability recipe with the awk -v escaping trap, and — stated plainly — what
it does NOT certify: the Later wave, WG-S01, branch protection, and the fact
that the `task check` stage still does not run on PRs.

F6 — the spec cited `provider_host.go:281-285` for loadResourceOwnerRegistry's
D-130 guard in three places; at b4f5054 it is 282-286. Pre-existing, but this
lane's new blanket "every line number in this section is as of b4f5054" now
vouches for it. Also corrects the Reuse list's second `SECURITY.md:80-98` to
80-93 (the same overshoot into the SBOM section already fixed in Problem) and
dates that list's line numbers to the same commit. Spot-checked the remaining
citations in that list against b4f5054: transport.go:100-116, run.go:465-474
and provider_host.go:82-86 are all correct as written.
… appears"

Independent review round 2, P1 (finding A). The guard-scoped assertion still
asked "does a `return … fmt.Errorf(` appear anywhere in the region". The
reviewer built two mutants — both gofmt-clean, both compiling, both leaving
REL-03 fully restored — that the gate exited 0 on:

  1. block-comment camouflage: the half-revert plus the return quoted inside a
     `/* … */` span. code_only stripped `//` lines only, so the script's own
     claim that a commented return cannot satisfy the assertion was false as
     written.
  2. nested fail-open, no comments at all: the return survives only under
     `if errors.Is(err, context.Canceled) { … }`, followed by `continue`. Every
     real forge error — 503, 401, 403, throttle — is skipped. This is the one
     that needs no trick.

Mutant 2 is caught today by `go test -race` in the same PR-visible verify job,
so nothing merges through right now; it stays P1 because that only holds for a
revert that keeps the behavioural tests, and a revert that nests the return AND
drops the 401/403 cases would be invisible to both layers. That is TEST-02's
own failure mode reproduced inside the gate built to prevent it.

Two fixes, both required:

  * TERMINAL PATH. The return must sit at exactly the guard's body indent — one
    level deeper than the `if`, and no deeper — so a return reachable only under
    a further condition does not count. gofmt (check stage 1) is what makes that
    indentation load-bearing rather than cosmetic.
  * code_only strips BLOCK comments too, via a state machine rather than a grep,
    since `/* … */` spans cross lines. It does not model Go string literals;
    that direction is fail-CLOSED (the assertion sees less code, never more) and
    is documented rather than left implicit. The claim is now one the code backs.

Both reviewer mutants added as controls, each asserting the mutant is one the
PREVIOUS version accepted: the block-comment mutant still contains the required
return text, and the nested-if mutant's guard block still contains a real,
uncommented return. Verified outside the gate as well — spliced into the real
provider_host.go, both compile (`go build ./cmd/assent`), the nested one is
gofmt-clean as written and the commented one after `gofmt -w`, and the gate
reds naming REL-03 on each.

Finding B (P2): the PASS banner claimed the controls "proved every assertion can
fail". This script emits roughly forty distinct findings; twenty-two carry a
control. An exit gate whose banner overstates its own coverage is the D-124
failure mode this epic exists to close, so both were addressed:

  * the two uncontrolled REQ-bearing sites now have controls — the CI step
    present but DISARMED (`continue-on-error: true` and `if: false`, both
    spellings, REQ-AUD2-S05-05's core property) and the check: stage still wired
    and named but its body no longer invoking this script (REQ-AUD2-S05-03's
    second half, the AUD-S18 gutted-stage-body lesson applied to this gate);
  * the banner now states what is actually proved: N controls ran
    (floor-asserted), each red for its own stated reason, covering every
    REQ-bearing assertion here — NOT every finding the script can emit.

MUTATIONS_PROVED 17 -> 22; floor and README updated with it. Re-verified
byte-identical output under Debian/mawk (ubuntu-latest's awk), since this round
adds three awk programs.
Independent review round 3, P1. `de30e4f`'s subject — "measure the REL-03
guard's terminal path" — OVERSTATED what that commit achieved, and this one
says so on the record: an indent rule measures where a return SITS, not whether
the guard's path can be taken without stopping the run. The reviewer's
polarity-swapped revert

    if !errors.Is(err, context.Canceled) {
        continue
    }
    return nil, nil, fmt.Errorf(...)

puts a real return at exactly the guard's body indent and skips every forge
error except context.Canceled. Reproduced here on the real tree: gofmt -l
silent, go vet clean, go build OK, golangci-lint clean — and the previous gate
exited 0 printing "REL-03 ... CLOSED", while `go test ./cmd/assent` fails
TestProviderDeclarationForgeErrorAbortsResolveRunFacts and the 401/403 cases.
It is also the more idiomatic of the two guard-clause spellings.

And it was a CLASS, not a call site. REL-07's fold assertion was body-wide and
unscoped, so the same idiom reverted it too: nest the fold under
`errors.Is(err, context.DeadlineExceeded)`, `return nil, err` otherwise, and
every real provider failure loses its diagnostic while one matching line
survives. Verified the same way (clean toolchain, TestExecStderrFoldedIntoError
fails, old gate exit 0).

The discriminating property, for both:

  REL-03 — no `continue` / `break` / `goto` anywhere inside the ErrNotFound
    guard, at any depth. The remediated guard has none in code; every revert
    shape needs one, because skipping the provider IS the defect. One assertion
    kills all four mutants: plain half-revert, block-comment camouflage,
    nested errors.Is fail-open, and the polarity swap.
  REL-07 — no `return` inside the `cmd.Run()` failure branch may omit the
    stderr sink. A path that does hands the operator a bare "exit status 1"
    however the condition around it is spelled.

The terminal-path checks stay as necessary conditions — they name the defect
precisely when the absence check fires — but they are now documented as
insufficient rather than as the property.

THE FILTER INVERSION, which is the part that could have traded one unfailable
assertion for another. code_only is tuned for PRESENCE: over-stripping hides a
return and causes a false RED (safe). An ABSENCE assertion inverts that —
over-stripping hides the token being hunted and goes falsely GREEN — so
code_only is NOT reused. Absence assertions read a second filter,
code_conservative, which can only ever keep too much: it strips a line only
when its first non-blank characters are `//`, and a block span only when the
opening line's first non-blank characters are `/*`. A trailing `//` comment and
a mid-line `/*` are deliberately not recognised, because deciding whether the
marker sits inside a string literal is exactly the guess that produces the false
green. Its one residual — a multi-line raw string literal — is refused outright
by a backtick check (assert_no_raw_string) rather than assumed away.

Also audits REL-01 as asked: rhs_of reads the FIRST assignment and Go runs the
LAST, so appending `cmd.Stdout = &bytes.Buffer{}` after the bounded capture
reverted REL-01 with every existing check still reading the good statement.
cmd.Stdout, cmd.Stderr, cmd.WaitDelay and both sink variables must now be
assigned exactly once.

Four new controls (MUTATIONS_PROVED 22 -> 26): the REL-03 polarity swap, the
REL-07 nested fold, the REL-07 polarity swap, and the REL-01 reassignment. Each
asserts a precondition proving it is a mutant the PREVIOUS version accepted —
the polarity mutants put their return at the right indent, the REL-07 nested
mutant keeps a stderr-carrying return, the REL-01 mutant keeps the bounded
capture — so each control grades the new assertion and not the old one.

Corrects the three places that claimed the invariant the gate did not have:
hack/audit/README.md's "Scoping is the whole gate" (rewritten to five items,
with item 2 now explicitly labelled necessary-but-not-sufficient), the script
comment above the terminal-path check, and this commit body for de30e4f's
subject. Re-verified byte-identical under Debian/mawk.
… shape

Independent review round 4, two P1s — and this commit stops patching shapes.

What broke round 4's version, both compiling, gofmt/vet clean, both failing the
real tests, both passing the gate at exit 0:

  * REL-03, condition NARROWING, one line, no camouflage:
        if !errors.Is(err, forge.ErrNotFound) && errors.Is(err, context.Canceled) {
    No fall-through, return at the correct body indent, every source-shape
    heuristic green.
  * REL-07, a bare return whose MESSAGE contains the identifier:
        return nil, fmt.Errorf("provider exec failed (stderr suppressed): %w", err)
    Both halves of the fold assertion are substring tests, not data flow, so
    both accept it. It is a plain double-quoted string literal, which is why no
    comment filter and no filter polarity can fix it — and it invalidates the
    "keeping too much is fail-closed" argument for that assertion specifically,
    since a NEGATED match makes extra kept text fail-OPEN.

And the demonstration that settles it: revert REL-03 *and* delete its two
behavioural tests — `go test ./cmd/assent/` green, gate green.

Anything that re-derives these two remediations from unparsed Go source text has
unbounded surface. So they are now pinned the way TEST-02 already was — BY TEST
NAME — and the shape checks are demoted to a documented secondary heuristic.

  REL-03 -> TestProviderDeclarationForgeErrorAbortsResolveRunFacts,
            TestProviderDeclarationUnauthorizedAbortsResolveRunFacts, and the
            []int{401, 403} case table, in cmd/assent/provider_host_test.go
  REL-07 -> TestExecStderrFoldedIntoError and its three t.Run cases, in
            internal/provider/transport_test.go

THE COMPOSITION, written into the script and the README so nobody simplifies one
half away: a revert that KEEPS the tests reds via `go test` — check stage 4,
before this gate's stage 19, and a step of the same PR-visible verify job; a
revert that DELETES or RENAMES them reds here, because `go test` reports a
deleted test as success. Neither half can be defeated by restructuring
production source, which is what every mutant that beat the shape checks does.
Verified end to end: with the narrowing applied and the tests renamed away, the
gate reds naming both missing tests.

The shape checks are kept, not deleted — they name the defect precisely on the
shapes they do recognise, and their controls are strong. They are just no longer
treated as the property. Both blind spots are now recorded as EXECUTABLE
controls that assert the heuristic still accepts them, so a future change that
drops the name pins turns them red instead of passing quietly.

Doc truth (F4). Removed every claim the gate cannot back: README item 3's "every
revert shape needs one, because skipping the provider IS the defect", the
REL-07 "however the condition around it is spelled" in both the README and the
script message, and item 4's "its ONE residual" (an ordinary string literal is a
second, and the fail-closed argument does not hold for REL-07's negated match at
all). Added a "What actually holds each remediation closed" table — the four are
not held by the same mechanism and the README said otherwise. The PASS banner
now states the composition per finding instead of implying uniform source pins.

Notes fixed, not chased (F5, F6): the rel07nested/rel07polarity mutants inject
errors.Is into transport.go, which does not import `errors`, so they do not
compile as spliced — the comment claiming "gofmt/vet/lint/build clean" was wrong
and now says the controls grade TEXT, with the compile-clean equivalent verified
separately on the real tree. And the rel07fold control's witness was
`return nil, err`, which already occurs twice in CallExec, so a no-op sed
reddened with "mutation harness: sed did not change" instead of naming REL-07;
the witness is now the CallExec-scoped absence of the execFailure call.

Four new controls (MUTATIONS_PROVED 26 -> 30): test rename and dropped case for
each of REL-03 and REL-07. Plus two non-counting blind-spot controls. Re-verified
byte-identical under Debian/mawk.
Independent review round 5, P1: a name is not a behaviour. Keep the pinned test
names, empty the bodies —

    func TestProviderDeclarationForgeErrorAbortsResolveRunFacts(t *testing.T) {
        t.Skip("temporarily disabled")
    }

— add the one-line condition narrowing, drop the orphaned imports, and the
result is gofmt silent, go build OK, go vet OK, `go test ./cmd/assent/` ok, and
this gate GREEN with REL-03 fully reverted. `t.Skip("flaky")` is a routine
event, not a contrivance. Round five's "keeps the tests / deletes the tests"
was presented as a partition and is not one: gutting is a third case that both
halves missed. There is no third backstop either — cmd/ is outside
./internal/..., so the coverage floor does not move when those tests are gutted.

The decisive argument was from this script itself: it already builds
Taskfile.gutted.yml to control for body-gutting against the Taskfile stage,
citing the AUD-S18 gutted-coverage-body lesson, and did not apply that same
reasoning to its own primary pin.

THE FIX, and it terminates the class because it measures behaviour instead of
reading text or names: copy the working tree's tracked files to $WORK, apply the
revert TO THE COPY, run the pinned tests against the copy, and require them to
FAIL. Indifferent to how the production revert is spelled (condition narrowing,
polarity swap, string-literal return) AND to how a test might be hollowed out
(t.Skip, a no-op body, a deleted assertion), because it reports what the tests
DO. Nothing is written to the real tree.

Three ways it could pass for the wrong reason are refused explicitly:
  * the pinned tests must first `--- PASS:` BY NAME on an unmutated copy —
    `go test` exits 0 both when a -run pattern matches nothing and when a test
    calls t.Skip, so an exit code would treat a disabled test as passing;
  * a `[build failed]` transcript on the reverted copy is refused — "the mutant
    does not compile" is not evidence about behaviour (controlled: a mutant that
    does not build reds with its own message);
  * the reverted run must fail AND name a pinned test in a `--- FAIL:` line.

Verified end to end on the real tree with EVERY text pin satisfied in live code
(names kept, `[]int{401, 403}` kept as a real statement, not a comment):
gofmt/build/vet clean, `go test ./cmd/assent/` ok — and the gate exits 1 with
"the pinned tests still PASS with … REVERTED in a copy of the tree".

Cost, measured: the tracked-file copy is ~1,200 files / 8.6 MB and is effectively
instant; the two `go test -run <pinned>` runs take ~2s each. Whole gate ~40s at
check stage 19, after `task test` has already built the packages. The behavioural
runs are top-level checks, NOT inlined into the per-file check functions — a
dozen mutation controls re-invoke those against mutant files, and inlining took
the gate from 4s to 65s.

--text-only added (the AUD-S18 idiom): pattern layer plus its full mutation
harness, skipping the behavioural runs, for exercising the patterns under
Linux/GNU grep + mawk in a container with no Go. Its PASS banner says plainly
that it certifies NOTHING about REL-03/REL-07. Both the Taskfile stage and the
verify.yaml step are now asserted to invoke the script with NO arguments, with a
control for each, so the flag cannot disarm the gate where it counts. The
control floor is mode-aware (36 full, 32 text-only) so neither mode can shrink.

F4: case pins now read a comment-stripped view. `[]int{401, 403}` was being
satisfied out of a Go comment left behind by a gutted body, while every
production-source assertion in this script already filtered comments.

F3: dropped check_named_tests' corpus control. `grep -cE '^func Test' >= 1`
cannot independently fail — any file satisfying a `func <pinned>(` pin
necessarily contains a `^func Test` line — which is the D-124 species this epic
exists to close.

Doc truth: hack/audit/README.md's "a revert that keeps the tests is caught by
`go test`" bullet and the keeps/deletes partition are removed and replaced by an
explicit correction recording what was false and why, plus what replaced it. The
"What actually holds each remediation closed" table row for REL-03/REL-07 and
the gate's own assert-table rows now name the mutation run. The PASS banner
states the same.

Also made the REL-03 revert program indent-anchored so it lands on the
provider-declaration guard only — the identical D-130 guard in
loadResourceOwnerRegistry sits at one tab, this one at three, and an unanchored
program reverted both.

Four new controls (MUTATIONS_PROVED 30 -> 36): t.Skip bodies, no-op bodies for
each finding, a non-compiling revert, and the two --text-only disarm controls.
Re-verified byte-identical under Debian/mawk in --text-only mode.
Independent review round 6, two P1s.

F1 — THE QUORUM WAS WEAKER THAN THE CLAIM. The behavioural run was satisfied
when AT LEAST ONE pinned test landed in a `--- FAIL:` line, while the banner and
README claimed indifference to hollowing "including a deleted assertion". Two
escapes, both executed by the reviewer and both now controls here:

  * gut only TestProviderDeclarationUnauthorizedAbortsResolveRunFacts (`_ = t`
    plus `_ = []int{401, 403}` in LIVE code so the case pin stays green),
    production source untouched -> go test ok, gate exit 0. Its sibling still
    failed under the revert and satisfied the quorum; the entire 401/403 auth
    branch was left undefended.
  * empty the body of t.Run("nonzero_exit_reports_stderr", …) — the canary that
    IS REL-07's behavioural defence — keeping the name. The function-level FAIL
    line still appeared (the sibling subtest fails), so the gate exited 0.

Fixed with an explicit must-fail list per finding, and the asymmetry is
deliberate and measured, not generalised:

  REL03_MUSTFAIL = ForgeError, Unauthorized/401, Unauthorized/403
  REL07_MUSTFAIL = nonzero_exit_reports_stderr,
                   runaway_stderr_is_bounded_and_truncated

REL-07's third subtest, stderr_never_merged_into_facts, is deliberately NOT
required: under the fold-dropping revert it LEGITIMATELY PASSES — it asserts
stderr does not leak into the fact map, which stays true when the fold is
removed — so demanding it would be an assertion no correct tree can satisfy. It
is still held by the case pin in check_named_tests. Transcript names measured,
not assumed:

  --- FAIL: TestExecStderrFoldedIntoError/nonzero_exit_reports_stderr
  --- PASS: TestExecStderrFoldedIntoError/stderr_never_merged_into_facts
  --- FAIL: TestExecStderrFoldedIntoError/runaway_stderr_is_bounded_and_truncated

REL-03 pins subtests too, which is stronger than the review asked for and
verified safe by the same measurement: dropping just the 401 case is now caught
at case granularity. Match uses a trailing space (`--- FAIL: X `) so a
function-level pin cannot be satisfied by one of its own subtests.

F2 — THE GATE EXITED 0 ON BASH 3.2. Under stock macOS /bin/bash the script died
at the first `local -n` nameref after one section header and exited 0. Confirmed
against the previous commit in place: EXIT=0, with "local: -n: invalid option"
and "fns[@]: unbound variable" on stderr. CI is ubuntu/bash 5 so nothing merges
through, but AGENTS.md rule 4 makes a green LOCAL `task check` a per-commit
precondition, and this is the anti-vacuity gate certifying nothing on a
maintainer's machine. Now asserted first, before anything can partially run;
observed EXIT=1 with a named message under /bin/bash 3.2.57.

F3 — "pure text over the source, needs no toolchain, fails in seconds" survived
at four sites and has been untrue since the behavioural runs landed. All four
corrected: .github/workflows/verify.yaml, Taskfile.yml, this script's header,
and hack/audit/README.md — the last was worst, because it DERIVED the PR-reach
argument from a property the gate no longer has and contradicted its own runtime
figure sixty lines below. The reach argument is now made on its own terms (the
verify job is the one that fires on pull_request; release-exitgate does not),
and --text-only is named as the mode that is still toolchain-free.

F4 — the gate step sat ABOVE actions/setup-go in verify.yaml. With
`toolchain go1.26.6` in go.mod the first `go test` would have had to download a
toolchain with no Go cache present, and this branch has no PR and no CI run, so
the placement had never executed. Moved below setup-go, with the reason recorded
in the step so it is not "tidied" back up.

MUTATIONS_PROVED 36 -> 38; full-mode floor raised with it (text-only floor
unchanged at 32). Runtime measured here at 52s (38.6s for the reviewer); the
figure is now stated as a range in all three places rather than as one machine's
number. Re-verified --text-only byte-identical under Debian/mawk, and re-ran the
three other verify.yaml readers after moving the step.
@konih
konih merged commit 2903b10 into main Aug 19, 2026
8 checks passed
@konih
konih deleted the lane/aud2-s05-integrate branch August 19, 2026 03:30
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