fix(cli): follow externalized state in squad copilot and squad rc#1464
Merged
tamirdresher merged 1 commit intoJul 14, 2026
Merged
Conversation
After squad externalize, both commands kept operating on the local .squad/team.md. squad copilot edited (or scaffolded) a stale local roster the externalized project never reads, and squad rc loaded its agent list from the same dead file, so the remote UI showed an empty or stale team. squad copilot now resolves the roster through effectiveSquadDir() — the same resolution used by export, build, loop, plugin, watch, and doctor — and reads/writes team.md in the effective state dir. squad rc routes the team.md read through resolveStateDir(), extracted into an exported loadRosterAgents() so it's testable. The squadDir passed to RemoteBridge stays the local path on purpose: the bridge derives the copilot session cwd from it by stripping the /.squad suffix, so handing it the external state dir would point sessions at the wrong directory. Fixes bradygaster#1397 Fixes bradygaster#1398 Part of bradygaster#1402 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
🛫 PR Readiness Check
PR Scope: 📦🔧 Mixed (product + infrastructure)
|
| Status | Check | Details |
|---|---|---|
| ✅ | Single commit | 1 commit — clean history |
| ✅ | Not in draft | Ready for review |
| ✅ | Branch up to date | Up to date with dev |
| ❌ | Copilot review | No Copilot review yet — it may still be processing |
| ✅ | Changeset present | Changeset file found |
| ✅ | Scope clean | No .squad/ or docs/proposals/ files |
| ✅ | No merge conflicts | No merge conflicts |
| ✅ | Copilot threads resolved | No Copilot review threads |
| ❌ | CI passing | 7 check(s) still running |
Files Changed (5 files, +167 −18)
| File | +/− |
|---|---|
.changeset/fix-1397-1398-external-state-reads.md |
+5 −0 |
packages/squad-cli/src/cli/commands/copilot.ts |
+9 −9 |
packages/squad-cli/src/cli/commands/rc.ts |
+21 −8 |
test/cli/copilot.test.ts |
+63 −1 |
test/cli/rc.test.ts |
+69 −0 |
Total: +167 −18
This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.
Contributor
🟡 Impact Analysis — PR #1464Risk tier: 🟡 MEDIUM 📊 Summary
🎯 Risk Factors
📦 Modules Affectedroot (1 file)
squad-cli (2 files)
tests (2 files)
This report is generated automatically for every PR. See #733 for details. |
13 tasks
Contributor
Author
|
green and unreviewed for a couple of days now — this is the copilot/rc half of the external-state cluster, same fix pattern as #1465 which already merged |
tamirdresher
approved these changes
Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
squad copilotandsquad rcnow follow thestateLocation: externalmarker: roster reads and writes go to the external state dir instead of the local.squad/team.md.Why
Closes #1397
Closes #1398
Part of #1402
After
squad externalize, both commands kept operating on the working-tree copy.squad copilotedited (or, on add, effectively scaffolded) a local roster the externalized project never reads — the real team.md in the external dir never learned about @copilot.squad rcloaded its agent list from the same dead file, so the remote UI showed an empty or stale roster.How
commands/copilot.ts: resolves througheffectiveSquadDir()— the same external-state-aware resolution already used by export, build, loop, plugin, watch, and doctor (fix(cli): resolve externalized state in squad export #1443 precedent) — and reads/writesteam.mdin the effective state dir. The.github/copilot-instructions.mdcopy is a working-tree file and is untouched.commands/rc.ts: the roster load moves into an exportedloadRosterAgents(squadDir)that routes theteam.mdread throughresolveStateDir(). Deliberately narrow: thesquadDirpassed toRemoteBridgestays the local path, because the bridge derives the copilot session cwd from it by stripping the/.squadsuffix (packages/squad-sdk/src/remote/bridge.ts) — handing it the external state dir would point ACP sessions at the wrong directory. Only the read is redirected..ai-teambehavior is unchanged in both commands — no external marker there, resolution falls through to the local path.squad castagent discovery) is not in this PR; it crosses into squad-sdk'sresolveSquadPaths/LocalAgentSourceand lands separately.Testing
test/cli/copilot.test.ts: two new tests against a marker-only.squad/+ external state dir (the layoutsquad externalizeleaves behind, same APPDATA/XDG override pattern as the fix(cli): resolve externalized state in squad export #1443 export tests): add writes the Coding Agent section to the externalteam.mdand does not grow a local one;--offremoves it from the external file.test/cli/rc.test.ts: two new tests forloadRosterAgents— local read without the marker, and the marker redirecting to the externalteam.mdwhile a stale local roster is present (the stale copy must lose).npm run build— passes.npm run lint(tsc) — passes.npm run lint:eslint— 0 errors (pre-existing warnings only).npx vitest run test/cli/copilot.test.ts test/cli/rc.test.ts test/cli/export-import.test.ts— all four new tests pass; the export suite (adjacent feature area) passes.module exports …test in each of these two files times out at 5s on this Windows box — verified byte-identical failures on a cleanupstream/devcheckout with a clean build (stash + rebuild + rerun), so it's the documented pre-existing cold-import flakiness (same class as noted on feat(cli): add squad update-check --json for tooling/CI #1440), not this change. All other 51 tests in the two files pass.git diff --checkreports CR on added lines — expected for this file, no mixed endings introduced (git ls-files --eol:i/crlf w/crlf)..changeset/fix-1397-1398-external-state-reads.md(patch bump,@bradygaster/squad-clionly)PR Readiness Checklist
Branch & Commit
devdevgit diff --cached --stat+git diff -wwhitespace pass)Build & Test
npm run buildpassesnpm testpasses (see testing notes for the pre-existing local cold-import timeouts)npm run lintpasses (type check clean)npm run lint:eslintpasses (0 errors)Changeset
@bradygaster/squad-cli)Docs
Exports
loadRosterAgentsis a named export fromcommands/rc, which already has a subpath export; no new moduleBreaking Changes
None. Projects without the external marker resolve to the local
.squad/exactly as before.Waivers
None.