@bradygaster/squad-cli 0.9.5-insider.2 → 0.9.6-insider.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/install-hooks.d.ts +26 -0
- package/dist/cli/commands/install-hooks.d.ts.map +1 -0
- package/dist/cli/commands/install-hooks.js +244 -0
- package/dist/cli/commands/install-hooks.js.map +1 -0
- package/dist/cli/commands/migrate-backend.d.ts +16 -0
- package/dist/cli/commands/migrate-backend.d.ts.map +1 -0
- package/dist/cli/commands/migrate-backend.js +87 -0
- package/dist/cli/commands/migrate-backend.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +24 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +257 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/watch/config.d.ts +4 -1
- package/dist/cli/commands/watch/config.d.ts.map +1 -1
- package/dist/cli/commands/watch/config.js +2 -1
- package/dist/cli/commands/watch/config.js.map +1 -1
- package/dist/cli/core/init.d.ts +2 -0
- package/dist/cli/core/init.d.ts.map +1 -1
- package/dist/cli/core/init.js +63 -3
- package/dist/cli/core/init.js.map +1 -1
- package/dist/cli-entry.js +27 -5
- package/dist/cli-entry.js.map +1 -1
- package/package.json +6 -5
- package/templates/notes-protocol.md +202 -0
- package/templates/scribe-charter.md +95 -1
- package/templates/scripts/notes/fetch.ps1 +88 -0
- package/templates/scripts/notes/write-note.ps1 +126 -0
- package/templates/skills/cross-machine-coordination/SKILL.md +8 -0
- package/templates/skills/init-mode/SKILL.md +3 -3
- package/templates/skills/model-selection/SKILL.md +8 -0
- package/templates/skills/nap/SKILL.md +8 -0
- package/templates/skills/personal-squad/SKILL.md +8 -0
- package/templates/skills/ralph-two-pass-scan/SKILL.md +8 -0
- package/templates/skills/release-process/SKILL.md +91 -5
- package/templates/squad.agent.md.template +137 -14
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
# scripts/notes/write-note.ps1
|
|
3
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
# Helper for agents to write notes without wrestling with JSON escaping.
|
|
5
|
+
# Validates namespace ownership, handles conflicts, pushes automatically.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# ./scripts/notes/write-note.ps1 -Agent data -Type decision \
|
|
9
|
+
# -Content '{"decision":"Use JWT","reasoning":"..."}' \
|
|
10
|
+
# [-Commit HEAD] [-Promote] [-Archive]
|
|
11
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
[CmdletBinding()]
|
|
14
|
+
param(
|
|
15
|
+
[Parameter(Mandatory)][string]$Agent,
|
|
16
|
+
|
|
17
|
+
[Parameter(Mandatory)]
|
|
18
|
+
[ValidateSet("decision","research","review","security-review","progress",
|
|
19
|
+
"api-contract","risk-assessment","routing-discovery","counter-argument")]
|
|
20
|
+
[string]$Type,
|
|
21
|
+
|
|
22
|
+
[Parameter(Mandatory)]
|
|
23
|
+
[string]$Content, # JSON object with type-specific fields
|
|
24
|
+
|
|
25
|
+
[string]$Commit = "HEAD",
|
|
26
|
+
[string]$RepoPath = ".",
|
|
27
|
+
[string]$Remote = "origin",
|
|
28
|
+
[switch]$Promote, # set promote_to_permanent: true
|
|
29
|
+
[switch]$Archive, # set archive_on_close: true
|
|
30
|
+
[switch]$NoPush, # skip auto-push
|
|
31
|
+
[switch]$Quiet
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
function Log ([string]$msg, [string]$color = "White") {
|
|
35
|
+
if (-not $Quiet) { Write-Host "[notes/write] $msg" -ForegroundColor $color }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
$repo = Resolve-Path $RepoPath
|
|
39
|
+
$namespace = "squad/$($Agent.ToLower())"
|
|
40
|
+
|
|
41
|
+
# ── Validate JSON content ────────────────────────────────────────────────────
|
|
42
|
+
try {
|
|
43
|
+
$parsed = $Content | ConvertFrom-Json -ErrorAction Stop
|
|
44
|
+
} catch {
|
|
45
|
+
Write-Error "Content must be valid JSON. Got: $Content"
|
|
46
|
+
exit 1
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# ── Build full note object ────────────────────────────────────────────────────
|
|
50
|
+
$note = [ordered]@{
|
|
51
|
+
agent = (Get-Culture).TextInfo.ToTitleCase($Agent.ToLower())
|
|
52
|
+
timestamp = [System.DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
53
|
+
type = $Type
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Merge content fields into note
|
|
57
|
+
$parsed.PSObject.Properties | ForEach-Object { $note[$_.Name] = $_.Value }
|
|
58
|
+
|
|
59
|
+
# Add flag fields
|
|
60
|
+
if ($Promote) { $note["promote_to_permanent"] = $true }
|
|
61
|
+
if ($Archive) { $note["archive_on_close"] = $true }
|
|
62
|
+
|
|
63
|
+
$noteJson = $note | ConvertTo-Json -Compress -Depth 10
|
|
64
|
+
|
|
65
|
+
# ── Fetch first to avoid conflicts ───────────────────────────────────────────
|
|
66
|
+
Log "Fetching notes before write..."
|
|
67
|
+
git -C $repo fetch $Remote "refs/notes/*:refs/notes/*" 2>&1 | Out-Null
|
|
68
|
+
|
|
69
|
+
# ── Check if note already exists on this commit ─────────────────────────────
|
|
70
|
+
$existing = git -C $repo notes --ref=$namespace show $Commit 2>&1
|
|
71
|
+
$useAppend = ($LASTEXITCODE -eq 0)
|
|
72
|
+
|
|
73
|
+
if ($useAppend) {
|
|
74
|
+
Log "Note exists on $Commit — appending" DarkYellow
|
|
75
|
+
git -C $repo notes --ref=$namespace append -m $noteJson $Commit
|
|
76
|
+
} else {
|
|
77
|
+
git -C $repo notes --ref=$namespace add -m $noteJson $Commit
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if ($LASTEXITCODE -ne 0) {
|
|
81
|
+
Write-Error "Failed to write note to refs/notes/$namespace on $Commit"
|
|
82
|
+
exit 1
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Log "Note written to refs/notes/$namespace on $($Commit.Substring(0,[Math]::Min(8,$Commit.Length)))" Green
|
|
86
|
+
|
|
87
|
+
# ── Push with retry ──────────────────────────────────────────────────────────
|
|
88
|
+
if (-not $NoPush) {
|
|
89
|
+
$maxRetries = 5
|
|
90
|
+
$nsRef = "refs/notes/$namespace"
|
|
91
|
+
|
|
92
|
+
for ($i = 0; $i -lt $maxRetries; $i++) {
|
|
93
|
+
Log "Pushing notes (attempt $($i+1))..."
|
|
94
|
+
$pushOut = git -C $repo push $Remote "${nsRef}:${nsRef}" 2>&1
|
|
95
|
+
if ($LASTEXITCODE -eq 0) {
|
|
96
|
+
Log "Notes pushed successfully." Green
|
|
97
|
+
break
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if ($pushOut -match "non-fast-forward|fetch first|rejected") {
|
|
101
|
+
Log "Push conflict — fetch-first retry..." DarkYellow
|
|
102
|
+
|
|
103
|
+
# Force-fetch: overwrite local ref with current remote state
|
|
104
|
+
git -C $repo fetch $Remote "${nsRef}:${nsRef}" 2>&1 | Out-Null
|
|
105
|
+
|
|
106
|
+
# Re-append our note on top of the now-current remote state
|
|
107
|
+
git -C $repo notes --ref=$namespace append -m $noteJson $Commit 2>&1 | Out-Null
|
|
108
|
+
|
|
109
|
+
$jitter = Get-Random -Minimum 0 -Maximum 1000
|
|
110
|
+
$sleep = [Math]::Pow(2, $i) + $jitter / 1000
|
|
111
|
+
Start-Sleep -Seconds $sleep
|
|
112
|
+
|
|
113
|
+
} else {
|
|
114
|
+
Log "Push error: $pushOut" Red
|
|
115
|
+
if ($i -eq $maxRetries - 1) {
|
|
116
|
+
Write-Warning "Failed after $maxRetries retries. Push manually: git push origin '${nsRef}:${nsRef}'"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# ── Show result ───────────────────────────────────────────────────────────────
|
|
123
|
+
if (-not $Quiet) {
|
|
124
|
+
Log "Note content:"
|
|
125
|
+
$note | ConvertTo-Json -Depth 5 | Write-Host -ForegroundColor DarkGray
|
|
126
|
+
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "cross-machine-coordination"
|
|
3
|
+
description: "Enables squad agents on different machines to share work via git-based task queuing"
|
|
4
|
+
domain: "orchestration"
|
|
5
|
+
confidence: "medium"
|
|
6
|
+
source: "manual"
|
|
7
|
+
---
|
|
8
|
+
|
|
1
9
|
# Skill: Cross-Machine Coordination Pattern
|
|
2
10
|
|
|
3
11
|
**Skill ID:** `cross-machine-coordination`
|
|
@@ -20,7 +20,7 @@ Init Mode activates when `.squad/team.md` does not exist, or exists but has zero
|
|
|
20
20
|
|
|
21
21
|
No team exists yet. Propose one — but **DO NOT create any files until the user confirms.**
|
|
22
22
|
|
|
23
|
-
1. **Identify the user.** Run `git config user.name` to learn who you're working with. Use their name in conversation (e.g., *"Hey
|
|
23
|
+
1. **Identify the user.** Run `git config user.name` to learn who you're working with. Use their name in conversation (e.g., *"Hey {user}, what are you building?"*). Store their name (NOT email) in `team.md` under Project Context. **Never read or store `git config user.email` — email addresses are PII and must not be written to committed files.**
|
|
24
24
|
2. Ask: *"What are you building? (language, stack, what it does)"*
|
|
25
25
|
3. **Cast the team.** Before proposing names, run the Casting & Persistent Naming algorithm (see that section):
|
|
26
26
|
- Determine team size (typically 4–5 + Scribe).
|
|
@@ -82,8 +82,8 @@ The `union` merge driver keeps all lines from both sides, which is correct for a
|
|
|
82
82
|
|
|
83
83
|
**Example flow:**
|
|
84
84
|
1. Coordinator detects no team.md → Init Mode
|
|
85
|
-
2. Runs `git config user.name` → "
|
|
86
|
-
3. Asks: *"Hey
|
|
85
|
+
2. Runs `git config user.name` → "{user}"
|
|
86
|
+
3. Asks: *"Hey {user}, what are you building?"*
|
|
87
87
|
4. User: *"TypeScript CLI tool with GitHub API integration"*
|
|
88
88
|
5. Coordinator runs casting algorithm → selects "The Usual Suspects" universe
|
|
89
89
|
6. Proposes: Keaton (Lead), Verbal (Prompt), Fenster (Backend), Hockney (Tester), Scribe, Ralph
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "model-selection"
|
|
3
|
+
description: "Determines which LLM model to use for each agent spawn"
|
|
4
|
+
domain: "orchestration"
|
|
5
|
+
confidence: "medium"
|
|
6
|
+
source: "extracted"
|
|
7
|
+
---
|
|
8
|
+
|
|
1
9
|
# Model Selection
|
|
2
10
|
|
|
3
11
|
> Determines which LLM model to use for each agent spawn.
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "ralph-two-pass-scan"
|
|
3
|
+
description: "Cuts GitHub API calls by separating lightweight list scanning from full hydration"
|
|
4
|
+
domain: "work-monitoring"
|
|
5
|
+
confidence: "high"
|
|
6
|
+
source: "extracted"
|
|
7
|
+
---
|
|
8
|
+
|
|
1
9
|
# Skill: Ralph — Two-Pass Issue Scanning
|
|
2
10
|
**Confidence:** high
|
|
3
11
|
**Domain:** work-monitoring
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "release-process"
|
|
3
|
+
description: "Pre-release validation, npm publish procedures, and post-publish verification"
|
|
4
|
+
domain: "release"
|
|
5
|
+
confidence: "high"
|
|
6
|
+
source: "earned"
|
|
7
|
+
---
|
|
8
|
+
|
|
1
9
|
# Release Process
|
|
2
10
|
|
|
3
|
-
> Earned knowledge from the v0.9.0→v0.9.1
|
|
11
|
+
> Earned knowledge from the v0.9.0→v0.9.1 and v0.9.4 incidents. Every agent involved in releases MUST read this before starting release work.
|
|
12
|
+
> See also: `.copilot/skills/release-process/SKILL.md` for the Copilot-facing runbook.
|
|
4
13
|
|
|
5
14
|
## SCOPE
|
|
6
15
|
|
|
@@ -17,7 +26,7 @@
|
|
|
17
26
|
|
|
18
27
|
## Confidence: high
|
|
19
28
|
|
|
20
|
-
Established through the v0.9.1 incident (8-hour recovery). Every rule below is battle-tested.
|
|
29
|
+
Established through the v0.9.1 incident (8-hour recovery) and reinforced by the v0.9.4 release delay (PRs #1042, #1043, #1044). Every rule below is battle-tested.
|
|
21
30
|
|
|
22
31
|
## Context
|
|
23
32
|
|
|
@@ -92,8 +101,9 @@ Set this environment variable in all CI build steps to prevent the build script
|
|
|
92
101
|
```
|
|
93
102
|
□ All tests passing on dev
|
|
94
103
|
□ No file:/link: references in packages/*/package.json
|
|
95
|
-
□
|
|
96
|
-
□
|
|
104
|
+
□ Root package.json version matches sub-packages (v0.9.4 lesson — PR #1043)
|
|
105
|
+
□ CHANGELOG.md has ## [$VERSION] section (not just [Unreleased]) (v0.9.4 lesson — PR #1042)
|
|
106
|
+
□ Version bumps committed: npm version $VERSION --workspaces --include-workspace-root --no-git-tag-version
|
|
97
107
|
□ npm auth verified (Automation token)
|
|
98
108
|
□ No draft GitHub Releases pending
|
|
99
109
|
□ Local build + test: npm run build && npx vitest run
|
|
@@ -102,7 +112,8 @@ Set this environment variable in all CI build steps to prevent the build script
|
|
|
102
112
|
□ Preview CI green (squad-preview validates)
|
|
103
113
|
□ Promote preview → main
|
|
104
114
|
□ squad-release auto-creates GitHub Release
|
|
105
|
-
□ squad-npm-publish auto-triggers
|
|
115
|
+
□ squad-npm-publish auto-triggers (⚠️ may be BLOCKED — see GITHUB_TOKEN limitation below)
|
|
116
|
+
□ If publish didn't trigger: gh workflow run squad-npm-publish.yml --ref main -f version=X.Y.Z
|
|
106
117
|
□ Monitor publish workflow
|
|
107
118
|
□ Post-publish smoke test
|
|
108
119
|
```
|
|
@@ -116,6 +127,79 @@ Set this environment variable in all CI build steps to prevent the build script
|
|
|
116
127
|
| `npm -w publish` hangs with 2FA | Silent hang, no error | Never use `-w` for publish |
|
|
117
128
|
| Draft GitHub Releases | npm publish workflow doesn't trigger | Never create drafts |
|
|
118
129
|
| User npm tokens with 2FA | EOTP errors in CI | Use Automation token type |
|
|
130
|
+
| Root package.json version drift (v0.9.4) | squad-release.yml fails CHANGELOG check | Always bump all 3 package.json files together (PR #1043) |
|
|
131
|
+
| CHANGELOG.md missing `## [$VERSION]` (v0.9.4) | squad-release.yml exits with error | Convert `[Unreleased]` → `[$VERSION] - YYYY-MM-DD` before promoting to main (PR #1042) |
|
|
132
|
+
| GITHUB_TOKEN can't trigger downstream workflows (v0.9.4) | squad-npm-publish.yml never fires | Manual `gh workflow run` or use PAT/GitHub App token (see below) |
|
|
133
|
+
| Lockfile integrity check rejects workspace packages (v0.9.4) | False failures in squad-npm-publish.yml | Only validate packages resolved from npm registry (`startsWith('https://')`) (PR #1044) |
|
|
134
|
+
| `prebuild` version bump breaks workspace linking (v0.9.4) | Local builds fail after bump-build.mjs runs | `git checkout -- package.json packages/*/package.json` then fresh install |
|
|
135
|
+
|
|
136
|
+
## v0.9.4 Incident Learnings
|
|
137
|
+
|
|
138
|
+
> Source: v0.9.4 release session. PRs #1042, #1043, #1044.
|
|
139
|
+
|
|
140
|
+
### Root Package.json Version Must Match Sub-Packages
|
|
141
|
+
|
|
142
|
+
`squad-release.yml` reads version from ROOT `package.json` (lines 31-35):
|
|
143
|
+
```bash
|
|
144
|
+
VERSION=$(node -e "console.log(require('./package.json').version)")
|
|
145
|
+
if ! grep -q "## \[$VERSION\]" CHANGELOG.md; then
|
|
146
|
+
echo "::error::Version $VERSION not found in CHANGELOG.md"
|
|
147
|
+
exit 1
|
|
148
|
+
fi
|
|
149
|
+
```
|
|
150
|
+
If root package.json is behind (e.g., 0.9.1 while sub-packages are 0.9.4), the release workflow FAILS. This was the root cause of the v0.9.4 release delay — PR #1043 fixed it.
|
|
151
|
+
|
|
152
|
+
**Rule:** When bumping versions, ALWAYS bump all 3 package.json files together:
|
|
153
|
+
```bash
|
|
154
|
+
npm version $VERSION --workspaces --include-workspace-root --no-git-tag-version
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### CHANGELOG.md Must Have Version Entry
|
|
158
|
+
|
|
159
|
+
`squad-release.yml` validates that `CHANGELOG.md` contains `## [$VERSION]`. If the version section is still `[Unreleased]` and no `[$VERSION]` section exists, the release workflow exits with error. PR #1042 fixed this for v0.9.4.
|
|
160
|
+
|
|
161
|
+
**Rule:** Before promoting to main, convert `[Unreleased]` to `[$VERSION] - YYYY-MM-DD` in CHANGELOG.md and add a fresh `[Unreleased]` section above it.
|
|
162
|
+
|
|
163
|
+
### GITHUB_TOKEN Event Propagation Limitation (CRITICAL)
|
|
164
|
+
|
|
165
|
+
When `squad-release.yml` creates a GitHub Release using the default `GITHUB_TOKEN`, the `release: published` event does NOT trigger `squad-npm-publish.yml`. This is a GitHub security feature to prevent infinite workflow loops.
|
|
166
|
+
|
|
167
|
+
**Workaround:** After the release workflow succeeds and creates the tag + GitHub Release, manually trigger the publish workflow:
|
|
168
|
+
```bash
|
|
169
|
+
gh workflow run squad-npm-publish.yml --ref main -f version=X.Y.Z
|
|
170
|
+
```
|
|
171
|
+
IMPORTANT: Use `--ref main` to ensure the workflow runs against the main branch (where the release artifacts exist).
|
|
172
|
+
|
|
173
|
+
**Permanent fix (TODO):** Use a PAT or GitHub App token in `squad-release.yml` instead of `GITHUB_TOKEN`.
|
|
174
|
+
|
|
175
|
+
### Lockfile Integrity — Workspace Package Handling
|
|
176
|
+
|
|
177
|
+
The lockfile stability check in `squad-npm-publish.yml` (line 82) filters packages for integrity hashes. Workspace packages resolve to bare relative paths (e.g., `packages/squad-sdk`), NOT `file:` URLs. The check must filter for registry-resolved packages only (`startsWith('https://')`). PR #1044 fixed this.
|
|
178
|
+
|
|
179
|
+
### Prebuild Version Bump Breaks Local Workspace Resolution
|
|
180
|
+
|
|
181
|
+
`scripts/bump-build.mjs` runs during `npm run prebuild` and bumps versions like `0.9.4` → `0.9.4-build.1`. This breaks workspace linking because CLI depends on exact `"@bradygaster/squad-sdk": "0.9.4"` but SDK becomes `0.9.4-build.1`.
|
|
182
|
+
|
|
183
|
+
**Fix for local dev:**
|
|
184
|
+
```bash
|
|
185
|
+
git checkout -- package.json packages/*/package.json
|
|
186
|
+
rm -rf node_modules packages/*/node_modules
|
|
187
|
+
npm install
|
|
188
|
+
npm run build
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### The Full Promotion Chain (v0.9.4 Documented)
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
dev → preview → main (via squad-promote.yml)
|
|
195
|
+
main push → squad-release.yml validates CHANGELOG, creates tag + GitHub Release
|
|
196
|
+
release published → squad-npm-publish.yml (⚠️ BLOCKED by GITHUB_TOKEN limitation)
|
|
197
|
+
manual workaround → gh workflow run squad-npm-publish.yml --ref main -f version=X.Y.Z
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### npm Publish Workflow Dispatch Target
|
|
201
|
+
|
|
202
|
+
When using `workflow_dispatch` to trigger `squad-npm-publish.yml`, the default ref is the repo's default branch (`dev`). Always specify `--ref main` explicitly to ensure the workflow runs against the branch with the release tag and latest workflow fixes.
|
|
119
203
|
|
|
120
204
|
## CI Gate: Workspace Publish Policy
|
|
121
205
|
|
|
@@ -126,6 +210,8 @@ See `.github/workflows/squad-ci.yml` → `publish-policy` job for implementation
|
|
|
126
210
|
## Related
|
|
127
211
|
|
|
128
212
|
- Issues: #556–#564 (release:next)
|
|
213
|
+
- v0.9.4 fixes: PR #1042 (CHANGELOG), PR #1043 (root package.json), PR #1044 (lockfile integrity)
|
|
129
214
|
- Retro: `.squad/decisions/inbox/surgeon-v091-retrospective.md`
|
|
130
215
|
- CI audit: `.squad/decisions/inbox/booster-ci-audit.md`
|
|
216
|
+
- Copilot-level skill: `.copilot/skills/release-process/SKILL.md`
|
|
131
217
|
- Playbook: `PUBLISH-README.md` (repo root)
|
|
@@ -32,7 +32,7 @@ Check: Does `.squad/team.md` exist? (fall back to `.ai-team/team.md` for repos m
|
|
|
32
32
|
|
|
33
33
|
No team exists yet. Propose one — but **DO NOT create any files until the user confirms.**
|
|
34
34
|
|
|
35
|
-
1. **Identify the user.** Run `git config user.name` to learn who you're working with. Use their name in conversation (e.g., *"Hey
|
|
35
|
+
1. **Identify the user.** Run `git config user.name` to learn who you're working with. Use their name in conversation (e.g., *"Hey {user}, what are you building?"*). Store their name (NOT email) in `team.md` under Project Context. **Never read or store `git config user.email` — email addresses are PII and must not be written to committed files.**
|
|
36
36
|
2. Ask: *"What are you building? (language, stack, what it does)"*
|
|
37
37
|
3. **Cast the team.** Before proposing names, run the Casting & Persistent Naming algorithm (see that section):
|
|
38
38
|
- Determine team size (typically 4–5 + Scribe).
|
|
@@ -107,6 +107,8 @@ The `union` merge driver keeps all lines from both sides, which is correct for a
|
|
|
107
107
|
|
|
108
108
|
**On every session start:** Run `git config user.name` to identify the current user, and **resolve the team root** (see Worktree Awareness). Store the team root — all `.squad/` paths must be resolved relative to it. Pass the team root and the current datetime (from `<current_datetime>` in your system context) into every spawn prompt as `TEAM_ROOT` and `CURRENT_DATETIME` respectively. Pass the current user's name into every agent spawn prompt and Scribe log so the team always knows who requested the work. Check `.squad/identity/now.md` if it exists — it tells you what the team was last focused on. Update it if the focus has shifted.
|
|
109
109
|
|
|
110
|
+
**Resolve state backend:** Read `.squad/config.json` and check the `stateBackend` field. Valid values: `"worktree"` (default), `"git-notes"`, `"orphan"`, `"two-layer"`. Store as `STATE_BACKEND` and pass it into every spawn prompt. This determines how agents read and write mutable state (history, decisions, logs). Static config (charters, team.md, routing.md) always lives on disk regardless of backend. The `"two-layer"` option combines git-notes (commit-scoped annotations) with orphan branch (permanent state) — see the blog post for the full architecture.
|
|
111
|
+
|
|
110
112
|
**⚡ Context caching:** After the first message in a session, `team.md`, `routing.md`, and `registry.json` are already in your context. Do NOT re-read them on subsequent messages — you already have the roster, routing rules, and cast names. Only re-read if the user explicitly modifies the team (adds/removes members, changes routing).
|
|
111
113
|
|
|
112
114
|
**Session catch-up (lazy — not on every start):** Do NOT scan logs on every session start. Only provide a catch-up summary when:
|
|
@@ -223,13 +225,16 @@ The `name` parameter generates the human-readable agent ID shown in the tasks pa
|
|
|
223
225
|
|
|
224
226
|
**When you detect a directive:**
|
|
225
227
|
|
|
226
|
-
1.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
228
|
+
1. Capture the directive:
|
|
229
|
+
- **worktree/orphan backend:** Write it immediately to `.squad/decisions/inbox/copilot-directive-{timestamp}.md` using this format:
|
|
230
|
+
```
|
|
231
|
+
### {timestamp}: User directive
|
|
232
|
+
**By:** {user name} (via Copilot)
|
|
233
|
+
**What:** {the directive, verbatim or lightly paraphrased}
|
|
234
|
+
**Why:** User request — captured for team memory
|
|
235
|
+
```
|
|
236
|
+
- **git-notes backend:** Persist via:
|
|
237
|
+
`powershell .squad/scripts/notes/write-note.ps1 -Ref "squad/directives" -Content '{"timestamp": "{timestamp}", "by": "{user name}", "what": "...", "why": "User request"}'`
|
|
233
238
|
2. Acknowledge briefly: `"📌 Captured. {one-line summary of the directive}."`
|
|
234
239
|
3. If the message ALSO contains a work request, route that work normally after capturing. If it's directive-only, you're done — no agent spawn needed.
|
|
235
240
|
|
|
@@ -242,12 +247,12 @@ The routing table determines **WHO** handles work. After routing, use Response M
|
|
|
242
247
|
| Names someone ("Ripley, fix the button") | Spawn that agent |
|
|
243
248
|
| Personal agent by name (user addresses a personal agent) | Route to personal agent in consult mode — they advise, project agent executes changes |
|
|
244
249
|
| "Team" or multi-domain question | Spawn 2-3+ relevant agents in parallel, synthesize |
|
|
245
|
-
| Human member management ("add
|
|
250
|
+
| Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) |
|
|
246
251
|
| Issue suitable for @copilot (when @copilot is on the roster) | Check capability profile in team.md, suggest routing to @copilot if it's a good fit |
|
|
247
252
|
| Ceremony request ("design meeting", "run a retro") | Run the matching ceremony from `ceremonies.md` (see Ceremonies) |
|
|
248
253
|
| Issues/backlog request ("pull issues", "show backlog", "work on #N") | Follow GitHub Issues Mode (see that section) |
|
|
249
254
|
| PRD intake ("here's the PRD", "read the PRD at X", pastes spec) | Follow PRD Mode (see that section) |
|
|
250
|
-
| Human member management ("add
|
|
255
|
+
| Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) |
|
|
251
256
|
| Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) |
|
|
252
257
|
| General work request | Check routing.md, spawn best match + any anticipatory agents |
|
|
253
258
|
| Quick factual question | Answer directly (no spawn) |
|
|
@@ -292,7 +297,7 @@ After routing determines WHO handles work, select the response MODE based on tas
|
|
|
292
297
|
| **Full** | Multi-agent work, complex tasks touching 3+ concerns, "Team" requests | Parallel fan-out, full ceremony, Scribe included | ~40-60s |
|
|
293
298
|
|
|
294
299
|
**Direct Mode exemplars** (coordinator answers instantly, no spawn):
|
|
295
|
-
- "Where are we?" → Summarize current state from context: branch, recent work, what the team's been doing.
|
|
300
|
+
- "Where are we?" → Summarize current state from context: branch, recent work, what the team's been doing. A user favorite — make it instant.
|
|
296
301
|
- "How many tests do we have?" → Run a quick command, answer directly.
|
|
297
302
|
- "What branch are we on?" → `git branch --show-current`, answer directly.
|
|
298
303
|
- "Who's on the team?" → Answer from team.md already in context.
|
|
@@ -344,7 +349,12 @@ prompt: |
|
|
|
344
349
|
TARGET FILE(S): {exact file path(s)}
|
|
345
350
|
|
|
346
351
|
Do the work. Keep it focused.
|
|
352
|
+
{% if STATE_BACKEND == "git-notes" %}
|
|
353
|
+
If you made a meaningful decision, persist it via:
|
|
354
|
+
`powershell .squad/scripts/notes/write-note.ps1 -Ref "squad/{name}" -Content '{"decision": {"title": "...", "what": "...", "why": "..."}}'`
|
|
355
|
+
{% else %}
|
|
347
356
|
If you made a meaningful decision, write to .squad/decisions/inbox/{name}-{brief-slug}.md
|
|
357
|
+
{% endif %}
|
|
348
358
|
|
|
349
359
|
⚠️ OUTPUT: Report outcomes in human terms. Never expose tool internals or SQL.
|
|
350
360
|
⚠️ RESPONSE ORDER: After ALL tool calls, write a plain text summary as FINAL output.
|
|
@@ -598,8 +608,9 @@ When the user gives any task, the Coordinator MUST:
|
|
|
598
608
|
To enable full parallelism, shared writes use a drop-box pattern that eliminates file conflicts:
|
|
599
609
|
|
|
600
610
|
**decisions.md** — Agents do NOT write directly to `decisions.md`. Instead:
|
|
601
|
-
- Agents write decisions to individual drop files: `.squad/decisions/inbox/{agent-name}-{brief-slug}.md`
|
|
602
|
-
-
|
|
611
|
+
- **worktree/orphan backend:** Agents write decisions to individual drop files: `.squad/decisions/inbox/{agent-name}-{brief-slug}.md`
|
|
612
|
+
- **git-notes backend:** Agents persist decisions via their git notes ref (see State Protocol). Scribe reads all agent notes and merges decisions.
|
|
613
|
+
- Scribe merges into the canonical `.squad/decisions.md` and clears the inbox (or note entries)
|
|
603
614
|
- All agents READ from `.squad/decisions.md` at spawn time (last-merged snapshot)
|
|
604
615
|
|
|
605
616
|
**orchestration-log/** — Scribe writes one entry per agent after each batch:
|
|
@@ -799,7 +810,71 @@ prompt: |
|
|
|
799
810
|
- Commit and push from the worktree
|
|
800
811
|
{% endif %}
|
|
801
812
|
|
|
813
|
+
STATE_BACKEND: {state_backend}
|
|
814
|
+
|
|
815
|
+
{% if STATE_BACKEND == "git-notes" %}
|
|
816
|
+
## State Protocol — Git Notes
|
|
817
|
+
This project uses git-notes for mutable state. **DO NOT write to `.squad/` files for state.**
|
|
818
|
+
Static config (charters, team.md, routing.md) is on disk as normal — read those with `view`.
|
|
819
|
+
|
|
820
|
+
**Reading your state:**
|
|
821
|
+
Run: `powershell .squad/scripts/notes/fetch.ps1 -Setup` (first time per session)
|
|
822
|
+
Then: `git notes --ref=squad/{name} show $(git rev-list --max-parents=0 HEAD) 2>$null`
|
|
823
|
+
Falls back to empty if no note exists.
|
|
824
|
+
|
|
825
|
+
**Writing state (history, decisions, learnings):**
|
|
826
|
+
Run: `powershell .squad/scripts/notes/write-note.ps1 -Ref "squad/{name}" -Content '{json}'`
|
|
827
|
+
The helper handles JSON validation, conflict retry, and push.
|
|
828
|
+
|
|
829
|
+
**Decisions:** Write decisions as JSON via your note ref. Scribe will merge them.
|
|
830
|
+
**Skills:** Skills are static config — write to `.squad/skills/` on disk as normal.
|
|
831
|
+
{% endif %}
|
|
832
|
+
|
|
833
|
+
{% if STATE_BACKEND == "orphan" %}
|
|
834
|
+
## State Protocol — Orphan Branch
|
|
835
|
+
This project uses an orphan branch (`squad-state`) for mutable state.
|
|
836
|
+
Static config (charters, team.md, routing.md) is on disk as normal — read those with `view`.
|
|
837
|
+
|
|
838
|
+
**Reading state:** Read `.squad/` files on disk — they are synced from the orphan branch.
|
|
839
|
+
**Writing state:** Write to `.squad/` files on disk as normal during your session.
|
|
840
|
+
Scribe will commit your changes to the orphan branch (not the working branch) and
|
|
841
|
+
ensure they persist across branch switches.
|
|
842
|
+
|
|
843
|
+
**Important:** Do NOT commit `.squad/` state files to the working branch yourself.
|
|
844
|
+
Scribe handles the orphan branch commit workflow.
|
|
845
|
+
{% endif %}
|
|
846
|
+
|
|
847
|
+
{% if STATE_BACKEND == "two-layer" %}
|
|
848
|
+
## State Protocol — Two-Layer (Git Notes + Orphan Branch)
|
|
849
|
+
This project uses the two-layer architecture from Tamir's blog:
|
|
850
|
+
- **Layer 1 (git notes):** Commit-scoped "why" annotations — invisible in PRs
|
|
851
|
+
- **Layer 2 (orphan branch):** Permanent state store — decisions, histories, logs
|
|
852
|
+
|
|
853
|
+
Static config (charters, team.md, routing.md) is on disk as normal.
|
|
854
|
+
|
|
855
|
+
**During your session:**
|
|
856
|
+
1. Write commit-scoped annotations as git notes on HEAD:
|
|
857
|
+
`git notes --ref=squad/{name} add -f -m '{"agent":"{Name}","type":"decision","decision":"...","promote_to_permanent":true}' HEAD`
|
|
858
|
+
2. Write bulk state (history, logs) to `.squad/` files on disk — Scribe moves them to the orphan branch.
|
|
859
|
+
|
|
860
|
+
**Note flags:**
|
|
861
|
+
- `"promote_to_permanent": true` — Ralph promotes this to decisions.md after PR merge
|
|
862
|
+
- `"archive_on_close": true` — Worth keeping even if PR is rejected (valuable research)
|
|
863
|
+
- Neither flag — silently ignored if PR is rejected (correct for branch-specific decisions)
|
|
864
|
+
|
|
865
|
+
**Important:** Do NOT commit `.squad/` state files to the working branch.
|
|
866
|
+
Scribe handles orphan commits. Ralph handles note promotion.
|
|
867
|
+
{% endif %}
|
|
868
|
+
|
|
869
|
+
{% if STATE_BACKEND == "worktree" or STATE_BACKEND is not defined %}
|
|
802
870
|
Read .squad/agents/{name}/history.md (your project knowledge).
|
|
871
|
+
{% endif %}
|
|
872
|
+
{% if STATE_BACKEND == "git-notes" %}
|
|
873
|
+
Read your agent state from git notes (see State Protocol above).
|
|
874
|
+
{% endif %}
|
|
875
|
+
{% if STATE_BACKEND == "orphan" or STATE_BACKEND == "two-layer" %}
|
|
876
|
+
Read .squad/agents/{name}/history.md (your project knowledge — synced from orphan branch).
|
|
877
|
+
{% endif %}
|
|
803
878
|
Read .squad/decisions.md (team decisions to respect).
|
|
804
879
|
If .squad/identity/wisdom.md exists, read it before starting work.
|
|
805
880
|
If .squad/identity/now.md exists, read it at spawn time.
|
|
@@ -823,10 +898,27 @@ prompt: |
|
|
|
823
898
|
⚠️ DATES: When writing dates in any file (decisions, history, logs), use ONLY the CURRENT_DATETIME value above. Never infer or guess the date.
|
|
824
899
|
|
|
825
900
|
AFTER work:
|
|
901
|
+
{% if STATE_BACKEND == "git-notes" %}
|
|
902
|
+
1. Persist your learnings as JSON via the State Protocol:
|
|
903
|
+
`powershell .squad/scripts/notes/write-note.ps1 -Ref "squad/{name}" -Content '{"learnings": ["..."], "timestamp": "{current_datetime}"}'`
|
|
904
|
+
2. If you made a team-relevant decision, include it in the JSON:
|
|
905
|
+
Add a `"decision"` field with `"title"`, `"what"`, and `"why"` keys.
|
|
906
|
+
Scribe will merge decisions into the canonical decisions.md.
|
|
907
|
+
{% elif STATE_BACKEND == "two-layer" %}
|
|
908
|
+
1. APPEND to .squad/agents/{name}/history.md under "## Learnings":
|
|
909
|
+
architecture decisions, patterns, user preferences, key file paths.
|
|
910
|
+
(Scribe commits this to the orphan branch.)
|
|
911
|
+
2. If you made a team-relevant decision, write BOTH:
|
|
912
|
+
a. A git note on HEAD with promote flag:
|
|
913
|
+
`git notes --ref=squad/{name} add -f -m '{"agent":"{Name}","type":"decision","decision":"...","promote_to_permanent":true}' HEAD`
|
|
914
|
+
b. A drop file: .squad/decisions/inbox/{name}-{brief-slug}.md
|
|
915
|
+
(Scribe merges to orphan branch; Ralph promotes note after PR merge.)
|
|
916
|
+
{% else %}
|
|
826
917
|
1. APPEND to .squad/agents/{name}/history.md under "## Learnings":
|
|
827
918
|
architecture decisions, patterns, user preferences, key file paths.
|
|
828
919
|
2. If you made a team-relevant decision, write to:
|
|
829
920
|
.squad/decisions/inbox/{name}-{brief-slug}.md
|
|
921
|
+
{% endif %}
|
|
830
922
|
3. SKILL EXTRACTION: If you found a reusable pattern, write/update
|
|
831
923
|
.squad/skills/{skill-name}/SKILL.md (read templates/skill.md for format).
|
|
832
924
|
|
|
@@ -878,18 +970,47 @@ prompt: |
|
|
|
878
970
|
You are the Scribe. Read .squad/agents/scribe/charter.md.
|
|
879
971
|
TEAM ROOT: {team_root}
|
|
880
972
|
CURRENT_DATETIME: {current_datetime}
|
|
973
|
+
STATE_BACKEND: {state_backend}
|
|
881
974
|
|
|
882
975
|
SPAWN MANIFEST: {spawn_manifest}
|
|
883
976
|
|
|
884
977
|
Tasks (in order):
|
|
885
|
-
|
|
978
|
+
{% if STATE_BACKEND == "orphan" or STATE_BACKEND == "git-notes" or STATE_BACKEND == "two-layer" %}
|
|
979
|
+
0. STATE LEAK GUARD: Check if any agent accidentally committed or staged state files
|
|
980
|
+
(.squad/decisions.md, agents/*/history.md, log/*, orchestration-log/*, decisions/inbox/*)
|
|
981
|
+
to the working branch. If found: unstage with `git reset HEAD -- {file}`, restore with
|
|
982
|
+
`git checkout HEAD -- {file}`. If leaked in last commit, amend to remove. Log count.
|
|
983
|
+
{% endif %}
|
|
984
|
+
0b. PRE-CHECK: Stat decisions.md size and count inbox/ files. Record measurements.
|
|
886
985
|
1. DECISIONS ARCHIVE [HARD GATE]: If decisions.md >= 20480 bytes, archive entries older than 30 days NOW. If >= 51200 bytes, archive entries older than 7 days. Do not skip this step.
|
|
986
|
+
{% if STATE_BACKEND == "git-notes" %}
|
|
987
|
+
2. DECISION MERGE (git-notes): For each agent ref `squad/{agent}`, read notes via `git notes --ref=squad/{agent} show $(git rev-list --max-parents=0 HEAD)`. Extract any `decision` entries. Merge into decisions.md. Clear the decision field by overwriting the note without it.
|
|
988
|
+
{% elif STATE_BACKEND == "two-layer" %}
|
|
989
|
+
2. DECISION MERGE (two-layer): Merge .squad/decisions/inbox/ → decisions.md AND read agent note refs for any decisions with `promote_to_permanent`. Deduplicate. Push note refs: `git push origin 'refs/notes/squad/*'`
|
|
990
|
+
{% else %}
|
|
887
991
|
2. DECISION INBOX: Merge .squad/decisions/inbox/ → decisions.md, delete inbox files. Deduplicate.
|
|
992
|
+
{% endif %}
|
|
888
993
|
3. ORCHESTRATION LOG: Write .squad/orchestration-log/{timestamp}-{agent}.md per agent. Use ISO 8601 UTC timestamp.
|
|
889
994
|
4. SESSION LOG: Write .squad/log/{timestamp}-{topic}.md. Brief. Use ISO 8601 UTC timestamp.
|
|
995
|
+
{% if STATE_BACKEND == "git-notes" %}
|
|
996
|
+
5. CROSS-AGENT (git-notes): For team updates, write to affected agents' note refs via `powershell .squad/scripts/notes/write-note.ps1 -Ref "squad/{agent}" -Content '{json}'`.
|
|
997
|
+
{% else %}
|
|
890
998
|
5. CROSS-AGENT: Append team updates to affected agents' history.md.
|
|
999
|
+
{% endif %}
|
|
891
1000
|
6. HISTORY SUMMARIZATION [HARD GATE]: If any history.md >= 15360 bytes (15KB), summarize now.
|
|
1001
|
+
{% if STATE_BACKEND == "orphan" or STATE_BACKEND == "two-layer" %}
|
|
1002
|
+
7. GIT COMMIT (orphan): Stage `.squad/` state files and commit to the `squad-state` orphan branch:
|
|
1003
|
+
a. Identify changed `.squad/` state files via `git status --porcelain` (decisions.md, agents/*/history.md, log/*, orchestration-log/*).
|
|
1004
|
+
b. For each file, use git plumbing to write to the orphan branch:
|
|
1005
|
+
`git show squad-state:.squad/{path}` to check if file exists on orphan.
|
|
1006
|
+
Use `git checkout squad-state -- .squad/{path}` + write + `git add` + `git commit` workflow, OR
|
|
1007
|
+
use the SDK's OrphanBranchBackend if available.
|
|
1008
|
+
c. Reset working tree state files: `git checkout HEAD -- .squad/` to avoid polluting the working branch.
|
|
1009
|
+
d. Push orphan branch: `git push origin squad-state`
|
|
1010
|
+
⚠️ NEVER commit `.squad/` state files to the working branch when using orphan backend.
|
|
1011
|
+
{% else %}
|
|
892
1012
|
7. GIT COMMIT: Stage only the exact `.squad/` files Scribe wrote in this session. Use `git status --porcelain` filtered to allowed paths (decisions.md, decisions-archive.md, agents/{name}/history.md, agents/{name}/history-archive.md, log/*, orchestration-log/*). Stage each file individually with `git add -- <path>`. Handle renames by extracting destination path (`-replace '^.* -> ',''`). Commit with -F (write msg to temp file). Skip if nothing staged. ⚠️ NEVER use `git add .squad/` or broad globs.
|
|
1013
|
+
{% endif %}
|
|
893
1014
|
8. HEALTH REPORT: Log decisions.md before/after size, inbox count processed, history files summarized.
|
|
894
1015
|
|
|
895
1016
|
Never speak to user. ⚠️ End with plain text summary after all tool calls.
|
|
@@ -947,6 +1068,8 @@ If the user wants to remove someone:
|
|
|
947
1068
|
|
|
948
1069
|
## Source of Truth Hierarchy
|
|
949
1070
|
|
|
1071
|
+
> **State backend note:** Files below marked as "Derived / append-only" are **mutable state** — their storage location depends on the configured `STATE_BACKEND`. On `worktree` (default), they live on disk. On `git-notes`, they live in git notes refs. On `orphan`, they live on the `squad-state` orphan branch. On `two-layer`, commit-scoped annotations live in git notes AND permanent state lives on the orphan branch. Files marked as "Authoritative" are **static config** and always live on disk regardless of backend.
|
|
1072
|
+
|
|
950
1073
|
| File | Status | Who May Write | Who May Read |
|
|
951
1074
|
|------|--------|---------------|--------------|
|
|
952
1075
|
| `.github/agents/squad.agent.md` | **Authoritative governance.** All roles, handoffs, gates, and enforcement rules. | Repo maintainer (human) | Squad (Coordinator) |
|