Files
simplify-code/references/CONSOLIDATION.md
T
Giancarmine SalucciandClaude Opus 4.8 81b33fff26 refactor: report-only skill — actionable findings, no apply/modes
The skill no longer modifies code. It emits exactly two artifacts under simplify/:
findings.json (machine-actionable ledger) + a ranked report. Every finding now REQUIRES
title/action/verify (locked in ledger.schema.json) so each is independently executable by
the calling agent. Removed: apply/report modes, Track A autofix execution, baseline gate,
verify-each-change loop, the include-tests switch (tests excluded by default). Reframed
SKILL.md, README, PATTERNS (deterministic/judgment), DETECTION, OPTIMIZATION (judge-only
model tiering), PORTABILITY, SVELTE, CONSOLIDATION accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 02:53:19 +02:00

5.8 KiB
Raw Blame History

Pass B — consolidation & anti-pattern analysis

Pass B finds cross-file, AI-typical problems that per-node rules (Pass A) can't: duplication, failure to reuse, reinvented utilities. It is report-only (these changes risk coupling — never autofix) and every candidate is judged by a model with AHA guardrails before it's reported, because mechanical similarity has false positives.

Pipeline (each detector): extract (0 tokens) → cluster (tool or cheap model) → JUDGE (mandatory) → consolidation report. Tools are the bundled, non-intrusive binaries (bin/manifest.json); nothing is written into the target project.


The judge contract (shared by all Pass B detectors)

For each candidate cluster, give the model the real code spans and ask for exactly:

{
  "same_concept": true,
  "verdict": "consolidate | partial | keep-separate",
  "confidence": 0.0,
  "why": "cite concrete evidence from the code",
  "risk": "what coupling/regression consolidating could cause",
  "recommendation": "the concrete change, or why to leave it"
}

Only report findings with verdict != keep-separate AND confidence >= 0.6. For keep-separate, record the reason in the report so re-runs don't re-flag it.

When you write the finding into findings.json, the judge's recommendation becomes the required action (a concrete, executable instruction) and you must add a verify (the config build/test/typecheck command) and a one-line title — these three fields are mandatory for every finding (see assets/ledger.schema.json) so the acting agent can execute it without re-running this skill.

AHA guardrails (put these in the judge prompt — they prevent harmful merges)

  • Rule of three: 2 occurrences usually isn't worth abstracting; prefer ≥3.
  • "The wrong abstraction is worse than duplication" (Sandi Metz). If unifying would need extra params/conditionals to satisfy diverging callers → keep-separate.
  • Respect boundaries: do NOT merge across layers / bounded contexts — e.g. a DB enum vs an API/wire enum vs a UI label set; one adapter vs another adapter; per-service copies in a microservice split. These look identical but are decoupled on purpose.
  • Preserve intentional subsets: a smaller set that's a named category (e.g. COORDINATOR_ROLESAgentRole) is not duplication — recommend deriving it from the canonical source, not merging it away.
  • Drift is a signal, not always a bug: when near-identical definitions have diverged (one has an extra member), flag the divergence — it may be a latent bug (a value produced but unrepresentable elsewhere).

Model tiering (see OPTIMIZATION.md): cluster + judge on a cheap model; escalate to a stronger model only on low confidence. Fan out one judge per cluster where the runtime has sub-agents; else judge sequentially.


F1 — Consolidation core

Duplicate enums / labels / unions

  1. Extract with ast-grep: enum_declaration, type_alias_declaration (keep string-literal unions), as const arrays/objects. Record each definition's member set + location.
  2. Cluster (cheap model, small N): group by member-set overlap — exact, subset/superset, high Jaccard.
  3. Judge each cluster. Typical outcomes: identical union+const in the same package → consolidate (idiomatic TS: one as const array as source of truth, derive the union via typeof arr[number]); same-named types in different packages that drifted → consolidate + reconcile; intentional subset → derive, don't merge.

Near-duplicate functions

Two complementary signals:

  • Exact / copy-pastecpd (bundled): cpd <paths> --min-tokens 50 --reporters json --output <tmp> --silent. Token-based (Type-1/2). 0 model tokens.
  • Renamed / structural ("almost the same") → ast-grep extracts function nodes; normalize each to a skeleton (strip comments; replace identifiers→V, strings/numbers→L; drop whitespace); group by identical skeleton (ignore trivial: skeleton < ~120 chars). This catches Type-2/3 that cpd misses (proven on software-house: 7 clusters). Then judge each cluster: unify (extract shared helper / parametrize the literal that differs) | partial (share a stateless core, keep thin wrappers) | keep-separate (the "not quite" is essential — different data source, retry strategy, adapter, etc.).

Untyped repeated object shapes (→ DTO)

  1. ast-grep extracts object literals; record each one's top-level key set.
  2. Keep only shapes with ≥3 keys repeated ≥3× that do NOT match an existing interface/type member set. (An inline object matching an existing interface is normal usage — TS structurally type-checks it — not a smell. Do not report those.)
  3. Judge: is this a real DTO worth naming, or incidental? Recommend an interface + reuse.

F2 — Reinventing-the-wheel

  1. ast-grep builds a lightweight signature index across the repo: {name, params, returns, file, line} for every function/method (no extra tool; universal-ctags is GPL → excluded).
  2. For a target (a changed span, or scanning the repo): find existing functions with high name/parameter/return similarity to the candidate.
  3. Judge: does the new code re-implement an existing utility? If yes, recommend importing the existing one. Guardrail: confirm the existing function's contract actually fits (don't force reuse across incompatible interfaces/perf constraints).

Output

Write simplify/consolidation-report.md: clusters grouped by detector, each with the verdict, why, risk, and recommendation; a separate "kept separate (and why)" section; and a "latent drift/bugs" callout. Add a ledger finding per reported cluster with kind: "consolidation" (see assets/ledger.schema.json). Pass B never edits files, regardless of the run mode.