skills
decompose
Vindt de klassen die te veel doen, en onderbouwt elke vondst.
Je weet dat er iets te groot is geworden. Je weet niet welk stuk.
Installeren
/plugin marketplace add https://aranea-development.nl/plugins/marketplace.json
/plugin install decompose@araneaEen structurele scan die met parallelle agents zoekt naar god classes, opgeblazen modules en logica die niet klopt. Elke vondst wordt daarna in de bron nagetrokken, zodat wat overblijft ook echt bestaat, en pas dan komt er een plan om die klassen uit elkaar te halen.
Dat natrekken is waar het om draait. Een scan die dertig verdachten oplevert waarvan de helft geen stand houdt, kost je meer tijd dan hij bespaart.
Bron
---
name: decompose
description: >
Structural health scan that finds god classes, bloated modules, and failing logic across a codebase
using parallel agents, then fact-checks every finding and generates an approvable decomposition plan.
Triggers on "scan for god classes", "find god classes", "decompose", "structural audit",
"refactor audit", "bloated classes", "health scan", "failing logic", "codebase health".
---
# Decompose — Structural Health Scan
## Overview
A multi-agent codebase scan that identifies structural rot — god classes, monolithic modules, fragile logic, and anti-patterns — then **fact-checks every finding against the actual source**, eliminates false positives, and produces a ranked decomposition plan the user approves item-by-item before any code is touched.
**Core Principle: No finding without evidence. No plan item without a concrete decomposition target. No code changes without user approval.**
Every finding must include:
1. The exact file, class, or function that exhibits the problem
2. Quantitative evidence (line count, responsibility count, coupling count, test failure output)
3. Verification that the finding is real and not an artifact of generated code or intentional design
4. A concrete decomposition or fix proposal with named target components
## Process
```dot
digraph decompose {
rankdir=TB;
"1. Reconnaissance" -> "2. Parallel Agent Scans";
"2. Parallel Agent Scans" -> "3. Raw Findings Pool";
"3. Raw Findings Pool" -> "4. Fact-Check Phase";
"4. Fact-Check Phase" -> "5. Verified?";
"5. Verified?" -> "6. Confirmed Findings" [label="yes"];
"5. Verified?" -> "7. Discard (false positive)" [label="no"];
"6. Confirmed Findings" -> "8. Rank & Classify";
"8. Rank & Classify" -> "9. Generate DECOMPOSE-PLAN.md"];
"9. Generate DECOMPOSE-PLAN.md" -> "10. Interactive Approval";
"10. Interactive Approval" -> "11. User: approve/skip/defer";
"11. User: approve/skip/defer" -> "10. Interactive Approval" [label="next item"];
"11. User: approve/skip/defer" -> "12. Dispatch Fix Agents" [label="all triaged"];
"12. Dispatch Fix Agents" -> "13. Quality Gates";
"13. Quality Gates" -> "14. All pass?" [label="lint + types + tests"];
"14. All pass?" -> "15. Update DECOMPOSE-PLAN.md" [label="yes"];
"14. All pass?" -> "13. Quality Gates" [label="no — fix regressions"];
}
```
## Phase 1: Reconnaissance
Before dispatching scan agents, establish ground truth:
- **Stack & language**: infer from file extensions, `package.json`, `tsconfig.json`, build configs
- **Module boundaries**: directory structure, barrel exports, monorepo package layout
- **Existing design docs**: `CLAUDE.md`, `README`, `/docs` — look for intentional architecture decisions. An intentional god class documented as a façade is not a finding.
- **Test surface**: what test files exist, what runs, what fails. Run the test suite and capture failures before scanning.
- **Most-changed files**: `git log --format= --name-only | sort | uniq -c | sort -rn | head -30` — hot files are high-leverage targets.
- **Size outliers**: find files over 300 lines with `find . -name "*.ts" -o -name "*.js" | xargs wc -l | sort -rn | head -30` (adapt for language). Long files are candidates, not confirmed findings.
**Read CLAUDE.md and any architecture docs FIRST.** Do not flag intentional façades, intentional aggregation points, or documented design decisions as god classes.
## Phase 2: Parallel Agent Scans
Dispatch parallel subagents, one per category. Each returns raw findings with evidence. Never wait for one to finish before starting another — dispatch all simultaneously.
### Agent 1: God Class Scanner
**Goal:** Find classes and modules that violate the Single Responsibility Principle by doing too many distinct things.
**Heuristics (flag if ≥2 apply):**
- Class/module > 300 lines of substantive code (excluding comments and blanks)
- > 10 public methods with no clear unifying responsibility
- Methods cover ≥3 distinct domains (e.g., persistence + business logic + HTTP response formatting)
- > 7 constructor/top-level dependencies injected
- The class name is vague: `Manager`, `Service`, `Helper`, `Utils`, `Handler` with no qualifier
- Other classes import this one for fundamentally different reasons (check importers)
**How to search:**
```
# Find large files
find . -name "*.ts" -o -name "*.js" -o -name "*.py" | xargs wc -l | sort -rn | head -40
# Count methods per class (TypeScript/JS)
grep -n "^\s*\(public\|private\|protected\|async\)\s" <file> | wc -l
# Find classes with "Manager", "Service", "Utils", "Helper" in name
grep -rn "class.*\(Manager\|Service\|Helper\|Utils\|Handler\)" src/
# Count importers — a class imported by many different domains is a candidate
grep -rl "from.*<target-module>" src/ | wc -l
```
**For each candidate:** list the top-level methods grouped by responsibility. If methods naturally split into ≥2 named groups with no shared state, it's a confirmed god class.
**Output per finding:**
- File and class name
- Line count
- List of responsibilities with example method names per group
- Proposed decomposition: named target classes/modules with what moves where
---
### Agent 2: Bloated Function / Spaghetti Logic Scanner
**Goal:** Find functions and methods that are too long, too deeply nested, or do too many things to be reliably maintained or tested.
**Heuristics (flag if ≥1 applies):**
- Function > 80 lines
- Cyclomatic complexity proxy: > 5 levels of nesting (count indent levels)
- Function does I/O AND computation AND side effects with no separation
- Multiple `return` paths with different shapes (returns `string` in one branch, `object` in another)
- Boolean flag parameters that change core behavior (`doSomething(x, true, false, true)`)
- Copy-paste duplication: near-identical logic blocks within the same file
**How to search:**
```
# Find long functions — look for function declarations and count lines until next function
# Read the files, don't just grep line counts
# Find deeply nested code (4+ levels)
grep -n " " <file> — excessive indentation is a smell
# Find boolean-flag parameters
grep -rn "function.*bool\|: boolean)" src/ — then check callers
# Find TODO/FIXME/HACK markers — devs signal pain points themselves
grep -rn "TODO\|FIXME\|HACK\|XXX\|KLUDGE" src/
```
**For each candidate:** copy the function signature + first/last 10 lines as evidence. Propose a specific decomposition or simplification.
---
### Agent 3: Failing Logic Scanner
**Goal:** Find code that is broken, will break under realistic input, or fails silently.
**What to look for:**
| Pattern | Why It Fails |
|---------|--------------|
| Unhandled promise rejections | `.then()` without `.catch()`, `async` without try/catch at boundary |
| Swallowed errors | `catch (e) {}` or `catch (e) { return null }` — hides failures |
| Type coercion bugs | `== null` vs `=== null`, `+undefined`, falsy-check on 0 or "" |
| Off-by-one in loops | `<` vs `<=`, array length -1 missing or extra |
| Missing null/undefined guards | Accessing `.property` on a value that can be `undefined` |
| Race conditions | Parallel state mutations without coordination |
| Infinite loop risk | `while (condition)` where condition is never mutated |
| Regex with ReDoS potential | Nested quantifiers like `(a+)+` |
| Dead code branches | `if (false)`, `if (x === undefined && x !== undefined)` |
| Mutations of function arguments | Modifying object parameters (unexpected side effects for callers) |
**Also:** Capture all **current test failures** from the test run in Phase 1. Each failing test is a confirmed finding with built-in evidence.
**How to search:**
```
# Swallowed errors
grep -rn "catch.*{}" src/
grep -rn "catch.*return null\|catch.*return undefined" src/
# Unguarded access patterns
grep -rn "\.[a-zA-Z]\+\.[a-zA-Z]\+" src/ — then read context
# Bare .then() without .catch()
grep -rn "\.then(" src/ | grep -v "\.catch\|await"
# TODO/FIXME with "broken", "wrong", "bug", "crash"
grep -rni "TODO.*broken\|FIXME.*crash\|HACK.*wrong" src/
```
---
### Agent 4: Coupling & Dependency Smell Scanner
**Goal:** Find architectural coupling that will make decomposition painful and that flags design problems.
**What to look for:**
| Smell | Description |
|-------|-------------|
| **Circular imports** | A imports B which imports A — prevents tree-shaking, causes init bugs |
| **Layer violations** | UI code importing DB models directly; infra code importing domain logic |
| **Feature envy** | Function mostly calls methods on another object (should live there instead) |
| **Shotgun surgery** | Changing one concept requires touching 7+ files |
| **Inappropriate intimacy** | Class A accesses private internals of Class B via casting or `any` |
| **God module imports** | One file imported by > 20% of the codebase — single point of breakage |
| **Ambient globals** | `window.X =`, `global.X =`, module-level mutable state not injected |
**How to search:**
```
# Find files imported by many others
for f in $(find src -name "*.ts"); do
count=$(grep -rl "from.*$(basename $f .ts)" src/ | wc -l)
echo "$count $f"
done | sort -rn | head -20
# Detect circular imports (if madge is available)
npx madge --circular src/ 2>/dev/null
# Layer violations: UI importing DB
grep -rn "from.*prisma\|from.*repository\|from.*db" src/components/ 2>/dev/null
# Ambient globals
grep -rn "global\.\|window\." src/ | grep "="
```
---
## Phase 3: Fact-Check Phase
**This is the most important phase. Never skip it.**
For every raw finding from all four agents:
### Verification Checklist
1. **Does the code actually exist as described?** Read the specific file and lines. Confirm the pattern is real.
2. **Is it intentional?** Check CLAUDE.md, inline comments, architecture docs. An intentional aggregation point is not a bug.
3. **Is it actually reachable?** Dead code isn't a god class — it's a deletion candidate.
4. **Does the "god class" actually have mixed responsibilities?** Re-read the methods. Sometimes a large class has a single deep responsibility — a codec, a parser, a state machine.
5. **Is the failing logic actually triggered?** Trace the call path. An unreachable bad branch is INFO, not HIGH.
6. **Is the coupling actually harmful?** A shared `utils/strings.ts` imported everywhere is fine. A `userAuthDatabaseApiStateManager.ts` imported everywhere is not.
7. **Is the test failure pre-existing or new?** Check `git log` on the failing test file.
### Severity Classification
| Level | Criteria |
|-------|----------|
| **CRITICAL** | Active test failures; broken code on hot paths; unhandled exceptions in prod flows |
| **HIGH** | God class with ≥3 distinct responsibilities and > 400 lines; circular imports causing init failures; swallowed errors in critical paths |
| **MEDIUM** | God class with 2 responsibilities; long functions with extractable chunks; non-critical coupling smells |
| **LOW** | Style-level structural issues; naming that implies god-class but behavior is OK; minor duplications |
| **INFO** | Candidates worth watching; technical debt with no current impact |
### Discard When
- The file is generated code (check for `@generated`, `DO NOT EDIT`, build output paths)
- The "god class" is a documented façade or intentional aggregation point
- The "failing logic" is guarded by a condition that prevents it from ever running
- The coupling is between two things that should be coupled (same domain, same layer)
- The finding duplicates another finding at a higher severity (keep the higher one, drop the lower)
---
## Phase 4: Report Generation
Write the report to `DECOMPOSE-PLAN.md` in the project root.
```markdown
# Decompose Plan
**Date:** YYYY-MM-DD
**Scope:** [what was scanned]
**Test suite status at scan time:** [pass/fail — N failures]
## Executive Summary
- X findings total: N critical, N high, N medium, N low, N info
- Largest structural risks: [brief]
- Test failures discovered: [count]
## Findings
### [SEVERITY] Finding Title
**Status:** OPEN | [APPROVED] | [SKIPPED] | [DEFERRED] | [DONE] YYYY-MM-DD
**Location:** `src/path/to/File.ts` (class `TargetClass`)
**Category:** God Class | Bloated Function | Failing Logic | Coupling Smell
**Evidence:**
- Line count: N lines
- Responsibilities identified: [list]
- [Code snippet showing the problem — 5–15 lines max]
**Decomposition Proposal:**
- Extract `[NewClassName]` to `src/path/NewFile.ts` — takes [method list]
- Extract `[AnotherClass]` to `src/path/AnotherFile.ts` — takes [method list]
- [What stays in the original class after decomposition]
**Why this matters:**
[One sentence on the real risk — test brittleness, onboarding confusion, change-amplification, active failures]
---
## Dismissed Findings (False Positives)
| Candidate | Why Dismissed | Evidence |
|-----------|--------------|---------|
| `src/core/AppContext.ts` | Intentional facade documented in CLAUDE.md | CLAUDE.md:32 |
| ... | ... | ... |
## Summary Table
| # | Severity | Location | Category | Status |
|---|----------|----------|----------|--------|
| 1 | CRITICAL | `src/...` | Failing Logic | OPEN |
| 2 | HIGH | `src/...` | God Class | OPEN |
| ... | ... | ... | ... | ... |
```
---
## Phase 5: Interactive Approval
**Do NOT modify any code before this phase.**
Present findings to the user one by one for approval, starting from highest severity.
### Flow
1. Show the summary table first — total count by severity — so the user has full context
2. Walk through findings from CRITICAL → HIGH → MEDIUM → LOW → INFO
3. For each finding, show:
- Severity, location, category
- The evidence snippet
- The proposed decomposition
4. User responds:
- **approve** — queued for implementation
- **skip** — marked `[SKIPPED]` (user accepts current design)
- **defer** — marked `[DEFERRED]` (will address later)
- **edit** — user wants to adjust the proposal before approving
5. Shortcuts: "approve all critical", "skip info", "defer all medium", etc.
6. After all items triaged, show a final list of what will be implemented before proceeding.
### Approval Rules
- Present **one finding at a time** — do not batch without user permission
- **Wait for response** before showing the next finding
- If user says "approve all HIGH and above" — apply and continue triage for lower severities
- If user says "just show me the plan and I'll decide later" — stop after report generation, do not triage
- Never proceed to implementation without explicit approval
---
## Phase 6: Dispatch Fix Agents
Only implement what the user approved. For each approved finding, dispatch a focused agent.
### Agent Grouping Rules
- One agent per god-class decomposition (these are large and touch many files)
- One agent per test-failure fix (keep these isolated — one failure, one agent)
- Bundle LOW/INFO coupling fixes into one agent per directory
- Never bundle a CRITICAL with a MEDIUM — different blast radii
### Agent Prompt Template
```
Decompose the following structural finding in [file]:
Finding: [title from DECOMPOSE-PLAN.md]
Location: [file:line]
Category: [God Class / Bloated Function / Failing Logic / Coupling Smell]
Evidence:
[snippet from report]
Proposed change:
[decomposition proposal from report]
Instructions:
1. Read all affected files before making changes
2. Implement exactly the decomposition described — do not improvise scope
3. Update all import sites for moved symbols
4. Do NOT change behavior — only structure
5. Verify the code compiles and tests pass after your changes
```
### Behavior Constraints
- **Do not change observable behavior** during decomposition. Extract, don't rewrite.
- **Update all import sites.** A class rename with one import left behind is a broken build.
- **No new abstractions.** The task is decomposition, not redesign.
- **Run quality gates** after each agent completes before dispatching the next.
---
## Phase 7: Quality Gates
After all approved changes are applied:
1. **Type check** — `tsc --noEmit` or equivalent. Zero new errors.
2. **Tests** — full test suite. Must not regress. If new test failures appear, fix them before marking done.
3. **Lint** — zero new warnings.
4. **Build** — `npm run build` or equivalent. Must succeed.
If a gate fails, the fix agent must resolve it before the next finding is addressed.
---
## Phase 8: Report Update
Update `DECOMPOSE-PLAN.md` in-place after all approved changes are complete:
- Approved + done: `[DONE] YYYY-MM-DD`
- Skipped: `[SKIPPED]`
- Deferred: `[DEFERRED]`
- Any new findings discovered during implementation: appended as LOW/INFO
The file stays in the project. It is a living record. The user decides when to delete it.
---
## Red Flags — You're Doing It Wrong
- Reporting a god class without reading the methods to verify mixed responsibilities
- Flagging generated files (Prisma client, GraphQL types, build output)
- Flagging intentional facades or aggregation points documented in CLAUDE.md
- Treating file size alone as evidence — read the content
- Proposing decompositions that change behavior, not just structure
- Approving your own findings without user triage
- Implementing before the approval phase
- Bundling a god-class decomposition with unrelated bug fixes in one agent
- Reporting "failing logic" without tracing the call path to confirm reachability
## Common Mistakes
| Mistake | Fix |
|---------|-----|
| Flagging `utils/index.ts` as a god class because it re-exports many things | Re-exports are API surface design, not mixed responsibility |
| Reporting a 400-line class when 300 lines are JSDoc | Count substantive lines (code + logic), not comments |
| Calling a class a god class because it has 12 methods that all do one thing | Count distinct *domains*, not method count |
| Fixing test failures by deleting or skipping tests | Fix the code, not the test |
| Moving a class to a new file without updating all importers | Always grep for all import sites before finalizing |
| Reporting `catch (e) { logger.error(e); }` as a swallowed error | Logged errors are handled errors — check if the failure propagates correctly |
| Treating a class that orchestrates a pipeline as a god class | Orchestration is a responsibility. Check if it *also* does work it shouldn't. |
## Parallel Execution Strategy
For large codebases (> 50 files), dispatch all four scan agents simultaneously:
```
Agent 1: God Class Scanner ─┐
Agent 2: Bloated Logic Scanner ─┤→ collect all raw findings → fact-check → plan
Agent 3: Failing Logic Scanner ─┤
Agent 4: Coupling Smell Scanner ─┘
```
Each agent returns a structured list of raw findings (file, line, evidence, severity). The main session then runs Phase 3 (fact-check) across all findings before generating the report. Do not fact-check per-agent — do it centrally to catch duplicates and cross-category interactions.