Skip to content

feat: shared squad — external state backend for multi-clone workflows#959

Draft
akubly wants to merge 4 commits intobradygaster:devfrom
akubly:akubly/shared-squad-external-state
Draft

feat: shared squad — external state backend for multi-clone workflows#959
akubly wants to merge 4 commits intobradygaster:devfrom
akubly:akubly/shared-squad-external-state

Conversation

@akubly
Copy link
Copy Markdown

@akubly akubly commented Apr 10, 2026

What

Enable sharing a single squad team across multiple repository clones by storing team state externally in a git-backed squad repo. Adds a resolution chain that discovers shared state via ~/.squad/squad-repos.json pointer files, per-clone runtime state isolation, and concurrent-safe Scribe merge via claim protocol.

Why

Large monorepo workflows (e.g. repos with branch switching that destroys untracked files, multiple checkouts for parallel work, worktrees) lose .squad/ state on branch switches. Committing .squad/ to the repo isn't practical when the team is local. This feature externalizes squad state so it survives branch operations and can be shared across clones, machines, and worktrees.

Closes #958

How

Resolution chain (priority order):

  1. Local .squad/ directory (unchanged, always wins)
  2. SQUAD_REPO_KEY env -> lookupByKeyAcrossRepos() (checks git-backed pointers first, falls back to legacy)
  3. URL-based discovery via origin remote -> lookupByUrlAcrossRepos() (same pointer-first strategy)
  4. Legacy fallback
  5. Init Mode (no squad found)

Key components:

  • shared-squad.ts -- Registry CRUD, URL matching, git-backed repo pointers, path traversal validation
  • clone-state.ts -- Per-clone runtime state (projectDir), generic leaf name handling to avoid collisions
  • scribe-merge.ts -- Claim protocol for concurrent inbox merging (atomic claim files prevent last-writer-wins)
  • resolution-base.ts -- Shared primitives extracted to break circular dependency between resolution.ts and shared-squad.ts
  • CLI commands: squad shared status|add-url|list|doctor|diagnose
  • squad init --shared and squad migrate --to shared
  • .squad/ validation: walk-up now requires team.md or agents/ to avoid false positive on config directories

Security hardening:

  • Path traversal validation on repo keys (F1)
  • Agent name injection prevention in journal filenames (F5)
  • Symlink/junction redirect detection via realpathSync (F7)
  • Origin-only remote reading (F4)

Quick Check

  • If SDK/CLI source files changed: completed the applicable Changeset step below

PR Readiness Checklist

Branch and Commit

  • Branch created from dev (not main)
  • Branch is up to date with dev
  • Verified diff contains only intended changes (36 files)
  • PR is not in draft mode (mark ready when checks pass)
  • Commit history is clean (single squashed commit)

Build and Test

  • npm run build passes (pre-existing node-pty error only)
  • npm test passes -- 259/260 feature tests pass, 0 regressions
  • npm run lint passes
  • npm run lint:eslint passes (0 errors)
  • Test output summary included below (36+ files changed)

Test Output Summary

Feature tests (11 files, 260 tests): 259 passed, 1 skipped, 0 failed.
Full suite (220 files): 214 passed, 5 failed (pre-existing), 1 skipped.
Pre-existing failures: docs-build (Astro), cli-packaging-smoke (node-pty), 3 vitest timeouts.

Changeset

  • Changeset added via npx changeset add (minor for both squad-sdk and squad-cli)

Docs

  • N/A -- Design proposal at docs/proposals/ to be added in follow-up

Exports

  • package.json subpath exports updated (new modules: shared-squad, clone-state, scribe-merge, resolution-base)

Breaking Changes

None -- new feature, existing resolution behavior preserved via fallback chain.

Waivers

None required.

Copy link
Copy Markdown
Author

@akubly akubly left a comment

Choose a reason for hiding this comment

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

Code review panel findings.

Comment thread packages/squad-sdk/src/resolution.ts Outdated
Comment thread packages/squad-sdk/src/scribe-merge.ts Outdated
Comment thread packages/squad-sdk/src/clone-state.ts Outdated
Comment thread packages/squad-sdk/src/tools/index.ts
Comment thread packages/squad-sdk/src/shared-squad.ts
Comment thread packages/squad-sdk/src/resolution.ts
Comment thread packages/squad-sdk/src/shared-squad.ts Outdated
Comment thread packages/squad-cli/src/cli/commands/migrate.ts Outdated
Comment thread packages/squad-sdk/src/resolution.ts
Comment thread packages/squad-sdk/src/index.ts
akubly pushed a commit to akubly/squad that referenced this pull request Apr 11, 2026
…ROVE

Orchestration log entries:
- Flight: Structural review APPROVE (upgraded from REQUEST CHANGES)
- EECOM: Runtime review APPROVE (upgraded from APPROVE WITH NOTES)
- RETRO: Security review APPROVE (maintained)
- FIDO: Test verification APPROVE (upgraded)

Session log:
- All 8 original findings verified resolved
- Test results: 368 passed, 0 failed
- SDK builds clean
- Ready for merge

Decision inbox merged:
- 9 decision entries from agent inboxes (2025-2026)
- All entries dated and formatted per YYYY-MM-DD standard
- No duplicates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@akubly akubly marked this pull request as ready for review April 11, 2026 00:40
Copilot AI review requested due to automatic review settings April 11, 2026 00:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds “shared squad” support so squad state can live outside a repo (global app data or git-backed squad repos) and be auto-discovered across multiple clones/worktrees via origin URL matching and a global registry.

Changes:

  • SDK: introduce shared squad registry + URL normalization, clone-local state directories, shared-mode resolution, and Scribe inbox merge claim protocol.
  • CLI: add init --shared, shared <subcommand> management commands, and migrate --to shared workflow.
  • Tests/docs: extensive new test coverage for shared mode, clone state, URL normalization, and journal/merge behavior; update Scribe charter + decisions log.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/tools.test.ts Updates ToolRegistry tests for journal/inbox write pattern and injected ResolvedSquadPaths.
test/speed-gates.test.ts Adjusts help output line-count gate.
test/shared-squad.test.ts New tests for repo-key/write-path validation, sanitization, and registry CRUD.
test/sdk-feature-parity.test.ts Updates worktree-awareness tests to satisfy new squad-dir recognition rules.
test/scribe-merge.test.ts New tests for claim protocol merge behavior, dedup, recovery, sorting, wrappers.
test/resolution.test.ts Updates resolution tests to satisfy new squad-dir recognition rules.
test/resolution-shared-mode.test.ts New tests covering shared-mode resolution chain + env var behaviors.
test/platform-adapter.test.ts Adds test coverage for normalizeRemoteUrl across GitHub/ADO URL forms.
test/multi-squad.test.ts Updates documentation expectation in test around Windows appdata behavior.
test/integration.test.ts Updates integration test to assert memory writes go to inbox (journal pattern).
test/dual-root-resolver.test.ts Updates scaffolding to create team.md for squad dir recognition.
test/clone-state.test.ts New tests for clone-local state directory derivation/collision handling.
test/cli/shared.test.ts New tests for shared CLI commands + migrate-to-shared flow.
packages/squad-sdk/src/tools/index.ts Adds ResolvedSquadPaths support and journal/inbox write behavior for decide/memory.
packages/squad-sdk/src/storage/fs-storage-provider.ts Adds SQUAD_CASE_SENSITIVE override for case-sensitivity handling.
packages/squad-sdk/src/shared-squad.ts New shared-squad registry + validation + pointer lookup + shared discovery helpers.
packages/squad-sdk/src/scribe-merge.ts New claim-protocol merge implementation and convenience wrappers.
packages/squad-sdk/src/resolution.ts Extends resolution chain with shared-mode discovery; tightens squad-dir recognition.
packages/squad-sdk/src/resolution-base.ts New cycle-breaking shared primitives/types for resolution/shared-squad modules.
packages/squad-sdk/src/platform/index.ts Re-exports normalizeRemoteUrl and related types.
packages/squad-sdk/src/platform/detect.ts Implements normalizeRemoteUrl and NormalizedRemote type.
packages/squad-sdk/src/index.ts Expands public exports for shared squad, clone state, merge helpers, URL normalization.
packages/squad-sdk/src/clone-state.ts New module for per-clone runtime state directories under local app data.
packages/squad-sdk/package.json Adds subpath exports for new SDK modules.
packages/squad-cli/src/cli/core/init.ts Warns on init when a shared squad already exists for the repo.
packages/squad-cli/src/cli/commands/shared.ts New squad shared subcommand implementation (status/list/doctor/diagnose/add-url).
packages/squad-cli/src/cli/commands/migrate.ts Adds --to shared migration flow and optional cleanup behavior.
packages/squad-cli/src/cli/commands/init-shared.ts New init --shared command to create/connect to shared squads.
packages/squad-cli/src/cli/commands/doctor.ts Adds “shared” mode detection/checks to doctor.
packages/squad-cli/src/cli-entry.ts Wires new CLI flags/commands into entrypoint help + routing.
packages/squad-cli/package.json Adds CLI subpath exports for new commands; version bump.
package.json Version bump for root package.
.squad/orchestration-log/2026-04-10T234927Z-retro-rereview.md Adds logged security re-review outcome.
.squad/orchestration-log/2026-04-10T234927Z-flight-rereview.md Adds logged structural re-review outcome.
.squad/orchestration-log/2026-04-10T234927Z-fido-rereview.md Adds logged test verification re-review outcome.
.squad/orchestration-log/2026-04-10T234927Z-eecom-rereview.md Adds logged runtime re-review outcome.
.squad/log/2026-04-10T234927Z-pr959-rereview-session.md Adds logged panel session summary.
.squad/decisions.md Records decisions related to shared mode/journal pattern/merge protocol.
.squad/agents/scribe/charter.md Updates Scribe charter to include history inbox merge workflow.
.changeset/shared-squad-external-state.md Adds changeset for SDK+CLI minor releases.

Comment thread packages/squad-sdk/src/shared-squad.ts Outdated
Comment thread packages/squad-sdk/src/shared-squad.ts Outdated
Comment thread packages/squad-sdk/src/tools/index.ts
Comment thread packages/squad-sdk/src/scribe-merge.ts
Comment thread packages/squad-cli/src/cli/commands/migrate.ts Outdated
Comment thread packages/squad-sdk/src/tools/index.ts
Comment thread packages/squad-sdk/src/tools/index.ts Outdated
akubly pushed a commit to akubly/squad that referenced this pull request Apr 21, 2026
…ROVE

Orchestration log entries:
- Flight: Structural review APPROVE (upgraded from REQUEST CHANGES)
- EECOM: Runtime review APPROVE (upgraded from APPROVE WITH NOTES)
- RETRO: Security review APPROVE (maintained)
- FIDO: Test verification APPROVE (upgraded)

Session log:
- All 8 original findings verified resolved
- Test results: 368 passed, 0 failed
- SDK builds clean
- Ready for merge

Decision inbox merged:
- 9 decision entries from agent inboxes (2025-2026)
- All entries dated and formatted per YYYY-MM-DD standard
- No duplicates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@akubly akubly force-pushed the akubly/shared-squad-external-state branch from 1f37d97 to 254876b Compare April 21, 2026 20:01
Enable sharing a single squad team across multiple repository clones by
storing team state externally. Supports git-backed squad repos with a
~/.squad/squad-repos.json pointer file, per-clone runtime state isolation,
and concurrent-safe Scribe merge via claim protocol.

Key components:
- Registry CRUD and URL matching (shared-squad.ts)
- Per-clone runtime state isolation (clone-state.ts)
- Concurrent-safe Scribe merge with claim protocol (scribe-merge.ts)
- CLI commands: squad shared status|add-url|list|doctor|diagnose
- squad init --shared and squad migrate --to shared
- Resolution chain: local → SQUAD_REPO_KEY → git-backed pointers → legacy
- .squad/ validation: requires team.md or agents/ to be a team root

Closes bradygaster#958

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@akubly akubly force-pushed the akubly/shared-squad-external-state branch from 254876b to ca5b36a Compare April 21, 2026 20:19
@akubly akubly marked this pull request as draft April 21, 2026 20:23
Aaron Kubly and others added 3 commits April 21, 2026 15:27
Adds the shared strategy (git-backed squad repos via ~/.squad/squad-repos.json
pointer files) to the Worktree Awareness section. The coordinator now checks
pointer files before falling back to platform app data, preventing sessions
from failing to find shared squads after migration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The coordinator was short-circuiting after local .squad/ checks because
the top-level decision said 'No → Init Mode' without requiring the full
resolution chain. Now the 4-step chain (local → shared registry →
app data → worktree) is inline at the decision point with a bold
warning that ALL steps must be attempted before concluding Init Mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Enables creating shared squads in git-backed squad repo clones instead
of platform app data. Usage:

  squad init --shared --squad-repo D:\git\akubly.squad

Creates team scaffolding at {squad-repo}/{key}/, registers in the
clone's repos.json, and auto-adds the clone to ~/.squad/squad-repos.json
for discovery. Also fixes init --shared to check git-backed pointers
before concluding no existing squad exists.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: shared squad — external state backend for multi-clone workflows

2 participants