Uscha is spec-driven and tool-agnostic, and it starts before the spec. This is the operating manual for running it in Claude Code with the uscha-kit: each play tells you when it fires, what to do, and what verifies it.
Uscha rejects the usual assumption that you already know what to build. The expensive failure is a confident build of the wrong shape — so the first move is always to find the shape, and every later move advances on captured evidence, stopping short of merge.
Run /uscha-discovery when you have an idea but not a shape; run /uscha-adr-refine when the shape is known and only the edges need drawing. Neither writes code — they run on Read, Write, Glob, Grep (discovery adds WebFetch).
Grill, don't agree. A discovery where the assistant agreed with everything failed — an agreeable interviewer just inherits your blind spots and hands them back formatted as a plan. If you're not being pushed on, restart it — friction is the deliverable.
As decisions settle, write them straight into the repo — don't hoard for the end. The build reads files, not chat.
| CONTEXT.md | Domain glossary — kills fuzzy language. |
| DOMAIN-MODEL.md | The approved shape: entities + relations. |
| SPEC.md | Behavior, I/O, errors, acceptance, rollback. |
| docs/adr/*.md | One per durable decision; executable. |
| ACCEPTANCE.md | DoD as - [ ] — what readiness measures. |
| RISKS · HANDOFF | Residual risk; what to read before coding. |
Context resets (new session, /clear, compaction) lose the chat. Sub-agents and fresh sessions read files. The truth lives in versioned files.
Ask: what can this break, and what does the break cost? The answer sizes the apparatus. Don't drag the full machine behind a config tweak. Profiles are a process heuristic — no profile concept exists in the kit's code or config, and no profile selects gates automatically; you pick them.
| Profile | Example | Minimum gates |
|---|---|---|
| A · Low | minor UI / config | build + relevant test |
| B · Normal | local feature / bugfix | tests + static + review |
| C · Critical | payments / security | unit+integration+security+rollback |
| D · Multi-system | public API / events | contract tests + versioning |
| E · Legacy | refactor / migration | characterization + no-regression |
Profile E → golden testing is mandatory (see play 08). Baseline the old behavior before you touch it.
Three documents, three levels of force.
Miss one → it's a SPEC line. The Implementation Plan makes an ADR executable; code links back with // ADR: <slug>.
An ADR chooses; the CONSTITUTION forbids. An ADR may pick Postgres vs Redis. An ADR may not pick "store the secret in plaintext" — the CONSTITUTION vetoes it first. When the agent detects a violation it must log it via flag-blocker --kind constitution; once logged, it caps readiness ≤65 and blocks convergence until a human runs --resolve. The engine does not read CONSTITUTION.md itself — detection is the agent's (and your) duty; enforcement-after-logging is the engine's. Invariants are CWE-mapped.
The orchestrator takes the ADRs + ACCEPTANCE.md, builds, and runs a severity-gated review loop that stops. Three laws: converge, don't chase zero · tests are a guardrail, not the finale · generating tests ≠ running them.
qa_ledger.py init; ADRs + acceptance in. No acceptance → run /uscha-adr-refine first.log-gate, check converged/oscillation./uscha-sysdoc is optional reporting on request, not a mandatory phase.The Ralph Wiggum loop — the agent fires the "done" token too early. Only the objective gates plus the human at the merge gate close it; never the agent's own opinion — the engine doesn't close the loop by itself.
If the maker writes its own report card, it can log exit_code: 0 having run nothing. So the ledger parses real files — it doesn't transcribe claims.
# qa_ledger.py reads files, not the agent
coverage ← coverage report (e.g. jacoco.xml / lcov)
tests ← test result XML (e.g. JUnit / surefire)
static ← linters · type-checker · security scanner
LOC ← its own count (stdlib)
Absent = no evidence, never "OK". An empty-but-present report credits the fix; an absent report means the gate didn't run. A tool that didn't run is never invented as green — a lint-capable repo whose static gate never ran scores UNMEASURED (0.0) on that dimension, never a perfect 1.0.
Maker ≠ checker. The one who makes doesn't graduate the work — a fresh-context checker does. (Anthropic's evaluator-optimizer, Dec 2024.)
A gate that reads a fact may block the work. A gate that guesses over prose may only whisper. Break this and false positives kill the gate — the dev turns it off, and a dead gate is worse than none.
| Gate | Reads | |
|---|---|---|
| golden-diff | bytes vs .approved | BLOCKS |
| pit-check | mutation XML (scheduled/incremental tier, not inner-loop) | BLOCKS |
| gate-check | diff structure (deleted/disabled tests · lowered thresholds · added secrets — 1.12.0) | BLOCKS |
| static gate | 4 linters, normalized | BLOCKS |
| spec-check · structure | out-of-scope section + acceptance criteria present + traceable AC-n IDs | BLOCKS |
| phase --require pr-ready | state DERIVED from the ledger; a spike/* branch never passes (1.18.0–1.19.0) | BLOCKS |
| regression-check | findings closed with no new test = NARRATED (1.16.0); --strict gates it | ADVISES |
| waste-check | Type-1/2 clones of the diff vs the repo (reuse-first, 1.26.0) — the duplication simplicity-check can't see; flags name the file:line to reuse; gates only with --gate or defaults.waste.gate | ADVISES |
| rubric-ingest | rubric grade (versioned qualitative criteria, vendor-neutral JSON contract, 1.23.0); gates only when the human declares it | ADVISES |
| spec-check · prose | vague terms, EARS, stack naming (--strict gates) | ADVISES |
One uncorrelated checker caught 93.4% of what four caught (Osmani). Stack different opinions, not four similar linters. Fact gates run inline in /uscha-devloop (exit 0/1) and each verdict is persisted via qa_ledger.py log-gate — a persisted fail blocks convergence and caps readiness ≤65; a not-run is recorded but never green.
Everything else is agent-authored. The golden is the one thing it can't author — and that's the point. Capture what the old code actually does by running it, freeze it as human-approved .approved, then diff the migrated code against it.
golden-diff clean, or no merge..approved — a PreToolUse hook blocks the write.*.approved.* binary to .gitattributes — line endings will lie otherwise.If the agent authored the golden, it would encode the same partial understanding that lost the logic. The golden is a check on the agent, not one it grants itself — which is precisely why it exists.
The outer loop is a heartbeat that fires the inner one on a cadence. Don't build it until all four are true.
# heartbeat wrapping /uscha-devloop > /loop 0 3 * * * # nightly cadence /goal readiness ≥ 80 AND tests green AND 0 CRITICAL # fresh checker: other agent family, or at least # another profile — process, not enforced by code > run /uscha-devloop over <machine-checkable scope> stop = /goal met (fresh checker) OR budget out on-done = draft PR · escalate CONSTITUTION touches human = merge/deploy ALWAYS with approval
Unattended loop = unattended attack surface. SAST + secret-scan + dep-audit before any PR; vet every skill's origin before installing; non-verbose logs; re-audit perms every 30d, start read-only; rotate the session before it bloats. Metric: cost per accepted change — below 50% accept, the loop is losing.
Regulated/fiscal, payments, and safety-critical retail all sit on the "do NOT autonomize" side. Gated-by-design isn't a gap — it's the decision.
Fix first. But minimum evidence (what changed, how to roll back) + a retroactive SPEC/ADR are due within 24h — a process rule the team commits to, not a shipped feature. A designed escape valve keeps the method honest under pressure; an improvised one destroys it.
Claude Code + Python + git/gh + skills run the method. Stack-specific bits (build tool, database driver, linters) are the per-repo adapter in each CLAUDE.md — not the workbench.
# native installer — no Node, self-updating curl -fsSL https://claude.ai/install.sh | bash # mac/linux/wsl irm https://claude.ai/install.ps1 | iex # windows cp -r uscha-kit/.claude/skills/* ~/.claude/skills/ scoop bucket add gentleman https://github.com/Gentleman-Programming/scoop-bucket scoop install gentle-ai # author's toolchain — optional, not required by the kit claude --version && claude doctor
Cloning to a teammate isn't one file — it's 7 layers: config, plugins, skills, agents+commands, hooks, the external CLI, and MCP servers (author's setup — not shipped in the kit; the kit itself needs only Claude Code, Python 3.8+, git, optional gh, and the skills copied to ~/.claude/skills).
settings.json hardcodes C:\Users\…. The author's bootstrap tooling tokenizes the path on export and rewrites it on import (not shipped in the kit).| /uscha-discovery | idea→shape grill; proposes entities/endpoints. |
| /uscha-adr-refine | polish a decision's edges. |
| /uscha-devloop | plan → coverage → build → QA loop → integration. |
| /uscha-sysdoc | two-view deck from the ledger — optional reporting, on request. |
| doctor | installation diagnosis (flutter-doctor spirit): python/git, 9 skills, INV-GOLDEN-01 hook, config/ACCEPTANCE/ledger, per-type toolchains — exit 1 only on errors (1.22.0). |
| qa_ledger init | build ledger from uscha.config.json. |
| snapshot | coverage/tests/LOC (--phase pre|post). |
| check-coverage | exit 0 if ≥ threshold (phase-1 gate). |
| ingest-gate | parse linters, normalize severity, diff IDs. |
| converged | latest step of every QA tool clean + every linter clean + every persisted fact gate clean; a red measured snapshot vetoes a narrated green. |
| oscillation | period-2 fingerprint repeat. |
| readiness | 0–100 KPI that reports (always exit 0); hard caps: tests red ≤35, BLOCKER/CRITICAL ≤65, unresolved escalation ≤75. Single-verdict (anti-ceremony, 1.25.0): the default is ONE screen — verdict + a collapsed --- gates: line; --verbose expands the dimensions and by-repo detail. |
| rebuild | spec completeness: COVERS/PARTIAL/DIVERGE — exits 1 unless COVERS. |
| golden-diff | bytes vs .approved — field truth, human-approved. Exit 0 CLEAN · 1 DIVERGE · 2 NOT-RUN (zero fixtures = NOT-RUN, never CLEAN). |
| log-gate | persist a fact-gate verdict (golden-diff · gate-check · pit-check · simplicity · regression); a fail blocks convergence and caps readiness ≤65. |
| flag-blocker | log a CONSTITUTION breach; caps readiness ≤65 and blocks convergence until --resolve (which requires --escape-analysis: which gate/test should have caught it — 1.16.0). |
| resolve-escalation | human clears an escalation so readiness can rise past 75. |
| regression-check | Find Bugs Once (1.16.0): findings closed with no new test line = NARRATED (advises; --strict gates). |
| waste-check | reuse-first (1.26.0): deterministic Type-1/2 clones of the diff vs the repo — the duplication simplicity-check can't see; flags name the file:line to reuse; advisory unless --gate or defaults.waste.gate. |
| summary | retrospective metrics (--json is consumed by /uscha-sysdoc); includes first-time yield (FTY, 1.27.0): % of repos that cleared QA on the 1st cycle — informational, never gates. |
| phase | workflow state DERIVED from the ledger (plan/build/qa/escalated/pr-ready), never self-declared; --require pr-ready gates the PR and vetoes spike/* branches (1.18.0–1.19.0). |
| rubric-ingest | ingests the rubric grader JSON (evidence-or-nothing, weighted score vs threshold); advisory by default, --gate or defaults.rubric.gate makes it blocking (1.23.0). |
| init | ledger command. |
| log-step | records one QA-tool pass. |
| escalate | records a human escalation. |
| production-finding | records or resolves production feedback. |
| spec-doubt | records or resolves a SPEC doubt. |
| spec-change-request | records or resolves a human SPEC/ADR change request. |
| execution-policy | prints model/effort routing by phase. |
| dashboard | emits Mirador data contract. |
| simplicity-check | scores diff minimality and complexity. |
| pit-check | scores test effectiveness from PIT. |
| gate-check | detects weakened gates or secrets. |
| spec-check | validates SPEC/ACCEPTANCE structure and traceability. |
Before editing any tracked .md (CLAUDE.md, plan/delta docs, docs/adr), pull the repo's current version first. Those files carry live progress — never regenerate from scratch.