From 08ce96640e3ee6e84981a828596523f3d538797b Mon Sep 17 00:00:00 2001 From: Arena Agent Date: Sun, 25 Oct 2026 11:30:40 +0000 Subject: [PATCH 1/2] fix(governance): follow the standards repository transfer hyperpolymath/standards was transferred to metadatastician/standards at 10:13 UTC on 2026-10-25. A reusable-workflow reference does not follow that redirect: from the next run, hypatia-scan.yml and scorecard.yml failed at plan time with zero jobs and no name, while every workflow that only checks the repository out (secret-scanner, k9's checkout, the verdict-grid renderer) kept working, because git and the REST API do follow it. So the scanners that call a standards reusable were dark and the ones that check it out were not - and a run that fails with no jobs does not appear in a per-workflow status summary at all. Repoint every reference at metadatastician/standards, keeping the same pinned SHAs: they resolve in the new location with the same commit subjects, so no new code is trusted and only the name used to reach those commits has changed. The governance contract now fails if any workflow names the pre-transfer owner, or if the Scorecard reusable stops being the pinned file, and the mutation test carries a case for each, so a partial migration cannot pass. The incident, its detection (gh api repos// --jq .full_name) and why the two kinds of reference behave differently are recorded in docs/maintenance/repository-hygiene.md. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .github/workflows/hypatia-scan-reusable.yml | 10 ++--- .github/workflows/hypatia-scan.yml | 4 +- .github/workflows/k9-conformance-reusable.yml | 12 ++--- .github/workflows/scorecard.yml | 2 +- .github/workflows/secret-scanner-reusable.yml | 6 +-- docs/maintenance/repository-hygiene.md | 45 +++++++++++++++++++ scripts/check-governance-contract.sh | 18 ++++++-- scripts/tests/test-governance-contract.sh | 7 ++- 8 files changed, 83 insertions(+), 21 deletions(-) diff --git a/.github/workflows/hypatia-scan-reusable.yml b/.github/workflows/hypatia-scan-reusable.yml index b797c2f6..dc310eb7 100644 --- a/.github/workflows/hypatia-scan-reusable.yml +++ b/.github/workflows/hypatia-scan-reusable.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MPL-2.0 # This workflow is managed by gh actions-lock. # -# Fork-local copy of hyperpolymath/standards/.github/workflows/ +# Fork-local copy of metadatastician/standards/.github/workflows/ # hypatia-scan-reusable.yml at 01c9b0c9f2646ebea0b30a9588462642ac94aee9. # Keep that source pin when updating this file and reapply the three fork deltas: # 1. Do not upload SARIF for pull_request events. This lane is advisory on @@ -11,7 +11,7 @@ # Raw findings and the verdict grid still cover the PR, while push and # manual runs continue to reconcile code scanning on the default branch. # 2. Pin the standards checkout explicitly. job.workflow_sha now names a -# MetaManifold commit, not a commit in hyperpolymath/standards. +# MetaManifold commit, not a commit in metadatastician/standards. # 3. Filter only upstream-inherited TypeScript paths from the effective # findings, validate the raw/effective JSON with pinned ijson-jcs, and keep # raw scanner outputs plus fork-only paths/rules. @@ -619,7 +619,7 @@ jobs: continue-on-error: true uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - repository: hyperpolymath/standards + repository: metadatastician/standards persist-credentials: false # Includes the filter's completion output and literal-glob matching. # Keep the helper immutable and compatible with the strict gate. @@ -703,7 +703,7 @@ jobs: continue-on-error: true uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - repository: hyperpolymath/standards + repository: metadatastician/standards # This fork-local reusable's job.workflow_sha belongs to # MetaManifold, not standards, so the source commit must be literal. ref: 01c9b0c9f2646ebea0b30a9588462642ac94aee9 @@ -743,7 +743,7 @@ jobs: # No renderer is missing evidence, rendered as such, never a pass. jq -n '{schemaVersion: 1, label: "Hypatia grid", message: "indeterminate", color: "orange"}' > verdict-grid/badge.json printf '%s\n%s\n' '' \ - '๐ŸŸ  indeterminate ยท the verdict grid renderer could not be checked out from hyperpolymath/standards; see the job log.' \ + '๐ŸŸ  indeterminate ยท the verdict grid renderer could not be checked out from metadatastician/standards; see the job log.' \ > verdict-grid/report.md cat verdict-grid/report.md >> "$GITHUB_STEP_SUMMARY" echo "state=orange" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index b307aa35..e874741f 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MPL-2.0 # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) # -# Fork governance lane. DEED and K9 conformance come from hyperpolymath/standards; the +# Fork governance lane. DEED and K9 conformance come from metadatastician/standards; the # Hypatia verdict grid uses a fork-local copy of the standards reusable so its # advisory PR scan cannot become a blocking code-scanning-results check. Both # sources are pinned to commits. The grid covers Hypatia, panic-attack, pons @@ -52,7 +52,7 @@ jobs: deed: name: DEED syntax - uses: hyperpolymath/standards/.github/workflows/deed-conformance.yml@75bd5994470661a099df562d6d5ad2fe744dbd66 + uses: metadatastician/standards/.github/workflows/deed-conformance.yml@75bd5994470661a099df562d6d5ad2fe744dbd66 permissions: contents: read with: diff --git a/.github/workflows/k9-conformance-reusable.yml b/.github/workflows/k9-conformance-reusable.yml index 12e3806c..b58e6a85 100644 --- a/.github/workflows/k9-conformance-reusable.yml +++ b/.github/workflows/k9-conformance-reusable.yml @@ -42,7 +42,7 @@ name: k9-conformance # Caller: # jobs: # k9: -# uses: hyperpolymath/standards/.github/workflows/k9-conformance.yml@ +# uses: metadatastician/standards/.github/workflows/k9-conformance.yml@ # permissions: # contents: read # pull-requests: read @@ -89,7 +89,7 @@ jobs: # In this repo the PR's own validator is in the first checkout; a caller # gets validator, contract and renderer from the canon checkout at # job.workflow_sha. - CANON: ${{ github.repository == 'hyperpolymath/standards' && '.' || '.k9-canon' }} + CANON: ${{ github.repository == 'metadatastician/standards' && '.' || '.k9-canon' }} NICKEL_VERSION: '1.18.0' NICKEL_SHA256: '9cba4dd65ae9915ec61f73033aafcff307a377665a83fd8f530df086763318cb' IJSON_JCS_REV: '0fdeea716fd558e9807362acf6f8202d56d8d88f' @@ -104,10 +104,10 @@ jobs: persist-credentials: false - name: checkout the K9 validator, contract and renderer at this workflow's commit - if: github.repository != 'hyperpolymath/standards' + if: github.repository != 'metadatastician/standards' uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - repository: hyperpolymath/standards + repository: metadatastician/standards ref: c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d path: .k9-canon persist-credentials: false @@ -121,7 +121,7 @@ jobs: WORKFLOW_SHA: c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} run: | - if [ "$GITHUB_REPOSITORY" = "hyperpolymath/standards" ]; then + if [ "$GITHUB_REPOSITORY" = "metadatastician/standards" ]; then echo "CANON_REF=$HEAD_SHA" >> "$GITHUB_ENV" else echo "CANON_REF=$WORKFLOW_SHA" >> "$GITHUB_ENV" @@ -154,7 +154,7 @@ jobs: || echo "::warning::ijson-jcs did not install; report.json falls back to jq -S -c" - name: Renderer regression tests - if: github.repository == 'hyperpolymath/standards' + if: github.repository == 'metadatastician/standards' run: bash scripts/tests/k9-grid-test.sh - name: Validator self-test diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index c8bd4a46..42004987 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -20,7 +20,7 @@ jobs: scorecard: # The default-branch SARIF upload needs security-events: write; never # expose that grant or the publication OIDC token to PR code. - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d + uses: metadatastician/standards/.github/workflows/scorecard-reusable.yml@c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d permissions: actions: read contents: read diff --git a/.github/workflows/secret-scanner-reusable.yml b/.github/workflows/secret-scanner-reusable.yml index e9462860..14984b09 100644 --- a/.github/workflows/secret-scanner-reusable.yml +++ b/.github/workflows/secret-scanner-reusable.yml @@ -97,7 +97,7 @@ # scan: # permissions: # contents: read -# uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@ +# uses: metadatastician/standards/.github/workflows/secret-scanner-reusable.yml@ # # Deliberately NO `secrets:` line โ€” the callee declares none and # # needs none (see the Design note above). @@ -214,7 +214,7 @@ jobs: if: hashFiles('.gitleaks.toml') == '' uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - repository: hyperpolymath/standards + repository: metadatastician/standards ref: c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d path: .standards-gitleaks sparse-checkout: | @@ -291,7 +291,7 @@ jobs: if: steps.estate_baseline.outputs.referenced == 'true' uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - repository: hyperpolymath/standards + repository: metadatastician/standards ref: c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d path: .estate-baseline-checkout sparse-checkout: config/gitleaks diff --git a/docs/maintenance/repository-hygiene.md b/docs/maintenance/repository-hygiene.md index e63ef223..59ab8be0 100644 --- a/docs/maintenance/repository-hygiene.md +++ b/docs/maintenance/repository-hygiene.md @@ -217,6 +217,51 @@ acts on them; the first one was reached, wrongly, during the 2026-10-25 pass. A new directory under `docs/` needs a whitelist line or it will not be committed; `!docs/maintenance/` was added for this document. +## External pins can move under you + +**Incident, 2026-10-25.** `hyperpolymath/standards` โ€” the source of this +repository's DEED, K9, Hypatia, Scorecard and secret-scanner reusables โ€” was +transferred to `metadatastician/standards` at 10:13 UTC. From the next run +onwards, every workflow that called one of its reusable workflows **failed at +plan time with zero jobs**, and GitHub displayed the run under the workflow's +file path instead of its `name:`, because the workflow never loaded far enough +to have one: + +| Time | Workflow | Result | +| --- | --- | --- | +| 09:26 | `Governance (fork)` (`hypatia-scan.yml`) | success | +| 09:26 | `OpenSSF Scorecard` (`scorecard.yml`) | success | +| 10:13 | โ€” standards repository transferred โ€” | | +| 10:52 | `hypatia-scan.yml` on a pull request | failure, 0 jobs, 0 s | +| 11:27 | `hypatia-scan.yml`, `scorecard.yml` on the push | failure, 0 jobs, 0 s | +| 11:27 | `Secret Scanner` (local reusable only) | success | + +The distinction is the whole lesson: **`actions/checkout` with +`repository: hyperpolymath/standards` kept working**, because git and the REST +API follow a transfer's redirect, while a `uses: //.github/ +workflows/@` reference **does not**. So the scanners that *check the +repository out* were fine and the ones that *call a reusable workflow* were +dark. Both read as "governance is green" in a summary that does not look at +`conclusion` per workflow. + +How to detect it in one command, before trusting a red or a green: + +``` +gh api repos// --jq .full_name # a different name means transferred +``` + +What was done: every reference was repointed at `metadatastician/standards` +with the **same pinned SHAs** (verified to resolve in the new location, with +matching commit subjects), `scripts/check-governance-contract.sh` now fails if +any workflow names the pre-transfer owner or if the Scorecard reusable stops +being the pinned file, and the mutation test carries a case for each. The pins +themselves did not move, so no new code is trusted; only the name used to reach +the same commits. + +What a future reader should not do: "fix" a failed governance run by dropping +the `uses:` and inlining a scanner, or by pointing the pin at `@main`. Both turn +a loud failure into a quiet one. + ## Decisions for the owner These are not cleanup, they are choices with trade-offs; the reasoning is diff --git a/scripts/check-governance-contract.sh b/scripts/check-governance-contract.sh index 93609ee1..507b5edc 100755 --- a/scripts/check-governance-contract.sh +++ b/scripts/check-governance-contract.sh @@ -118,8 +118,13 @@ reusable="$(cat "$REUSABLE")" contains "$caller" 'uses: ./.github/workflows/hypatia-scan-reusable.yml' \ 'the governance lane calls the fork-local reusable' -not_contains "$caller" 'uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@' \ +# The standards repository is metadatastician/standards; it was +# hyperpolymath/standards until the transfer on 2026-10-25. Both names are +# checked, because a bypass through either one skips the fork guard. +not_contains "$caller" 'uses: metadatastician/standards/.github/workflows/hypatia-scan-reusable.yml@' \ 'the governance lane cannot bypass the fork guard by calling standards directly' +not_contains "$caller" 'uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@' \ + 'the governance lane cannot bypass the fork guard through the pre-transfer name' contains "$caller" 'needs: [workflow-contract]' \ 'this contract runs before the Hypatia scan' if grep -Eq '^ pull_request:$' <<<"$caller"; then @@ -261,7 +266,7 @@ not_contains "$reusable" 'steps.scan.outputs.critical > 0' \ 'the raw critical count cannot drive an exception-inconsistent advisory' if renderer="$(step_block "$REUSABLE" 'Check out the verdict grid renderer at this workflow'"'"'s commit')"; then - contains "$renderer" 'repository: hyperpolymath/standards' \ + contains "$renderer" 'repository: metadatastician/standards' \ 'the renderer comes from the standards repository' contains "$renderer" "ref: $STANDARDS_SHA" \ 'the standards renderer uses the immutable source pin' @@ -269,6 +274,13 @@ else fail 'the standards renderer checkout exists' fi +stale_owner="$(grep -rn 'hyperpolymath/standards' .github/workflows/ 2>/dev/null || true)" +if [ -z "$stale_owner" ]; then + pass 'no workflow still names the pre-transfer standards owner' +else + fail "workflows still reference hyperpolymath/standards, which no longer resolves for a reusable uses: - $stale_owner" +fi + upload_count="$(grep -c 'uses: github/codeql-action/upload-sarif@' "$REUSABLE" || true)" if [ "$upload_count" -eq 1 ]; then pass 'there is exactly one SARIF upload site to guard' @@ -313,7 +325,7 @@ not_contains "$secret_workflow" 'secrets:' 'the secret scanner receives no calle not_contains "$secret_workflow" 'continue-on-error:' 'secret scanner failures cannot be advisory' not_contains "$secret_workflow" 'pull_request_target:' 'secret scanning does not use a privileged PR trigger' scorecard_workflow="$(cat .github/workflows/scorecard.yml)" -contains "$scorecard_workflow" 'uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d' \ +contains "$scorecard_workflow" 'uses: metadatastician/standards/.github/workflows/scorecard-reusable.yml@c6d78606f3928c22c3b0bdc6f5f5b47b96e05a5d' \ 'Scorecard uses the audited immutable reusable' if grep -Eq '^ pull_request(_target)?:' <<<"$scorecard_workflow"; then fail 'Scorecard publication must not run against PR code' diff --git a/scripts/tests/test-governance-contract.sh b/scripts/tests/test-governance-contract.sh index 4d869365..8945b298 100644 --- a/scripts/tests/test-governance-contract.sh +++ b/scripts/tests/test-governance-contract.sh @@ -14,7 +14,7 @@ reset_fixture() { } reset_fixture bash "$fixture/scripts/check-governance-contract.sh" > "$fixture/log" 2>&1 -for mutation in allowlist-addition baseline-zero-gate baseline-operator-gate baseline-grouping-gate sarif upstream-exception effective-grid jcs-manifest jcs-canonicalizer raw-ijson k9-pin k9-require k9-indeterminate k9-verdict scanner-advisory scanner-secrets scanner-trigger scorecard-trigger; do +for mutation in allowlist-addition baseline-zero-gate baseline-operator-gate baseline-grouping-gate sarif upstream-exception effective-grid jcs-manifest jcs-canonicalizer raw-ijson k9-pin k9-require k9-indeterminate k9-verdict scanner-advisory scanner-secrets scanner-trigger scorecard-trigger stale-standards-owner scorecard-owner; do reset_fixture case "$mutation" in allowlist-addition) echo 'frontend/src/fork-only.ts' >> "$fixture/config/hypatia/upstream-typescript-allowlist.txt" ;; @@ -35,6 +35,11 @@ for mutation in allowlist-addition baseline-zero-gate baseline-operator-gate bas scanner-secrets) echo ' secrets: inherit' >> "$fixture/.github/workflows/secret-scanner.yml" ;; scanner-trigger) sed -i 's/^ pull_request:/ pull_request_target:/' "$fixture/.github/workflows/secret-scanner.yml" ;; scorecard-trigger) sed -i '/^on:/a\ pull_request:' "$fixture/.github/workflows/scorecard.yml" ;; + # The standards repository was transferred on 2026-10-25 and a reusable + # `uses:` no longer follows the old owner, so either of these mutations + # leaves a workflow that fails at plan time with no jobs at all. + stale-standards-owner) sed -i 's@metadatastician/standards@hyperpolymath/standards@g' "$fixture/.github/workflows/scorecard.yml" ;; + scorecard-owner) sed -i 's@metadatastician/standards/.github/workflows/scorecard-reusable.yml@metadatastician/standards/.github/workflows/other.yml@' "$fixture/.github/workflows/scorecard.yml" ;; *) echo "ERROR: unknown mutation $mutation" >&2; exit 1 ;; esac if bash "$fixture/scripts/check-governance-contract.sh" > "$fixture/log" 2>&1; then From 4784a67a483fe681cba0eb84d37014cd679245b4 Mon Sep 17 00:00:00 2001 From: Arena Agent Date: Sun, 25 Oct 2026 11:33:16 +0000 Subject: [PATCH 2/2] docs(hygiene): the transfer is blocked by the Actions reusable-workflow policy The repaired references still fail, and the annotation on the run says why: all reusable workflows must come from a repository owned by hyperpolymath, so metadatastician/standards is refused whatever the workflow file names. Record the error verbatim and the three ways out, smallest first: permit the new owner in Settings -> Actions, move the repository back, or inline DEED conformance from a checkout. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- docs/maintenance/repository-hygiene.md | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/maintenance/repository-hygiene.md b/docs/maintenance/repository-hygiene.md index 59ab8be0..bfae4b35 100644 --- a/docs/maintenance/repository-hygiene.md +++ b/docs/maintenance/repository-hygiene.md @@ -250,6 +250,33 @@ How to detect it in one command, before trusting a red or a green: gh api repos// --jq .full_name # a different name means transferred ``` +### The actual cause is an Actions policy, not just the rename + +Repointing the references is **not sufficient**, and the run says so once you can +read the annotation. A startup-failure run has no jobs and no logs, but its +workflow page carries one error: + +> The reusable workflow `metadatastician/standards/.github/workflows/deed-conformance.yml@75bd5994โ€ฆ` +> is not allowed in `hyperpolymath/MetaManifold-WebUI` because all reusable +> workflows must be from a repository owned by `hyperpolymath` or match the +> pattern: `arena-ai-coding-agent[bot]`. + +The repository's Actions policy permits reusable workflows only from +repositories owned by `hyperpolymath` โ€” so `hyperpolymath/standards` was allowed +and `metadatastician/standards` is not, whatever name the workflow file uses. +The `uses:` references therefore cannot be repaired by editing this repository +alone. Three ways out, in increasing order of effort: + +1. **Permit the new owner.** Repository โ†’ Settings โ†’ Actions โ†’ General โ†’ + *Access* for reusable workflows, and allow `metadatastician` (or "any + repository"). This is the smallest change and keeps the pins intact. +2. **Move `standards` back** under `hyperpolymath`. Then the existing workflow + files work unchanged, and no pull request is needed. +3. **Run DEED conformance from a checkout** instead of a remote `uses:`, the way + the K9, Hypatia and secret-scanner lanes already do. Correct, but it puts a + copy of someone else's workflow steps in this repository, and that copy then + drifts. + What was done: every reference was repointed at `metadatastician/standards` with the **same pinned SHAs** (verified to resolve in the new location, with matching commit subjects), `scripts/check-governance-contract.sh` now fails if