Grounded Self-Review Loop — User Guide¶
What it is: an integrated quality loop that runs before Claude hands you a plan or findings. It self-checks the result against a fixed 5-point contract — grounded, no fabrication, simplest that works, consistent, verified-by-execution — and appends a short Self-Review Ledger so you can see the checks happened. It exists so you stop having to repeat "make it fact-based, don't fabricate, don't overcomplicate, ground it in the data, and actually test it" after every plan.
Where it lives:
- Always-on (Tier 0): CLAUDE.md §8 — fires automatically, no command.
- On-demand deep pass (Tier 1): /gp → .claude/commands/gp.md → .claude/skills/grounded-plan/SKILL.md.
Why this exists¶
The criteria were already in the project — scattered across the memory directives
accuracy-consistency-no-fabrication, always-verify-dont-estimate, CLAUDE.md §7, and
the backend grounding registry (backend/services/grounding/registry.py). What was missing
was a loop that fires automatically and a visible receipt that it ran. This guide
documents that loop.
The Grounded Output Contract (the 5 gates)¶
Every plan/finding is checked against:
| Gate | Meaning |
|---|---|
| 1. Grounded | Every number, file path, line, behavior claim, and spec traces to a file read, a tool/command output, or your message — including absence claims ("nothing does X"), which need a search that would have found it, or they count as fabrication. |
| 2. No fabrication | Anything that can't be verified is labeled unknown / not verified — never plausibly filled in. |
| 3. Simplest that works | Fewest files/abstractions that meet the intent; reuse existing services over new code; scope creep is flagged. |
| 4. Consistent | One canonical term per concept throughout. |
| 5. Verified by execution | Any claim that code builds/passes/behaves a certain way is backed by running the relevant check — never asserted. (See the verification gate below.) |
The loop is draft → critique against the 5 gates → revise → run the targeted verification →
repeat, capped at 2–3 passes (the cap is itself an anti-overcomplication guard).
How to read the Self-Review Ledger¶
At the bottom of a plan/findings you'll see a block like this (example — values illustrative):
Self-Review ✓ (2 passes)
- Grounded: _pa_scoring.py (cost dimension), component_power.assess_power — read, not recalled
- Verified: tsc + vitest paSelection.test.ts → pass (3 files)
- Unverified: QPA9126 current catalog presence — flagged, not assumed
- Simpler option considered: reuse the existing application_fit weight → chose reuse (no new code)
- Additivity: verified — paSelection.test.ts unchanged & green (claim-triggered; omitted when no additivity claim is made)
Read it in ~5 seconds:
- Grounded — the sources behind the key claims. Spot-check one if you want.
- Verified — the actual check that was run and its result (e.g. tsc + vitest → pass), or
an honest not run (reason) / n/a — plan only. This is proof the claim was executed,
not assumed.
- Unverified — the honest gaps. This line is a feature: it surfaces what couldn't be
confirmed instead of hiding it behind a confident guess. A clean grounded line plus a frank
"unverified" line is exactly the trust signal that lets you skip the old "are you sure?"
follow-up.
- Simpler option considered — proof the overcomplication gate ran: what simpler path was
weighed, and why it was kept or dropped.
The verification gate (gate 5)¶
The loop doesn't just claim something works — when a code change is involved, it runs the relevant check and reports the result. It's scoped to stay fast and honest:
- Targeted, not blind. It runs the specific check for what changed —
cd frontend && npx tsc --noEmit+ the affectedvitestfile, orbackend/venv/Scripts/python.exe -m pytest <path>, or the evalguard_replay(offline first) — not the whole suite every time. - Reads the nightly report first. Before re-running a full suite it checks
test-reports/latest.md(the 4:30 AM self-test), so it doesn't redo work that's already green. - Loops on failure, capped. Fail → fix → re-run, up to ~3 attempts, then it surfaces the remaining failure honestly rather than hiding red or claiming a green it didn't see.
- Concurrency-aware. With another session editing the tree, the full suite reflects their in-flight work too — so it prefers the targeted test for your files.
- Plan-only is fine. If nothing's implemented yet, the gate just means the plan's
Verification section lists concrete, runnable commands; the ledger shows
Verified: n/a — plan only. - "Additive" must be proven, not asserted. If the output claims a change is additive or
doesn't alter existing behavior, that's a behavioral claim too — the loop proves it (existing
tests still pass unchanged, no call-site/flag/
condense.py-keep-list trap fired) or relabels it a behavior change. This is claim-triggered: a deliberate bug fix or refactor should change behavior — there the proof flips to "the fix's test goes red→green with no collateral regression," and additivity is never demanded.
The three ways to use it¶
1. Just ask — Tier 0 is automatic¶
Your default. Type your request normally; the ledger comes back attached.
You: plan a fix for the PA selector picking oversized GaN bricks for WiFi
Claude: [plan] + a Self-Review Ledger.
You did nothing extra — the quality bar is already applied, and you have the receipt.
2. /gp <request> — deep pass from the start¶
For a high-stakes plan where you want independent eyes before you even see a draft.
You: /gp redesign the power-tree gate-bias sequencing
Claude: [runs independent verifier agents — claims-vs-files checker, fabrication hunter, simplicity critic, test-runner — then synthesizes] → plan + a fuller ledger showing what each verifier caught and what the tests reported.
3. /gp alone — deep-check a plan you already have¶
This replaces the old habit of typing "are you sure this is all grounded, not overcomplicated, and actually tested?" — now it's two characters.
Claude: [normal Tier-0 plan + ledger]
You: /gp
Claude: [re-runs the deep adversarial pass + targeted tests on that same plan] → revised plan + what the independent check changed.
Quick reference¶
| Situation | What you do |
|---|---|
| Normal work | nothing — just ask (Tier 0 auto-fires) |
| "This one's important, get independent eyes" | /gp <request> |
| "I like this plan but double-check it hard" | /gp on its own |
Before / after (the friction this removes)¶
Before:
You: plan a fix for X Claude: [plan] You: ok but make sure it's fact-based, you didn't fabricate those paths, you're not overcomplicating it, and you actually ran the tests
You sent that second message every time.
After (Tier 0):
You: plan a fix for X Claude: [plan] +
Self-Review ✓ledger with sources, test results, and honest gaps
You read the ledger and move on. The reminder is baked in.
When to reach for /gp¶
Tier 0 (self-review) is me checking my own work — strong at catching unsourced claims,
needless complexity, and untested assertions, but a self-check has limits. Use /gp when:
- the change is high-stakes (touches power/thermal/compliance physics, or a shared engine),
- you want an independent agent to re-derive every claim from the files and run the tests, or
- the plan is large enough that one set of eyes might miss a blind spot.
For everyday work, Tier 0 is enough — reaching for /gp on a two-line plan is its own kind
of overcomplication.
Scope¶
Applies to plans, findings, audits, and substantive recommendations. It deliberately
skips trivial factual answers and tiny edits — adding a ledger to "what's the port
number?" would be ceremony, not value. The verification gate only runs when a code change is
actually involved; pure plans show Verified: n/a — plan only.
FAQ¶
Does this replace the backend guardrails? No. The backend grounding registry +
output_guard enforce grounding inside the product's agent loop. This loop is about how
Claude Code reviews its own plans/findings for you. They share the same criteria
(GROUNDED_CATEGORIES) but operate in different places.
Does it run the whole test suite every time? No — that would be slow and, with a sibling
session active, would test their in-flight work too. It runs the targeted check for what
changed and reads test-reports/latest.md before any full-suite run.
What if Tier 0 starts drifting? It's a CLAUDE.md directive, so it relies on the model
honoring it; the visible ledger is the forcing function. If it ever drifts in practice, the
fallback is a Stop hook — deliberately not built yet, to avoid premature complexity.
Can I rename /gp? Yes — it's just a short handle (grounded-plan). Edit
.claude/commands/gp.md (and the skill reference) to whatever you prefer (/verify,
/ground, …).