Skip to content

fix(cli): squad upgrade silently overwrites and can downgrade .github/agents/squad.agent.md #1589

Closed

Description

@bradygaster

Summary

squad upgrade overwrites .github/agents/squad.agent.md unconditionally, with no customization warning and no version check. If the bundled template is older than what is on disk, the coordinator is silently downgraded — including reverting merged, committed hardening.

This is not hypothetical. It happened in this repo on 2026-08-02 and shadowed #1537.

What happened

.github/agents/squad.agent.md was written to disk at 20:58:35 with pre-merge content. Four minutes later, cd6961e9 merged #1537 (squad/dispatch-enforcement, @tamirdresher) into dev.

Because the file was already dirty, git left it alone. The working copy then sat byte-identical to the pre-merge commit:

on-disk    2c9b5993
parent 1   2c9b5993   ← byte-identical (15af9864, pre-merge)
HEAD       da59cb5f   ← merge result, with the hardening

Nobody edited the file. It was written by tooling and then never advanced past the merge.

Consequence: every Copilot session in this repo since then loaded the stale coordinator. Verified by marker string — the on-disk copy contained work inline (fallback only — LAST RESORT), which does not exist in HEAD; HEAD instead says refuse, and carries the mandatory DispatchGuard bootstrap and the Direct-Mode whitelist. So Layer A tool restriction and DispatchGuard were both inert, silently, for a full day of sessions.

The irony is that the specific thing silently reverted was dispatch enforcement.

Root cause

packages/squad-cli/src/cli/core/templates.ts:33-38:

{
  source: 'squad.agent.md.template',
  destination: '../.github/agents/squad.agent.md',
  overwriteOnUpgrade: true,
  description: 'Squad coordinator agent prompt',
},

Overwriting is correct by design for consumer repos — Squad owns this file. The defects are the absent guards:

  1. No customization warning. Skills get one — upgrade.ts:744 calls warnIfSkillCustomized(srcPath, destPath, entry.source) before copying. The coordinator file, which is the single highest-impact file in the system, gets no equivalent (upgrade.ts:1176).
  2. No version/downgrade check. An older installed CLI happily overwrites a newer coordinator. Nothing compares the stamped version in the destination against the template's.
  3. No backup. The prior content is unrecoverable outside git.

Why this bites hardest in this repo

bradygaster/squad dogfoods itself. Any squad init / squad upgrade / npx @bradygaster/squad-cli run here overwrites the repo's own committed coordinator with whatever the installed CLI bundles — reverting merged PRs with no output indicating it happened.

Related: #1588 (unpinned SDK). Same family of problem — the installed artifact's contents are less pinned than they appear.

Suggested fix

At minimum, parity with the skills path:

  • Warn when the destination differs from the last-installed template (mirror warnIfSkillCustomized)
  • Compare the version stamp in the destination against the template; refuse or require --force on downgrade
  • Back up the previous file (e.g. .squad/.backup/squad.agent.md.{version}) before overwriting
  • Consider refusing to self-overwrite when the target repo is the squad repo

Repro

# in a repo with a customized/newer .github/agents/squad.agent.md
npx @bradygaster/squad-cli@<older> upgrade
git diff .github/agents/squad.agent.md   # silently reverted, no warning emitted

Found via

Investigating an unexplained 80-line "deletion" in the working tree while verifying #1587. The file was restored with git checkout (provably lossless — old content is preserved at 15af9864).

Activity

  1. bradygaster commented on Aug 30, 2026

    @bradygaster
    CollaboratorAuthor

    Related issue (Ralph triage): This is related to but not a duplicate of #1502. #1502 tracks the broader configurable runner/checkout umbrella; this issue is specifically the silent-overwrite/downgrade bug in \squad upgrade\ for .github/agents/squad.agent.md. Both should remain open and are tracked separately.

  2. added
    squadSquad triage inbox — Lead will assign to a member
    on Aug 30, 2026
  3. github-actions commented on Sep 10, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  4. github-actions commented on Sep 10, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  5. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  6. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  7. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  8. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  9. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: EECOM
    Reason: Matched module path "src/cli/" to primary owner "EECOM 🔧"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  10. github-actions commented on Sep 13, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: architect
    Reason: No module, routing, or role keyword match — routed to Lead/Architect
    Source: lead-fallback

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  11. added
    squad:cli-devAssigned to cli-dev (CLI Engineer)
    and removed
    squad:architectAssigned to architect (Lead Architect)
    on Sep 24, 2026
  12. github-actions commented on Sep 24, 2026

    @github-actions
    Contributor

    📋 Assigned to cli-dev (CLI Engineer)

    Issue: #1589 — fix(cli): squad upgrade silently overwrites and can downgrade .github/agents/squad.agent.md

    cli-dev will pick this up in the next Copilot session.

    For Copilot coding agent: If enabled, this issue will be worked automatically.
    Otherwise, start a Copilot session and say:
    cli-dev, work on issue #1589

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 integrationsquadSquad triage inbox — Lead will assign to a membersquad:cli-devAssigned to cli-dev (CLI Engineer)type:bugSomething brokenworkflows

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions