Skip to content

fix(governance-reusable): pin standards self-checkout to main (workflow_sha was caller-SHA)#219

Merged
hyperpolymath merged 1 commit into
mainfrom
fix/governance-reusable-workflow-sha-bug
May 27, 2026
Merged

fix(governance-reusable): pin standards self-checkout to main (workflow_sha was caller-SHA)#219
hyperpolymath merged 1 commit into
mainfrom
fix/governance-reusable-workflow-sha-bug

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

  • governance-reusable.yml:155 used ref: ${{ github.workflow_sha }} for the inner actions/checkout of hyperpolymath/standards into .standards-checkout/.
  • In a reusable workflow, github.workflow_sha resolves to the caller repo's commit SHA, not the SHA of the reusable workflow file in this repo. The fetch therefore asks the standards repo for a SHA that lives in the caller — exit code 128 after three retries.
  • Net effect: governance / Language / package anti-pattern policy (and any other job in the same workflow that depends on .standards-checkout/) fails on every governance run across the estate.
  • Pin ref: main instead. Caller repos already pin the reusable's YAML by SHA, so script-version drift is bounded to standards/main between the YAML pin and the script pin — acceptable because these scripts are read-only governance checks and standards/main is protected.

Evidence

From gossamer#59 governance run (https://github.com/hyperpolymath/gossamer/actions/runs/26459402802):

[command]/usr/bin/git -c protocol.version=2 fetch ... origin 67241f8b650db4feb70b5f2d23342c20bae4b0c4
The process '/usr/bin/git' failed with exit code 128
Waiting 10 seconds before trying again
... (×3) ...
  • gh api repos/hyperpolymath/standards/commits/67241f8b6...422 No commit found for SHA.
  • gh api repos/hyperpolymath/gossamer/commits/67241f8b6... → exists; it is the PR-merge commit for gossamer#59 (Merge 5b35d61f... into dd3a50a...).

This is exactly the symptom the estate has been observing as "Governance / governance / Language / package anti-pattern policy — Failing after 40s" across every open PR.

Why this is the right fix

  • The original intent (per the comment block) was "use the same SHA actually loaded for the reusable", but Actions doesn't surface that to a reusable workflow — github.workflow_sha is documented as the trigger commit of the caller, and no github.action_* context applies to reusable workflows.
  • Passing inputs.standards_ref was considered but rejected: every wrapper across the estate would need to thread it through, and the default would be main anyway.
  • main is protected and rebases are not part of normal flow here, so the failure mode "standards/main is gone" is not realistic.

Test plan

  • CI on this PR exercises the same job and should now pass.
  • After merge, retry a representative stuck PR (gossamer#56) and confirm governance / Language / package anti-pattern policy resolves to SUCCESS.
  • Hypatia detection rules to flag this anti-pattern (reusable workflow using github.workflow_sha as ref: for actions/checkout of a non-caller repo) will follow in a separate PR.

Related

  • Cascades into ~hundreds of stuck PRs across the estate (CHANGELOG seeding, scorecard wrappers, etc.). Once this lands, the queue drains.
  • Separately: at least one repo (.git-private-farm) also has a GitHub Actions spending-limit block that owner needs to clear in Settings → Billing & plans — out of scope for this PR.

🤖 Generated with Claude Code

…ow_sha resolves to caller, not standards)

The `Check out standards repo for shared scripts` step in governance-reusable.yml
used `ref: ${{ github.workflow_sha }}`, on the (incorrect) assumption that
`github.workflow_sha` would resolve to the SHA of the reusable workflow YAML
itself. In a reusable-workflow context it actually resolves to the *caller
repo's* commit SHA — so every governance run was issuing:

  git fetch origin <caller-SHA>

inside a clone of hyperpolymath/standards, where that SHA does not exist.
After three retries the checkout fails with exit code 128, and downstream
governance jobs (Language / package anti-pattern policy, etc.) never run.

Symptom across the estate: gossamer#59 governance / Language / package anti-pattern
policy "Failing after ~40s" on every PR, with the underlying log line:

  The process '/usr/bin/git' failed with exit code 128

verified for SHA 67241f8b650db4feb70b5f2d23342c20bae4b0c4 (a gossamer PR-merge
commit, not present in standards). Probing the same SHA in standards directly:

  $ gh api repos/hyperpolymath/standards/commits/67241f8b6...
  No commit found for SHA (HTTP 422)

Fix: pin `ref: main`. Caller repos already pin the reusable workflow YAML by
SHA, so script-version drift is bounded to "whatever's on standards/main when
the reusable resolves" — acceptable since these are read-only governance
checks and standards/main is protected.

Refs: hypatia rule-additions will follow in a separate PR so this can land fast.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 123 issues detected

Severity Count
🔴 Critical 65
🟠 High 48
🟡 Medium 10

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/changelog-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "changelog-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/deno-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "deno-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/elixir-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "elixir-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/elixir-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "elixir-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "rust-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "rust-ci-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Python file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit ad366b6 into main May 27, 2026
18 checks passed
@hyperpolymath hyperpolymath deleted the fix/governance-reusable-workflow-sha-bug branch May 27, 2026 05:13
hyperpolymath added a commit to hyperpolymath/absolute-zero that referenced this pull request May 27, 2026
## Root cause

`.github/workflows/governance.yml:34` pins
`governance-reusable.yml@3ec2e85` (2026-05-25) — predates
[standards#219](hyperpolymath/standards#219)
(`ad366b6`, 2026-05-27) which fixes `workflow_sha` resolution. Without
this fix, `governance / Language / package anti-pattern policy` fails
with exit 128 on the inner self-checkout.

## Pins changed

| File | Before | After |
|---|---|---|
| `.github/workflows/governance.yml:34` | `3ec2e85` (pre-#219) |
`5eb28d7` (standards/main, post-#219) |
| `.github/workflows/hypatia-scan.yml:28` | `97df762` (orphan PR-branch
SHA) | `5eb28d7` (canonical main; file unchanged since #193) |

## Auto-merge

SQUASH.

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/hypatia that referenced this pull request May 27, 2026
## Root-cause summary

`governance / Language / package anti-pattern policy` has been failing
on hypatia/main (and on every open PR) because:

- `.github/workflows/governance.yml:34` pinned
`governance-reusable.yml@66271d3` (2026-05-22) — predates
[hyperpolymath/standards#219](hyperpolymath/standards#219)
(merged `ad366b6`, 2026-05-27).
- standards#219 fixes a `workflow_sha` resolution bug: in a reusable
workflow, `github.workflow_sha` resolves to the **caller's** SHA, not
the reusable's SHA. The inner self-checkout of `hyperpolymath/standards`
therefore asked the standards repo for a SHA that only exists in hypatia
→ `exit 128` after 3 retries.

This PR bumps both standards-reusable pins past that fix.

## Pins changed

| File | Before | After |
|---|---|---|
| `.github/workflows/governance.yml:34` | `66271d3...` (2026-05-22) |
`5eb28d7d8790d5389b7b6a5233fe6265a775e3d0` (standards/main, 2026-05-27)
|
| `.github/workflows/hypatia-scan.yml:28` | `97df762...` (orphan SHA on
PR-branch for #193) | `5eb28d7d8790d5389b7b6a5233fe6265a775e3d0`
(canonical main) |

## Delta picked up (governance side)

7 commits, all fixes / hardening:

- `ad366b6` `fix(governance-reusable): pin standards self-checkout to
main` (#219) **— the load-bearing fix**
- `481c496` `feat(governance): add check-trusted-base CI enforcement`
(#211)
- `0ec0b83` `fix(governance): eradicate inline Python from
governance-reusable.yml` (#189)
- `3285ac1` `fix(baseline): file_pattern glob matching + jq scoping
bugs` (#180)
- `431adbb` `refactor(governance): subsume language-policy.yml + add
deno-ci-reusable` (#168)
- `91d8b88` `feat: consume .hypatia-baseline.json in governance gate`
(#166)
- `43b6563` `fix: checkout caller's repo in governance-reusable
workflow`

Delta on hypatia-scan side: **none** (reusable file unchanged since #193
squash-merge).

## Estate implication

This same stale-pin pattern affects every repo whose `governance.yml`
wrapper points to a pre-`ad366b6` SHA of `governance-reusable.yml`. An
estate-wide fan-out bump-PR sweep is the comprehensive remedy (cf.
session memory on the doomed-CI pilot). This PR is the per-repo first
cut for hypatia.

## Auto-merge

SQUASH (per estate policy).

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/echidna that referenced this pull request May 27, 2026
## Root cause

`.github/workflows/governance.yml:34` pins
`governance-reusable.yml@128a854` (2026-05-20) — predates
[standards#219](hyperpolymath/standards#219)
(`ad366b6`, 2026-05-27) which fixes `workflow_sha` resolution. Without
this fix, `governance / Language / package anti-pattern policy` fails
with exit 128 on the inner self-checkout.

## Pin changed

| File | Before | After |
|---|---|---|
| `.github/workflows/governance.yml:34` | `128a854` (pre-#219) |
`5eb28d7` (standards/main, post-#219) |

## Auto-merge

SQUASH.

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/hypatia that referenced this pull request May 27, 2026
…ti-pattern (#348)

## Summary

Two specific, sensitive checks in \`Hypatia.Rules.WorkflowAudit\`:

| Rule | When it fires | Severity |
|---|---|---|
| \`:workflow_sha_as_foreign_ref\` | \`actions/checkout\` uses \`ref:
\${{ github.workflow_sha }}\` against a \`repository:\` value that is
not \`\${{ github.repository }}\` | :critical |
| \`:reusable_caller_context_self_checkout\` | In a reusable workflow
(\`on: workflow_call\`), \`actions/checkout\` of a literal foreign repo
at \`ref:\` = any caller-context variable (\`github.ref\` / \`head_ref\`
/ \`sha\` / \`workflow_sha\`) | :critical |

## Why this rule pair

\`github.workflow_sha\` (and \`github.ref\`, \`head_ref\`, \`sha\`) all
resolve to the **caller repo's** value, never to the SHA of the reusable
workflow itself. Passing them as \`ref:\` to \`actions/checkout\` of a
*foreign* repository asks that repo for a SHA / branch that doesn't
exist — \`git fetch\` exits with code 128, three retries, then the step
(and downstream jobs) fail.

This is the exact bug shipped in \`hyperpolymath/standards#219\`'s
pre-fix \`governance-reusable.yml:155\`, which cascaded into governance
failures across hundreds of stuck PRs estate-wide on 2026-05-26 —
symptom \"governance / Language / package anti-pattern policy — Failing
after 40s\" on every PR.

## Design notes

### Sensitivity (catches the bug)

- Both rules use a YAML step-splitter (line-walker that respects indent)
instead of a multi-line regex, so they handle both \`actions/checkout\`
step shapes:
  - \`- uses: actions/checkout@…\` (uses-first)
  - \`- name: … / uses: actions/checkout@…\` (name-first)
- Verified against the verbatim pre-fix \`governance-reusable.yml\` body
— both rules fire.

### Specificity (low false-positive rate)

- Rule 1 does **not** fire when \`repository: \${{ github.repository
}}\` (the safe caller-self pattern shipped in many workflows).
- Rule 2 does **not** fire on non-reusable workflows (no
\`workflow_call:\`) or when \`ref:\` is pinned to a literal value
(\`main\`, \`v1.2.0\`, or an explicit SHA).
- Verified against the post-fix \`governance-reusable.yml\` (\`ref:
main\`) — both rules stay quiet.

### Why two rules, not one

- Rule 1 is the narrowest cut against the specific \`workflow_sha\`
mistake — high signal, zero false positives expected.
- Rule 2 is the broader anti-pattern: a reusable that puts ANY
caller-context ref against a foreign \`repository:\`. Catches the cousin
bugs (\`github.ref\` or \`github.sha\` used the same wrong way) that the
standards PR fix did not need to address but Hypatia should still warn
on.

## Test plan

- [x] \`mix test test/workflow_audit_test.exs\` — 12 new test cases (4 +
5 + 3) covering positive firing, negative firing, and the two checkout
step shapes.
- [x] Standalone smoke (10 assertions) covering both pre-fix and
post-fix \`governance-reusable.yml\` shapes — see PR body of
standards#219 for source.
- [ ] After merge: re-run Hypatia scan against
\`hyperpolymath/standards\` post-PR-219 and confirm neither rule fires
(it shouldn't — \`ref: main\` is the safe shape).
- [ ] Estate sweep: run Hypatia against the rest of
\`hyperpolymath/standards/.github/workflows/*-reusable.yml\` to confirm
no other reusables carry the same anti-pattern. (I scanned manually and
found only \`governance-reusable.yml\` — no false positives expected,
but worth confirming through the production scanner path.)

## Related

- \`hyperpolymath/standards#219\` — source-of-truth fix that unblocks
the stuck-PR cascade.
- The orthogonal CodeQL js-ts failure on \`.git-private-farm#24\` is a
GitHub Actions billing/spending-limit block — not a Hypatia-detectable
anti-pattern, just owner-action in Settings → Billing & plans.

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

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/hypatia that referenced this pull request May 27, 2026
…5-27 audit (#350)

## Summary

The 2026-05-27 estate doomed-CI audit produced deletion PRs for 5 pilot
repos (`road-skate`, `vext`, `quandledb`, `absolute-zero`, `Axiom.jl`).
Three of the underlying anti-patterns had no Hypatia coverage, or had
coverage too weak to drive action. This PR closes those gaps in
\`Hypatia.Rules.CicdRules\`.

| Track | Before | After |
|---|---|---|
| A1 — Jekyll on non-Pages | \`:irrelevant_jekyll\` at \`:low\`
(ignored) | bumped to \`:medium\` (acted on) |
| C — Subsumed standalone beside \`governance.yml\` | none (just a
comment) | new \`:redundant_subsumed_standalone\` at \`:medium\` |
| D — \`rust-ci.yml\` on no-Rust repo | only the inverse
(\`:missing_rust_ci\`) | new \`:irrelevant_rust_ci\` at \`:high\` |

## Why

(1) **Severity bump for \`:irrelevant_jekyll\`** — the existing
detection (no \`_config.yml\` AND no \`Gemfile\`) is accurate, but
\`:low\` meant it never made it onto any actionable backlog. Estate
language policy bans Jekyll outright in favour of
\`hyperpolymath/casket-ssg\`, so when the rule fires the finding is
unambiguously a delete candidate. 21 of 25 Jekyll-workflow repos in the
estate fire this rule.

(2) **\`:redundant_subsumed_standalone\`** — fires for any of the 9
standalone workflow names whose logic is provided by
\`hyperpolymath/standards/.github/workflows/governance-reusable.yml\`
when \`governance.yml\` is also present:

\`\`\`
workflow-linter.yml, language-policy.yml, quality.yml,
security-policy.yml, guix-nix-policy.yml, npm-bun-blocker.yml,
ts-blocker.yml, rsr-antipattern.yml, wellknown-enforcement.yml
\`\`\`

Authoritative subsumption list per the reusable's own header. Audit
found 107 instances across 88 repos. \`workflow-linter.yml\` alone is in
80 repos.

(3) **\`:irrelevant_rust_ci\`** — fires when \`rust-ci.yml\` exists but
the repo has no \`Cargo.toml\` at root AND no \`*.rs\` files anywhere
(workspace check via \`rs_file_count\` or extension scan). Cousin of
\`:missing_rust_ci\` (which catches the inverse). Audit found 11 doomed
cases.

## Validation

8/8 standalone smoke assertions pass:

- \`:redundant_subsumed_standalone\` fires on \`workflow-linter.yml +
governance.yml\`
- \`:redundant_subsumed_standalone\` fires on \`quality.yml +
governance.yml\`
- \`:redundant_subsumed_standalone\` count matches subsumed names
present
- silent without \`governance.yml\` (so vintage repos still on
standalones don't get pinged)
- \`:irrelevant_rust_ci\` fires when no \`Cargo.toml\` + no \`.rs\`
- silent when \`Cargo.toml\` present
- silent on workspace layouts (\`rs_file_count > 0\`)
- \`:irrelevant_jekyll\` severity is now \`:medium\`

## Related

- \`hyperpolymath/standards#219\` — the root-cause fix for the
governance-reusable \`workflow_sha\` bug that triggered the audit.
- \`#348\` — sibling rules for the \`workflow_sha\`
/ caller-context-\`ref\` anti-patterns (one PR over from this one in
time).
- Pilot deletion PRs validated against the existing rules: road-skate#1
(MERGED), vext#11, quandledb#16, absolute-zero#57, Axiom.jl#29.

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

Co-authored-by: Claude Opus 4.7 (1M context) <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.

1 participant