-
Notifications
You must be signed in to change notification settings - Fork 88
Description
Overview
Squad currently assumes .squad/ is co-located with the repository you're actively working in. This works well for single-repo setups, but it fundamentally breaks down for users who want clean production repos — and breaks silently, with no error message, making it look like a fresh install every time.
This issue proposes a first-class tiered Squad deployment model that spans from a single repo all the way to a personal meta-hub that monitors every squad you operate, across personal accounts and org accounts alike. Each tier supports GitHub Discussions as a communication layer — surfacing agent activity, decisions, and escalations to humans without polluting source repo backlogs.
The Core Problem
Squad resolves its team root by running git rev-parse --show-toplevel from the current working directory, then checking for .squad/ there. If nothing is found, it walks git worktree list looking for a main checkout. If that also fails, it enters Init Mode — silently, indistinguishably from a fresh install.
This means: if you open a terminal in a target repo that has no .squad/, Squad sees no team at all. The user must remember to always start sessions from the hub directory — easy to forget, not documented as required, no error when forgotten.
This cannot be fixed with documentation alone. The failure mode gives no signal that a hub exists elsewhere.
The Tiered Deployment Model
Squad should recognize and support three tiers of team state storage, each building on the one before. Every tier supports GitHub Discussions as an optional communication surface.
Tier 1 — Team (single repo)
The current default. .squad/ lives inside the source repo, or in a dedicated companion branch or companion repo for that project.
my-project/ ← source repo
.squad/ ← Squad state (current behavior)
— OR —
my-project/ ← source repo (Squad-clean)
my-project-squad/ ← private companion repo, Squad state only
Discussions at Tier 1:
my-project-squad (Discussions)
📋 Standup ← Scribe: session summaries after significant work
🚦 Decisions ← decisions posted for async human review
⚠️ Blocked ← issues an agent couldn't resolve alone
When to use: Solo projects, small teams, repos where Squad noise in git history is acceptable.
Tier 2 — Hub (domain-level, multiple repos)
A private hub repo owns Squad state for an entire domain of related repos. Target repos are completely Squad-clean — no .squad/, no agent history, nothing.
geraldinefberry-content-squad/ ← private hub: Azure content writing
.squad/
team.md, agents/, decisions.md, ...
geraldinefberry-samples-squad/ ← private hub: azure-samples code
.squad/
team.md, agents/, decisions.md, ...
(target repos — Squad-free, collaborators see nothing)
azure-docs-pr/
azure-samples/
sample-repo-1/
sample-repo-2/
Discussions at Tier 2:
geraldinefberry-content-squad (Discussions)
📋 Standup ← Scribe: daily summary of agent activity across all target repos
🚦 Decisions ← decisions that affect the domain (e.g., template changes)
⚠️ Blocked ← agent blocked on ambiguous requirements, needs human input
geraldinefberry-samples-squad (Discussions)
📋 Standup
🚦 Decisions
⚠️ Blocked
When to use:
- You manage many repos in a domain (e.g., all of azure-samples)
- Repos are shared or public and Squad state would be noise for collaborators
- You have distinct responsibility areas, each needing their own team and memory
- You want Squad product upgrades (new files, renamed files, schema changes) to land only in the hub, never in production repos
Tier 3 — Meta-Hub (cross-org, all squads)
A single personal or org-level repo — named by convention {username}/.squad — that knows about every squad you operate across personal accounts, work accounts, and org accounts.
geraldinefberry/.squad ← meta-hub: all squads
cross-squad/
registry.json ← index of all registered squad repos
geraldinefberry-content-squad/
geraldinefberry-samples-squad/
microsoft-azure-docs-squad/
geraldinefberry/content-squad ← hub for content domain
geraldinefberry/azure-samples-squad ← hub for samples domain
microsoft/azure-docs-squad ← org-level hub (if permitted)
The {username}/.squad naming mirrors GitHub's own {username}/.github convention — discoverable by design.
Discussions at Tier 3:
geraldinefberry/.squad (Discussions)
📢 Announcements ← meta Ralph: weekly board summary across all registered squads
🔄 Cross-Squad ← escalations that span multiple hubs
🏗️ Architecture ← decisions that affect multiple squads or all domains
What the meta-hub does:
| Capability | Detail |
|---|---|
| Registry | cross-squad/registry.json maps every squad repo by owner, org, domain, and access level |
| Cross-squad Ralph | Ralph runs at the meta level — monitors open issues and PRs across ALL registered squads |
| Health dashboard | Summarizes board status across all squads: issues open, PRs pending, squads idle |
| Promotion routing | Issues that span domains can be escalated to the meta Lead, who routes sub-tasks to domain squads |
| Credential scoping | Knows which gh contexts (personal, MSFT SSO, etc.) to use per squad |
When to use: You operate multiple squads across personal and org accounts and want one place to see the full picture.
Tier Summary
| Tier | Scope | Repo naming | Ralph scope | Discussions categories |
|---|---|---|---|---|
| team | One repo | .squad/ in repo, or {repo}-squad companion |
That repo's board | Standup, Decisions, Blocked |
| hub | One domain (multiple repos) | {domain}-squad or {username}-squad |
All repos in the domain | Standup, Decisions, Blocked |
| meta | All squads, all orgs | {username}/.squad or {org}/.squad |
All registered squads | Announcements, Cross-Squad, Architecture |
Companion Repo vs. Companion Branch
At Tier 1 and Tier 2, Squad state can be stored in either a branch or a repo:
| Concern | Branch (--squad-branch) |
Companion Repo (--companion-repo) |
|---|---|---|
| Squad files visible in public repo file tree | ❌ Yes (on that branch) | ✅ Never — different repo |
| History pollution in source repo | ❌ Orphan branch still in git log --all |
✅ Completely separate history |
| Visibility control | ❌ Inherits source repo visibility | ✅ Can be private while source is public |
| Organizational clarity | 🟡 Requires branch discipline | ✅ Wrong repo = obvious mistake |
| Multi-repo span | ❌ One branch per source repo | ✅ Single hub repo spans many sources |
Both should be first-class init options:
squad init --squad-branch squad→ orphan branch in same reposquad init --companion-repo→ new private sibling repo (recommended for public repos)squad init --hub→ promote to Tier 2 hub, spanning multiple repossquad init --meta→ scaffold Tier 3 meta-hub with registry
Discovery: Finding the Team Root
For Squad to work from any directory regardless of tier, it needs a multi-step discovery mechanism:
Resolution Order
SQUAD_TEAM_ROOTenv var — if set and valid, use immediately. No file scanning..squadrcpointer file — walk up from CWD (same as.gitdiscovery). If found, team root = path in file..squad/atgit rev-parse --show-toplevel— current behavior..squad/at main worktree — current fallback viagit worktree list.- Init Mode — but now with a hint: "No team found. If your team lives in a hub repo, set SQUAD_TEAM_ROOT or add a .squadrc file pointing to it."
.squadrc Format
# .squadrc (in target repo root, gitignored by default)
team_root = ~/repos/geraldinefberry-samples-squad
Discovered by walking up from CWD, so it works from any subdirectory of the target repo.
SQUAD_TEAM_ROOT env var
export SQUAD_TEAM_ROOT=~/repos/geraldinefberry-samples-squadZero repo changes. Set once in shell profile. Works from any directory.
Commit Targeting: Keeping Scribe on the Right Branch
Today Scribe commits .squad/ changes to whatever branch is checked out. For hub and meta repos this is fine, but for the --squad-branch pattern, Scribe needs to know to commit to the designated branch, not the current one.
Proposed: git.commit_branch in .squad/config.json
{
"git": {
"commit_branch": "squad"
}
}Scribe reads this field and commits to the specified branch. Field is optional — omitting it preserves current behavior.
Automated Setup via --squad-branch
squad init --squad-branch squad would:
- Create orphan
squadbranch (or use existing) - Add it as a git worktree at
../{repo-name}-squad/ - Initialize
.squad/in that worktree - Write
.squadrcin the project root pointing at the worktree - Set
git.commit_branch: "squad"in.squad/config.json
GitHub Discussions as Communication Layer
Squad's file-based state (decisions.md, history.md, logs) is machine-readable and agent-friendly, but invisible to humans unless they know to look. GitHub Discussions provides a complementary surface: human-readable, notification-driven, threaded, and built into GitHub with no extra tooling.
This is additive — Discussions surface Squad activity to humans without replacing file-based state. Agents write decisions and logs as today; Scribe optionally mirrors significant events to Discussions for async human visibility.
Per-Tier Discussion Categories
Each tier uses a different category set reflecting its scope:
| Tier | Categories | Purpose |
|---|---|---|
| Tier 1 (team) | Standup, Decisions, Blocked | Single-project agent activity and human check-ins |
| Tier 2 (hub) | Standup, Decisions, Blocked | Domain-wide agent activity across all target repos |
| Tier 3 (meta) | Announcements, Cross-Squad, Architecture | Cross-squad coordination and escalation |
What Gets Posted Where
| Signal | Agent | Tier | Category | Why |
|---|---|---|---|---|
| Session summary after significant work | Scribe | 1 or 2 | Standup | Async human catch-up |
| Decision that affects the domain | Scribe | 2 | Decisions | Human review before it propagates |
| Agent blocked on ambiguous requirements | Any agent | 1 or 2 | Blocked | Human input needed |
| Weekly board summary (issues closed, PRs merged) | Ralph | 3 (meta) | Announcements | Cross-squad visibility |
| Issue that spans two domains | Lead (hub) | 3 (meta) | Cross-Squad | Escalation with full context |
| Architectural decision affecting multiple squads | Lead (meta) | 3 (meta) | Architecture | Visibility before adoption |
Inter-Squad Escalation Flow
Tier 2 Hub (content-squad)
Scribe posts: "Decision: switching all Azure content to new template format"
↓
Tier 3 Meta-hub Lead sees it in Cross-Squad feed
↓
Meta Lead posts to meta Discussions: "This affects azure-samples-squad —
@geraldinefberry review before samples squad adopts same template"
↓
Human (geraldinefberry) responds in Discussion thread
↓
Meta Scribe writes resolution back to .squad/decisions/inbox/
Why Discussions Over Issues
- Issues are work items. A decision isn't a bug. An agent standup isn't a task. Using issues for communication pollutes the backlog.
- Discussions support threading. A cross-squad architectural debate can have a main post (Scribe) with human responses, without creating noise in either source repo.
- Discussions have categories. The structured categories map cleanly to signal types (decisions, standups, escalations).
- Discussions are searchable across repos. GitHub's search indexes Discussion content — a human can find a decision across all squad repos from one place.
Configuration
// .squad/config.json
{
"discussions": {
"enabled": true,
"standup_category": "Standup",
"decisions_category": "Decisions",
"blocked_category": "Blocked",
"post_after_session": true,
"post_decisions_threshold": "significant"
}
}squad init asks: "Enable GitHub Discussions for this squad? Scribe can post session summaries and decisions there. (yes/no)"
Cross-Org Considerations (Meta-Hub)
Squad repos inside Microsoft orgs (e.g., microsoft/azure-docs-squad) may not be readable from a personal meta-hub without token scoping. The meta-hub needs:
- Multiple
ghauth contexts (gh auth switchsupport) - Read-only mirroring of org squad state into
cross-squad/in the meta-hub - Respect for org visibility rules — private org squad state must not be written to a public meta-hub
- Discussions at the meta tier must respect the same visibility rules — private org Discussions must not be cross-posted to a public meta-hub
Why This Is a Product Gap, Not a Docs Fix
The hub repo pattern is the natural conclusion of recommending that users keep Squad state out of shared repos. If Squad recommends clean repos but silently fails when that architecture is used, the product is sending users toward a cliff.
The failure mode is indistinguishable from a fresh install: no error, no hint, no recovery path. A correctly configured hub user hits Init Mode on day one.
Acceptance Criteria
Discovery
- Squad resolves team root from
SQUAD_TEAM_ROOTenv var when set - Squad resolves team root from
.squadrcpointer file when present in CWD ancestry - When no team is found, Init Mode prompt includes a hint about
SQUAD_TEAM_ROOTand.squadrc -
.squadrcis added to Squad's default.gitignoretemplate (opt-in to commit)
Init flags
-
squad init --squad-branch <name>creates orphan branch + worktree +.squadrc+config.jsonautomatically -
squad init --companion-repocreates a private{repo}-squadsibling repo and writes.squadrc -
squad init --hubscaffolds a domain hub repo spanning multiple registered target repos -
squad init --metascaffolds a{username}/.squadmeta-hub withcross-squad/registry.json
Commit targeting
- Scribe reads
git.commit_branchfrom.squad/config.jsonand commits to that branch when set -
squad initwithout flags behaves exactly as today (no regression)
Tiered naming convention
-
{username}/.squadrecognized as a meta-hub by convention -
squad register {owner/squad-repo}CLI command adds a squad to the meta-hub registry - Ralph at meta tier can aggregate board status across all registered squads
GitHub Discussions
- Scribe can post to GitHub Discussions via
gh apior MCP tools whendiscussions.enabled: true - Each tier uses its default category set: Tier 1/2 → Standup/Decisions/Blocked; Tier 3 → Announcements/Cross-Squad/Architecture
- Meta-hub Ralph posts a weekly board summary to
{username}/.squadDiscussions > Announcements - Escalation routing: when a hub agent is blocked, Scribe opens a Discussion thread in the hub repo and (if configured) cross-posts to the meta-hub's Cross-Squad category
-
squad initoffers Discussions setup as an optional post-init step - Discussion post format is consistent: agent name, squad, date, concise summary, link to relevant
.squad/files - Discussions visibility follows org visibility rules — private org squad Discussions must not be cross-posted to a public meta-hub
Documentation
- Hub repo pattern documented as a first-class deployment option
- All three tiers documented with examples, tradeoff table, and Discussions category mapping
- Cross-org auth (multiple
ghcontexts) documented in.squadrcreference - GitHub Discussions configuration documented per tier with setup instructions