main
md 5.58 KB

Squad Notes Protocol

Contract for agent state via git notes. Agents write commit-scoped context here instead of modifying .squad/ files in PRs.

Version: 1.0 Backends: git-notes, orphan


Overview

Squad state has two layers:

  1. Git notes layer (this document) — thin, commit-scoped annotations that attach agent context to commits without appearing in PRs or diffs.
  2. Permanent state layer — long-lived decisions, routing rules, and archives stored via the configured state backend (git-notes or orphan branch).

Agents write notes during their work rounds. Ralph promotes flagged notes to permanent state after a PR merges.


Namespaces

Each agent writes to its own namespace to prevent conflicts:

Namespace Owner Purpose
refs/notes/squad/data Data Architecture decisions, implementation choices
refs/notes/squad/worf Worf Security reviews, vulnerability assessments
refs/notes/squad/seven Seven Documentation quality, API contract decisions
refs/notes/squad/ralph Ralph Work-round progress, task-state annotations
refs/notes/squad/q Q Devil's advocate findings, risk assessments
refs/notes/squad/research Any agent Research notes that should survive branch deletion
refs/notes/squad/review Any agent Code review context (mirrors Gerrit's pattern)

Rule: Only write to your own namespace. The shared namespaces (research, review) use append — never add.


Note JSON Schema

All notes MUST be valid JSON. Minimum required fields:

{
  "agent": "Data",
  "timestamp": "2026-03-23T14:00:00Z",
  "type": "decision | research | review | progress | security",
  "content": "..."
}

Decision notes

{
  "agent": "Data",
  "timestamp": "2026-03-23T14:00:00Z",
  "type": "decision",
  "decision": "Use JWT RS256 for auth middleware",
  "reasoning": "Existing pattern in codebase — auth.go:47-89.",
  "alternatives_considered": ["HS256", "session tokens"],
  "confidence": "high",
  "promote_to_permanent": true
}

Set "promote_to_permanent": true to signal Ralph to copy this to decisions.md after the PR merges.

Research notes

{
  "agent": "Data",
  "timestamp": "2026-03-23T14:00:00Z",
  "type": "research",
  "topic": "JWT vs session tokens",
  "findings": {},
  "effort_hours": 2.5,
  "archive_on_close": true
}

Set "archive_on_close": true to signal Ralph to archive this to state/research/ even if the PR is rejected.


Write Commands

# Write a decision note on the current commit
git notes --ref=squad/{your-agent} add \
  -m '{"agent":"{Agent}","timestamp":"...","type":"decision","decision":"..."}' \
  HEAD

# Append to an existing note (multiple items on same commit)
git notes --ref=squad/{your-agent} append \
  -m '{"agent":"{Agent}","timestamp":"...","type":"progress","content":"..."}' \
  HEAD

# Read your note
git notes --ref=squad/{your-agent} show HEAD

# List all commits with notes in your namespace
git notes --ref=squad/{your-agent} list

Or use the helper script:

./scripts/notes/write-note.ps1 -Agent data -Type decision \
  -Content '{"decision":"Use JWT","reasoning":"..."}' \
  [-Commit HEAD] [-Promote] [-Archive]

Fetch / Push

Notes are NOT fetched or pushed by default. Every clone needs setup.

One-time setup

git config --add remote.origin.fetch 'refs/notes/*:refs/notes/*'
git fetch origin 'refs/notes/*:refs/notes/*'

Or use the helper:

./scripts/notes/fetch.ps1 -Setup

Every work round

  1. Start: git fetch origin 'refs/notes/*:refs/notes/*'
  2. End: git push origin 'refs/notes/*:refs/notes/*'

Conflict Handling

  1. Per-agent namespaces prevent 99% of conflicts. Only one agent writes to refs/notes/squad/data, so there are no write conflicts in normal use.

  2. Same agent, two machines: First push wins. Losing machine should fetch and append: bash git fetch origin 'refs/notes/*:refs/notes/*' git notes --ref=squad/{agent} append -m '{...}' HEAD git push origin 'refs/notes/*:refs/notes/*'

  3. Shared namespaces (research, review): Always use git notes append, never git notes add.

  4. Push conflict recovery: bash git fetch origin 'refs/notes/*:refs/notes/*' git notes merge refs/notes/remotes/origin/squad/{namespace} git push origin 'refs/notes/*:refs/notes/*'


When to Use Notes vs State Backend

Use git notes Use state backend
Why THIS choice on THIS commit Universal routing rules, conventions
Decisions scoped to a feature Long-lived decisions for all future work
Research for a specific investigation Research archives (promoted from notes)
Security sign-offs per commit Agent history persisting across features
Agent-to-agent context for current feature Team agreements and policies

When in doubt: notes first, promote to permanent state later. Ralph handles the promotion automatically when promote_to_permanent is set.


Ralph Promotion Rules

After PR merge:

  1. Fetch all notes from remote
  2. Traverse commits reachable from the default branch that have notes
  3. For each note with "promote_to_permanent": true → append to decisions.md
  4. Push state

After PR close/rejection:

  1. List notes in squad/research on the closed branch's commits
  2. For each note with "archive_on_close": true → archive to research/
  3. Push state
  4. Notes on rejected commits are NOT promoted — this is the desired behavior