main
md 202 lines 5.58 KB
Rendered Raw
1 # Squad Notes Protocol
2
3 > Contract for agent state via git notes. Agents write commit-scoped context
4 > here instead of modifying `.squad/` files in PRs.
5 >
6 > **Version:** 1.0
7 > **Backends:** `git-notes`, `orphan`
8
9 ---
10
11 ## Overview
12
13 Squad state has two layers:
14
15 1. **Git notes layer** (this document) — thin, commit-scoped annotations that
16 attach agent context to commits without appearing in PRs or diffs.
17 2. **Permanent state layer** — long-lived decisions, routing rules, and archives
18 stored via the configured state backend (`git-notes` or `orphan` branch).
19
20 Agents write notes during their work rounds. Ralph promotes flagged notes to
21 permanent state after a PR merges.
22
23 ---
24
25 ## Namespaces
26
27 Each agent writes to its own namespace to prevent conflicts:
28
29 | Namespace | Owner | Purpose |
30 |-----------|-------|---------|
31 | `refs/notes/squad/data` | Data | Architecture decisions, implementation choices |
32 | `refs/notes/squad/worf` | Worf | Security reviews, vulnerability assessments |
33 | `refs/notes/squad/seven` | Seven | Documentation quality, API contract decisions |
34 | `refs/notes/squad/ralph` | Ralph | Work-round progress, task-state annotations |
35 | `refs/notes/squad/q` | Q | Devil's advocate findings, risk assessments |
36 | `refs/notes/squad/research` | Any agent | Research notes that should survive branch deletion |
37 | `refs/notes/squad/review` | Any agent | Code review context (mirrors Gerrit's pattern) |
38
39 **Rule**: Only write to your own namespace. The shared namespaces
40 (`research`, `review`) use `append` — never `add`.
41
42 ---
43
44 ## Note JSON Schema
45
46 All notes MUST be valid JSON. Minimum required fields:
47
48 ```json
49 {
50 "agent": "Data",
51 "timestamp": "2026-03-23T14:00:00Z",
52 "type": "decision | research | review | progress | security",
53 "content": "..."
54 }
55 ```
56
57 ### Decision notes
58
59 ```json
60 {
61 "agent": "Data",
62 "timestamp": "2026-03-23T14:00:00Z",
63 "type": "decision",
64 "decision": "Use JWT RS256 for auth middleware",
65 "reasoning": "Existing pattern in codebase — auth.go:47-89.",
66 "alternatives_considered": ["HS256", "session tokens"],
67 "confidence": "high",
68 "promote_to_permanent": true
69 }
70 ```
71
72 Set `"promote_to_permanent": true` to signal Ralph to copy this to
73 `decisions.md` after the PR merges.
74
75 ### Research notes
76
77 ```json
78 {
79 "agent": "Data",
80 "timestamp": "2026-03-23T14:00:00Z",
81 "type": "research",
82 "topic": "JWT vs session tokens",
83 "findings": {},
84 "effort_hours": 2.5,
85 "archive_on_close": true
86 }
87 ```
88
89 Set `"archive_on_close": true` to signal Ralph to archive this to
90 `state/research/` even if the PR is rejected.
91
92 ---
93
94 ## Write Commands
95
96 ```bash
97 # Write a decision note on the current commit
98 git notes --ref=squad/{your-agent} add \
99 -m '{"agent":"{Agent}","timestamp":"...","type":"decision","decision":"..."}' \
100 HEAD
101
102 # Append to an existing note (multiple items on same commit)
103 git notes --ref=squad/{your-agent} append \
104 -m '{"agent":"{Agent}","timestamp":"...","type":"progress","content":"..."}' \
105 HEAD
106
107 # Read your note
108 git notes --ref=squad/{your-agent} show HEAD
109
110 # List all commits with notes in your namespace
111 git notes --ref=squad/{your-agent} list
112 ```
113
114 Or use the helper script:
115
116 ```powershell
117 ./scripts/notes/write-note.ps1 -Agent data -Type decision \
118 -Content '{"decision":"Use JWT","reasoning":"..."}' \
119 [-Commit HEAD] [-Promote] [-Archive]
120 ```
121
122 ---
123
124 ## Fetch / Push
125
126 **Notes are NOT fetched or pushed by default.** Every clone needs setup.
127
128 ### One-time setup
129
130 ```bash
131 git config --add remote.origin.fetch 'refs/notes/*:refs/notes/*'
132 git fetch origin 'refs/notes/*:refs/notes/*'
133 ```
134
135 Or use the helper:
136
137 ```powershell
138 ./scripts/notes/fetch.ps1 -Setup
139 ```
140
141 ### Every work round
142
143 1. **Start**: `git fetch origin 'refs/notes/*:refs/notes/*'`
144 2. **End**: `git push origin 'refs/notes/*:refs/notes/*'`
145
146 ---
147
148 ## Conflict Handling
149
150 1. **Per-agent namespaces prevent 99% of conflicts.** Only one agent writes to
151 `refs/notes/squad/data`, so there are no write conflicts in normal use.
152
153 2. **Same agent, two machines:** First push wins. Losing machine should fetch
154 and append:
155 ```bash
156 git fetch origin 'refs/notes/*:refs/notes/*'
157 git notes --ref=squad/{agent} append -m '{...}' HEAD
158 git push origin 'refs/notes/*:refs/notes/*'
159 ```
160
161 3. **Shared namespaces** (`research`, `review`): Always use `git notes append`,
162 never `git notes add`.
163
164 4. **Push conflict recovery:**
165 ```bash
166 git fetch origin 'refs/notes/*:refs/notes/*'
167 git notes merge refs/notes/remotes/origin/squad/{namespace}
168 git push origin 'refs/notes/*:refs/notes/*'
169 ```
170
171 ---
172
173 ## When to Use Notes vs State Backend
174
175 | Use git notes | Use state backend |
176 |---------------|-------------------|
177 | Why THIS choice on THIS commit | Universal routing rules, conventions |
178 | Decisions scoped to a feature | Long-lived decisions for all future work |
179 | Research for a specific investigation | Research archives (promoted from notes) |
180 | Security sign-offs per commit | Agent history persisting across features |
181 | Agent-to-agent context for current feature | Team agreements and policies |
182
183 When in doubt: **notes first, promote to permanent state later.** Ralph handles
184 the promotion automatically when `promote_to_permanent` is set.
185
186 ---
187
188 ## Ralph Promotion Rules
189
190 **After PR merge:**
191
192 1. Fetch all notes from remote
193 2. Traverse commits reachable from the default branch that have notes
194 3. For each note with `"promote_to_permanent": true` → append to `decisions.md`
195 4. Push state
196
197 **After PR close/rejection:**
198
199 1. List notes in `squad/research` on the closed branch's commits
200 2. For each note with `"archive_on_close": true` → archive to `research/`
201 3. Push state
202 4. Notes on rejected commits are NOT promoted — this is the desired behavior