Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 32 additions & 26 deletions .github/workflows/actions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ workflows:
'.github/workflows/container-build.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/creusot.yml':
- 'hyperpolymath/cicd-suite@bf7dd95cf49733019343ff485c2f45c6b261839c'
- 'hyperpolymath/cicd-suite@47a5fe0aa1039ad8a6a0614137d575e66649a174'
'.github/workflows/dependabot-automerge.yml':
- 'dependabot/fetch-metadata@v3.1.0'
'.github/workflows/dogfood-gate.yml':
Expand All @@ -19,17 +19,17 @@ workflows:
'.github/workflows/estate-rules.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/governance.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/guix-policy.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/hypatia-scan.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/instant-sync.yml': []
'.github/workflows/label-triage.yml': []
'.github/workflows/labels.yml': []
'.github/workflows/lock-sync-gate.yml': []
'.github/workflows/mirror.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/openssf-compliance.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/pages.yml':
Expand All @@ -53,16 +53,16 @@ workflows:
'.github/workflows/runtime-policy.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/rust-ci.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/scorecard.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/secret-scanner.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/security-policy.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/squabble-action.yml': []
'.github/workflows/standards-pipeline.yml':
- 'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d'
- 'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
'.github/workflows/static-analysis-gate.yml':
- 'actions/checkout@v7.0.1'
- 'actions/download-artifact@v8.0.2'
Expand Down Expand Up @@ -197,9 +197,9 @@ dependencies:
commit: 'sha1-0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d'
owner_id: 75048950
repo_id: 623796603
'hyperpolymath/cicd-suite@bf7dd95cf49733019343ff485c2f45c6b261839c':
ref: 'bf7dd95cf49733019343ff485c2f45c6b261839c'
commit: 'sha1-bf7dd95cf49733019343ff485c2f45c6b261839c'
'hyperpolymath/cicd-suite@47a5fe0aa1039ad8a6a0614137d575e66649a174':
ref: '47a5fe0aa1039ad8a6a0614137d575e66649a174'
commit: 'sha1-47a5fe0aa1039ad8a6a0614137d575e66649a174'
owner_id: 6759885
repo_id: 1326697643
uses:
Expand All @@ -211,24 +211,15 @@ dependencies:
commit: 'sha1-e384daf6167a7a7567642d6a62060106244d2413'
owner_id: 6759885
repo_id: 1352485172
'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293':
ref: 'd55304a01b5260b0511aae0d14ed8b8770b00293'
commit: 'sha1-d55304a01b5260b0511aae0d14ed8b8770b00293'
owner_id: 297579217
repo_id: 1116521501
uses:
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8'
- 'goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406'
- 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
'metadatastician/standards@8e48b1caade08a552646adeab66558ac43b4360d':
ref: '8e48b1caade08a552646adeab66558ac43b4360d'
commit: 'sha1-8e48b1caade08a552646adeab66558ac43b4360d'
'metadatastician/standards@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12':
ref: 'a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
commit: 'sha1-a797d308c0517d4e2d21cc7f1cb08d41f82b1a12'
owner_id: 297579217
repo_id: 1116521501
uses:
- 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9'
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333'
- 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9'
- 'denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed'
- 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8'
Expand All @@ -237,11 +228,21 @@ dependencies:
- 'github/codeql-action@b96794f015dfd88f77b49b1c93e0fa7110f94c63'
- 'goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406'
- 'haskell-actions/setup@0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d'
- 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293'
- 'metadatastician/standards@d55304a01b5260b0511aae0d14ed8b8770b00293'
- 'ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e'
- 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6'
- 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
- 'swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0'
- 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555'
'metadatastician/standards@d55304a01b5260b0511aae0d14ed8b8770b00293':
ref: 'd55304a01b5260b0511aae0d14ed8b8770b00293'
commit: 'sha1-d55304a01b5260b0511aae0d14ed8b8770b00293'
owner_id: 297579217
repo_id: 1116521501
uses:
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8'
- 'goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406'
- 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
'ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e':
ref: 'v2.5.0'
commit: 'sha1-fa7117db83c52d787ae5a89f350999701505d78e'
Expand All @@ -262,6 +263,11 @@ dependencies:
commit: 'sha1-6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
owner_id: 580492
repo_id: 298565987
'swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0':
ref: 'v2.9.3'
commit: 'sha1-d1527c8f67ef9af357290475d4af4b0fab8f12e0'
owner_id: 580492
repo_id: 298565987
'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555':
ref: 'v0.10.0'
commit: 'sha1-e83874834305fe9a4a2997156cb26c5de65a8555'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/creusot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ permissions:

jobs:
creusot:
uses: hyperpolymath/cicd-suite/.github/workflows/creusot-gate.yml@bf7dd95cf49733019343ff485c2f45c6b261839c
uses: hyperpolymath/cicd-suite/.github/workflows/creusot-gate.yml@47a5fe0aa1039ad8a6a0614137d575e66649a174
with:
# Paired inputs: Creusot v0.14.0 is built against nightly-2026-08-03
# (creusot-rs/creusot's own rust-toolchain at that tag, mirrored in
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/governance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ permissions:

jobs:
governance:
uses: metadatastician/standards/.github/workflows/governance-reusable.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/governance-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
Comment thread
hyperpolymath marked this conversation as resolved.
Resolved
permissions:
actions: read
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/hypatia-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ permissions:

jobs:
hypatia:
uses: metadatastician/standards/.github/workflows/hypatia-scan-reusable.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/hypatia-scan-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
2 changes: 1 addition & 1 deletion .github/workflows/mirror.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:
contents: read
jobs:
mirror:
uses: metadatastician/standards/.github/workflows/mirror-reusable.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/mirror-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
# Only the seven forge keys the callee declares (standards#1108 §6b);
# `secrets: inherit` forwarded every repository secret (WH008, zizmor
# secrets-inherit) to a workflow that asks for exactly these.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ permissions:
contents: read
jobs:
rust-ci:
uses: metadatastician/standards/.github/workflows/rust-ci-reusable.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/rust-ci-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
permissions:
actions: read
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ permissions:

jobs:
scorecard:
uses: metadatastician/standards/.github/workflows/scorecard-reusable.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/scorecard-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
permissions:
actions: read
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/secret-scanner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ permissions:
# .github/workflows/README.adoc.
jobs:
scan:
uses: metadatastician/standards/.github/workflows/secret-scanner-reusable.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/secret-scanner-reusable.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
# No `secrets:` block, deliberately: secret-scanner-reusable.yml @75bd5994
# declares no caller secrets and reads no `secrets.*` context, so
# `secrets: inherit` only forwarded every repository secret to a workflow
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/standards-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ jobs:
# `workflow_call.inputs` only, has no `secrets:` block and references no
# `secrets.*` anywhere; `secrets: inherit` would hand the whole store to a
# workflow that consumes none of it.
uses: metadatastician/standards/.github/workflows/ci-pipeline.yml@8e48b1caade08a552646adeab66558ac43b4360d
uses: metadatastician/standards/.github/workflows/ci-pipeline.yml@a797d308c0517d4e2d21cc7f1cb08d41f82b1a12
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
75 changes: 64 additions & 11 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,26 @@ workflows and pinned actions. Nothing is written anywhere.
squabble chains . ../standards gh:hyperpolymath/typed-wasm --follow 1
----

* *Blocking* (exit 4): dependency cycles, and dead upstreams. A deleted action
repo produces no check run at all, so the board reads green.
* *Blocking* (exit 4): dependency cycles, dead upstreams, and moved upstream
coordinates confirmed in requested subjects or through exact pinned
dependency routes. A deleted reusable workflow can fail before any job reports.
* *Warnings*: diamonds (one repo's CI receives an upstream at two pins, one
of them via a reusable workflow), pin skew across repos, tag/branch pins,
and **moved upstreams** (see below).
of them via a reusable workflow), pin skew across repos, and tag/branch pins.
* It also prints an upstreams-first landing order and the longest chain.

