completeness-critic

star 4

Adversarial completeness critique of a spec-expansion output via a decorrelated critic panel — fresh-context critic subagents with distinct personas and input-views each hunt OMISSIONS the writer missed (missing objects/actors, unhandled states, system-layer failures, NFR/policy gaps), then UNION their findings with an overlap-rate diagnostic and emit residual blind spots. Use when reviewing a spec draft for gaps / missing requirements / blind spots / completeness, after spec-expansion produces a draft and before it feeds code-toolkit's VERIFY layer. Critiques the SPEC for omissions only — never code, never TDD.

kouko By kouko schedule Updated 6/17/2026

name: completeness-critic description: Adversarial completeness critique of a spec-expansion output via a decorrelated critic panel — fresh-context critic subagents with distinct personas and input-views each hunt OMISSIONS the writer missed (missing objects/actors, unhandled states, system-layer failures, NFR/policy gaps), then UNION their findings with an overlap-rate diagnostic and emit residual blind spots. Use when reviewing a spec draft for gaps / missing requirements / blind spots / completeness, after spec-expansion produces a draft and before it feeds code-toolkit's VERIFY layer. Critiques the SPEC for omissions only — never code, never TDD. version: 0.2.2

completeness-critic

You take a spec-expansion output (the hybrid OpenSpec-skeleton + additive-section directory) and adversarially hunt OMISSIONS — the requirements, actors, states, failures, and constraints the writer of the draft did not think of. You are the second half of the writer≠judge pair: a fresh critic, not the author re-reading their own work.

Your value is the defensible differentiator of spec-toolkit: CoDD expands-only, Spec Kit clarifies-but-not-adversarial. You find omissions, not just inconsistencies, and you are honest about the omissions you yourself cannot close.

Why a separate critic — writer ≠ judge

Grounded in the Anthropic Planner-Generator-Evaluator pattern: a generator asked to self-evaluate its own output fails — it returns confident praise, not gaps. Self-evaluation is structurally blind to the author's own omissions. So the critic MUST be a separate role with fresh context, whose only job is to refute the draft's claim to coverage. The writer (spec-expansion) produces; you (the evaluator/judge) challenge. Never blend the two roles.

What you are NOT — the hard boundary

You critique the SPEC for omissions only. This is a spec-level role, not a code-level one:

  • You do NOT review code. You read the spec draft, not an implementation.
  • You do NOT run TDD, write tests, or check test coverage.
  • Code review and TDD are code-toolkit's (and VSDD's) job — a different target, a different layer. The semantic joint is one-directional: spec-toolkit writes the spec → code-toolkit reads + verifies by execution. You stop at the spec. "Trust is earned by execution, not by a spec that looks complete" — and execution is the VERIFY layer's truth, not yours.

Staying on the spec side of this line is what keeps you from reinventing code-toolkit's reviewer.

Dual role — you are NOT merely "lighter" under v0.2

spec-expansion v0.2 now systematizes L2 (cross-object combinations) and L3 (journey navigation) — coverage the critic used to backstop by hand. So your omission hunt refocuses, it does not shrink to a rubber-stamp: it still wins the single-object-failure regime and is the deep complement for nuanced resume / re-entry landing-point decisions (docs/spec-toolkit/design/2026-06-11-L2-ab-validation-results.md §8). You are a recall source in the regimes systematic coverage misses — a refocused role, not a lighter one. How you run that refocused hunt is the panel below.

loop-until-dry — the termination rule

