← Back to Thinking

RouteKit Shell — The Current Architecture

Vince Mease• Technical Deep Dive• 6/30/2026
blogtechnicalproject:routekit-shellai-agentsgovernance

A present-tense overview of RouteKit Shell (rks) today: the Dispatcher → Governor → Agent tiers, the skill vocabulary, the story lifecycle state machine, concern-based decomposition, redirect hooks, autonomous CI and cost observability, RAG grounding, and the multi-project registry. Breadth-first, with per-feature deep dives to follow.

Executive Summary

RouteKit Shell (rks) is an opinionated framework that lets an agent do real process-defined work — SDLC, and other defined processes — while keeping every step reviewable, grounded in project knowledge, and cheap to observe.

The architecture is three tiers:

  • Dispatcher — classifies intent from plain-language chat and routes it to skills.
  • Governors — autonomous subagents, one per state of a story's life.
  • MCP tools + Agents — the substrate that plans, executes, refines, ships, and researches against a RAG index.

Around them: a hook layer that redirects risky operations onto the governed path, a state machine that makes every lifecycle transition explicit and testable, and telemetry that keeps CI health and token cost visible.

This is a breadth-first tour of the whole system. Each component gets what it needs and no more; the deep dives are listed at the end. Prior posts supply background: the workflow deep dive (tool-level orchestration) and the agentified architecture (the three tiers).

One principle organizes everything: guardrails, not walls. rks optimizes for Agent Experience (AX) the way good tooling optimizes for developer experience. The agent should be productive; guardrails make good paths easy and bad paths hard. That is an AX investment, not a restriction.


1. The System in One Diagram

Rendering diagram...

Three layers:

  • Dispatcher — CLAUDE.md, in the user's Claude Code session. Classifies intent, launches the matching skill. Never calls workflow MCP tools directly. Never runs two Governors at once.
  • Governors — subagents launched as Task() calls. Each owns one state. Their context is ephemeral, garbage-collected on return; the Dispatcher keeps only a small structured summary.
  • MCP tools + Agents — the substrate. Tools (rks_plan, rks_exec, rks_refine, rks_ship, telemetry, RAG, guardrails) do the work; server-side agents orchestrate multi-step sequences.

The request always flows the same way:

Rendering diagram...

One message in. Research, refine, plan, review, execute, test, ship — all inside a Governor whose context evaporates on return.


2. The Skill Vocabulary

The interface is chat. The user talks to the Dispatcher in plain language; the Dispatcher routes that to a skill. The skill names are deliberately legible — the user watches the routing and understands what is happening. Each skill is a thin SKILL.md wrapper that bootstraps exactly one Governor (two call MCP tools directly). Ten, plus /release:

Skill Purpose
/research Research questions or produce a note; query mode answers inline, document mode writes a paper
/pipeline Full PO → QA → ARCH → Build sequence from a task description
/po Create a new backlog story
/qa Add test requirements; advance a story to ready
/arch Architectural review gate; approve or request revision
/build Implement an existing story
/ship Commit and ship uncommitted changes
/telemetry Recent activity, failures, and token-cost — calls MCP directly, no Governor
/ops Runtime/operational tasks, no plan/exec cycle
/ci Read-only, autonomous CI inspection
/release Release staging → main via rks_release under an ops Governor

Verbosity resolves through four tiers: per-invocation flag → project.json skillDefaults → SKILL.md frontmatter → implicit heartbeat. It is a context-window budget control — how much Governor chatter reaches the Dispatcher.


3. The Story Lifecycle (State Machine v2)

Every unit of work is a story. It advances through a fixed set of states. The contract lives in PHASE_MACHINE.states at packages/mcp-rks/src/workflow/phases.mjs:

Rendering diagram...

Two properties define the machine. File administration is decoupled from lifecycle state: backlog.z_implemented.* is a filename prefix, an archival marker, while the lifecycle state stays at integrated. And every state write routes through a single advancePhase() helper — one testable transition contract, not scattered field updates.

The branching split matters. A two-branch project (rks itself) goes executed → integrated directly; a three-branch project passes through committed first. Those flows and their migration mechanics are their own deep dive.


4. The Governor Pipeline

Six Governors form the pipeline — PO, QA, ARCH, Build, Ship — with Research apart, producing notes rather than code. The gates before Build are strict by design.

Some of these agents are adversarial. Their job is to reject work that is not good enough. ARCH returns needs-revision and blocks Build. The regression-witness scan fails a change that would break an existing test contract. Plan-review sends a weak plan back to refine. The reviewer can reject exec output. rks does not only help do work — it runs agents built to push back.

The concrete rejecters: stories can pass a plain-language review and still carry wrong-side conditions or circular dependencies that only a code-reading review catches, so the ARCH Governor reads the highest-risk target files and applies a checklist. A regression-witness scan runs after research — a guard that the change does not silently break the test contracts other parts of the system depend on.

The Build Governor runs a fixed chain: init → refine → research → refine → plan → plan-review (adaptive polling) → exec (self-heal, rollback) → auto-ship. Its state transitions flow through advancePhase().

Rendering diagram...

For rks's own development, the off-rail path is not an escape hatch. It is the expected path: the code being changed is the plan/exec engine the Build Governor would otherwise use. Guardrails-off is gated on a state file, not on moving files, and on the story having cleared the arch-approved gate.

Off-rail has a real cost. A Build Governor's context is ephemeral — GC'd on return, leaving the Dispatcher only a summary. Off-rail work runs in the Dispatcher's own context: it reads, edits, and tests directly, so it consumes the Dispatcher's context window rather than isolating it. Necessary for dogfooding the engine, but not context-free the way the Governor path is.


5. Decompose by Concern

rks splits a story by concern. Concern is a judgment — recognizably human, but one an agent makes well and fast. A single coherent change can carry many acceptance criteria and touch many files and still be one concern; two unrelated changes bundled into one story are two, however small.

The decision sits with the PO Governor. For each concern, it cites which acceptance criteria and which files belong to it. A gap that is the same concern — a change propagating to another layer or caller — is pulled into scope. A genuinely independent concern is deferred to a follow-up story, never merged in silently.

rks supports create-and-update in one plan. The planner pre-computes the paths a plan will create and threads them into the validators, which skip on-disk checks for those paths only. A dangling reference to a file nothing in the plan creates still fails.

This is the move rks makes everywhere. ARCH judges correctness by reading code. The research agent judges truth by citing ground-truth notes. Decomposition judges scope by concern-coherence.


6. Hooks That Redirect, Not Deny

rks's 45 hooks live permanently in .routekit/hooks/, in system, read, and write tiers. A state file (guardrails-state.json) controls per-tier enforcement. The pattern that matters is the redirect, and its role as a safety net.

Rendering diagram...

A blocked raw operation does not just deny. It emits a REDIRECT ORDER — a structured deny whose additionalContext names the Governor or agent to route through instead. The work continues down the correct path rather than dead-ending. Hooks fire on raw tools, not on agent tools, so following a redirect cannot trigger another redirect. No loops. In normal operation the Dispatcher delegates before a hook ever fires; the redirect exists to catch drift.


7. Eyes on CI — The /ci Skill and Observability

The system ships autonomously. It must see its own CI and cost without a human in the loop.

Diagnosing a CI failure by hand is slow — minutes per run, pasting logs. The /ci skill removes that. It wraps gh run list|view and the vitest-report analyzer behind a read-only allowlist in the bash-redirect hook: gh run reads pass, mutations are blocked. Five modes (latest, a run id, green, red, failures) return a status header, per-shard summaries, and a failure list.

Rendering diagram...

Cost sits alongside CI. rks_token_cost_report surfaces a waste ratio with green/yellow/red health bands, standard in /telemetry output.


8. Grounding — RAG, Note Authority, and Multi-Project

A design agent must know what is true. rks declares which notes describe reality and which describe intent. The research agent treats backlog.z_implemented.* notes as ground truth on what shipped, overriding conflicting research.* design snapshots. Without that ordering the agent reports a shipped feature as "not built" because a planning note still describes it in the future tense. The RAG layer is LanceDB, a 1.5× relevance boost for implemented work, and auto-embed on every commit.

rks runs many projects at once. A registry (routekit/registry.json plus a projects/index.jsonl manifest) tracks sibling directories, not monorepo members. attachProject() bootstraps a project's .rks/ config, hooks, and notes; each project declares its own offRail.roots so guardrails-off works across any directory layout. A new user runs a seven-stage onboarder that ends in a merged PR, not a README. One caveat: attachProject() does not yet auto-distribute Governor prompts and skills — that still needs the manual vendor-skills.sh — so a fresh project is structurally complete but not functional until that step runs.

The MCP server runs build-free. A thin bin/mcp-rks.mjs shim dynamically imports src/server.mjs and calls startServer(). No compile, no bundle. It redirects console.log to stderr on its first line, because MCP speaks JSON-RPC over stdout and a stray log corrupts the protocol. Edit source, restart, run.


9. Coming Next — The Per-Feature Deep Dives

This post stayed broad. Each of these is its own post:

  • The state machine — the advancePhase() contract, 2-branch vs. 3-branch flows, and the migration tool.
  • /ci: an agent with eyes on its own CI — read-only allowlists, sharded vitest, the dark-masking needs: gate, and autonomous failure diagnosis.
  • Decompose by concern — concern-coherence as a judgment an agent makes well and fast.
  • Hooks as redirects, not walls — the REDIRECT ORDER protocol and why hooks skip agent tools.
  • Off-rail is the expected path — guardrails as a state file, per-project roots, and the dogfood circularity problem.
  • Telemetry as a product surface — the event catalogue, correlation-id timelines, and token-cost health bands.
  • Capability composition — agents that compose other agents, with the external research agent as proof.
  • Multi-project rks — the registry, attachProject(), and the onboarder that ends in a real PR.

Conclusion

rks is three tiers — Dispatcher, Governor, Agent — wrapped around a plan/exec engine, and organized by a single principle: guardrails, not walls. What makes it more than a task runner is the quality of judgment built into each layer: correctness gates that read code rather than trust heuristics, decomposition that reasons about concerns rather than counts, hooks that redirect onto the governed path rather than dead-end, a state machine with one explicit transition contract, and observability pointed at both CI health and token cost. Every step is grounded in project knowledge and cheap to inspect. That is the whole picture; the per-feature deep dives fill in the depth.


Prior posts: RouteKit Shell Workflow Deep Dive · RouteKit Shell Agentified Workflow Deep Dive