Skip to content

fix(cli): resolvable squad_state bridge spec, doctor bridge probe, versioned health, state-mcp lifecycle (2.0.0-preview.2) - #2301

Merged
tamirdresher merged 6 commits into
devfrom
squad2-preview2-bridge-fixes
Oct 24, 2026
Merged

tamirdresher merged 6 commits into
devfrom
squad2-preview2-bridge-fixes

Conversation

@tamirdresher

@tamirdresher tamirdresher commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #2296
Fixes #2300

Related to #2047, but intentionally does not change template/workflow refresh behavior.

Summary

  • generate a deterministic squad_state launch spec: direct node <installed or locally built cli-entry.js> state-mcp when available, with an exact-version npx fallback and machine-specific metadata
  • preserve repo MCP siblings, remove only matching Squad-managed hashed user declarations after backup, and dedupe project identities with realpathSync plus Windows drive-letter normalization
  • add a real stdio doctor handshake (initialize, tools/list, squad_state_health) with version, tool inventory, team-root, ETARGET, and repair diagnostics
  • include squad-state <version> and the resolved team directory in health output; tighten the coordinator handshake
  • exit state-mcp after stdin EOF, parent disconnect, SIGPIPE, or EPIPE with a 500 ms grace period
  • document Copilot lingering-session behavior and PID-only parent-gone cleanup
  • independently close the rejected fix(sdk): accept squad root in StateBackendStorageAdapter list reads #2237 root-safety gap: only list-shaped adapter operations accept root aliases; file and destructive operations, including deleteDir, reject root before backend access

Commits

  • 41ccb64e bridge resolution, doctor probe, versioned health, and lifecycle
  • 8fb93b87 isolated state-root operation guard requested by Worf
  • 78189136 CI follow-up: source-driven init/doctor use the in-repo built CLI entry instead of fetching the published package through npx

Validation

  • npm run lint
  • SKIP_BUILD_BUMP=1 npm run build
  • bridge core: 43/43
  • doctor: 59/59
  • state-mcp: 11/11 before the root-list addition; focused adapter-backed root-list integration also passes
  • upgrade portability: 20/20
  • state-root alias/operation matrix: 13/13 plus adapter-backed state-mcp root-list integration
  • exact Linux CI regressions reproduced locally after the follow-up: init scaffolding, profile teamRoot upgrade, and MCP resolution 61/61
  • adjacent suites completed: tools 94/94, clients 146/146, init 18/18, upgrade 47/47 with 1 existing skip
  • lifecycle stress: 10 direct Node bridge processes initialized, transports closed, and all PIDs returned to baseline
  • manual probe of C:\.tools\squad-2.0.0-preview.1\node_modules\@bradygaster\squad-cli\dist\cli-entry.js: initialize returned 2.0.0-preview.1, 15 tools, and health/team-dir; its missing version line is now detected by doctor

Scope notes

Copilot AI balanced review requested due to automatic review settings October 24, 2026 07:40
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

🟠 Impact Analysis — PR #2301

Risk tier: 🟠 HIGH

📊 Summary

Metric Count
Files changed 23
Files added 6
Files modified 17
Files deleted 0
Modules touched 5
Critical files 1

🎯 Risk Factors

  • 23 files changed (21-50 → HIGH)
  • 5 modules touched (5-8 → HIGH)
  • Critical files touched: packages/squad-sdk/src/tools/index.ts

📦 Modules Affected

docs (1 file)
  • docs/src/content/docs/scenarios/troubleshooting.md
root (2 files)
  • .changeset/calm-bridges-exit.md
  • .changeset/safe-state-root.md
squad-cli (8 files)
  • packages/squad-cli/src/cli/commands/doctor.ts
  • packages/squad-cli/src/cli/commands/state-mcp.ts
  • packages/squad-cli/src/cli/core/init.ts
  • packages/squad-cli/src/cli/core/managed-file.ts
  • packages/squad-cli/src/cli/core/mcp-probe.ts
  • packages/squad-cli/src/cli/core/mcp-root.ts
  • packages/squad-cli/src/cli/core/mcp-spec.ts
  • packages/squad-cli/src/cli/core/upgrade.ts
squad-sdk (3 files)
  • packages/squad-sdk/src/client/adapters/coordinator.ts
  • packages/squad-sdk/src/state-backend.ts
  • packages/squad-sdk/src/tools/index.ts
tests (9 files)
  • test/cli/doctor.test.ts
  • test/cli/state-mcp-lifecycle.test.ts
  • test/cli/state-mcp.test.ts
  • test/cli/upgrade-portability.test.ts
  • test/fixtures/fake-state-mcp.mjs
  • test/mcp-root-write.test.ts
  • test/mcp-spec-init.test.ts
  • test/npm-registry-fallback.test.ts
  • test/state-backend-root-guard.test.ts

⚠️ Critical Files

  • packages/squad-sdk/src/tools/index.ts

This report is generated automatically for every PR. See #733 for details.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

🏗️ Architectural Review

Authoritative evidence: base-controlled pull_request_target reporter.

⚠️ Architectural review: 2 warning(s).

Severity Category Finding Files
🟡 warning bootstrap-area 6 file(s) in the bootstrap area (packages/squad-cli/src/cli/core/) were modified. These files must maintain zero external dependencies. Review carefully. packages/squad-cli/src/cli/core/init.ts, packages/squad-cli/src/cli/core/managed-file.ts, packages/squad-cli/src/cli/core/mcp-probe.ts, packages/squad-cli/src/cli/core/mcp-root.ts, packages/squad-cli/src/cli/core/mcp-spec.ts, packages/squad-cli/src/cli/core/upgrade.ts
🟡 warning sweeping-refactor This PR touches 23 files (23 modified/added, 0 deleted). Large PRs are harder to review — consider splitting if possible. —

Automated architectural review — informational only.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit ac674e1

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 4 item(s) to address before review

Status Check Details
❌ Single commit 6 commits — consider squashing before review
✅ 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 5 unresolved Copilot thread(s) — fix and resolve before merging
❌ CI passing 1 check(s) failing: Verify exact SHA and build evidence

Files Changed (23 files, +1416 −262)

File +/−
.changeset/calm-bridges-exit.md +6 −0
.changeset/safe-state-root.md +5 −0
docs/src/content/docs/scenarios/troubleshooting.md +37 −0
packages/squad-cli/src/cli/commands/doctor.ts +80 −0
packages/squad-cli/src/cli/commands/state-mcp.ts +39 −1
packages/squad-cli/src/cli/core/init.ts +15 −1
packages/squad-cli/src/cli/core/managed-file.ts +35 −6
packages/squad-cli/src/cli/core/mcp-probe.ts +234 −0
packages/squad-cli/src/cli/core/mcp-root.ts +117 −4
packages/squad-cli/src/cli/core/mcp-spec.ts +70 −92
packages/squad-cli/src/cli/core/upgrade.ts +19 −6
packages/squad-sdk/src/client/adapters/coordinator.ts +1 −1
packages/squad-sdk/src/state-backend.ts +77 −36
packages/squad-sdk/src/tools/index.ts +9 −3
test/cli/doctor.test.ts +64 −1
test/cli/state-mcp-lifecycle.test.ts +129 −0
test/cli/state-mcp.test.ts +49 −0
test/cli/upgrade-portability.test.ts +17 −9
test/fixtures/fake-state-mcp.mjs +46 −0
test/mcp-root-write.test.ts +229 −3
test/mcp-spec-init.test.ts +38 −84
test/npm-registry-fallback.test.ts +8 −15
test/state-backend-root-guard.test.ts +92 −0

Total: +1416 −262


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved shutdown, declaration-migration, and bridge-validation defects undermine the intended reliability improvements.

6 open issues
What changed in this PR

This PR improves Squad’s state bridge launch reliability, diagnostics, and shutdown behavior for #2296 and #2300. Template/workflow refresh behavior remains outside its scope.

Changes:

  • Prefer installed launchers with exact-version fallback metadata and remove matching legacy user declarations.
  • Add doctor handshake checks, versioned health output, and stricter projected coordinator checks.
  • Add transport-shutdown handling, regression tests, and process-cleanup guidance.
File Description
test/​npm-registry-fallback.test.ts Verify deterministic exact-version fallback.
test/​mcp-spec-init.test.ts Cover installed launchers and fallback selection.
test/​mcp-root-write.test.ts Test metadata, legacy cleanup, and project identities.
test/​fixtures/​fake-state-mcp.mjs Provide a configurable bridge-probe fixture.
test/​cli/​upgrade-portability.test.ts Update launch-spec and metadata expectations.
test/​cli/​state-mcp.test.ts Check versioned health output.
test/​cli/​state-mcp-lifecycle.test.ts Check process exit after stdin closure.
test/​cli/​doctor.test.ts Cover bridge handshake and launch diagnostics.
packages/​squad-sdk/​src/​tools/​index.ts Add runtime version to health output.
packages/​squad-sdk/​src/​client/​adapters/​coordinator.ts Tighten projected coordinator handshake requirements.
packages/​squad-cli/​src/​cli/​core/​upgrade.ts Reconcile legacy declarations during upgrade.
packages/​squad-cli/​src/​cli/​core/​mcp-spec.ts Resolve direct launchers and exact-version fallbacks.
packages/​squad-cli/​src/​cli/​core/​mcp-root.ts Record metadata and reconcile hashed registrations.
packages/​squad-cli/​src/​cli/​core/​mcp-probe.ts Resolve and probe configured bridges over stdio.
packages/​squad-cli/​src/​cli/​core/​init.ts Reconcile legacy declarations during initialization.
packages/​squad-cli/​src/​cli/​commands/​state-mcp.ts Add shutdown handlers and runtime-version propagation.
packages/​squad-cli/​src/​cli/​commands/​doctor.ts Validate bridge version, health, and team directory.
docs/​src/​content/​docs/​scenarios/​troubleshooting.md Document lingering sessions and targeted cleanup.
.changeset/​calm-bridges-exit.md Record CLI and SDK patch changes.

Review effort: Balanced

};
}

const expectedTeamDir = path.resolve(effectiveSquadDir(cwd).stateDir);
process.stdout.on('error', onStdoutError);

try {
await server.connect(transport);
) {
return undefined;
}
return { command: entry.command, args: entry.args as string[] };
Comment on lines +323 to +324
const paths = [normalizeSquadProjectPath(dest), normalizeDriveLetter(path.resolve(dest))];
return [...new Set(paths.map(value => `squad_state_${simpleHash(value)}`))];
success(`removed stale squad_state from ${tomb.path} (now lives in .mcp.json)`);
filesUpdated.push('.copilot/mcp-config.json (tombstoned)');
}
const userConfig = reconcileSquadStateUserConfig(dest);
14. **Fact Checker (verification and devil's advocate).** Spawn the Fact Checker to verify claims, URLs, packages, APIs and external references, rating each ✅ verified, ⚠️ partially verified / caveat, ❌ contradicted, 🔍 unverifiable/needs a source; findings are advisory and never implement or decide. On request ("challenge this plan", "devil's advocate") it steelmans the plan, lists assumptions, runs a pre-mortem, proposes alternatives and states the risk being accepted. Audit trail: \`${S}/fact-checker/audit-trail.md\`.
15. **Ceremonies.** Read \`${S}/ceremonies.md\`. Before spawning work, run any ceremony whose trigger is \`before\` (e.g. design review) and after work completes run \`after\` ceremonies (e.g. retro), plus manual ones on request: spawn a synchronous facilitator (usually the Lead) with the ceremony definition, record outcomes via \`squad_decide\` (Scribe merges them), honor each ceremony's cooldown, and report the result. Details: \`${S}/templates/ceremony-reference.md\`.
16. **Memory governance and state-backend handshake.** Before any state write, check \`squad_state_health\` once per session (it reports the backend: local, orphan, two-layer...). Use governed runtime tools only: \`squad_decide\` for decisions, \`squad_state_*\` for runtime state, and \`memory.*\` tools (classify/search/write/promote/delete/audit) when the MCP server exposes them. Never claim memory you cannot persist. If the bridge is unavailable for a non-local backend, stop and say so. Capture persistent user directives ("always...", "never...") via \`squad_decide\`, acknowledge them, and dispatch any implementation separately.
16. **Memory governance and state-backend handshake.** Before any state write, check \`squad_state_health\` once per session. Require its \`squad-state <version>\` line to match this coordinator's stamped Squad version and its \`Team squad dir:\` line to match the resolved \`${S}\`; an older/misdirected bridge is unavailable, not healthy. It also reports the backend (local, orphan, two-layer...). Use governed runtime tools only: \`squad_decide\` for decisions, \`squad_state_*\` for runtime state, and \`memory.*\` tools (classify/search/write/promote/delete/audit) when the MCP server exposes them. Never claim memory you cannot persist. If the bridge is unavailable for a non-local backend, stop and say so. Capture persistent user directives ("always...", "never...") via \`squad_decide\`, acknowledge them, and dispatch any implementation separately.
@tamirdresher
tamirdresher force-pushed the squad2-preview2-bridge-fixes branch from a2adbef to 54dc3c0 Compare October 24, 2026 07:56
Geordi (Squad) and others added 3 commits October 24, 2026 11:48
Fixes #2296 and #2300.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
Accept state-root aliases only for list-shaped operations and reject file or destructive root access before it reaches the backend.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
Use packages/squad-cli/dist/cli-entry.js when init and doctor run from source, avoiding an npx registry fetch in CI and contributor environments.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
@tamirdresher
tamirdresher force-pushed the squad2-preview2-bridge-fixes branch from 54dc3c0 to 7818913 Compare October 24, 2026 08:52
Include the raw resolved-path hash and the original SHA-256 key format when removing legacy user-level squad_state entries. Add independent Windows and POSIX regression coverage that preserves unrelated registrations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
Update upgrade portability coverage for the direct Node source entry while retaining an exact-version npx fallback assertion for installed deployments.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
Write reconciled user MCP config through a flushed sibling and atomic rename, with fault-injection coverage that preserves the original. Give the real cold two-layer health integration a documented bounded Windows budget.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
@tamirdresher

Copy link
Copy Markdown
Collaborator Author

Addresses review findings BR-1, BR-5, BR-3, and BR-4.

  • 8077779a removes both historical raw-path key formats, including the Windows uppercase-drive hash, with independent Windows/POSIX regressions.
  • 5d494245 updates source-run portability coverage for direct Node + built cli-entry.js while asserting the exact-version npx fallback.
  • ac674e1e makes user-config reconciliation atomic with failure coverage and gives the cold two-layer health integration an explicit bounded timeout.

Validation: build and lint passed; 12 bridge/doctor/state/upgrade suites passed sequentially (206 passed, 1 platform skip).

@tamirdresher
tamirdresher merged commit de1c4e6 into dev Oct 24, 2026
21 of 22 checks passed
tamirdresher added a commit that referenced this pull request Oct 24, 2026
squad-release-verify.yml ran policy-gates.mjs --mode=release on pull_request
too, so every PR carrying a changeset failed the gate (#2283, #2301). The
workflow now passes --mode=ci on pull_request and --mode=release only on the
release path (workflow_call from squad-release.yml). In ci mode the gate still
runs: pending fragments are allowed but must be well-formed (allowlisted
package, patch|minor|major bump, non-empty summary); malformed ones fail.
Release mode keeps enforcing the drain unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
tamirdresher added a commit that referenced this pull request Oct 24, 2026
* fix(cli): 2.0.0-preview.2 upgrade/health fixes from dogfooding

- upgrade --self: honor --dry-run (zero exec), follow the installed channel
  (prerelease -> @insider, stable -> @latest), refuse downgrades without --force (#2295)
- upgrade: one content-compared plan for every squad-owned file; verified
  <file>.local-backup before overwrite; shipped-files manifest distinguishes user
  edits from template revisions; dry-run writes nothing and reports nothing
  right after an upgrade (also on CRLF checkouts); .gitignore/.gitattributes
  appended in the file's own EOL; retired files removed when unmodified;
  provably Squad-shipped stale .copilot/skills copies cleaned (#2297, #2266,
  #2047, #2232)
- health: table headers/placeholders never parsed as agents, built-ins are
  valid routing targets, BOM/pipe-joined legacy charters parse, missing
  identity is a warn with a hint, roster drift warns; upgrade adds built-in
  rows to team.md (#2298, #2234, #1785)
- Rai -> rai: two-step rename recorded with git mv; templates reference
  agents/rai/; init scaffolds rai/ (#2299)
- squad client list|add, dry-run header shows project name, update-check
  stale cache, squad_decide workstream inbox + 80-char slug, doctor Mode: local
  for same-project teamRoot and no DEP0190 (#2299, #2174)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9

* fix(release): make the changeset-drain policy gate event-aware

squad-release-verify.yml ran policy-gates.mjs --mode=release on pull_request
too, so every PR carrying a changeset failed the gate (#2283, #2301). The
workflow now passes --mode=ci on pull_request and --mode=release only on the
release path (workflow_call from squad-release.yml). In ci mode the gate still
runs: pending fragments are allowed but must be well-formed (allowlisted
package, patch|minor|major bump, non-empty summary); malformed ones fail.
Release mode keeps enforcing the drain unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9

* test(cli): align legacy upgrade/help tests with content-compared upgrade and lowercase rai init

- upgrade.test: customized-skill expectations now assert the .local-backup message;
  Rai migration test recreates the legacy mixed-case layout (init scaffolds rai/)
- command-help.test: 'client' has a dedicated help block
- cli-entry: --self --dry-run returns through the single success branch (performed=false)
- team-md: never invent a roster table in a team.md without one
- .github/agents/squad.agent.md: agents/rai/ (template-sync parity)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9

* fix(cli): make optional built-ins explicit

Keep team.md byte-stable during upgrade, report unconfigured optional built-ins as informational, and add a provenance-backed roster command with exact restore semantics.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9

* fix(upgrade): preserve compound text templates

Treat compound .example templates as text for EOL-normalized planning and distinguish unproven first-upgrade provenance from confirmed customization in backup output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9

---------

Co-authored-by: B'Elanna (Squad) <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 995eea17-c356-4912-90ea-5e5b144e7ba9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants