Repository navigation
Description
RFC: Git-Notes State Solution — Solving #643, #498, #670 in One Architectural Change
Problem Statement
Three open issues share a common root cause — Squad state (.squad/) lives in the working tree:
| Issue | Problem | Impact |
|---|---|---|
| #643 | State destroyed when .squad/ is gitignored + branch switch |
Data loss — hit twice in one session on Azure CLI |
| #498 | .squad/ tracked in version control causes merge conflicts, CI noise, privacy concerns |
v1.0 blocker — must resolve before release |
| #670 | 5 independent code paths hardcode .squad/ paths with no single source of truth |
Bug factory — caused #77 (skills discovery bug) |
Prior Art
This solution draws from real-world experience documented in:
- Part 7: Enterprise State Problem — identifies the problem
- Part 7b: Git Notes & Orphan Branches — proposes the solution
Proposed Architecture
Core idea: Move Squad state from the working tree to git refs (git-notes or orphan branches), making state immune to branch switches, gitignore, and merge conflicts.
Option A: Git Notes (refs/notes/squad)
refs/notes/squad/
├── team.md (team roster — readable via git notes show)
├── routing.md (routing rules)
├── decisions.md (append-only decisions log)
├── agents/
│ ├── fido/history.md
│ ├── eecom/history.md
│ └── ...
└── casting/
├── policy.json
└── registry.json
Pros: Native git feature, survives checkout/rebase/stash, pushable/pullable
Cons: Limited tooling support, not human-browsable in GitHub UI
Option B: Orphan Branch (squad-state)
git checkout --orphan squad-state
# Branch has no parent — completely independent of main/dev
# Contains only .squad/ files
# Never merged into main/dev
# Read/written by squad CLI transparently
Pros: Full GitHub UI support (browsable), familiar git operations, works with existing CI
Cons: Slightly more complex read/write (checkout dance or worktree)
Option C: External State Directory (fallback)
~/.squad/projects/<repo-hash>/
├── team.md
├── routing.md
├── agents/...
└── ...
Pros: Zero git interaction, works for repos you don't own
Cons: Not portable, not shared across machines, no version history
Recommended Approach
Primary: Option B (orphan branch) — best balance of features and usability
Fallback: Option C (external dir) — for contributor scenarios on repos you don't own
squad build regenerates working-tree .squad/ from squad.config.ts when needed (CI, fresh clones)
How This Solves Each Issue
| Issue | How It's Solved |
|---|---|
| #643 (state destroyed) | State is in a ref, not the working tree — git checkout doesn't touch it |
| #498 (remove from VCS) | .squad/ gets gitignored; real state lives in orphan branch or external dir |
| #670 (manifest/layout) | Manifest lives in orphan branch; single source of truth for all paths |
Implementation Phases
Phase 1: State Read/Write Abstraction
- Create
StateBackendinterface (similar to StorageProvider from PR feat(sdk): StorageProvider abstraction — complete migration + example providers #640) - Implement
GitNotesBackend,OrphanBranchBackend,ExternalDirBackend - Default:
OrphanBranchBackendfor owned repos,ExternalDirBackendfor contributor mode
Phase 2: Migration
squad migrate-statecommand moves.squad/to orphan branch- Add
.squad/to.gitignore git rm -r --cached .squad/(untrack, keep on disk)- CI workflows add
squad buildstep before reading.squad/team.md
Phase 3: Integration with Manifest (#670)
- Manifest lives in orphan branch alongside state
- All 5 code paths read from StateBackend instead of filesystem directly
squad doctorvalidates state backend health
Questions for Discussion
- Orphan branch name:
squad-statevsrefs/squad/statevs something else? - Should state be per-branch (branch-specific decisions) or global (one state for all branches)?
- How does this interact with worktree-based agent isolation?
- Should we support both Options A and B, or pick one?
Related
- Squad state destroyed when .squad/ is gitignored and agents switch branches #643 (state destroyed on branch switch)
- PRD: Remove .squad/ from version control before v1.0 #498 (remove .squad/ from VCS)
- PRD: Versioned file layout manifest - single source of truth for directory structure #670 (versioned file layout manifest)
- PR feat(sdk): StorageProvider abstraction — complete migration + example providers #640 (StorageProvider abstraction — similar pattern)
- Blog: Part 7b
Activity
github-actions commentedon Mar 29, 2026
📋 Assigned to Flight (Lead)
Issue: #678 — RFC: Git-Notes State Solution — solve state destruction, VCS removal, and layout manifest in one architectural change
Flight will pick this up in the next Copilot session.
github-actions commentedon Mar 29, 2026
🏗️ Squad Triage — Flight (Lead)
Issue: #678 — RFC: Git-Notes State Solution — solve state destruction, VCS removal, and layout manifest in one architectural change
Assigned to: FIDO (Quality Owner)
Reason: Issue relates to testing/quality work
@copilot evaluation: 🔴 Not suitable — issue involves work outside the coding agent's capability profile.
Team roster:
squad:flightsquad:proceduressquad:eecomsquad:fidosquad:paosquad:capcomsquad:controlsquad:surgeonsquad:boostersquad:gncsquad:networksquad:retrosquad:incosquad:guidosquad:telemetrysquad:voxsquad:dskysquad:simssquad:handbooksquad:ralphsquad:copilotgithub-actions commentedon Mar 29, 2026
📋 Assigned to EECOM (Core Dev)
Issue: #678 — RFC: Git-Notes State Solution — solve state destruction, VCS removal, and layout manifest in one architectural change
EECOM will pick this up in the next Copilot session.
feat(sdk): StateBackend POC — orphan branch state persistence (#678)
tamirdresher commentedon Mar 29, 2026
Update: Relationship with PR #640 (StorageProvider)
@diberry posted an excellent analysis on PR #640 about how StateBackend (#680) and StorageProvider (#640) compose:
They're complementary layers:
.squad/state live? (location strategy)Composition:
OrphanBranchBackend→ uses git plumbing directly (no StorageProvider needed)FilesystemBackend→ should delegate to StorageProvider after feat(sdk): StorageProvider abstraction — complete migration + example providers #640 mergesMerge order: #640 first → then #680 adapts
FilesystemBackendto wrapStorageProviderinstead of rawnode:fs. Since #680 is DO NOT MERGE (POC), this is natural.See full analysis: https://github.com/bradygaster/squad/pull/640#issuecomment-4150187509
diberry commentedon Mar 31, 2026
🔄 Ralph status: RFC — git-notes state solution. POC in PR #680 (DO NOT MERGE). Research phase. Refs #643, #498, #670.
diberry commentedon Mar 31, 2026
✅ Status Update — Issue #678
PR #680 (POC - DO NOT MERGE):
Note: This is a POC/spike. Not intended for merge — for evaluation only.
bradygaster commentedon Apr 25, 2026
Closed by #theSquadsquad triage — verified fixed/superseded in v0.9.4.