Skip to content

fix(governance): let the hypatia baseline filter actually run (scan exit-on-findings under bash -e)#464

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/neurophone-repo-setup-envzix
Jul 3, 2026
Merged

fix(governance): let the hypatia baseline filter actually run (scan exit-on-findings under bash -e)#464
hyperpolymath merged 1 commit into
mainfrom
claude/neurophone-repo-setup-envzix

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Follow-up to #455. That PR wired apply-baseline.sh into validate-hypatia-baseline, but the fix never actually ran: 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) could run.

This is also why the pre-#455 job was always red on every repo with findings: its dead jq count never executed either. The scan's exit-1 killed the step every time.

Caught by verifying end-to-end on neurophone#171, where the job died at:

[hypatia] scan complete: 18 findings >= medium (critical=3, high=9, medium=6); exit 1
##[error]Process completed with exit code 1.

…with no apply-baseline.sh output at all.

The fix

HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.raw.json || true
# never swallow a genuine scanner crash into a false pass:
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
  • || true — tolerate the scan's by-design exit-on-findings so the baseline filter runs and becomes the gate.
  • JSON-array guard — a genuine scanner crash (non-array / empty output) still fails loudly, so tolerating the exit code can't produce a silent-green.

Both behaviours simulated locally under bash -e:

sim 1 (scan exits 1, valid output)  -> REACHED-FILTER   rc=0   ✓
sim 2 (scanner crash, non-array)    -> GUARD-FAIL        rc=1   ✓ (no silent-green)

Heads-up for callers (separate, repo-side)

A newer hypatia HEAD reports more findings than when a repo's .hypatia-baseline.json was written (neurophone: 18 now vs 14 when its baseline was authored in #168). So after this lands, a caller may still see its gate stay red on genuinely-new findings — that is the filter working correctly. Resolution is per-repo: extend the baseline (or fix at source), not here.

Draft pending CI + your review (edits the shared security gate). Same opt-in-via-SHA-pin safety as #455.

🤖 Generated with Claude Code

https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh


Generated by Claude Code

…indings)

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh
@sonarqubecloud

sonarqubecloud Bot commented Jul 3, 2026

Copy link
Copy Markdown

@hyperpolymath hyperpolymath marked this pull request as ready for review July 3, 2026 02:36
@hyperpolymath hyperpolymath merged commit f81bb04 into main Jul 3, 2026
20 checks passed
@hyperpolymath hyperpolymath deleted the claude/neurophone-repo-setup-envzix branch July 3, 2026 02:37
hyperpolymath added a commit that referenced this pull request Jul 3, 2026
…checkout tooling) (#466)

## Summary

Third and final piece of the `validate-hypatia-baseline` fix (after #455
wired the filter and #464 made it run). The gate checks out standards'
`scripts/` into `.standards-checkout/` to get `apply-baseline.sh` — but
that directory sits **inside the caller's working tree**, so
`hypatia-cli.sh scan .` scanned it too and reported **standards' own
files as the caller's findings**.

Caught on neurophone#172, where 4 of the 8 "unfiltered" findings were
pure tooling pollution:
```
.standards-checkout/scripts/check-ts-allowlist.ts                      banned_language (critical)
.standards-checkout/neurosym-a2ml/scripts/bootstrap.sh                 shell_download  (high)
.standards-checkout/agentic-a2ml/scripts/bootstrap.sh                  shell_download  (high)
.standards-checkout/.../rsr-deployer/scripts/bootstrap.sh              shell_download  (high)
```
None is the caller's code. **Every** adopting repo would inherit these.

## The fix

```bash
cp .standards-checkout/scripts/apply-baseline.sh "$RUNNER_TEMP/apply-baseline.sh"
rm -rf .standards-checkout          # <- before the scan
HYPATIA_FORMAT=json … scan . …      # now only sees the caller's own tree
…
bash "$RUNNER_TEMP/apply-baseline.sh" …
```

Copy the filter out to `$RUNNER_TEMP` (outside the workspace), delete
`.standards-checkout/`, then scan. hypatia only ever sees the repo under
audit; the tooling can't pollute the finding set.

## Net effect

With **#455** (baseline actually consulted) + **#464** (filter actually
runs) + **this** (clean scan tree), the estate gate finally behaves as
intended: suppress a repo's acknowledged baseline entries, fail on
genuinely-new findings, and never conflate the tooling with the repo.
Opt-in per repo via SHA-pin as before.

Draft pending CI + your review. (As with #455/#464, this job **skips**
on standards' own CI — no baseline here — so it was reasoned through
against neurophone#172's real output.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh

---
_Generated by [Claude
Code](https://claude.ai/code/session_0172RBMz3qYjb1ttzD2i7RNh)_

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants