Skip to content

gh-aw activation CLI pin decays silently every release — no drift guard #1825

Closed

Description

@bradygaster

Problem

The gh-aw activation workflow pins SQUAD_CLI_VERSION to a fixed released version. That pin decays silently with every npm release and there is no mechanism that detects it.

Evidence

  • Pin introduced 2026-08-07 in 60032b5b, referencing 0.11.0. It was correct that day — v0.11.0 published 2026-06-30, and v0.12.0 did not exist yet.
  • v0.12.0 published 2026-08-13. The pin became stale with nobody touching it.
  • git log -S shows the pin line has been modified exactly once, ever — at introduction.
  • It ran 8 days undetected and was caught only because an agent chose to run a cold start against a throwaway repo. Fixed manually in PR fix(gh-aw): bump activation CLI pin 0.11.0 → 0.12.0 (new-repo readiness) #1818.

This is structural decay, not sloppiness: every release silently re-breaks new-repo activation.

Why a fixed pin is still correct

Activation runs on an unrestricted-network job and hands state to the sandboxed agent job. A bad point release mid-hop is expensive to debug. Reproducibility argues for pinning. The pin is not the problem — the absence of a drift mechanism is.

⚠️ Trap for whoever implements this

Do NOT derive the pin from in-repo packages/squad-cli/package.json. It currently reads 0.13.0 — an unpublished version that resolves to E404 on npm, with 3 pending unmerged changesets. Automating from it would drive straight into the exact failure PR #1818 just fixed.

A guard must compare two independent sources: the workflow file's pin versus the highest published release tag (or npm dist-tags). Anything that reads the thing it guards is decoration, per .squad/decisions.md:604.

Current npm state for reference: dist-tags = { latest: 0.12.0, insider: 0.12.0, preview: 0.8.17-preview }.

Suggested direction

  1. Release-time bump — the release flow updates the pin as part of publishing.
  2. CI guard as backstop — compare pin against highest published release tag; fail if behind. This catches the case where (1) is skipped or a release happens out-of-band.

Both are wanted. (1) alone reintroduces the failure whenever someone releases manually; (2) alone leaves a red build with no fix path.

Note

The pin was one minor version behind (0.11.0 vs published 0.12.0), not two. The in-repo 0.13.0 is unpublished and does not count.

Owners

FIDO (CI guard) with EECOM (release flow).

Activity

  1. added
    squadSquad triage inbox — Lead will assign to a member
    on Aug 23, 2026
  2. bradygaster commented on Aug 23, 2026

    @bradygaster
    CollaboratorAuthor

    1. Owner & rationale

    Owner: squad:surgeon. This is release hygiene around the activation CLI pin; Surgeon owns release-manager flow, with Booster as CI backstop reviewer.

    Labels reconciled as: gh-aw, type:bug, priority:p1, wave:1-next, squad:surgeon, triaged, go:spec-ready.

    2. Files in scope

    Verified existing paths:

    • workflows/shared/squad.md
    • .github/workflows/squad-release.yml
    • .github/workflows/squad-standalone-release.yml
    • templates/workflows/squad-release.yml
    • test/release.test.ts
    • test/promote-insider-tag.test.ts
    • test/publish-policy.test.ts

    3. Reproduction / measurement

    These commands were execution-tested and use no output suppression:

    Select-String -Path workflows\shared\squad.md -Pattern 'SQUAD_CLI_VERSION|@bradygaster/squad-cli@'
    npm view @bradygaster/squad-cli dist-tags --json

    They show the activation fallback pin in workflows/shared/squad.md and the currently published npm dist-tags to compare it against.

    4. Verification bar

    A CI/release guard must compare the workflow pin against the highest published npm release/dist-tag and fail when the pin lags. The guard must fail if workflows/shared/squad.md is pinned below published latest, and pass when the pin equals the intended published stable version.

    5. Traps

    Do not read packages/squad-cli/package.json as the target version. It currently reads 0.13.0, which is unpublished; npm view @bradygaster/squad-cli@0.13.0 version returns E404. The guard must compare the workflow pin against the highest published npm release / dist-tag, not an in-repo pre-release workspace version.

    6. Out of scope

    Do not switch activation to an unpinned install, change the package versioning policy, or make broad release-template refactors. Keep the fix to release-time pin maintenance plus a drift guard.

    7. Session-stall guard

    Before starting: this repo has phantom CRLF diffs (#1793). If git status shows files modified that you did not touch, run git diff --ignore-cr-at-eol. If that output is empty, the diff is line-ending churn, not real edits — run git add --renormalize . and continue. Do not halt and ask for confirmation; halting on phantom diffs is the documented cause of stuck sessions in this repo.

  3. bradygaster commented on Aug 24, 2026

    @bradygaster
    CollaboratorAuthor

    Half of this shipped in #1855 (merged). Leaving this open for the other half.

    Measured first: the pin is 0.12.0 and npm dist-tags.latest is 0.12.0 — they already agree, so there was nothing to bump. This issue was never really about a stale number; it was about there being no mechanism to notice when it does go stale.

    Shipped:

    • .github/workflows/squad-cli-pin-drift.yml — daily 07:15 UTC + workflow_dispatch. Extracts the pin, compares to npm dist-tags.latest, files a de-duplicated issue and fails on drift.
    • test/squad-cli-pin.test.ts — offline self-consistency: the header comment and the env: literal cannot disagree, and the guard must read npm rather than the in-repo manifest.
    • Removed an unreachable third version literal at workflows/shared/squad.md:90. ${SQUAD_CLI_VERSION:-0.12.0} could never fire, because vars.X || '0.12.0' always yields a non-empty value. A bare ${SQUAD_CLI_VERSION} now fails loudly instead of silently masking an empty pin.

    The trap worth recording: the in-repo packages/squad-cli/package.json says 0.13.0, which is unpublished and E404s on npm. Deriving the pin from it reproduces exactly the failure PR #1818 fixed. The drift guard therefore reads npm, and a test enforces that it keeps doing so.

    Still open — the release-time half. Nothing moves the pin as part of publishing. The daily guard is a backstop: it catches drift the morning after, not at the moment it is introduced. Closing this issue now would claim a release-time guarantee that does not exist.

    Also of note for whoever picks this up: CI lints with shellcheck 0.10.0 pinned, and actionlint silently skips its shellcheck integration when shellcheck is absent from PATH. A local lint can therefore pass while CI fails — it did here (SC2016 on the markdown backticks in the issue-body printf block). Install shellcheck 0.10.0 locally before trusting a clean local run.

  4. added a commit that references this issue on Aug 25, 2026
    5a361b3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    gh-awGitHub Agentic Workflows integrationgo:spec-readyReady for formal spec/proposalpriority:p1This sprintsquadSquad triage inbox — Lead will assign to a membertriagedIssue has been triagedtype:bugSomething brokenwave:1-nextWave 1 — immediate next sprint

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions