Record architecture decisions in SPINE.md
Keep project invariants, rejected patterns, and deliberate design choices in a reviewable repository file.
SPINE.md is an architecture manifest intended to live in Git alongside your code. Use it to keep future sessions aware of constraints that are easy to lose in conversation history, and review automated changes like any other repository edit.
Bootstrap and review
Generate an initial manifest
In your project's REPL:
/spine initAFK gathers invariant, contract, and history comments, project AFK.md, Git revert history, a short CHANGELOG.md excerpt, and the location of an ADR directory if present. A classifier proposes entries from that material.
Inspect the result
/spine showRead SPINE.md directly and correct any overgeneralizations. The classifier is an aid, not an authority. If authentication or classification fails, initialization can still produce an empty skeleton.
Include it in your normal review
Review the diff and commit the file with your project's usual workflow. Ask the agent to read it before implementation, or use /ground-state, whose reconnaissance includes a spine survey.
/spine init refuses to overwrite an existing file. /spine init --force regenerates it, so inspect or preserve any hand-written decisions first. Regeneration is useful after a major architecture change, not a requirement for every session.
Entry format
| Section | Prefix | Meaning |
|---|---|---|
| Invariants | INV | Contracts that must remain true |
| Explicitly Rejected Patterns | REJ | Approaches deliberately ruled out |
| Taste Calls Made | TST | Design choices where valid alternatives exist |
## Invariants
- **INV-001** (2026-10-17, spine-init): Database writes must finish before success is rendered.
## Explicitly Rejected Patterns
- **REJ-001** (2026-10-17, spine-init): Do not keep a second mutable cache of account balances.
## Taste Calls Made
- **TST-001** (2026-10-17, spine-init): Prefer explicit parameters for extracted helpers.IDs remain stable when descriptions change. Manual entries should use the same zero-padded INV-NNN, REJ-NNN, or TST-NNN shape, followed by date, session attribution, and a one-line description. Unrecognized text is preserved as trailer content when the document is serialized.
Automatic maintenance
The top-level SessionEnd hook examines the session checkout's tracked diff against HEAD, excluding SPINE.md itself. It skips empty or spine-only diffs, subagent sessions, and an unchanged diff fingerprint already handled for that checkout.
The classifier makes a single Haiku call using Anthropic credentials. It sends up to 20,000 characters of the diff plus the current manifest, so this is model processing with potential provider cost, not a purely local parser.
| Classification | Action |
|---|---|
new-addition | Add a new entry |
strengthens | Annotate the entry as reinforced and log the finding |
weakens | Annotate the entry as partially weakened and log it for review |
contradicts | Preserve the existing entry and queue the conflict for human review |
When automatic changes are made, AFK writes the manifest atomically and attempts to stage SPINE.md with Git. If no manifest exists yet, a classifiable addition can create it. Failures are handled on a best-effort basis and logged rather than breaking session teardown.
For linked worktrees, the classified diff comes from the session's own checkout, but the manifest is read and written in the repository's main common-root checkout. Concurrent sessions can overwrite one another's manifest updates. Review staged changes before committing, especially during parallel work.
Review queued findings
/spine pendingThe queue is spine-pending.jsonl in the shared state directory. It can include reinforcements, weakened entries, unresolved IDs, contradictions, and hook errors, not just conflicts. It is not a separate queue per repository.
For a contradiction, inspect the relevant project and edit SPINE.md if the new design should replace the old constraint. Then dismiss the notification:
/spine dismiss 2Use /spine dismiss-all only when you intend to clear the whole displayed queue. Dismissing a notification does not apply its proposed change. Contradictions also trigger a best-effort Telegram notification when Telegram is configured.
Disable automatic updates
Set AFK_DISABLE_SPINE_UPDATE=1 to skip the session-end classifier:
AFK_DISABLE_SPINE_UPDATE=1 afk chat "Review the current diff without changing files"You can also store that variable in afk.env. It disables automatic updates, not the explicit /spine init command. Use manual edits if you want architecture documentation without a classifier call.