Found during a multi-persona review of REQ-GUARD-GATE-EVIDENCE-002. Verified at 618b29df.
tools/check_fuzz_targets.py was added to stop the fuzz target list drifting from its declaration. It audits the wrong one of the two lists — the advisory one.
The three lists
fuzz/Cargo.toml — three [[bin]] declarations.
.github/workflows/fuzz-nightly.yml — matrix.include, audited by check_fuzz_targets.py:196 (its default --workflow). Not a required context — its job name is templated (Fuzz ${{ matrix.target }} (1h)), which by check_required_contexts.py's own rules means it can never be one.
.github/workflows/ci.yml:419-424 — job Fuzz smoke (60s/target), which hand-writes the same three targets as three separate run: steps. This one IS a required context. Nothing compares it to anything.
So the covered list is advisory and the uncovered list blocks merges. Add a fourth harness to fuzz/Cargo.toml plus a fourth nightly matrix entry, and check_fuzz_targets.py correctly reports All 4 declared fuzz targets are run — while Fuzz smoke keeps fuzzing 3 of 4, green, forever.
Today the three lists happen to agree (fuzz_aadl_parse, fuzz_scheduler_solver, fuzz_codegen_roundtrip), so this is latent, live on the next edit.
Note for whoever fixes it
Pointing the existing tool at ci.yml does not work. _MATRIX_TARGET (check_fuzz_targets.py:65) is ^\s*-\s+target:\s*(\S+)\s*$; fuzz-smoke's targets sit inside cargo +nightly fuzz run ... <name> within - name: steps. Executed:
$ tools/check_fuzz_targets.py --workflow .github/workflows/ci.yml
run by .github/workflows/ci.yml: 0 []
::error::no `- target:` entries found — ... broken scan ...
EXIT=2
The broken-scan guard fires correctly, which is the tool behaving well — it needs a second extractor, not a second --workflow value.
Also worth noting: set equality over declarations proves declaration parity, not execution. A leg carrying continue-on-error: true or if: false still counts as "run".
Wording
REQ-GUARD-GATE-EVIDENCE-002 obligation (h) says the nightly "names its three targets in three hand-written steps" — which literally describes fuzz-smoke, not the nightly's matrix.include. And obligation (g), two paragraphs earlier in the same requirement, establishes "for every tool, not one". So either the fix covers fuzz-smoke, or (h) should be amended to state explicitly that a required context is left uncovered.
Acceptance: adding a [[bin]] to fuzz/Cargo.toml without adding it to ci.yml's fuzz-smoke job must fail a gate.
🤖 Generated with Claude Code
Found during a multi-persona review of REQ-GUARD-GATE-EVIDENCE-002. Verified at
618b29df.tools/check_fuzz_targets.pywas added to stop the fuzz target list drifting from its declaration. It audits the wrong one of the two lists — the advisory one.The three lists
fuzz/Cargo.toml— three[[bin]]declarations..github/workflows/fuzz-nightly.yml—matrix.include, audited bycheck_fuzz_targets.py:196(its default--workflow). Not a required context — its job name is templated (Fuzz ${{ matrix.target }} (1h)), which bycheck_required_contexts.py's own rules means it can never be one..github/workflows/ci.yml:419-424— jobFuzz smoke (60s/target), which hand-writes the same three targets as three separaterun:steps. This one IS a required context. Nothing compares it to anything.So the covered list is advisory and the uncovered list blocks merges. Add a fourth harness to
fuzz/Cargo.tomlplus a fourth nightly matrix entry, andcheck_fuzz_targets.pycorrectly reportsAll 4 declared fuzz targets are run— whileFuzz smokekeeps fuzzing 3 of 4, green, forever.Today the three lists happen to agree (
fuzz_aadl_parse,fuzz_scheduler_solver,fuzz_codegen_roundtrip), so this is latent, live on the next edit.Note for whoever fixes it
Pointing the existing tool at
ci.ymldoes not work._MATRIX_TARGET(check_fuzz_targets.py:65) is^\s*-\s+target:\s*(\S+)\s*$;fuzz-smoke's targets sit insidecargo +nightly fuzz run ... <name>within- name:steps. Executed:The broken-scan guard fires correctly, which is the tool behaving well — it needs a second extractor, not a second
--workflowvalue.Also worth noting: set equality over declarations proves declaration parity, not execution. A leg carrying
continue-on-error: trueorif: falsestill counts as "run".Wording
REQ-GUARD-GATE-EVIDENCE-002 obligation (h) says the nightly "names its three targets in three hand-written steps" — which literally describes
fuzz-smoke, not the nightly'smatrix.include. And obligation (g), two paragraphs earlier in the same requirement, establishes "for every tool, not one". So either the fix coversfuzz-smoke, or (h) should be amended to state explicitly that a required context is left uncovered.Acceptance: adding a
[[bin]]tofuzz/Cargo.tomlwithout adding it toci.yml'sfuzz-smokejob must fail a gate.🤖 Generated with Claude Code