Two layers: the engine and the harness
The engine answers “how do I build this?” The harness answers “how careful should I be, and who needs to approve?” They're independent — and that's the whole trick.
⚙ The engine — skills
skills/ · agents/Invocable /skills that actually do the work. Each has hard gates and a defined handoff to the next.
- brainstorm · research · plan
- build · review · ship
- chained — no skipping steps
🛡 The harness — risk/trust
feature-intake · hooks/ · rules/A thin control layer that decides — before the engine runs — how much process a change needs and when to ask a human.
- classify lane + confidence
- route to the right path
- corroborate the claim at commit
Two independent dials
RISK
how much proof & process — planning, reviews, evidence, rollback — a change carries.
AMBIGUITY
whether a human is asked — never to classify risk, only to confirm intent or authorize a dangerous boundary.
So a high-risk-but-clear change runs autonomously through heavy proof. A tiny-but-unclear change stops to ask. Risk ≠ interruption.
Try the classifier
/feature-intake runs first on every change request — a 10-flag risk checklist + hard gates assign a lane, a confidence score decides whether a human is needed. Pick a request and watch it route.
Three risk lanes
The lane decides how much of the workflow actually runs. Skipping a step the lane requires is a hard gate violation.
Full auto. No planning, no human confirmation — the machine gates (ruff-on-edit, commit-quality-gate, risk-corroboration) are the safety net.
Auto with proof gates. Clear work proceeds with a notify-and-proceed notice instead of blocking; per-task spec→quality review stays always-on.
Auto-plan, gated-execute. The full chain runs; a hard gate discovered mid-task escalates regardless of the original lane.
The hard gates
These categories always force high-risk and can only be lowered by a human narrowing scope. The agent can't classify a risky change as "tiny" and slip it through — a hook corroborates the diff against the declared lane at commit time.
settings.json, hooks/*, skill enginesThese eight are detectable — risk-corroboration.sh scans the diff for them. Three more are judgment gates that no regex can catch, so an agent or human must call them: remove-functionality · session-scope · replace-service.
A hard gate hit and not yet narrowed by a human → write a block to specs/<slug>/ESCALATIONS.md and stop. It's deny-on-no-response: with no recorded decision, the work stays blocked.
brainstorm → ship
Each step hands off to the next. /feature-intake runs first and decides how many of these steps apply — the high-risk lane runs them all; tiny drops straight to a direct edit.
The skill library
Each skill is a Markdown prompt program with a defined scope, hard gates, and a handoff. Click one to expand.
Rules enforced by code, not hope
What can be mechanized is a hook — convention is the residue, not the rule. Hooks fire on Claude Code lifecycle events. ● wired = registered & firing · ○ dormant = on disk, not registered.
| hook | trigger | action | status |
|---|---|---|---|
| check-untracked-py.sh | PreToolUse · git | Block commit/push if untracked .py files exist | ● wired |
| commit-quality-gate.sh | PreToolUse · git commit | Secrets scan + debug-artifact check + targeted pytest | ● wired |
| risk-corroboration.sh | PreToolUse · git commit | Block if staged diff trips a hard gate but declared lane is below high-risk | ● wired |
| branch-guard.sh | PreToolUse · git commit | Warn when committing on main | ● wired |
| branch-isolation-guard.sh | PreToolUse · Edit/Write | Block a code edit when implementation is underway on a shared branch with no isolated worktree | ● wired |
| ruff-on-edit.sh | PostToolUse · Edit/Write | ruff --fix + ruff format on edited .py | ● wired |
| blast-radius-check.sh | PostToolUse · Edit/Write | Warn when an edit touches a file outside the active plan's file set | ● wired |
| render-plan-on-write.sh | PostToolUse · Edit/Write | Auto-render specs/<slug>/PLAN.md → PLAN.html on save (deterministic, no LLM) | ● wired |
| scope-gate.sh | UserPromptSubmit | Warn on implementation intent with no plan referenced (lane-aware) | ● wired |
| session-knowledge.sh | SessionStart | Load the knowledge base (INDEX + critical patterns) into session context; never blocks | ● wired |
| state-breadcrumb.sh | SessionEnd | Append a dated session breadcrumb to specs/STATE.md for cross-session resumption; never blocks | ● wired |
| auto-test-on-change.sh | PostToolUse · Edit/Write | Run the project's tests when a test file is touched — runner detected per ecosystem (pytest / vitest / jest / go test) | ○ dormant |
| protected-path-guard.sh | PreToolUse · Edit/Write | Block a write to a high-blast file unless a break-glass reason is pre-registered. Dormant by design — wiring it is itself a hard-gate change | ○ dormant |
A graph that knows the code, a memory that compounds
Two systems make the skills smarter over time — a structural knowledge graph for navigation, and a knowledge base that turns every solved problem into reusable context.
▣ code-review-graph · MCP
A persistent, incremental knowledge graph — Tree-sitter parses the codebase into structural nodes & edges. Skills query it before Grep/Glob: it's faster, cheaper in tokens, and gives structure that file-scanning can't.
detect_changes— risk-scored review of a diffget_impact_radius— blast radius of a changequery_graph— callers · callees · imports · testssemantic_search_nodes— find by name or keyword
✦ /compound + docs/solutions
After a session with a non-obvious fix, pattern, or decision, /compound mines the transcript and writes a discoverable doc. Four track types: bug · knowledge · decision · failure (a tried-and-abandoned approach, so it's never repeated).
- front-matter: module · tags · severity ·
applicable_when critical-patterns.md— read at planning time- every bug doc requires a
## Regression Test - read back by
/brainstorming&/xia2
There's also context7 (a user-level MCP server) for fetching version-matched library docs on demand — so skills answer from current docs, not stale training data.
Drop it into your repo
Skills are loaded by the Claude Code CLI. Add the harness to an existing project with one line.
01 · Install into an existing project
Clones the harness, copies it in, and builds .claude/. Needs git + jq. Existing files are backed up first.
# one-liner — adds skills, agents, hooks & rules
curl -fsSL "https://raw.githubusercontent.com/minhtran3124/agent-harness/main/scripts/install-harness.sh?$(date +%s)" | bash -s -- --yes
02 · Wire the knowledge graph (MCP)
The repo wires code-review-graph via uvx — no manual pip install. You just need uv.
curl -LsSf https://astral.sh/uv/install.sh | sh # installs uv + uvx uvx code-review-graph serve # exactly what mcp.json invokes
03 · Or develop on the harness itself
Root dirs are the source of truth; Claude Code loads a derived, gitignored .claude/. Rebuild it, then restart Claude Code.
bash scripts/deploy-harness.sh # idempotent: installs, then updates
04 · Use it
In any change request, the harness starts with intake — then routes you down the right path.
/feature-intake # classify → lane + confidence → route