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

106 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```json
{
"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_ROLES``AgentRole`) 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-paste** → `cpd` (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.