Writ Complete Overview

The whole system, one page, seven diagrams.

Writ sits between an AI coding agent and the file system. It pulls the right rules from a knowledge graph in well under a millisecond, then refuses to let the agent write code until the user has approved a plan and tests. This page walks the whole system end to end, switching diagram types to fit what each part actually is.

5
retrieval stages, sub-millisecond p95
~30
bash hooks, 11 trigger types
12
knowledge-graph node types
4
session modes, 4 phase gates
3
authority levels in the rule ladder
Diagram 1 / Block diagram

What talks to what

Four layers: the agent at top, the hook scripts in the middle, the HTTP service below them, and the persistent stores at the bottom. Hooks shell out to a session helper and to the HTTP API; the API does the heavy retrieval work over the graph and the two indexes.

Agent Hook layer (bash) HTTP service (FastAPI :8765) Stores & indexes Claude Code (agent) user-facing CLI / IDE SessionStart bootstrap, load mandatory 1 hook UserPromptSubmit RAG inject, context watch 3 hooks PreToolUse / PostToolUse validate, gate, mark tests 20 hooks Stop / SessionEnd run tests, audit, log 7 hooks Pre/PostCompact snapshot & restore state 2 hooks bin/lib/writ-session.py session state: mode, phase, budget, gates FastAPI service (writ/server.py) /query, /propose, /feedback, /pre-write-check, /session/* (~36 endpoints) RetrievalPipeline (writ/retrieval/pipeline.py): domain filter -> BM25 -> ANN -> graph traversal -> two-pass rank Neo4j graph: 12 node types, edges Tantivy index BM25 keyword search hnswlib + MiniLM 384-dim vector index Session cache per-session JSON state workflow-friction.log append-only event stream bible/ markdown files (canonical rule source; ingested into Neo4j on import; exported back on edit) import export

How to read it. Solid arrows are runtime calls (the hooks shell out to writ-session.py and curl the HTTP API). Dashed arrows are offline data transfers: rule markdown gets imported into Neo4j once, and exports flow back out when a rule is added or edited.

Diagram 2 / Process flowchart

Session lifecycle: START to END

Classic process flowchart of one coding session. Rectangles are work, diamonds are decisions, dashed pink arrows are iterate-until-it-passes loops. The non-Work modes (Conversation, Debug, Review) skip past the four phase gates.

START Session bootstrap load mandatory rules User submits prompt UserPromptSubmit fires Inject rules (RAG) 5-stage pipeline runs Which mode? set before any write Conv / Debug / Review Respond directly no phase gates END Work Write plan.md Files / Analysis / Rules / Capabilities Plan approved? user types "approved" no yes Write test skeletons signatures + assertions only Tests approved? user types "approved" no yes Implement + run tests + verify iterate until green, update capabilities on success

Why a flowchart here. The session is a process: start state, ordered steps, decision points, terminate state. Loop-back arrows make the iterate-until-it-passes pattern visible. For the inside of one RAG query, the sequence diagram below is the better idiom.

Diagram 3 / Sequence diagram

What happens when you press Enter

Time goes top to bottom. Each vertical lane is one actor. The whole round trip, from user keypress to rules-in-context, finishes in roughly the time it takes to run a single Python function.

User Claude Code Hook layer HTTP API Pipeline Stores submit prompt UserPromptSubmit hook fires POST /query (prompt, budget) pipeline.query(text) BM25 search (Tantivy) 50 candidates ANN search (hnswlib) 10 candidates 2-hop expand (cache) neighbors ranked rules (RRF + weights) JSON: rules within budget inject rules into prompt response (rule-aware) End-to-end latency: dominated by the hook shell overhead. Pipeline itself is sub-millisecond p95 on a 276-rule corpus. All five retrieval stages (domain filter, BM25, ANN, graph traversal, ranking) run in-memory off pre-warmed indexes; no Neo4j round trip per query.

Why a sequence diagram here. Six actors and a strict message ordering. A flowchart would hide the fact that the API holds open one request while the pipeline does three sub-queries in sequence.

Diagram 4 / Funnel

5-stage retrieval, candidates narrowing

A funnel: corpus on the left, the top few rules that land in the agent's context on the right. Each stage drops candidates that do not help, so by the end only the small bundle the agent actually needs remains.

All rules corpus ~10K indexed Domain filter Stage 1 ~500 in-domain BM25 + ANN Stages 2 + 3 60 union of candidates Graph expand Stage 4 ~80 + neighbors Rank (RRF) Stage 5 all scored Budget cap trim 5 - 8 Injected into agent context final bundle Ranking weights (Stage 5): Vector 0.594    BM25 0.198    Severity 0.099    Confidence 0.099    Graph proximity 0.01

Why a funnel here. The pipeline is fundamentally a narrowing process: lots in, few out. The flowchart and sequence diagrams would not show the candidate-count compression that defines the design.

Diagram 5 / State machine

Modes and phases as a formal state machine

Top row: the four session modes. Bottom row: the four phase sub-states that exist only inside Work mode. Each arrow is a legal transition. Anything off this diagram is denied by a hook.

null no mode set mode set Conversation discuss / brainstorm Debug root-cause evidence Review structured findings Work enters phase gates ↓ enter Work Inside Work mode: phase sub-states planning writes plan.md testing writes test skeletons implementation writes code + runs tests verification updates capabilities.md approve approve tests pass rewrite plan rewrite tests tests fail / fix complete end

Why a state machine here. Modes and phases are states with strict legal transitions. A flowchart would imply a single linear path; a state diagram makes the legal/illegal edges explicit, which is what the gate hooks actually enforce.

Diagram 6 / Graph view

The knowledge graph: not a flat list

A miniature view of the rule corpus as it actually lives in Neo4j. One node per category, real edge types. The retrieval pipeline walks these edges to find related rules when a single rule is hit.

COUNTERS TEACHES DEMONSTRATES CONTAINS CONTAINS DISPATCHES SUPERSEDES RELATED_TO DEPENDS_ON PRESSURE_TESTS GATES ATTACHED_TO Rule Rule (old) Anti Pattern Rational Skill Technique Playbook Phase Subagent Role Worked Example Pressure Scenario Forbidden Response Abstrac- tion
Rule Skill AntiPattern Playbook Abstraction ForbiddenResponse (always-on) Other types (Phase, Rationalization, Technique, WorkedExample, PressureScenario, SubagentRole)

Why a graph here. Because the knowledge base is a graph. Edges carry meaning: a rule that TEACHES a skill is different from a rule that COUNTERS an anti-pattern, and the retrieval pipeline uses those edge types to expand a hit into the bundle of rules that travel together.

Diagram 7 / Lifecycle

How a rule earns its weight

Rules do not just live in the corpus, they evolve. A proposal starts at the bottom of the authority ladder and only earns higher confidence after structural review, human approval, and finally empirical observation in production.

AI proposal writ propose ... authority: ai-provisional Gate? 5 checks Rejected cited reasons returned fail pass ai-provisional conf: speculative (0.3) in graph, queryable Human review? writ review --promote Rejected / deleted writ review --reject no promote ai-promoted conf: peer-reviewed (0.6) empirical tracking on battle tested empirical 1.0 n >= 50 and pos/total >= 0.75 empirical ratio overrides static weight Authority ladder: human (default) → ai-provisional → ai-promoted Confidence ladder: speculative 0.3 → peer-reviewed 0.6 → production-validated 0.8 → battle-tested 1.0

Why a lifecycle here. Time matters and authority matters. A flat box-and-arrow diagram would hide that "ai-provisional" and "battle-tested" are not categories but stages a rule moves through, with explicit thresholds and decision points between them.