Every Writ-enforced coding session walks this flow. Click any
shape to see what triggers it, which hooks fire, and what state
changes. The detail panel below stays in view; the flowchart on the
right scrolls horizontally.
Click any shape on the right to see its detail.
Stage 1 / Setup
START
A coding session begins. Claude Code launches; Writ has not yet been touched.
State at this point
- No session cache exists on disk.
- Mode is unset; phase is unset.
- The agent has no Writ rules in context yet.
Stage 2 / Setup
Session bootstrap
The SessionStart hook fires once and prepares Writ for the rest of the session.
What runs
.claude/hooks/session-start-bootstrap.sh
What it does
- Calls
GET /always-on to fetch the mandatory rules bundle (capped near 5K tokens).
- Creates a session-cache file keyed by session_id.
- Initializes
mode = null, phase = null, loaded_rule_ids = [].
Why it matters
- Without bootstrap there is no session state, and the gate hooks have nothing to gate against.
Stage 3 / Setup
User submits prompt
Every Enter-press fires UserPromptSubmit. Three hooks run in order.
Hooks (in order)
auto-approve-gate.sh: defense-in-depth pattern match on "approved" (primary path is the writ-approve tool call).
writ-rag-inject.sh: calls POST /query to retrieve relevant rules.
writ-context-watcher.sh: records a context-pressure snapshot.
Stage 4 / Setup
Inject rules (the RAG pipeline)
The five-stage retrieval pipeline picks the most relevant rules for this prompt and injects them into the agent's context.
The five stages
- Domain filter, BM25 (Tantivy), ANN vector (hnswlib), graph traversal (Neo4j adjacency cache), two-pass ranking with RRF.
What the agent sees
- The always-active rules block (mandatory, every turn).
- A small bundle of retrieved domain rules (3 to 8 typically).
Source
writ/retrieval/pipeline.py for the orchestration.
writ/retrieval/ranking.py for the weight formula.
Decision / Routing
Which mode? (decision)
Before any write, the agent declares the session's mode. Until a mode is set, gate hooks deny all writes except plan.md.
The four modes
- Conversation: discuss, brainstorm. No phase gates.
- Debug: investigate a problem. No code generation expected.
- Review: evaluate existing code against rules. Structured findings only.
- Work: build or modify code. Enters the four phase gates.
How the agent sets mode
python3 bin/lib/writ-session.py mode set <mode> <session_id>
- With
--orchestrator for sub-agent dispatch workflows.
Source
bin/lib/writ-session.py:835-985
Non-Work branch
Respond directly
In Conversation, Debug, and Review modes, the agent answers the prompt with no phase gates and no write enforcement (beyond the always-active rules).
Why this path exists
- Most prompts are not "write me production code." Modes that do not generate code skip the gate ceremony entirely.
- RAG still injects relevant rules. The mandatory rules still apply (forbidden phrases, etc.).
Mode-specific deliverables
- Debug: root-cause evidence (per ENF-PROC-DEBUG-001).
- Review: per-file structured findings.
Terminal
END (non-Work)
For non-Work modes, the response is the deliverable. The SessionEnd hook still runs for friction logging.
Work mode / Phase 1
Write plan.md
The agent writes plan.md and capabilities.md to the project root, then presents the plan and waits for the user.
Required sections
## Files, ## Analysis, ## Rules Applied, ## Capabilities.
- No placeholder text (TBD, TODO, "similar to N") - enforced by ENF-PROC-PLAN-001.
Hooks involved
validate-exit-plan.sh (PreToolUse on ExitPlanMode).
validate-file.sh (PostToolUse): runs the structural gate.
Decision / Phase gate 1
Plan approved? (decision)
The user reads the plan and either approves it or asks for changes. Approval is recorded in the audit trail.
How approval advances the phase
- User types "approved".
- Agent invokes the
writ-approve tool.
- That calls
POST /session/{id}/advance-phase with confirmation_source: "tool".
- Phase moves planning -> testing.
Outcomes
yes: advance to Testing
no: rewrite plan, loop back
Work mode / Phase 2
Write test skeletons
The agent writes test files: class names, method signatures, and assertions, but no implementation code.
Hooks involved
validate-test-file.sh (PreToolUse): structural check on test files.
writ-mark-pending-test.sh (PostToolUse): records the test path for the run hook.
What the agent shows the user
- Class names and test counts only. No method-by-method listing.
Decision / Phase gate 2
Tests approved? (decision)
User reviews the test list. Approval moves the phase to implementation.
Outcomes
yes: advance to Implementation
no: rewrite tests, loop back
Work mode / Phase 3
Write implementation
The agent writes production code. Every Write or Edit fires more hooks: validate, rule-check, re-inject rules, mark tests pending.
Per-write hooks
pre-validate-file.sh (PreToolUse): structural check.
writ-pre-write-dispatch.sh (PreToolUse): can-write gate.
validate-file.sh (PostToolUse): rule-compliance check.
validate-rules.sh (PostToolUse): asserts no rule violations.
writ-posttool-rag.sh (PostToolUse): re-injects rules surfaced by the file just written.
writ-quality-judge.sh (PostToolUse): per-rubric quality scoring.
writ-mark-pending-test.sh (PostToolUse): marks test for next Stop hook.
Work mode / Phase 3
Run pending tests
When the agent pauses (Stop hook), Writ runs every test marked this session and writes the result to the friction log.
What runs
.claude/hooks/writ-run-pending-tests.sh
- 60-second timeout, runner grouping (pytest, PHPUnit, jest detected from paths).
What lands in the friction log
writ-run-pending-tests event with result_code and resolved_count.
Decision / Phase gate 3
Tests pass? (decision)
If tests pass, the agent advances to verification. If they fail, it loops back to implementation and tries again.
Outcomes
yes: advance to Verification
no: agent fixes code, re-runs tests, loop back
Why automatic rather than user-approved
- Test pass/fail is a fact, not a judgment. The runner exit code is authoritative.
- The user is still informed via the friction log and the agent's own summary.
Work mode / Phase 4
Verify + update capabilities.md
The agent checks off completed items in capabilities.md, citing verification evidence (test runs, file paths, line numbers).
Hooks involved
writ-verify-before-claim.sh (PreToolUse on TodoWrite, and on Stop): denies completion marks without evidence.
Why this is the strictest hook
- False completion claims compound across the rest of the workflow. The gate forces evidence in the same message as the claim.
Cleanup
Session end: friction log + audit
SessionEnd hooks write the final friction entries, persist session state, and emit a pressure audit.
Hooks involved
writ-session-end.sh: persists final session cache.
writ-pressure-audit.sh: emits a context-pressure summary.
friction-logger.sh: writes the final friction entries.
enforce-violations.sh: applies any pending violations.
What lands on disk
workflow-friction.log: append-only event stream.
- Session cache file remains for replay or post-mortem.
Terminal
END
Session complete. The agent's outputs (code, plan, capabilities) and the friction log are the artifacts that survive.