Architecture
Warden operates as a hook-based runtime layer. Every tool call your AI assistant makes passes through the hook pipeline before execution. The entire round-trip completes in under 2 milliseconds.
Hook Pipeline
The daemon handles the fast path via named pipes (Windows) or Unix sockets. On the allow path, a single RegexSet DFA pass evaluates all ~300 patterns simultaneously — keeping latency below the threshold where agents would notice.
Hook Types
Warden registers handlers for every hook point the AI assistant supports:
| Hook | When it fires | What Warden does |
|---|---|---|
| PreToolUse | Before a Bash command, file read, or file write | Rule evaluation: safety, substitution, hallucination, path protection. May deny or advise. |
| PostToolUse | After a tool call completes | Session state update, output compression, loop detection, verification debt tracking. |
| PreCompact | Before the assistant compacts its context | Injects the resume packet so critical context survives compaction. |
| PostCompact | After context compaction | Validates the resume packet was preserved; re-injects if needed. |
| SessionStart | When a new session begins | Loads session state, injects the resume packet from the previous session if available. |
| SessionEnd | When the session ends | Generates the scorecard, triggers dream state processing, writes session summary. |
| UserPromptContext | When the user sends a new prompt | Injects context-aware advisories based on current session phase. |
| StopCheck | When the agent considers stopping | Evaluates whether stopping is premature (e.g., verification debt is high). |
Each hook handler is panic-isolated. If a handler crashes, it exits 0 and never blocks the AI assistant. A crashed handler is logged for post-mortem debugging, and the daemon self-heals on the next call.
Daemon
The Warden daemon is a long-lived background process that handles all hook evaluation. It exists for one reason: latency. Spawning a new process for every hook call would add 50-200ms of overhead. The daemon keeps everything hot in memory and responds over IPC in under 2ms.
Key properties:
- IPC transport: Named pipes on Windows, Unix domain sockets on Linux/macOS.
- Startup: Automatically spawned on
warden init,warden install, or the first hook call that finds no running daemon. - Self-healing: If the daemon crashes or is killed, the next hook call detects the dead pipe and spawns a fresh instance. Session state is persisted to disk, so the new daemon picks up where the old one left off.
- Cache: Rule evaluations, compiled RegexSets, and session state are held in memory for the duration of the session. No disk I/O on the hot path.
- Background tasks: The daemon runs the dream state worker in a low-priority thread during idle periods (between sessions or during long gaps between tool calls).
- Monitoring:
warden daemon-statuschecks if the daemon is running.warden daemon-stopterminates it gracefully.
Relay (Windows)
On Windows, hook commands spawn a console window (CMD flash). The relay binary (warden-relay.exe) is a windowless shim that forwards hook calls to the main binary without the flash. It’s installed automatically alongside the main binary.
The relay uses the Windows CREATE_NO_WINDOW flag so no console appears. It reads the hook payload from stdin, forwards it to the daemon over named pipes, and writes the response back. The relay adds less than 1ms of overhead.
3-Binary Architecture
Warden runs as three cooperating binaries, each with a distinct role:
| Binary | Size | Role |
|---|---|---|
relay (warden-relay.exe) | ~215KB | Windowless shim (Windows only). Receives the hook payload from stdin and forwards it to the warden binary without the CMD flash. |
| warden | ~3.7MB | The main binary. Tries to connect to the running daemon first. If the daemon isn’t running, spawns it, then forwards the request. Also handles CLI commands (warden doctor, warden describe, etc.). |
| daemon | (background) | Long-lived process that holds compiled regexes, session state, and dream artifacts in memory. All rule evaluation happens here. |
The flow on each hook call: relay (stdin) -> warden (IPC connect) -> daemon (evaluate + respond). On the first call of a session, warden spawns the daemon if needed. Subsequent calls hit the already-warm daemon directly.
IPC Transport
| Platform | Transport | Path |
|---|---|---|
| Windows | Named pipes | \\.\pipe\warden-<project-hash> |
| Linux / macOS | Unix domain sockets | /tmp/warden-<project-hash>.sock |
The transport is selected at compile time. Both use a simple length-prefixed JSON protocol: 4-byte little-endian length header followed by the JSON payload.
Self-Healing
The daemon is designed to recover from any failure state without user intervention:
- Auto-start: If a hook call finds no running daemon, the warden binary spawns one automatically. The first call pays ~50ms startup cost; all subsequent calls hit the warm daemon.
- Stale PID cleanup: On startup, the daemon checks for a PID file from a previous instance. If the PID is no longer running, the stale file is removed and a fresh daemon starts.
- Binary rebuild detection: The daemon records the hash of its own binary at startup. If a
warden updatereplaces the binary, the next hook call detects the mismatch and restarts the daemon with the new binary. - Idle timeout: The daemon shuts itself down after a configurable idle period (default: 30 minutes with no hook calls). This prevents orphaned daemons from consuming resources. The next session’s first hook call starts a fresh instance.
Dream State
Between sessions, Warden’s background worker analyzes completed runs through 10 prioritized learning tasks:
| Priority | Task | What it produces |
|---|---|---|
| 1 | LearnEffectiveness | Which rules preceded progress vs. were ignored. Feeds the injection budget. |
| 2 | BuildResumePacket | Compact session summary for the next session to pick up from. |
| 3 | LearnSequences | Successful action sequences worth repeating (e.g., “run lint before build”). |
| 4 | ClusterErrors | Group repeated errors into durable knowledge (e.g., “this project’s type errors are usually in the handler layer”). |
| 5 | LearnRepairPatterns | Map error signatures to fixes that worked. |
| 6 | LearnConventions | Project conventions from recurring patterns (naming, file structure, testing style). |
| 7 | UpdateWorkingSetRanking | Rank files/directories by recency, frequency, and outcome. |
| 8 | BuildDeadEndMemory | Approaches that were tried and failed, so the next session avoids them. |
| 9 | ScoreArtifacts | Prune weak or outdated learning artifacts by usefulness. |
| 10 | ConsolidateEvents | Compress raw event logs into higher-level facts (housekeeping). |
Tasks run in priority order during daemon idle time. If the daemon is shut down before all tasks complete, the remaining tasks run on the next daemon start.
Storage
Warden uses redb — an embedded key-value store written in Rust — for all persistent data. The database file lives at ~/.warden/data/<project-hash>/warden.redb.
Key tables:
| Table | Contents |
|---|---|
| sessions | Per-session state: turn count, trust score, phase, focus metrics, edited files |
| events | Raw event log: every hook call, every rule firing, every advisory |
| dream | Dream state artifacts: learned patterns, error clusters, repair maps |
| resume_packets | Compact session summaries for cross-session continuity |
| effectiveness | Per-rule effectiveness scores (was the intervention helpful?) |
| working_set | File/directory rankings by recency-frequency-outcome |
| dead_ends | Approaches that were tried and failed |
The database is append-optimized and uses MVCC for concurrent reads. The daemon writes in batches during idle periods, never on the hot path.
Session State
During an active session, Warden tracks the following state in memory (persisted to redb on each turn):
| Field | Description |
|---|---|
turn | Current turn number (incremented on each tool call) |
phase | Current session phase (Warmup, Productive, Exploring, Struggling, Late) |
trust_score | Composite trust metric (0-100) |
focus_score | How concentrated the work is across the file system |
edited_files | Set of files modified this session |
verified_files | Subset of edited files that have been tested/built |
error_count | Running count of command errors |
subsystem_switches | Number of times the agent changed working directory clusters |
dead_ends | Count of approaches that were started and then abandoned |
loop_state | Recent command patterns for loop detection |
adaptive_params | Phase-adjusted thresholds (compression limits, intervention frequency) |
The Resume Packet
The resume packet is the bridge between sessions and across context compactions. It contains:
- Working set: The top files by importance, so the next session (or post-compaction context) knows where to focus.
- Dead ends: Approaches that failed, to avoid repeating them.
- Conventions: Project patterns learned during the session.
- Error clusters: Common error types and their known fixes.
- Session summary: What was accomplished, what was left unfinished.
When context compaction occurs (the AI assistant runs out of context and summarizes), the PreCompact hook injects the resume packet into the compaction input. This means the most critical session knowledge survives even when the model forgets everything else.
When a new session starts, the SessionStart hook checks for resume packets from previous sessions and injects the most recent one. The agent begins with context it didn’t have to earn — it already knows the working set, the dead ends, and the project conventions.