Skip to content

chore(ci): agent-reaper pins two actions to SHAs its comments misname #437

Description

@bioedca

Maintenance kind

CI

Work requested

.github/workflows/agent-reaper.yml pins two third-party actions to SHAs that its own trailing
comments misname. One comment is merely wrong; the other hides the fact that the reaper runs an
untagged commit from December 2023.

Every upstream claim below was re-resolved online on 2026-08-13 with
git ls-remote --tags <upstream-url>, and every repository-internal count was read from
origin/main at b078f47. Read them from a freshly fetched origin/main: a checkout predating
#434 has no .github/workflows/wiki.yml and therefore counts 19 where this issue says 20.

1. actions/checkout — the comment is wrong, the SHA is right.

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5.0.1

That SHA is tagged v7 and v7.0.1 upstream — git ls-remote --tags https://github.com/actions/checkout prints both refs at it; the commit subject is
prep v7.0.1 release (upstream pull request 2531), dated 2026-07-17. The pin itself is current and
correct. The label is not, and it is wrong in exactly one place: the repository uses this same SHA
21 times across .github/workflows/, and the other 20 all label it # v7.0.1ci.yml
×6, release.yml ×3, deep-gpu.yml, deep.yml, deps-audit.yml, docs.yml,
large-fixtures.yml, packaging.yml, schema-guard.yml, scorecard.yml, sidecar-measure.yml,
sidecar.yml, wiki.yml. So the repository contradicts itself about one SHA, and
agent-reaper.yml is the sole outlier.

That comment has never named its SHA correctly, and the real v5.0.1 is not involved at any point.
# v5.0.1 entered the file when it was created — c74cdb5 (#276, 2026-07-29) — annotating
9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0, which upstream is refs/tags/v7.0.0. The actual
v5.0.1 is 93cb6efe18208431cddfb8368fd83d5badbf9bfd and appears nowhere in .github/.

2. actions/setup-python — the SHA matches no release at all.

- uses: actions/setup-python@e9d6f990972a57673cdb72ec29e19d42ba28880f # v5.4.0

No tag in actions/setup-python points at that SHA — it appears in no git ls-remote --tags
line for that repository. It is a commit of 2023-12-14 whose subject is Replace setup-python@v4 by setup-python@v5 in README (upstream pull request 776) — a README edit, not a release. Real
v5.4.0 is 42375524e23c412d93fb67b49958b491fce71c38. Meanwhile every other setup-python pin in
the repository — six of them, in ci.yml ×4, deep-gpu.yml and docs.yml — is
5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0, and that SHA does carry v7 and v7.0.0
upstream. The reaper is the only workflow still on the old commit, and its comment asserts a pinned
release that is not what it runs.

Dependabot will not repair the label, and the record shows why. agent-reaper.yml sits in
.github/workflows, which is inside the directory: "/" scope of the github-actions entry in
.github/dependabot.yml, and there is no ignore entry anywhere in that file — so the bot does
reach this file, and it has: the grouped actions pull request that merged as 87da5b7 (#398,
2026-08-07) bumped this very pin from 9c091bb2… to 3d3c42e5… and carried the # v5.0.1
comment across untouched
, while in the same commit updating scorecard.yml's
github/codeql-action/upload-sarif comment from # v4.37.3 to # v4.37.4. A bump therefore
advances the SHA and leaves the label as it found it, which is exactly how this line came to
misname what it runs. Nothing about the setup-python pin is explained by Dependabot behaviour
either way: it has not moved since the file was created, 5fda3b95… # v7.0.0 reached the six
sibling call sites in #254 (2053241, 2026-07-29) which merged before this file existed, and
neither grouped actions pull request since (#398, #446) has touched setup-python anywhere. Both
lines need a hand.

Why this matters here specifically. agent-reaper.yml is the only thing that reclaims dead
claim refs (AGENTS.md §Concurrent GitHub Flow: "the scheduled reaper … is the only thing that
may"). It runs unattended on a schedule with contents: write and issues: write, and nobody
watches it the way a PR check gets watched. A reviewer reading the file cannot tell what is actually
executing, because the comment is the only human-readable statement of the version and it is false
in both lines.

This is a hygiene and accuracy defect, not a vulnerability. SHA pinning is the secure practice
and it is intact — both pins are immutable and resolve, so there is no injection or tag-move
exposure and no reason for the private advisory flow. What is broken is that the labels cannot be
trusted, and that one pin is over two and a half years stale relative to the rest of the repository.

Acceptance criteria

Superseded by the grooming block at the end of this issue, which is authoritative.

Scope and non-goals

In scope: .github/workflows/agent-reaper.yml only — two lines, no logic change, no permissions
change, no change to the sweep behaviour and no change to .agents/bin/reaper.py.

Out of scope: every other workflow (all already correct, re-verified in the sweep that found this
and again on 2026-08-13); any other dependency bump; and a repository-wide check that every
uses: <action>@<40-hex> # <tag> comment resolves to that tag
— that is the durable fix for the
class rather than the instance, but it is a new CI job or test and belongs in its own issue rather
than being absorbed here. #448 is the narrow, already-filed member of that family (one action, one
guard).

Size estimate

XS — up to 50 added lines

Risk level

high — the lane, and a Greptile credit is worth spending if the seat has budget

Stated as high because the form's own guidance puts CI and dependency changes there, and because
criterion 2 genuinely changes which third-party code executes in a scheduled workflow that holds
contents: write. The diff is two lines; the scrutiny is for what those two lines run, not for
their size.

Does this need an architecture decision record?

no — a pin correction inside an existing workflow; no schema, dependency-isolation, architectural or
scientifically consequential choice.

Dependencies / blockers

none

Execution autonomy

agent-can-do-alone

Related work / file overlap

Found while finishing #189 / #434 and deliberately not absorbed into it, per AGENTS.md §Outcome
and authority ("Do not absorb unrelated discoveries"). No file overlap with #434, which touched
wiki/Home.md and .github/workflows/wiki.yml only. #448 is the sibling issue on the same defect
family. Duplicate search returned nothing for setup-python pin, action pin SHA, agent-reaper,
checkout v5.0.1 and pinned action version comment across open and closed issues.

Target area

CI / repository governance

Milestone

none / cross-cutting

Required safety attestations

  • I searched existing issues and this is not a duplicate.
  • I am not reporting a vulnerability publicly; security reports use the private advisory flow.
  • I included no secrets or private, raw, unlicensed, user, or lab data.

Grooming status — 2026-08-13

  • Status: unblocked.
  • Open dependencies: none.
  • Autonomy: agent-can-do-alone.
  • Why it is agent-doable: both target versions are determinable from the upstream repositories
    with git ls-remote --tags, the edit is two lines, and the verification is a dry-run
    workflow_dispatch the agent can trigger. No new version is chosen — criterion 2 adopts the value
    six other pins in this repository already carry.
  • Chosen design: keep the actions/checkout SHA and fix only its label; move
    actions/setup-python onto 5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0, the repository's
    existing consensus pin, rather than onto real v5.4.0. That makes all seven setup-python pins
    agree and puts the reaper on the same code four ci.yml jobs and docs.yml already run.
  • Counting note — do not use git grep -c for the before/after numbers below. It prints one
    path:count line per matching file (13 of them for the actions/checkout pattern), never the
    total, and at zero matches it prints nothing and exits 1. Use a form that emits the number, and
    -F since every pattern here is a fixed string:
    • WSL bash: git grep -o -F "<pattern>" -- .github/ | wc -l
    • native PowerShell: (git grep -o -F "<pattern>" -- .github/ | Measure-Object -Line).Lines
  • Review risk: high. Two lines, but one of them changes which third-party code executes in a
    scheduled workflow holding contents: write and issues: write. Spend a Greptile credit if the
    seat has budget (read the balance first with <py> .agents/bin/greptile_usage.py).
  • Terminal condition: PR-ready handoff. No merge authority is granted here; a maintainer arms
    the merge.

Acceptance criteria

  • The actions/checkout line in .github/workflows/agent-reaper.yml keeps SHA
    3d3c42e5aac5ba805825da76410c181273ba90b1 unchanged and its trailing comment reads # v7.0.1.
    Counted with the command form above, over -- .github/:
    3d3c42e5aac5ba805825da76410c181273ba90b1 # v5.0.1 is 1 today and 0 after, and
    3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 is 20 today and 21 after.

  • actions/setup-python in that workflow is pinned to
    5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0. Counted the same way:
    actions/setup-python@e9d6f990972a57673cdb72ec29e19d42ba28880f is 1 today and 0 after;
    actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 goes from 6 to
    7.

  • Both post-edit SHAs are re-resolved against the upstream repositories and the resolved tag is
    quoted in the PR, so the fix is verified rather than asserted. git ls-remote --tags https://github.com/actions/checkout must print refs/tags/v7.0.1 at
    3d3c42e5aac5ba805825da76410c181273ba90b1, and git ls-remote --tags https://github.com/actions/setup-python must print refs/tags/v7.0.0 at
    5fda3b95a4ea91299a34e894583c3862153e4b97. Filter with | grep <sha> in WSL bash or
    | Select-String <sha> in native PowerShell. A comment may name only a tag one of those
    commands actually printed. Do not soften this to "it matches what the other 20 files say"
    the repository agreeing with itself is exactly how a 21st wrong label gets written, and ci(deps): Bump the actions group with 2 updates #398
    shows a bump carrying a wrong label forward untouched.

  • The new setup-python pin is shown to serve python-version: "3.12" from inside this
    repository, not by appeal to upstream release notes:
    git grep -A3 -F "actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97" -- .github/
    shows python-version: "3.12" under all six existing call sites, four of which are ci.yml
    jobs behind required contexts. Quote that in the PR.

  • The reaper still works on the new setup-python: a dry-run workflow_dispatch run of
    agent-reaper.yml on the agent's own branch is green and its run URL is linked in the PR.
    gh workflow run agent-reaper.yml --ref agent/issue-437 -f dry_run=true — which resolves only
    after agent/issue-437 has been pushed to origin, so push first. This is the only pre-merge
    exercise available: the schedule trigger only ever runs the default branch, so a post-merge
    green sweep is not evidence for the PR. A dry_run=true dispatch is authorized here and
    mutates nothing — the workflow's step runs python .agents/bin/reaper.py --dry-run (not
    claim.py), which reports only; workflow_dispatch.inputs.dry_run already defaults to true
    and the step's DRY_RUN is ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }},
    so leaving the input alone is the read-only path. Never dispatch it with dry_run=false: a
    live sweep deletes claim refs, and AGENTS.md reserves that to the schedule. The workflow's
    concurrency group is agent-reaper with cancel-in-progress: false, so the run may queue
    behind a scheduled sweep — read its conclusion before quoting it, and quote the conclusion, not
    the fact that it started.

  • If the dispatch cannot be performed — the operator's permission layer refuses it, or the run
    cannot be read — say exactly that in the PR in those words and hand off. Do not imply the run
    happened, and do not substitute a static assertion for it.

  • The change is confined: git diff --name-only origin/main...HEAD prints exactly
    .github/workflows/agent-reaper.yml, and the diff of that file touches only the two uses:
    lines' trailing comment and SHA. No permissions: block change, no concurrency change, no
    sweep-behaviour change, no .agents/bin/reaper.py change, no other workflow.

  • Local gates green: pre-commit run --all-files and the test-matrix line for your lane from
    AGENTS.md §Local gates before review. No docs or schema change, so mkdocs build --strict
    and scripts/dump_schema.py --check are not required — say so in the PR rather than leaving it
    ambiguous.

  • Ready condition: met; awaiting a fresh exact-scope marker.

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:P2Mediumrisk:highDeclared risk: high. Routes nothing - every PR walks the same lane. May only increase.size:XSDiff budget <=50 changed lines (excl. lockfiles/generated)status:readyReadytype:ciCI/CD

    Projects

    Status
    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions