Skip to content

ci(lock): drop orphan asana/setup-python records from actions.lock - #1238

Merged
hyperpolymath merged 2 commits into
mainfrom
claude/gallant-euler-yinsyw
Oct 13, 2026
Merged

hyperpolymath merged 2 commits into
mainfrom
claude/gallant-euler-yinsyw

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

#1233 already did the first half of this job. In .github/actions/signed-push/action.yml, the "Push local commits as Verified" step now runs push-verified.sh, a bash script beside the action. It uses gh and jq, the App installation token from steps.app-token, and createCommitOnBranch with expectedHeadOid, so if the remote head moves the push fails closed. The inputs did not change: app-id, private-key, branch. The action has no outputs. It never had any.

#1233 left the lock records in place on purpose. This PR removes them. Nothing references either one any more:

Record removed from dependencies: Why it was safe to remove
asana/push-signed-commits@d615ca88… (ref v1.3) No uses: anywhere names it, and neither does any workflows: list.
actions/setup-python@v2 Its only reference was the Asana record's nested uses:. It was also the only key in the lock that is not a SHA.

The diff deletes 12 lines and changes nothing else.

How the records were removed

The repo's lock tooling cannot do this:

So I removed the two dependencies: blocks with a gawk filter that only touches that section. Afterwards prune-stale.sh was a no-op, and close-lock.sh found 0 dangling refs and left the file alone.

Testing

All lock gates were run before and after the deletion, with the pinned tool versions:

Gate Result
scripts/check-lock-sync.sh in sync
.githooks/validate-actions-lock.sh 25 refs found among 27 lock keys (was 28)
scripts/check-actions-lock-gate.sh (gh-actions-lock v0.1.6, the version CI pins) "Immutable direct and transitive lockfile coverage verified"
scripts/prune-stale.sh no-op
scripts/close-lock.sh 0 dangling refs
scripts/lock-selfcheck.sh HEAD SELF-CONSISTENT

Script tests that touch this action or the lock all pass:

Test Result
validate-sha-pins-test 22/22
signed-push-test 13/13
check-actions-lock-gate-test 23/23
validate-actions-lock-test 5/5
check-lock-sync-test 10/10
prune-stale-test 15/15
close-lock-test 9/9
lock-selfcheck-test 5/5
regen-dependabot-locks-test 34/34
update-actions-lock-test 15/15
kyaml-format-test 17/17

The full run-shell-test-suite.sh passed 79 of 81 files. The other two fail the same way on main in this container because tools are missing:

  • check-ijson-jcs-test needs the ijson-jcs binary.
  • science-ci-security-test needs ssh-keygen.

Neither test reads actions.lock.

The pre-commit hook passed in full (gitleaks included), and the commit-msg hook passed.

signed-push-smoke.yml was not run. It is dispatch-only and needs APP_ID/APP_PRIVATE_KEY, which config/README.adoc says this repo does not hold yet.

Follow-up, not done here (outside this PR's scope)

🤖 Generated with Claude Code

https://claude.ai/code/session_014h2gFLLQibfB5N5hFz9ZCD


Generated by Claude Code

signed-push stopped calling Asana/push-signed-commits in #1233, which
replaced it with push-verified.sh (bash, gh, jq). Two records it brought
into actions.lock were left behind and nothing references them now:

- Asana/push-signed-commits@d615ca8
- actions/setup-python@v2, its only transitive edge. This was the only
  non-SHA key in the lock.

No workflows: list and no nested uses: names either ref. The lock tools
cannot remove them: prune-stale.sh works only on the workflows: section,
and close-lock.sh only adds records. So the two dependencies: blocks were
deleted with a gawk filter that only touches that section. Nothing else
in the lock changed.

Checks, run before and after the deletion:
- check-lock-sync: in sync.
- validate-actions-lock: 25 refs, 27 keys (was 28).
- check-actions-lock-gate with gh-actions-lock v0.1.6: coverage verified.
- prune-stale: no-op.
- close-lock: 0 dangling refs.

Refs #1122.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014h2gFLLQibfB5N5hFz9ZCD
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

K9 contract conformance

run https://github.com/hyperpolymath/standards/actions/runs/38483762373

K9 normative contract typecheck

k9_contract.ncl typechecks

K9 contract self-test

== the bash mirrors cannot drift from the normative contract ==
ok   leash_levels mirrors k9_contract.ncl
ok   core_capabilities mirrors k9_contract.ncl
ok   contract_version mirrors k9_contract.ncl
ok   schema_major mirrors k9_contract.ncl
== capability arithmetic (§8) ==
ok   capability_ok fs.read accepted
ok   capability_ok rollback.apply accepted
ok   capability_ok x-acme.gpu.alloc accepted
ok   capability_ok x-acme rejected
ok   capability_ok x-.gpu rejected
ok   capability_ok fs.delete rejected
ok   capability_ok  rejected
== the extractor ==
ok   extracts pedigree.security.leash
ok   extracts pedigree.component_type
ok   extracts pedigree.metadata.name
ok   pedigree leash is not reported as top-level leash
ok   required_capabilities for a quiet component
ok   required_capabilities follows allow_network
== the envelope strip keeps line numbers (§3.6) ==
ok   line 1 becomes a comment
ok   line count is preserved
ok   schema_version stays on line 5
== L3: signature presence is not verification (§10) ==
ok   no verifier -> K9-C001 is SKIPPED, never a pass
ok   the skip states presence does not authorise 'Hunt
ok   verifier accepts -> verdict 'Verified, no K9-C001 finding
ok   verifier refuses -> K9-C001 error, verdict 'Rejected
== the fixture runner's attribution cannot be fooled by a filename ==
ok   every extracted finding is well-formed rule+layer
ok   the rule that really fired is attributed
ok   a rule named only in the filename is NOT attributed
ok   K9-C001 is present as a skipped finding
ok   and that same finding is NOT extractable as a rejection
== the dialect discriminator agrees with the coordination grammar (§4.3) ==
ok   magic file opening '---' is coordination
ok   magic file opening 'metadata:' is coordination
ok   plain file opening '---' is unclaimed
ok   plain file opening 'metadata:' is unclaimed
== no Nickel reserved word is used as an identifier ==
ok   the contract and all 27 fixtures avoid Nickel's reserved words

self-test: all assertions passed

K9 conformance fixtures

== positive controls (must pass) ==
ok   extension-capability.k9.ncl
ok   extension-fields.k9.ncl
ok   hunt-fully-granted.k9.ncl
ok   kennel-data.k9.ncl
ok   library-base.ncl
ok   yard-typed-config.k9.ncl

== negative controls (must fail, by the named rule) ==
ok   L0-K9-E001-bad-magic.k9.ncl (rejected by K9-E001 at L0)
ok   L0-K9-E002-nul-byte.k9.ncl (rejected by K9-E002 at L0)
ok   L0-K9-E003-crlf.k9.ncl (rejected by K9-E003 at L0)
ok   L0-K9-E004-no-spdx.k9.ncl (rejected by K9-E004 at L0)
ok   L0-K9-E005-unclaimed-body.k9.ncl (rejected by K9-E005 at L0)
ok   L0-K9-S012-library-with-pedigree.ncl (rejected by K9-S012 at L0)
ok   L0-K9-S014-stray-leash.ncl (rejected by K9-S014 at L0)
ok   L1-K9-S001-no-pedigree.k9.ncl (rejected by K9-S001 at L1)
ok   L1-K9-S002-wrong-major.k9.ncl (rejected by K9-S002 at L1)
ok   L1-K9-S003-todo-component-type.k9.ncl (rejected by K9-S003 at L1)
ok   L1-K9-S004-unknown-leash.k9.ncl (rejected by K9-S004 at L1)
ok   L1-K9-S005-missing-name.k9.ncl (rejected by K9-S005 at L1)
ok   L1-K9-S006-unknown-capability.k9.ncl (rejected by K9-S006 at L1)
ok   L1-K9-S007-ungranted-flag.k9.ncl (rejected by K9-S007 at L1)
ok   L1-K9-S008-hunt-signature-not-required.k9.ncl (rejected by K9-S008 at L1)
ok   L1-K9-S009-hunt-no-signature-block.k9.ncl (rejected by K9-S009 at L1)
ok   L1-K9-S010-hunt-empty-side-effects.k9.ncl (rejected by K9-S010 at L1)
ok   L1-K9-S011-recipes-at-yard.k9.ncl (rejected by K9-S011 at L1)
ok   L1-K9-S013-dangling-import.k9.ncl (rejected by K9-S013 at L1)
ok   L2-K9-N001-two-segment-version.k9.ncl (rejected by K9-N001 at L2)
ok   L2-K9-N001-wrong-field-type.k9.ncl (rejected by K9-N001 at L2)

fixtures: 6 positive, 21 negative (0 needing nickel), 0 failure(s)

K9 corpus conformance (L2)

[validate-k9] 14 conforming, 0 grandfathered (layer all, contract v1.0.0)

@hyperpolymath
hyperpolymath marked this pull request as ready for review October 13, 2026 23:24
@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 13, 2026 23:24
@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 13, 2026 23:24
@github-actions

Copy link
Copy Markdown
Contributor

K9 contract conformance

run https://github.com/hyperpolymath/standards/actions/runs/38484021187

K9 normative contract typecheck

k9_contract.ncl typechecks

K9 contract self-test

== the bash mirrors cannot drift from the normative contract ==
ok   leash_levels mirrors k9_contract.ncl
ok   core_capabilities mirrors k9_contract.ncl
ok   contract_version mirrors k9_contract.ncl
ok   schema_major mirrors k9_contract.ncl
== capability arithmetic (§8) ==
ok   capability_ok fs.read accepted
ok   capability_ok rollback.apply accepted
ok   capability_ok x-acme.gpu.alloc accepted
ok   capability_ok x-acme rejected
ok   capability_ok x-.gpu rejected
ok   capability_ok fs.delete rejected
ok   capability_ok  rejected
== the extractor ==
ok   extracts pedigree.security.leash
ok   extracts pedigree.component_type
ok   extracts pedigree.metadata.name
ok   pedigree leash is not reported as top-level leash
ok   required_capabilities for a quiet component
ok   required_capabilities follows allow_network
== the envelope strip keeps line numbers (§3.6) ==
ok   line 1 becomes a comment
ok   line count is preserved
ok   schema_version stays on line 5
== L3: signature presence is not verification (§10) ==
ok   no verifier -> K9-C001 is SKIPPED, never a pass
ok   the skip states presence does not authorise 'Hunt
ok   verifier accepts -> verdict 'Verified, no K9-C001 finding
ok   verifier refuses -> K9-C001 error, verdict 'Rejected
== the fixture runner's attribution cannot be fooled by a filename ==
ok   every extracted finding is well-formed rule+layer
ok   the rule that really fired is attributed
ok   a rule named only in the filename is NOT attributed
ok   K9-C001 is present as a skipped finding
ok   and that same finding is NOT extractable as a rejection
== the dialect discriminator agrees with the coordination grammar (§4.3) ==
ok   magic file opening '---' is coordination
ok   magic file opening 'metadata:' is coordination
ok   plain file opening '---' is unclaimed
ok   plain file opening 'metadata:' is unclaimed
== no Nickel reserved word is used as an identifier ==
ok   the contract and all 27 fixtures avoid Nickel's reserved words

self-test: all assertions passed

K9 conformance fixtures

== positive controls (must pass) ==
ok   extension-capability.k9.ncl
ok   extension-fields.k9.ncl
ok   hunt-fully-granted.k9.ncl
ok   kennel-data.k9.ncl
ok   library-base.ncl
ok   yard-typed-config.k9.ncl

== negative controls (must fail, by the named rule) ==
ok   L0-K9-E001-bad-magic.k9.ncl (rejected by K9-E001 at L0)
ok   L0-K9-E002-nul-byte.k9.ncl (rejected by K9-E002 at L0)
ok   L0-K9-E003-crlf.k9.ncl (rejected by K9-E003 at L0)
ok   L0-K9-E004-no-spdx.k9.ncl (rejected by K9-E004 at L0)
ok   L0-K9-E005-unclaimed-body.k9.ncl (rejected by K9-E005 at L0)
ok   L0-K9-S012-library-with-pedigree.ncl (rejected by K9-S012 at L0)
ok   L0-K9-S014-stray-leash.ncl (rejected by K9-S014 at L0)
ok   L1-K9-S001-no-pedigree.k9.ncl (rejected by K9-S001 at L1)
ok   L1-K9-S002-wrong-major.k9.ncl (rejected by K9-S002 at L1)
ok   L1-K9-S003-todo-component-type.k9.ncl (rejected by K9-S003 at L1)
ok   L1-K9-S004-unknown-leash.k9.ncl (rejected by K9-S004 at L1)
ok   L1-K9-S005-missing-name.k9.ncl (rejected by K9-S005 at L1)
ok   L1-K9-S006-unknown-capability.k9.ncl (rejected by K9-S006 at L1)
ok   L1-K9-S007-ungranted-flag.k9.ncl (rejected by K9-S007 at L1)
ok   L1-K9-S008-hunt-signature-not-required.k9.ncl (rejected by K9-S008 at L1)
ok   L1-K9-S009-hunt-no-signature-block.k9.ncl (rejected by K9-S009 at L1)
ok   L1-K9-S010-hunt-empty-side-effects.k9.ncl (rejected by K9-S010 at L1)
ok   L1-K9-S011-recipes-at-yard.k9.ncl (rejected by K9-S011 at L1)
ok   L1-K9-S013-dangling-import.k9.ncl (rejected by K9-S013 at L1)
ok   L2-K9-N001-two-segment-version.k9.ncl (rejected by K9-N001 at L2)
ok   L2-K9-N001-wrong-field-type.k9.ncl (rejected by K9-N001 at L2)

fixtures: 6 positive, 21 negative (0 needing nickel), 0 failure(s)

K9 corpus conformance (L2)

[validate-k9] 14 conforming, 0 grandfathered (layer all, contract v1.0.0)

@hyperpolymath
hyperpolymath merged commit 7d2041a into main Oct 13, 2026
61 of 62 checks passed
@hyperpolymath
hyperpolymath deleted the claude/gallant-euler-yinsyw branch October 13, 2026 23:24
@sonarqubecloud

Copy link
Copy Markdown

hyperpolymath added a commit that referenced this pull request Oct 14, 2026
Closes #963.

## Summary

Removes the `.hypatia-baseline.json` acknowledgement for
`invalid_actions_lock`. The entry had:
- `rule_module: ["workflow_audit", "workflow_hardening"]`
- `file_pattern: "**actions.lock"`
- tracking issue #963
- `expires_at: 2026-12-22`

It acknowledged `asana/push-signed-commits@d615…`, which declared the
floating transitive `actions/setup-python@v2`. One of its listed exit
criteria was "we replace the action", and that is now met:
- #1233 replaced the Asana action in `.github/actions/signed-push/` with
`push-verified.sh`.
- #1238 deleted both the `asana/push-signed-commits` and the
`actions/setup-python@v2` records from `actions.lock`.

While the entry stood, `**actions.lock` would have muted **any** new
`invalid_actions_lock` finding in the repo until 2026-12-22.

## Evidence the rule no longer fires on `main`

These are from the Hypatia scan on `main` at `7d2041a` ([run
38484072239](https://github.com/hyperpolymath/standards/actions/runs/38484072239),
scanner pinned at `51ab6496`):
- The scan reported 59 findings: critical=2, high=2, medium=34, warn=21.
- `findings_kept` is `[]`.
- None of the 59 suppressed findings has type `invalid_actions_lock`.
The two highs are WH013 and `ncl_k9_missing_pedigree`.
- No finding names `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:
- the non-SHA key grep;
- the non-SHA nested `uses:` grep.

## Changes

| File | Change |
|---|---|
| `.hypatia-baseline.json` | One entry deleted, 12 lines. jq confirms
the result equals the original with only that entry removed. No other
entry changes. |
| `scripts/tests/apply-baseline-test.sh` | The "SHIPPED ledger" section
asserted that the real baseline holds **exactly one** such ack and
suppresses both emission paths, so it would go red on this removal. It
is inverted: it now asserts the ledger holds **no**
`invalid_actions_lock` ack and that both emission paths **reach the
gate** (`workflow_audit`/`actions.lock` and
`workflow_hardening`/`.github/workflows/actions.lock`). The
fixture-based tests for list-valued `rule_module` are unchanged. |

`docs/HYPATIA-BASELINE-FORMAT.adoc`, the schema description and the
comment in `apply-baseline.sh` still use `invalid_actions_lock` as 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

| Check | Result |
|---|---|
| `bash scripts/tests/exemption-ratchet-test.sh` | 14 passed, 0 failed |
| `bash scripts/tests/apply-baseline-test.sh` | 32 passed, 0 failed |
| `bash scripts/tests/hypatia-blocking-gate-test.sh` | exit 0 |
| `scripts/check-exemption-ratchet.sh origin/main` | `SHRANK
.hypatia-baseline.json: 189 -> 188`. OK, and no `Ratchet-exception:` was
needed. |
| `apply-baseline.sh` on `[]` in blocking mode | schema-valid, exit 0 |
| `apply-baseline.sh` with both `invalid_actions_lock` emissions in
blocking mode | kept=2, suppressed=0, **exit 1**. A recurrence now
blocks. |
| `.githooks/pre-commit` and `commit-msg` | passed. Included gitleaks
8.28.0, validate-actions-lock and validate-sha-pins, using
checksum-verified gitleaks and mikefarah yq v4.47.1. |

The Hypatia scanner itself was **not** run locally, because the
container has no Elixir. This PR's own `scan / Hypatia Neurosymbolic
Analysis` run is the live confirmation.

Licence headers are untouched.

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

https://claude.ai/code/session_01TbbnKqskQA5mj5gfMniPzi

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