Objective
.github/workflows/branch-cleanup.yml is rejected by GitHub as an invalid workflow file. Every push to every branch — including main — produces an instantly-failed run. The workflow has never successfully executed, and its red check is what holds otherwise-green PRs at mergeable_state: unstable.
One-line fix, no logic change.
Root cause
The permissions: block declares a scope that does not exist:
permissions:
contents: write
pull-requests: read
workflows: write # <-- not a valid permission scope
Per the workflow syntax reference, the valid keys are actions, artifact-metadata, attestations, checks, code-quality, contents, deployments, discussions, id-token, issues, packages, pages, pull-requests, security-events, statuses, vulnerability-alerts. workflows is not among them.
The confusion is understandable: workflow is a real scope for PATs and OAuth apps (the one needed to push changes to files under .github/workflows/). It is not grantable to GITHUB_TOKEN via the permissions: block, so this key never granted anything — it only invalidated the file.
Evidence
The failure signature is distinctive and matches an unparseable workflow rather than a failing job:
- Runs are named by file path (
.github/workflows/branch-cleanup.yml) instead of by the name: field (Branch Cleanup). GitHub falls back to the path when it cannot load the workflow.
created_at, run_started_at, and updated_at are byte-identical — e.g. all three are 2026-08-05T10:20:38Z on run 30997035127. Zero duration; no job ever starts.
- Runs fire on branches the trigger filter excludes. The file declares
on.push.branches: ["claude/branch-cleanup-*"], yet runs exist on main, groupthinking-fix-upstream-error-leakage, dependabot/github_actions/github/gh-aw-actions/setup-0.84.0, and others. An invalid file is reported on every push regardless of its filters.
Scale, from the workflow's own run history:
| Metric |
Value |
| Total runs |
1,163 |
| Conclusion |
failure — 100%, no successes |
| Latest run numbers sampled |
1134–1163, all failed |
| Distinct branches affected in one 30-run page |
10, including main |
It is also the only workflow in the repository using this key — a survey of the permissions: blocks across .github/workflows/*.yml (top-level and per-job) yields actions, checks, contents, deployments, id-token, issues, pull-requests, security-events, statuses, workflows, and branch-cleanup.yml is the sole source of that last one. It is likewise the only workflow producing this failure signature.
Acceptance criteria
Remediation
permissions:
contents: write
pull-requests: read
- workflows: write
The header comment above it should be corrected too — it currently claims the token needs "contents: write and workflows: write rights to delete/restore refs."
Removing the key changes no effective permission, because an invalid key grants nothing; the workflow has never run with it in force.
Declared file scope
.github/workflows/branch-cleanup.yml
Risk
- Risk level: low. Deleting an ineffective key from a workflow that has never executed.
- Failure mode: none for the delete path — branch deletion and archive-tag pushes need
contents: write, which is retained.
- Worth verifying on first real run: the restore path (
git push origin "refs/tags/archive/$b:refs/heads/$b") recreates a ref whose tree may contain .github/workflows/ files. GITHUB_TOKEN is restricted from creating or updating workflow files, and no permissions: key can lift that. If restore fails that way, it is a pre-existing latent constraint this fix merely makes reachable for the first time — not a regression. It would need a PAT with the workflow scope, or a restore performed locally.
- Rollback: revert the one-line change.
Notes
Found while driving PR #1381 through its CI gate under the PR remediation runbook. #1381's substantive checks (CI, CodeQL, Security Scan, Coverage, PR Checks, PR Governance, Secret Scan, Dependency Review) are all green on 36645ad; this invalid workflow is the remaining red mark.
I have not landed the fix. My branch assignment for this session is claude/clever-heisenberg-pedqbz, which already carries #1404 with a different canonical issue, and PR Governance requires one issue per PR — so folding an unrelated CI fix into it would break that gate. Happy to open it as its own PR on request; it is a one-line diff.
Objective
.github/workflows/branch-cleanup.ymlis rejected by GitHub as an invalid workflow file. Every push to every branch — includingmain— produces an instantly-failed run. The workflow has never successfully executed, and its red check is what holds otherwise-green PRs atmergeable_state: unstable.One-line fix, no logic change.
Root cause
The
permissions:block declares a scope that does not exist:Per the workflow syntax reference, the valid keys are
actions,artifact-metadata,attestations,checks,code-quality,contents,deployments,discussions,id-token,issues,packages,pages,pull-requests,security-events,statuses,vulnerability-alerts.workflowsis not among them.The confusion is understandable:
workflowis a real scope for PATs and OAuth apps (the one needed to push changes to files under.github/workflows/). It is not grantable toGITHUB_TOKENvia thepermissions:block, so this key never granted anything — it only invalidated the file.Evidence
The failure signature is distinctive and matches an unparseable workflow rather than a failing job:
.github/workflows/branch-cleanup.yml) instead of by thename:field (Branch Cleanup). GitHub falls back to the path when it cannot load the workflow.created_at,run_started_at, andupdated_atare byte-identical — e.g. all three are2026-08-05T10:20:38Zon run 30997035127. Zero duration; no job ever starts.on.push.branches: ["claude/branch-cleanup-*"], yet runs exist onmain,groupthinking-fix-upstream-error-leakage,dependabot/github_actions/github/gh-aw-actions/setup-0.84.0, and others. An invalid file is reported on every push regardless of its filters.Scale, from the workflow's own run history:
failure— 100%, no successesmainIt is also the only workflow in the repository using this key — a survey of the
permissions:blocks across.github/workflows/*.yml(top-level and per-job) yieldsactions,checks,contents,deployments,id-token,issues,pull-requests,security-events,statuses,workflows, andbranch-cleanup.ymlis the sole source of that last one. It is likewise the only workflow producing this failure signature.Acceptance criteria
branch-cleanup.ymlloads: a push produces a run named Branch Cleanup, not the file path.decidestep already handles this viago=no).claude/branch-cleanup-*once the file is valid.mergeable_state: unstableon account of this check.Remediation
permissions: contents: write pull-requests: read - workflows: writeThe header comment above it should be corrected too — it currently claims the token needs "
contents: writeandworkflows: writerights to delete/restore refs."Removing the key changes no effective permission, because an invalid key grants nothing; the workflow has never run with it in force.
Declared file scope
.github/workflows/branch-cleanup.ymlRisk
contents: write, which is retained.git push origin "refs/tags/archive/$b:refs/heads/$b") recreates a ref whose tree may contain.github/workflows/files.GITHUB_TOKENis restricted from creating or updating workflow files, and nopermissions:key can lift that. If restore fails that way, it is a pre-existing latent constraint this fix merely makes reachable for the first time — not a regression. It would need a PAT with theworkflowscope, or a restore performed locally.Notes
Found while driving PR #1381 through its CI gate under the PR remediation runbook. #1381's substantive checks (
CI,CodeQL,Security Scan,Coverage,PR Checks,PR Governance,Secret Scan,Dependency Review) are all green on36645ad; this invalid workflow is the remaining red mark.I have not landed the fix. My branch assignment for this session is
claude/clever-heisenberg-pedqbz, which already carries #1404 with a different canonical issue, andPR Governancerequires one issue per PR — so folding an unrelated CI fix into it would break that gate. Happy to open it as its own PR on request; it is a one-line diff.