/over-engineering-review — On-Demand Discriminator Pass
Runs the 3-clause discriminator over a target artifact and reports findings
classified safe-remove, needs-decision, keep, or harmful-theater.
Composes /simplify and /code-review — does not reimplement them.
Rules
- Discriminator is the test; context tunes severity, not detection. The discriminator fires context-free. Severity and stop/ask posture adjust to context; whether the flag fires does not.
- Compose, don't reimplement. Run
/simplifyand/code-reviewas sub-passes. Add only the requirement-ledger freeze and the discriminator. - Freeze the ledger before review. Extract stated requirements, observed failures, and named safety properties from conversation context, PRD, and any referenced docs before evaluating any element. Post-hoc requirement invention does not enter the ledger.
- Cost-gate the counterfactual. A full counterfactual on a trivial or reversible target is itself axis-8 over-engineering. Escalate only for qualifying targets (see Step 5).
- Findings are flags, never scores. Emit classified findings with cited clause-absence. No numeric ratings.
- Correctness/safety floor is clause 3 of the discriminator. Floor items
pass clause 3 — they are classified
keep, not flagged.
Step 1 — Resolve Target
Parse the argument after /over-engineering-review:
- No argument /
diff:git diff HEAD— the current working-tree diff. - File path: read the named file.
planor natural language referencing a plan/design: read the referenced plan or design doc from conversation context.
If the target is empty (no diff, no file, nothing in context), stop and ask the user what to review.
Step 2 — Freeze the Requirement Ledger
Before evaluating any element, extract and freeze the requirement ledger.
Sources (priority order):
- Explicit user statements in this conversation
- The target artifact itself — requirements embedded in the diff, file, or plan under review
- Any source-of-truth docs named as authoritative by the target (e.g., an issue doc or spec the target references)
prd.md(if present in the project root)docs/ARCHITECTURE_AND_DESIGN.md(if present)
Tag each requirement by provenance: [user-stated] or [agent-inferred].
Agent-inferred requirements that justify nothing are not added to the ledger. If an agent-inferred entry is the sole justification for an element, that element is a flag candidate.
Emit the frozen ledger before proceeding:
REQUIREMENT LEDGER (frozen)
[user-stated] <requirement>
[agent-inferred] <inferred property> ← escalated if unjustified
Step 3 — Run /simplify and /code-review
Invoke as sub-passes in sequence:
/simplify— simplification and redundancy findings/code-review— correctness, bug, and reuse findings
Retain their outputs to feed Step 4's per-element discriminator pass. Do not re-emit them verbatim in the final report.
If /simplify or /code-review is unavailable, proceed with the
discriminator pass on the target directly and note the absence in the summary:
NOTE: /simplify unavailable — discriminator applied to raw target only.
Step 4 — Run the Discriminator Per Element
For each element in the target artifact (including any surfaced by Step 3):
Does it trace to (1) a stated requirement, (2) an observed failure, or (3) a correctness/security defect on a reachable path at a trust boundary? If none → flag.
Apply modifiers after the flag, not before:
- Context tunes severity, not detection. Blast radius × lifespan (plus explicit security/data-sensitivity signal) tune enforcement posture and severity label. They do not suppress a flag.
- Reversibility licenses a seam, not a feature. A one-way door (persisted data, published contract, wire format, public name) licenses a cheap reversal seam — never the speculative feature itself. Burden of proof: name all four — (a) the irreversible surface, (b) the plausible future change, (c) the concrete later cost, (d) the smallest present action — or YAGNI wins. An unproven one-way claim is treated as two-way and deferred. Blast-radius-escape count: 0 triggers → defer (YAGNI); 1 → seam only; 2+ → surface to user.
- Cause-agnostic. Act on the output signature — an element that fails the discriminator. Do not let inferred intent or the reason it was produced affect whether the flag fires.
- Clause 3 IS the floor. Delete-the-element test: does removing it produce
a wrong result, lost/corrupted data, a security hole, or a
silently-swallowed failure on a reachable path at a trust boundary?
- Yes →
keep(floor item) - Loses only convenience / future flexibility → flag
- Yes →
Boundary cases — one rule: trust boundary + reachability + named failure mode:
| Element | Floor (keep) |
Excess (flag) |
|---|---|---|
| Retries | transient/idempotent op, bounded, surfaced failure | unbounded / non-idempotent / masks failure |
| Logging | required output/audit; stderr insufficient to operate | decorative / duplicates available signal |
| Input validation | external/untrusted boundary, reachable path | internal trusted caller |
| Error handling | preserves invariant/cleanup; sharpens reachable failure | swallows/masks; wraps infallible code |
Step 5 — Cost-Gate and Optionally Run Counterfactual
Escalate to a partial cold counterfactual (re-derive one layer/section from the frozen ledger by a different model, original removed from context) only when at least one qualifying condition is met:
- Target is design-stage, OR
- Diff is large (>200 lines), OR
- Target contains "production-ready" / "enterprise-grade" / similar phrase clusters, OR
- Multiple axes (≥3) are triggered, OR
- Safety-inversion risk is present
And the target clears the cost gate. Skip if ALL of: diff is <100 lines, ≤2 axes triggered, and 0 blast-radius-escape triggers (reversible, no outside dependents must change). When qualifying conditions are met but the cost gate is ambiguous, surface to user:
COUNTERFACTUAL: cost gate ambiguous — <size/axes/triggers>. Run? [y/n]
Counterfactual scope: partial (one layer/section). Full rewrite is reserved for axis-2 structural over-engineering where the shape is the excess.
Announce the decision before running:
COUNTERFACTUAL: escalating — <reason>. Re-deriving <layer/section> via
<different model> with original removed from context.
COUNTERFACTUAL: skipped — <reason>. Cost-gate (trivial/reversible/small).
After the counterfactual completes, compare the re-derived section to the original:
- Identify elements present in the original but absent or simpler in the re-derivation — these are additional flag candidates.
- For each such element, run the discriminator (Step 4) and apply modifiers.
- Feed results into Step 6 classification alongside the primary pass findings.
- Note the counterfactual source in each finding it contributes:
[counterfactual]suffix on the tag.
Step 6 — Classify and Emit Findings
Classify each finding:
| Tag | When to use | Selection criteria |
|---|---|---|
safe-remove |
Fails discriminator; no clause passes; reversibility is proven two-way (0 blast-radius-escape triggers). | All three clauses absent + 0 outside dependents must change. |
needs-decision |
Fails discriminator; contested. | Reversibility claim unproven (≥1 blast-radius-escape trigger or burden-of-proof fields incomplete), OR blast-radius is high, OR ledger signal conflicts. Surface to user — do not auto-resolve. |
keep |
Passes at least one clause. | Cite which clause: clause 1 (stated requirement), clause 2 (observed failure), or clause 3 (correctness/security defect on a reachable path at a trust boundary). |
harmful-theater |
Fails discriminator AND its presence introduces a specific, named harm on a reachable path. | Must cite the harm: swallows a failure, creates a false safety signal, masks a real error. Remove before proceeding. |
Emit format — one line per finding, including severity and clause-absence citation:
path:line [tag] HIGH|MEDIUM|LOW axis-N clauses 1+2+3 absent: <unjustified element>. <simpler alternative or "remove".>
Severity guide: HIGH = harmful-theater or safe-remove with broad blast radius; MEDIUM = safe-remove or needs-decision with contained blast radius; LOW = safe-remove with zero external dependents.
For keep items, cite the passing clause:
path:line [keep] clause-N: <element>. Justification: <stated requirement / observed failure / named failure mode on reachable path>.
For counterfactual-sourced findings, append [counterfactual]:
path:line [safe-remove][counterfactual] MEDIUM axis-2 clauses 1+2+3 absent: <element>. <simpler alternative>.
End with a summary block:
OVER-ENGINEERING REVIEW SUMMARY
harmful-theater : N (remove before proceeding)
safe-remove : N
needs-decision : N (surfaced below for user)
keep : N
NEEDS-DECISION ITEMS:
[each item with context and recommendation]
The 8-Axis Reference
| # | Axis | Principle |
|---|---|---|
| 1 | Speculative scope | YAGNI |
| 2 | Premature abstraction | KISS |
| 3 | Premature optimization | KISS |
| 4 | Defensive bloat | clause-3 predicate, flag side |
| 5 | Robustness / ops theater | YAGNI |
| 6 | Test / doc ceremony | DRY / YAGNI |
| 7 | Data / schema / API over-modeling | YAGNI |
| 8 | Process over-engineering (meta) | do not over-apply this gate itself |
Anti-Bias Directive
Failure mode: confirming quality rather than finding unjustified complexity.
Counter it:
- Default posture: flag aggressively. Ask "does a concrete justification exist for this element?" — not "is this good practice?"
- Good practice without a concrete justification is still a flag.
- Do not emit
keepfindings for items not positively verified against clause 1, 2, or 3. - Apply axis 8 to yourself: one discriminator pass per element; not a parallel subsystem per concern.