From cfdddd91130056f0f5e320d8b9141ad0a7c911ba Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 02:27:32 +0000 Subject: [PATCH] fix(governance): let the baseline filter actually run (scan exit-on-findings) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #455. That PR wired apply-baseline.sh into validate-hypatia-baseline but missed that `hypatia-cli.sh scan .` exits non-zero *by design* whenever it finds anything — and the step runs under `bash -e`, so errexit aborted the step at the scan line, before the relativization + apply-baseline.sh (the real gate) ever ran. (This is also why the pre-#455 job was always red: its dead `jq` count never executed either.) Caught by verifying the fix end-to-end on neurophone#171, where the job died at "scan complete: N findings; exit 1" with no filter output. Fix: tolerate the scan's own exit code (`|| true`) so the filter runs and gates instead — but guard against a genuine scanner crash being swallowed into a false pass by requiring the scan output to be a valid JSON array first (fail loudly if not; no silent-green). Both behaviours simulated locally under `bash -e`. Note (separate, repo-side): a newer hypatia HEAD now reports more findings than when a given repo's .hypatia-baseline.json was written, so a caller may still see its gate stay red on genuinely-new findings after this lands — that is the filter working correctly, and is resolved per-repo by extending the baseline (or fixing at source), not here. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh --- .github/workflows/governance-reusable.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/governance-reusable.yml b/.github/workflows/governance-reusable.yml index a8f2402f..b2047c91 100644 --- a/.github/workflows/governance-reusable.yml +++ b/.github/workflows/governance-reusable.yml @@ -128,7 +128,17 @@ jobs: BLOCKING_THRESHOLD: info run: | echo "Scanning repository: ${{ github.repository }} (checking baseline)" - HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.raw.json + # hypatia's `scan` exits non-zero whenever it finds anything — that is + # by design, and under `bash -e` it would abort this step at this line, + # before the baseline filter (the real gate) ever runs. Tolerate the + # scan's own exit code… + HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.raw.json || true + # …but never swallow a genuine scanner crash into a false pass: require a + # valid JSON array before trusting the output as "the findings". + if ! jq -e 'type == "array"' hypatia-findings.raw.json >/dev/null 2>&1; then + echo "::error::hypatia scan did not produce a valid JSON findings array (scanner error, not a baseline result)" + exit 1 + fi # Relativize finding paths before matching. Hypatia's honest_completion # and code_safety modules emit ABSOLUTE host paths in `.file`