Repository navigation
ci(hypatia): retire the cured invalid_actions_lock ack (#963) - #1239
Conversation
The .hypatia-baseline.json entry for invalid_actions_lock (rule_module [workflow_audit, workflow_hardening], file_pattern `**actions.lock`, tracking #963, expires 2026-12-22) acknowledged asana/push-signed-commits@d615... declaring the floating transitive actions/setup-python@v2 in .github/workflows/actions.lock. Its exit criterion "we replace the action" is met: - #1233 replaced the Asana action in .github/actions/signed-push/ with push-verified.sh. - #1238 removed both the asana/push-signed-commits and actions/setup-python@v2 records from actions.lock. Every lock key and every nested `uses:` ref is now a 40-hex SHA. Evidence the rule no longer fires: the Hypatia scan on main at 7d2041a (run 38484072239, scanner 51ab6496) reports 59 findings, none of type invalid_actions_lock and none naming actions.lock. findings_kept is empty, and the ack matched nothing in findings_suppressed. While it stood, `**actions.lock` would have muted ANY new invalid_actions_lock in the repo until 2026-12-22. Removing it shrinks the ledger, which check-exemption-ratchet.sh permits. No other entry changes. scripts/tests/apply-baseline-test.sh pinned the shipped ledger to hold exactly one such ack, so that section is inverted. It now asserts the ledger holds none and that both emission paths (workflow_audit `actions.lock`, workflow_hardening `.github/workflows/actions.lock`) reach the gate. The fixture-based list-valued rule_module tests are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbbnKqskQA5mj5gfMniPzi
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📜 Recent review details
📝 Summary
Merge Risk: ⚪ Minimal · up to
|
K9 contract conformancerun https://github.com/hyperpolymath/standards/actions/runs/38493064951 K9 normative contract typecheckK9 contract self-testK9 conformance fixturesK9 corpus conformance (L2) |
|
|
❌ Failed to create Coding Agent finishing-touch task. Please try again. |
…1305) ## Summary Follow-up to #1239. SonarCloud's quality gate passed on #1239 but reported **1 new issue**. The session that wrote #1239 could not open the finding, because its proxy blocks sonarcloud.io. The only conditional #1239 added is `if [ "$got" = "0" ]` in `scripts/tests/apply-baseline-test.sh`, the guard that keeps an `invalid_actions_lock` ack out of the shipped baseline. #1291 answered the same Sonar rule elsewhere in this repo with Bash `[[ ... ]]`, so this PR does the same to this one line: ```diff - if [ "$got" = "0" ]; then + if [[ "$got" == "0" ]]; then ``` The rest of the file is unchanged. ## Testing | Check | Result | |---|---| | `bash scripts/tests/apply-baseline-test.sh` | 52 passed, 0 failed | | Mutation: an `invalid_actions_lock` ack restored to a copy of `.hypatia-baseline.json` | 2 FAIL, exit 1. The guard still fails on its target. | | `.githooks/pre-commit` and `commit-msg` | passed, including gitleaks, SPDX and validate-actions-lock | **Unconfirmed:** I could not read the Sonar finding itself, so this PR's Sonar run is the confirmation. If Sonar still reports a new issue here, it was something else and I'll follow up. --- _Generated by [Claude Code](https://claude.ai/code/session_01TbbnKqskQA5mj5gfMniPzi)_ Co-authored-by: Claude <noreply@anthropic.com>
…eep it that way (#1304) ## Summary `.hypatia-baseline.json` was valid I-JSON but not JCS: it had 516 indented lines and unsorted member names. `3-practice/JSON-POLICY.adoc` §6 left this file undecided. On 2026-10-19 the owner ruled that it must be converted. This PR has two commits. ### 1. `chore(json): canonicalise .hypatia-baseline.json` - I ran `ijson-jcs fix` with the binary built from the commit CI pins (`0fdeea71`). The file is now one sorted line ending in LF, which satisfies `.editorconfig`. Its parsed value is unchanged: `jq` reads `$old == $new` as true. - No tool rewrites this file in this repo. People and agents edit it by hand or with `jq` in PRs. Every reader parses it with `jq`, so the single-line layout breaks no consumer: - `apply-baseline.sh` - `filter-sarif-by-baseline.sh` - `check-exemption-ratchet.sh` - the banned-language lookup in `governance-reusable.yml` - `tests/test_secret_scanner_no_inherit.sh` - Docs: - `JSON-POLICY.adoc` §6 records the ruling. - `HYPATIA-BASELINE-FORMAT.adoc` tells editors to run `ijson-jcs fix .hypatia-baseline.json` after an edit. It also says the indented example there is for reading only. ### 2. `ci(json): block drift on converted JSON` (separate commit, so it can be dropped) - Adds the job **"Converted JSON stays canonical"** to `ijson-jcs.yml`. It runs `check-ijson-jcs.sh --enforce .hypatia-baseline.json` and nothing else. The repo-wide scan stays report-only. - Why it's needed: the baseline is edited often (#1239 and #1244 last week). A plain `jq` edit writes it back indented, and the report-only scan would not fail on that. This follows the precedent of `package.json` in LANGUAGE-POLICY §1.4, where the conversion comes with a job that fails if someone forgets to re-canonicalise. - ⚠ This makes one file blocking. Per JSON-POLICY §3, making the gate blocking is an owner decision. If you only want the conversion, drop this commit. ## Testing - `check-ijson-jcs.sh --enforce .hypatia-baseline.json` exits 0 on this branch and 1 on `origin/main`'s copy. - `apply-baseline.sh` gives **byte-identical output** on the old and new files, in both `advisory` and `blocking` modes. The input had 62 matching findings plus one planted finding that should not match: 62 were suppressed and 1 was kept, in both. - `check-exemption-ratchet.sh origin/main` passes, with `.hypatia-baseline.json` unchanged at 62 entries. - These tests pass: | Test | Result | |---|---| | `exemption-ratchet-test` | 14/14 | | `apply-baseline-test` | 52/52 | | `check-ijson-jcs-test` | 31/31 | | `hypatia-blocking-gate-test` | pass | | `test_secret_scanner_no_inherit` | pass | - Workflow checks: `actionlint` 1.7.7 is clean. `validate-sha-pins`, `validate-actions-lock`, `check-lock-sync`, `check-workflow-duplicate-keys`, `validate-permissions` and the actions-lock gate all pass. The pre-commit and commit-msg hooks pass. - `validate-spdx-workflows` fails when run across the whole repo. The failure is on `9-archive/rhodium-standard-repositories/satellites/rsr-deployer/.github/workflows/jekyll-gh-pages.yml`, which this PR does not touch. The staged-file run in pre-commit passes. ## Trade-off Because the file is now one line, every future edit shows in a diff as a whole-line change. To review a change, run `jq . <file>` on both sides and compare those, or use `git diff --word-diff`. --- _Generated by [Claude Code](https://claude.ai/code/session_014h2gFLLQibfB5N5hFz9ZCD)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
… support) (#1315) ## Problem `governance / Validate Hypatia Baseline` is red on `main` (`b3ce78e`, run 39340237981) and on every open PR, including #1309, #1310 and #1311. The only blocking findings are: ``` invalid_actions_lock (workflow_audit, high): {:line, 4, {:unsupported_version, "v0.0.3"}} invalid_actions_lock (workflow_hardening, high): actions.lock failed closed: {:line, 4, {:unsupported_version, "v0.0.3"}} ``` The baseline job does not build Hypatia HEAD. Both `governance-reusable.yml` and `hypatia-scan-reusable.yml` default `hypatia-ref` to the vetted SHA `51ab6496…` (2026-10-01), and that commit's lockfile parser accepts only `v0.0.2`. `gh actions-lock` now writes `v0.0.3`. The lockfile is tool-owned, and this finding is deliberately not baselinable (#1239, #1305), so the scanner pin is what has to move. ## Change Both `hypatia-ref` defaults move from `51ab6496bf47e30a0576d503df31fec30f3cfe56` to `aa34a4cc6ba39d873710ff39763fdb9cde715f9d`. They move together, as their descriptions require. `aa34a4cc` is hypatia `main` after hyperpolymath/hypatia#938, which adds proper `v0.0.3` support, including the one field `v0.0.3` introduces (the optional per-dependency `hostname`). Unknown versions still fail closed. No `uses:` ref changes, so `actions.lock` is untouched. ## Blast radius (measured, not assumed) The bump carries every Hypatia commit since `51ab6496` (23 of them, including the `research_extensions` rules and hyperpolymath/hypatia#922's finding-shape change), and a pin move broke every caller once before (hyperpolymath/hypatia#895). So I replayed the `validate-hypatia-baseline` step locally at both pins on three repos: scan, path relativisation, then `apply-baseline.sh` with `BLOCKING_THRESHOLD=info`. | Repo | Kept at `51ab6496` | Kept at `aa34a4cc` | Change | |---|---|---|---| | standards (`d55304a`) | 2 × `invalid_actions_lock` | **0** | gate passes | | echidna | 2 × `invalid_actions_lock`, 1 `DependencyPinning` | same 3 | none* | | hypatia | 2 × `invalid_actions_lock` + 28 pre-existing (RE001/4/5, WH013) | the 28 | −2 | (The table leaves out `GS002`/`GS005`, which come from my detached local checkouts.) - On all three repos the raw findings only *lose* `invalid_actions_lock` and the derived `DependencyPinning`. There is no new finding type and no severity change. - All emitted severities stay inside `hypatia-scan-reusable.yml`'s accepted set. The new `support`/`evidence`/`level` finding fields are additive, and the only `.level` the reusable reads is the SARIF one. - \*echidna's lockfile now parses, but it has two real dangling edges (`slsa-framework/slsa-github-generator@f7dd8c54…` and `hyperpolymath/panic-attack@b689a74d…` are listed under `workflows:` with no top-level record, the startup-failure case `scripts/close-lock.sh` documents). That is an echidna repair, not something this PR changes. ## Checks run locally - `scripts/tests/governance-reusable-contract-test.sh`: PASS - `scripts/tests/hypatia-blocking-gate-test.sh`: PASS - `scripts/tests/apply-baseline-test.sh`: 52 passed, 0 failed - `scripts/tests/check-workflow-duplicate-keys-test.sh`: 17 passed, 0 failed with mikefarah yq v4.47.2 (checksum-verified). It fails 13/4 on `main` too when only the Python `yq` is on PATH. `scripts/check-workflow-duplicate-keys.sh` on both files: clean. - `actionlint` 1.7.7 on both files: output identical to `main`. - `yq '.on.workflow_call.inputs."hypatia-ref".default'` → `aa34a4cc…` in both files. ## After merge Open PRs (#1309, #1310, #1311) need `main` merged into them. Re-running their failed jobs won't help, because a re-run reuses the PR's old merge commit, which still carries `51ab6496`. --- _Generated by [Claude Code](https://claude.ai/code/session_01KUZiEB43T3E9fJAXqwbSDm)_ Co-authored-by: Claude <noreply@anthropic.com>



Closes #963.
Summary
Removes the
.hypatia-baseline.jsonacknowledgement forinvalid_actions_lock. The entry had:rule_module: ["workflow_audit", "workflow_hardening"]file_pattern: "**actions.lock"expires_at: 2026-12-22It acknowledged
asana/push-signed-commits@d615…, which declared the floating transitiveactions/setup-python@v2. One of its listed exit criteria was "we replace the action", and that is now met:.github/actions/signed-push/withpush-verified.sh.asana/push-signed-commitsand theactions/setup-python@v2records fromactions.lock.While the entry stood,
**actions.lockwould have muted any newinvalid_actions_lockfinding in the repo until 2026-12-22.Evidence the rule no longer fires on
mainThese are from the Hypatia scan on
mainat7d2041a(run 38484072239, scanner pinned at51ab6496):findings_keptis[].invalid_actions_lock. The two highs are WH013 andncl_k9_missing_pedigree.actions.lock, asana or setup-python anywhere in the log.The ack was matching nothing. Both lock checks from the task print nothing on this branch:
uses:grep.Changes
.hypatia-baseline.jsonscripts/tests/apply-baseline-test.shinvalid_actions_lockack and that both emission paths reach the gate (workflow_audit/actions.lockandworkflow_hardening/.github/workflows/actions.lock). The fixture-based tests for list-valuedrule_moduleare unchanged.docs/HYPATIA-BASELINE-FORMAT.adoc, the schema description and the comment inapply-baseline.shstill useinvalid_actions_lockas their example of one defect emitted by two modules. That describes how the scanner behaves, not a live ack, so they are left as they are.Testing
bash scripts/tests/exemption-ratchet-test.shbash scripts/tests/apply-baseline-test.shbash scripts/tests/hypatia-blocking-gate-test.shscripts/check-exemption-ratchet.sh origin/mainSHRANK .hypatia-baseline.json: 189 -> 188. OK, and noRatchet-exception:was needed.apply-baseline.shon[]in blocking modeapply-baseline.shwith bothinvalid_actions_lockemissions in blocking mode.githooks/pre-commitandcommit-msgThe Hypatia scanner itself was not run locally, because the container has no Elixir. This PR's own
scan / Hypatia Neurosymbolic Analysisrun is the live confirmation.Licence headers are untouched.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TbbnKqskQA5mj5gfMniPzi