Directives
A directive is a unit of work. It specifies what to build, who should build it, and what done looks like. It's the contract between the Colonel and the Grunt.
Why not just chat?
If the Colonel tells the Grunt what to do in a chat message, that instruction lives in the chat thread — which is scaffolding. It's not in the graph, it's not queryable, and when the chat thread closes, the instruction goes with it.
Directives solve this. A directive entry is permanent. The grunt can re-read it at any point. The Colonel can check whether the acceptance criteria were met. The General can see all open directives across all branches without digging through chat logs.
Directives also enable spawning: you can't spawn_grunt against a chat message. You can against a directive ID.
Anatomy of a directive
{
"entry_type": "directive",
"title": "Add rate limiting to /api/entries",
"body": "Implement per-IP rate limiting on POST /api/entries.
Use the existing Redis client in lib/cache.ts.
Limit: 100 requests per minute per IP.
Return 429 with Retry-After header on limit hit.
Acceptance:
- Unit tests cover the happy path and limit breach
- Existing integration tests still pass
- No changes to the public API shape",
"metadata": {
"target": {
"role": "grunt",
"attention": true
},
"claim_scope": [
"src/api/entries.ts",
"src/lib/ratelimit.ts",
"tests/ratelimit.test.ts"
]
},
"branch": "platform",
"thread": "security-hardening"
}title
Short, imperative. One sentence. “Add rate limiting to /api/entries” not “Rate limiting feature implementation.”
body
The full specification. Should be self-contained — the grunt shouldn't need to read other entries to understand what to do. Include:
- What to build and where (file paths help)
- Constraints and requirements
- Clear acceptance criteria — what does “done” look like?
metadata.target
Who this directive is for. role: "grunt" means any grunt can claim it. You can also target a specific session by ID or set attention: true to flag it for the orchestrator.
metadata.claim_scope
The paths/modules the grunt is expected to touch. This is broadcast to peer sessions so they know not to step on the same files. It's advisory, not enforced — but following it prevents coordination headaches.
The directive tail
Directives accumulate amendments as work progresses. The tail is an ordered sequence of stage entries:
| Stage | Written by | Meaning |
|---|---|---|
claimed | Grunt | Grunt registered the claim, recorded intent |
checkpoint | Grunt | Progress note (repeatable) |
implementation | Grunt | Work done — files touched, acceptance checklist |
review | Colonel / LT | Verdict: approved, rejected, or escalate |
The tail enforces stage ordering. A grunt can't write implementation before claimed. The Lieutenant reads the implementation amendment to know which files to commit.
Implementation amendment is the handoff
The implementation amendment's payload.files is the list of files the LT will git add. If you omit it, the commit chain blocks.
Directive states
Directives move through states: pending → claimed → done (after review approval). They can also be reopened (rejected and sent back) or superseded (abandoned in favor of a replacement).
Writing good directives
The test: can the grunt implement this without asking any follow-up questions? If the answer is no, the directive isn't done yet. Add more context, more specific acceptance criteria, or a reference to the relevant spec entries.
Grunts are not supposed to make judgment calls about scope. If the directive is ambiguous, the grunt will write a blocking question and stop until the orchestrator resolves it. That's expensive. A clear directive is cheaper.
Next: Conventions
Directives specify individual tasks. Conventions specify how the project works — and they auto-inject into every grunt session. Read about conventions →