Every upstream coordinate is resolved through REST with redirects followed, and
its canonical `full_name` is compared with the name as written — names, never
pins. A difference is reported as a moved upstream: a reusable coordinate under
a renamed/transferred owner can die as a zero-job `startup_failure` ("workflow
was not found") that no PR check list shows, so it is named *before* CI goes
quiet. It stays a warning while the redirect still works (that is a risk, not an
observed failure); `squabble zero-job` is what turns an observed failure into a
blocking finding. The same canonicalisation groups pin skew, so the old and new
quiet. A confirmed reference blocks even when the repository API follows a
redirect: Actions does not redirect the `uses:` reference. A reference found
only on an upstream's default branch remains an unconfirmed warning unless
every hop from a requested subject matches the scanned revision and called
workflow file. The report retains both confirmed and unconfirmed locations.
`squabble zero-job` separately reports
the failed runs that were actually observed. The same canonicalisation groups
pin skew, so the old and new
spellings of one upstream cannot hide a split. `--no-canonical` skips the REST
reads and says so — a deliberate blind spot, not a clean bill.

Expand All @@ -76,7 +81,8 @@ layer.

Some workflows fail *before any job exists*. GitHub creates no check run, the PR
check list stays tidy, and a required context is simply absent. Two first-class
classes are modelled, each with its own move:
coordinate classes are modelled, each with its own move. Optional native lock
verification adds source diagnoses which never propose permission changes:

[cols="2,1,2"]
|===
Expand All @@ -96,20 +102,67 @@ classes are modelled, each with its own move:
(a different coordinate may already be admitted, and under `verified_allowed`
an uncovered action is reported `Unattributed` rather than refused, because
creator status cannot be resolved here).

| *invalid native Actions lock*
| Diagnosis only
| The official native parser rejected the lock at the failed run's exact
source revision. Retain its exit and diagnostic, then review a candidate
produced by the repository's official regeneration chain.

| *Actions lock/workflow mismatch*
| Diagnosis only
| The official offline verifier reported coverage findings for this workflow
at the failed run's exact source revision. This is separate from malformed
lock syntax and from a tool or setup failure.
|===

[source,sh]
----
squabble zero-job . --limit 30 # attribute the latest zero-job runs
squabble zero-job . --limit 30 --json # the same, machine-readable
squabble zero-job . --actions-lock-verifier /verified/gh-actions-lock --json
----

Per run it reports the repo, the workflow, the coordinate **as written**, the
canonical target, and the required allow-list pattern — plus the sequencing: fix
the repoint first, then admit the canonical pattern if the run is still refused.
Exit `4` means zero-job runs were observed, attributed or not: a run it cannot
attribute is still a run that never reported. Exit `0` speaks only for the
scanned window.
Both `startup_failure` and ordinary `failure` conclusions are investigated;
GitHub reports both for runs which created no jobs. The jobs endpoint must
independently establish a zero count before source attribution. Ordinary
failures with observed jobs belong to execution-phase diagnosis. Unreadable
counts and contradictory startup evidence remain visible and blocking without
inventing a zero count or proposing a repair.

The run's full commit ID must match the local repository root and its
unmodified workflow tree. A different revision, nested directory, unreadable
source, or changed workflow stays `Unattributed`; a current checkout cannot
explain a historical run by coincidence. Exit `4` means a failed candidate
remains in the report, attributed or not. Exit `0` speaks only for the scanned
window.

`--actions-lock-verifier` takes an absolute path to an independently verified
official `gh-actions-lock` v0.2.0 binary. It invokes only `--version` and
`--verify-local --json --hostname github.com`: no download, resolution, auth,
network request or write mode. Tokens and subject-override environment variables
are removed from that child process. The JSON report retains the tool version,
exact source, exit, stdout, stderr and classification.

The native probe requires a *pristine full checkout*, including ignored and
untracked files, with no symlink/gitlink inputs or hidden index changes. Use a
fresh checkout at the failed run's commit. This stricter opt-in requirement
includes same-repository `$/...` action definitions outside workflows: an
ignored `action.yml` can shadow a committed `action.yaml`. If that complete
input set cannot be bound to the source, the probe is explicitly unverified.
The command never removes or changes a dirty file to meet the requirement.
An unavailable optional lock probe is retained beside any independently
established coordinate attribution; it neither hides that diagnosis nor
establishes a lock repair or a successful verification.

The native reader checks the official exit/JSON contract and complete workflow
population. Empty, malformed, partial, duplicate-key, contradictory or unknown
verifier-version output cannot become verified. A local verification pass is coverage
evidence only; a reproduced source defect is not proof of the sole GitHub
startup cause. Neither is a CI pass, repair outcome or training success.

`zero-job` is *outside* `squabble-contract/1.0.0`: that revision's surface stays
at four subcommands, and nothing here adds meaning to it. Like `chains`, the
Expand Down
Loading
Loading