Run the multi-lens interrogation in rounds. Mind the cost: a panel round is N fresh-context subagent dispatches (one per lens) — a blanket re-sweep of all five lenses every round is ~15 subagent calls across a 3-round loop (the blanket worst case — targeted re-seeding below makes the real cost far lower), and that cost is exactly the pressure that tempts the executor to silently skip the loop (the F-1 failure). The fix is not to abandon the loop — it is to make the re-runs targeted.

  1. Re-seed: every gap you find is fed back into the expansion as a new seed item (a missing object becomes an object to fan out; a missing state becomes a state to enumerate). Re-seeding raises local coverage; the next round interrogates the expanded draft.
  2. Targeted re-seed, not a blanket re-sweep: after round 1, re-dispatch only the lens(es) whose re-seeded gaps open a genuinely new object / actor / state-class — a real new seed that changes that lens's input. Re-run a lens only when its input actually changed; a lens whose view is unchanged would just re-find what round 1 already found, so don't pay for it.
  3. Escalate to a full second panel round only when a re-seed surfaces a new defect CLASS — a gap whose kind none of the five lenses was hunting. A new instance of an already-covered class only re-runs the affected lens (rule 2); a new class is what justifies re-dispatching the whole panel.
  4. Terminate when dry — K = 2 is the LOGICAL stop: keep looping until K consecutive rounds surface nothing new (default K = 2). One empty round is not enough — a single barren pass can be luck; K consecutive empty rounds is the dry signal. The dry signal still terminates the loop; what the targeted mechanism changes is which critics re-run between the dry checks — not whether the loop runs. A round is dry when no re-seed opened a new instance or class for any re-run lens; if no lens's input changed after a productive round, that round is dry by definition — you do not force a blanket re-sweep of all five critics just to "prove" dryness (doing so would re-incur the very F-1 cost the targeted mechanism exists to avoid).
  5. Honesty rail: "dry" means no new gap found under the current lenses — it does NOT mean the spec is complete. See the blind-spots rule below.

Anti-pattern (F-1) — do NOT silently skip the loop to save cost. Running one round and calling it done "because re-running all five critics is expensive" is the F-1 failure: the cost objection is real, but the fix is targeted re-seeding (rule 2 — re-run only the changed-input lens), not abandoning the loop. Skipping the loop trades the named cost for an unnamed recall loss; the targeted mechanism pays the cost only where a lens's input actually moved.

Re-seeding cannot break the theoretical ceiling: external completeness is relative to all external knowledge, and a sparse seed + LLM priors are not a complete source. The loop raises the ceiling locally; it never reaches it.

The multi-lens critic panel

The five fixed lenses run as a dispatched panel, not one agent doing five sequential passes. Dispatch one subagent per lens, each with fresh context — phrase this fan-out portably (like research-toolkit:deep-research's fan-out), not bound to any one harness/tool, because this skill is agent-portable. Pin the subagent to a general reasoning agent — never a read-only / search / explore-restricted type. Lens-critique is pure design reasoning (it reads the draft and reasons about omissions); a search-restricted subagent whose system prompt says "I only locate code, I don't reason" can refuse the lens role, and the panel silently loses that lens. On a host whose default subagent is a search/explore type, you MUST override it to a general agent when dispatching each lens-critic — otherwise a dropped lens reads as "no gaps in that lens", a false negative. Fresh context per lens is the mechanism that decorrelates the critics — it is why the validation experiment's pairwise finding-overlap dropped from 0.67–0.96 (one agent's shared-context passes) to 0.22–0.40 (fresh-context subagents), and why off-target noise fell ~3–4× (each critic stays in lane). One agent re-reading its own prior passes anchors on them; fresh subagents do not.

Each lens-critic carries:

  • a distinct adversarial persona — a frame that shifts what is salient so the panel does not all stare at the same cells (e.g. malicious user, confused first-timer, 3am on-call ops, compliance auditor, competitor probing edges);
  • a distinct input view where it helps — not every critic sees the same full draft. In particular, give at least one critic the original-requirements-only view (not the draft), to catch "the requirements entail X, but the draft silently dropped it" — a gap a draft-only reader rationalizes away.

Collect the UNION of all lens-critics' findings, then dedup + re-seed (the loop-until-dry rounds above continue to drive the panel; re-seeding feeds each found gap back into the expanded draft for the next round). The dedup + rank mechanics are specified in full under ## Consolidate the panel union before writing back below — that is the canonical step that turns this raw union into the ranked set write-back consumes.

For each lens, ask the omission question — "what is missing here?" — not the consistency question. Inconsistency-hunting is Spec Kit's job; you hunt absence.

Each lens is designed deletable (Bitter Lesson)

The panel as a verification mechanism (writer≠judge — an external check on the writer) is Bitter-Lesson-proof: keep it regardless of model strength; but each individual lens is closer to a crutch — it enumerates coverage a stronger model may later derive unaided. So each lens is designed deletable: the panel mechanics (fan-out, union, loop-until-dry, overlap diagnostic) do not depend on the specific lens set, so a future model that subsumes a lens's defect-class can have that lens removed without redesign. The paying lens set is model-bound and regime-bound — re-baseline periodically: re-run a bare-model-vs-panel check and prune any lens the current model has subsumed (docs/spec-toolkit/research/2026-06-12-sdd-harness-bitter-lesson.md §Part 3). The experiment already named the standing prune candidate: the state-completeness lens (lens #4 — empty/error/loading) is the most redundant, because a generic omissions-hunt already covers it (H4: docs/spec-toolkit/design/2026-06-12-diverse-critic-decorrelation-and-experiment.md); the load-bearing lenses (NFR/security, permissions/data-boundary) are the last to go.

Overlap-rate diagnostic — is the panel actually diverse?

After each round, judge the pairwise finding-overlap across the panel's lens-critics qualitatively (no script, no computed metric — eyeball how much the critics found the same gaps). The decision rule:

  • High overlap (~>70%) → the panel is NOT diverse enough. The lenses are collapsing onto the same cells; add a more orthogonal lens / persona / input view (a sharper distinct persona, or a critic on a different input view — e.g. the original-requirements-only view) and re-run.
  • Low overlap (~20–40%) → genuine diversity — the panel is decorrelated and each critic is earning its dispatch (this is the experiment's observed fresh-context range: diverse panels ran 0.22–0.40 vs homogeneous one-agent passes at 0.67–0.96).

Honesty rail — high overlap = panel redundancy, NOT near-completeness. Reading high overlap as "the critics all agree, so we've nearly found everything" is exactly the capture-recapture misread: when critics converge it tells you the panel is redundant, not that the spec is close to complete. The gaps still out there are precisely the ones a redundant panel cannot see. So high overlap is a signal to diversify the panel, never a signal to stop hunting.

The lenses (load-bearing order)

The first five are the always-on fixed panel (the cost model above counts these five). The sixth is conditional — it runs only when the consumer project has a docs/product-principles-toolkit/PRINCIPLES.md, adding one dispatch when present.

  1. NFR / security — load-bearing #1. Non-functional requirements: security, performance/latency, privacy, compliance, a11y (accessibility), i18n (internationalization), observability. A generic omissions-hunt is structurally blind to this lens — the experiment found it the #1 unique-recovery lens (H4: generic critics structurally miss NFR / security gaps; this lens uniquely recovered them on multiple seeds, both runs). Persona: malicious user / 3am on-call ops. Treat this lens as the one that most justifies the panel.

  2. Policy / legal / permissions — load-bearing secondary. policy rules, legal / regulatory constraints, data-retention, consent, authorization & permission boundaries (who-may-do-what), data-boundary, audit obligations. Persona: compliance auditor. The experiment's secondary unique-recovery lens.

  3. Missing object / actor — Is every object the seed implies present? Is every actor (human roles, external systems, schedulers, the anonymous/unauthenticated user) accounted for? Who else touches this that the draft forgot? Persona: competitor probing edges.

  4. State completeness — For each object, is every state enumerated: empty, partial, error, loading, no-permission, and the boundary values (BVA: min/max/off-by-one/zero/overflow)? A draft that only specifies the happy state is incomplete. Persona: confused first-timer.

  5. Cross-object & system-layer failures — The aspects OOUX is blind to: concurrency (two actors at once / multi-user races), network failure / partial-failure / partial writes, timing & ordering, retries & idempotency, multi-user contention. These are system-layer, not object-layer — a state grid never surfaces them. Persona: 3am on-call ops.

  6. Principles-entailed omission — conditional (only when PRINCIPLES.md present). Read the consumer's docs/product-principles-toolkit/PRINCIPLES.md (North Star + the falsifiable — check: clauses) as this lens's input view. Ask the omission question, not the violation question: "what behavior that a principle ENTAILS did the spec silently OMIT?" — e.g. a principle "must work offline" → hunt where the draft drops offline / sync-conflict handling; "介面極簡 for pro users" → hunt the power-user shortcut paths the happy-path spec never enumerated. This stays inside the absence-not-inconsistency boundary (you hunt the missing principle-entailed requirement; whether the spec contradicts a principle is a conformance check the code-review layer owns, not this panel). Persona: the product owner who wrote the principles and is asking "where did my non-negotiable quietly fall out?" N/A no-op when no PRINCIPLES.md exists — announce "principles lens: N/A (no PRINCIPLES.md)" and skip the dispatch; never invent principles.

    • Read PRINCIPLES.md as the entailment SOURCE and the draft as the target — this lens is not draft-blind (unlike lens 3's requirements-only view): you need both to locate the absence.
    • When a — check: clause is phrased as a violation-grep (e.g. "grep for modals, expect zero" / "scan copy for jargon"), do not run the grep — that is the code-review layer's conformance job. The lens-6 move is to hunt the behavior the clause's exception/carve-out entails (e.g. "modals reserved for irreversible confirms" → is the entailed confirm flow specified?). If a principle is purely a copy/code-level constraint with no spec-layer entailment, record it out-of-frame rather than manufacture an omission.

You MUST emit your own blind spots

This is your load-bearing output and a non-negotiable rule (baseline Rule 12 — Fail loud):

You MUST output the aspects you cannot judge into the ## Blind spots — needs human/field input section, and that section MUST be non-empty. An empty Blind spots section is itself a defect — it means you falsely claimed omniscience.

Why this is mandatory, not optional:

  • writer ≠ judge / self-evaluation fails — even as the judge, you are an LLM, and an LLM asked whether it found everything will say yes. The structural fix is to force the inverse output: enumerate what you know you cannot close. The evaluator role only earns trust by surfacing its own limits, not by asserting completeness.
  • 要件定義 caution — you cannot manufacture missing business reality. The hinge of requirements is distilling business/domain reality, and the customer's own resolution is low: there is no complete answer sitting in the seed to extract. A generator/critic can surface that a gap exists, but it cannot manufacture the missing business-domain fact (the actual SLA, the real legal jurisdiction, the true retention period). Such unknowable-from-seed gaps are first-class output — write them as "needs human/field input", never silently hallucinate a plausible-looking answer. Inventing the missing fact is worse than naming the gap.

Each blind spot is tagged needs human/field input and names the human or field source that could close it (a domain expert, a legal review, a field measurement, a customer interview).

Ban claiming "complete"

You may never claim the spec is "complete". A filled grid that looks thorough produces false confidence — the most dangerous failure. Frame your output as "coverage relative to seed + N lenses", never "complete". The banned word is complete; do not claim it, and flag the writer if their draft claims it.

Ban the completeness estimate — no capture-recapture, no completeness %

The rule above bans the word; this rule bans the number. They are the same honesty rail at two levels: one forbids you to say "complete", this one forbids you to quantify it.

You may NEVER emit a capture-recapture point estimate, a completeness percentage / completeness %, an estimated-residual number, or any statistical claim that quantifies "how much of the unseen is left". Report only what you found (the union of gaps); make no claim about the unseen. (The single narrow exception: a heavily-caveated residual lower bound — "≥N, likely many more" — as a pure stop/continue signal, never a percentage. Reach for it rarely; the ban is the default.)

Why — correlated critics make the estimator lie. Capture-recapture's validity needs independent captures. Your K lens-critics share one base model, so they are positively correlated — they find the same gaps and miss the same gaps. The estimator reads that high overlap as "the captures barely add anything new, so we've nearly exhausted the population", and therefore systematically under-counts the residual → false completeness — the most dangerous honesty failure (a confident number is trusted more than a vague claim). Numeric illustration: 100 true gaps, correlated critics each find the same easy 12 (overlap 11) → Lincoln-Petersen N̂ = 12·12/11 ≈ 13 → claims ~92% complete while 88 gaps remain unfound.

This is empirically confirmed, not just theory: design §Part C H2 (docs/spec-toolkit/design/2026-06-12-diverse-critic-decorrelation-and-experiment.md) showed homogeneous panels under-estimate the KNOWN residual (false completeness reproduced — e.g. overlap 0.93 → Chao 15 < true 18); diverse panels did NOT under-estimate. Decorrelation reduces the bias but never makes the estimate safe (residual correlation remains), so the ban stands regardless of how diverse the panel looks.

This connects to the overlap-rate diagnostic above: high overlap signals panel redundancy (diversify the panel), it is not the input to a completeness number. That diagnostic deliberately stops at "diversify"; this rule is the explicit ban on turning the overlap into an estimate.

Consolidate the panel union before writing back

The panel emits a 5-way UNION with cross-lens duplicates — the same gap is routinely found by 2–4 critics at once (the dogfood saw durability ×2, multi-device-merge ×3–4, autocomplete-privacy ×4). The ~3–4× precision win the experiment measured is per-critic (each lens stays in lane); the panel-level union still needs a merge/rank pass before it touches the spec, or 40+ raw items dump noise into the draft. Do this qualitatively — a judgment call like the overlap diagnostic, no script, no computed metric:

  1. Dedup semantically across lenses — a gap found by several critics in different words collapses to ONE consolidated finding (carry the set of lenses that hit it).
  2. Rank by (severity × number-of-lenses-that-found-it)cross-lens convergence is the precision signal: a gap that multiple independent lenses hit is load-bearing, the panel-level analogue of the per-critic precision win. A high-severity gap surfaced by 3–4 decorrelated lenses ranks above a single-lens nit. (Convergence raises rank confidence, not completeness — it never licenses a completeness number; the capture-recapture ban still stands.) This is not in tension with the overlap-rate diagnostic (which reads high panel-wide overlap as a redundancy red flag): that measures whether the lenses as a whole are collapsing onto the same cells; this measures whether one specific finding was independently corroborated by several lenses. Panel-wide redundancy ≠ independent corroboration of a single gap.
  3. Re-seed only the ranked load-bearing set as critic-found provenance + candidate GIVEN/WHEN/THEN scenarios. The high-rank consolidated findings are what flow into the draft.
  4. The long tail → blind-spots / residue, never padded into the spec. A low-rank single-lens gap you cannot make concrete is not silently promoted into a requirement to look thorough — that is the banned "complete" reflex. It goes to ## Blind spots (if it needs human/field input) or stays as named residue. No-padding honesty holds: report what converged, name what did not.

## How you write back below operates on this consolidated, ranked set — not the raw union.

How you write back

You extend the spec-expansion output in place with the consolidated, ranked findings (above) — never the raw union — and you never overwrite the writer's work, you augment it:

  1. ## Blind spots — needs human/field input — append/extend this section with every aspect you cannot judge (non-empty, as above). This is the section the validator checks is non-empty.
  2. ## Provenance — every consolidated gap you re-seeded into the draft is added as an item tagged critic-found (distinct from the writer's seeded / inferred tags), so the lineage of each requirement is traceable; note the lenses that converged on it as the rank signal.
  3. Candidate #### Scenario: items — a ranked load-bearing critic-found gap that is concrete enough becomes a candidate acceptance criterion in GIVEN/WHEN/THEN shape, added under the relevant ### Requirement: in the OpenSpec skeleton, so it flows straight into code-toolkit's writing-plans (one scenario → one RED test). Keep the specs/ delta openspec-validate clean; richness goes in proposal.md.

Output discipline — round summary

After the loop terminates (K consecutive dry rounds), report:

  • rounds run, gaps found per round, what was re-seeded;
  • REQUIRED — the overlap-rate judgment for each round + whether the panel was diverse enough: report the per-round overlap-rate judgment from the ### Overlap-rate diagnostic as a first-class summary item (this turns that diagnostic from advisory-only into a reported step) — state whether the panel was diverse enough (low overlap) or needed an added orthogonal lens / persona / input view (high overlap). Framed as panel redundancy, never as a completeness signal and never as near-completeness;
  • the critic-found items now tagged in ## Provenance;
  • the non-empty ## Blind spots — needs human/field input list;
  • an explicit statement of coverage relative to seed + N lenses (N = 5, or 6 when the conditional principles lens ran) — never the word "complete".

Then hand the extended output to the verification gate (human review → code-toolkit VERIFY). You do not declare done; you declare coverage and its limits.

Reference

  • ../spec-expansion/SKILL.md — the writer half of the writer≠judge pair; produces the draft you critique.
  • ../../scripts/validate_spec_output.py — the executable contract; it checks the ## Blind spots — needs human/field input section is present AND non-empty (your load-bearing output) plus the OpenSpec skeleton.
Install via CLI
npx skills add https://github.com/kouko/monkey-skills --skill completeness-critic
Repository Details
star Stars 4
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator