|
| 1 | +--- |
| 2 | +name: reduce-complexity |
| 3 | +description: > |
| 4 | + Analyze code for complexity hotspots and suggest simplifications. Identifies functions |
| 5 | + exceeding evidence-based LOC and nesting thresholds, classifies complexity as essential |
| 6 | + (domain-inherent, leave alone) or accidental (reducible), and produces actionable |
| 7 | + reduction suggestions with safety annotations. Use PROACTIVELY when: reviewing files |
| 8 | + or modules for maintainability, before refactoring to find highest-ROI targets, triaging |
| 9 | + tech debt, when the user says "simplify", "reduce complexity", "find complex functions", |
| 10 | + "what should I refactor", "maintainability review", "this file is too complex", "hard |
| 11 | + to understand", or asks about code quality or readability of specific files. Also use |
| 12 | + when examining large functions (>100 lines) during code review. Works on any language |
| 13 | + with emphasis on Rust-specific patterns. Does NOT perform automated refactoring -- it |
| 14 | + detects, explains, and suggests. |
| 15 | +--- |
| 16 | + |
| 17 | +# Code Complexity Reduction |
| 18 | + |
| 19 | +Detect complexity hotspots, classify them as essential or accidental, and suggest |
| 20 | +specific reduction techniques with safety annotations. The core value is not metric |
| 21 | +computation (Clippy already does that) but explaining WHY code is complex and WHETHER |
| 22 | +reduction is safe in context. |
| 23 | + |
| 24 | +## When to use |
| 25 | + |
| 26 | +- Reviewing a file or module for maintainability |
| 27 | +- Before refactoring, to identify the highest-ROI targets |
| 28 | +- Triaging tech debt across a codebase or directory |
| 29 | +- When a function feels hard to understand and you want to know why |
| 30 | +- During code review of large or deeply nested functions |
| 31 | + |
| 32 | +## When NOT to use |
| 33 | + |
| 34 | +- For code review (use code-review skills instead) |
| 35 | +- For performance optimization (use performance-analyzer) |
| 36 | +- For automated refactoring (use refactoring-assistant) |
| 37 | +- For style/formatting issues (use cargo fmt / linters) |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +## Input |
| 42 | + |
| 43 | +| Form | Example | Behavior | |
| 44 | +|------|---------|----------| |
| 45 | +| File path | `/reduce-complexity src/cache.rs` | Analyze all functions in the file | |
| 46 | +| Directory | `/reduce-complexity src/` | Scan source files, report top-N hotspots | |
| 47 | +| No argument | `/reduce-complexity` | Scan all non-test source files, report top-10 | |
| 48 | + |
| 49 | +Exclude test files (`*_tests.rs`, `tests/`) from default scans unless explicitly passed. |
| 50 | +Test code has different complexity norms. |
| 51 | + |
| 52 | +--- |
| 53 | + |
| 54 | +## Analysis Pipeline |
| 55 | + |
| 56 | +Execute these four phases in order. Read the target code before starting. |
| 57 | + |
| 58 | +### Phase 1: Detection |
| 59 | + |
| 60 | +Enumerate every function in the target scope. For each, measure: |
| 61 | + |
| 62 | +1. **LOC** -- lines from opening `{` to closing `}`, excluding blanks and comment-only lines |
| 63 | +2. **Max nesting depth** -- with the Rust match discount (see below) |
| 64 | +3. **Parameter count** -- including `&self`/`&mut self` |
| 65 | +4. **Unsafe presence** -- whether the function body contains `unsafe` blocks |
| 66 | +5. **Clippy annotations** -- any `#[allow(clippy::...)]` on the function or enclosing impl |
| 67 | + |
| 68 | +Flag a function if ANY independent threshold triggers: |
| 69 | + |
| 70 | +| Metric | Advisory | Moderate | High | Critical | |
| 71 | +|--------|----------|----------|------|----------| |
| 72 | +| LOC | 51-100 | 101-200 | 201-400 | >400 | |
| 73 | +| Nesting | 4 | 5-6 | 7+ | -- | |
| 74 | +| Params | 6-7 | 8+ | -- | -- | |
| 75 | + |
| 76 | +Advisory items appear only in the codebase overview unless another metric also triggers. |
| 77 | + |
| 78 | +**Rank** flagged functions by: number of thresholds exceeded (descending), then LOC |
| 79 | +(descending). Cap output at 15 functions per file, 25 per directory. |
| 80 | + |
| 81 | +#### Why these metrics, not cyclomatic/cognitive complexity |
| 82 | + |
| 83 | +LOC is the most stable defect predictor across all major studies (Menzies, Hatton, |
| 84 | +Lessmann). Cyclomatic complexity correlates with LOC at r > 0.9 -- it catches |
| 85 | +nothing LOC misses. Cognitive complexity adds only 5.26% accuracy and the Clippy |
| 86 | +team placed their implementation in the `restriction` group as unreliable for Rust. |
| 87 | +Independent threshold checks are transparent and evidence-based. |
| 88 | + |
| 89 | +#### Rust match discount |
| 90 | + |
| 91 | +An exhaustive `match` on an enum with <= 6 variants counts as nesting +0 (no increment). |
| 92 | +Rust's exhaustive matching is a type-safety mechanism, not decision complexity. A |
| 93 | +`match` on `Result<T, E>` or a 4-variant enum is idiomatic. |
| 94 | + |
| 95 | +A `match` on a runtime value (integer, string) or an enum with >6 variants counts |
| 96 | +as normal nesting +1. |
| 97 | + |
| 98 | +### Phase 2: Classification |
| 99 | + |
| 100 | +For each flagged function, read it and its surrounding context (enclosing impl, |
| 101 | +module doc, called functions). Classify as: |
| 102 | + |
| 103 | +- **ESSENTIAL** -- complexity is inherent to the problem domain; leave alone |
| 104 | +- **ACCIDENTAL** -- complexity is reducible; suggestions follow |
| 105 | +- **MIXED** -- some essential, some accidental; suggestions target only the accidental part |
| 106 | + |
| 107 | +Use these tests to make the judgment: |
| 108 | + |
| 109 | +1. **Domain necessity**: Would a clean-room reimplementation solving the same problem |
| 110 | + have similar structure? If yes, the complexity is essential. |
| 111 | + |
| 112 | +2. **Error handling**: Does each branch handle a semantically distinct error case with |
| 113 | + distinct recovery (logging, circuit breaker signaling, metrics, cleanup)? If yes, |
| 114 | + the branching is essential -- not reducible by collapsing. |
| 115 | + |
| 116 | +3. **Sequential coupling**: Do steps have data or control dependencies preventing |
| 117 | + reordering? If yes, the sequential length is essential. |
| 118 | + |
| 119 | +4. **Accidental indicators**: Duplicated logic blocks (same pattern 3+ times), deep |
| 120 | + nesting flattenable with early returns, boilerplate extractable to a helper, |
| 121 | + parameters always passed together (struct opportunity), conditions testing |
| 122 | + implementation state rather than domain state. |
| 123 | + |
| 124 | +Include a 1-2 sentence rationale with each classification. |
| 125 | + |
| 126 | +### Phase 3: Suggestions |
| 127 | + |
| 128 | +For ACCIDENTAL and MIXED functions, recommend specific techniques. Read |
| 129 | +`references/techniques.md` for the full catalog of 12 techniques with preconditions, |
| 130 | +contraindications, and presentation templates. |
| 131 | + |
| 132 | +Techniques are classified by confidence: |
| 133 | + |
| 134 | +| Category | Techniques | Confidence | |
| 135 | +|----------|-----------|------------| |
| 136 | +| Fully automatable (5) | Guard clauses, redundant else removal, remove unnecessary Result, pass by reference, type aliases | `auto-apply` or `suggest` | |
| 137 | +| Judgment-required (4) | Extract function, ? operator, merge match arms, let-else | `suggest` or `flag-for-review` | |
| 138 | +| Not automatable (3) | Collapse if-chains, polymorphism, decompose state machine | `flag-for-review` only | |
| 139 | + |
| 140 | +**Never suggest more than 3 techniques per function.** More than 3 signals the |
| 141 | +function needs broader redesign, not incremental fixes. Say so explicitly. |
| 142 | + |
| 143 | +### Phase 4: Safety Checks |
| 144 | + |
| 145 | +Apply these checks after generating suggestions. They can override or annotate output. |
| 146 | + |
| 147 | +1. **Unsafe exclusion zone**: If the function contains `unsafe`, or calls a function |
| 148 | + in the same module that contains `unsafe` -- label "MANUAL REVIEW REQUIRED" and |
| 149 | + suppress all suggestions except guard clauses. Unsafe invariants (like `set_len` + |
| 150 | + `truncate`, `#[repr(align)]`, FFI contracts) often span multiple statements and are |
| 151 | + invisible to any analysis. |
| 152 | + |
| 153 | +2. **Clippy annotation respect**: If the function has `#[allow(clippy::...)]`, note |
| 154 | + the developer made a deliberate decision. Do not suppress suggestions but lower |
| 155 | + confidence by one level. |
| 156 | + |
| 157 | +3. **Over-abstraction brake** (for extract-function suggestions): |
| 158 | + - **Shallow module check**: If `param_count + return_type_fields >= body_lines / 3`, |
| 159 | + warn that the extraction interface is nearly as complex as the body. |
| 160 | + - **Single call-site + high coupling**: If the extracted code would be called from |
| 161 | + exactly 1 site AND requires >3 parameters, warn about locality destruction. |
| 162 | + - **Zero intention gap**: If the body is only stdlib/library calls with no domain |
| 163 | + logic, warn that a function name adds no information. |
| 164 | + |
| 165 | +4. **Async boundary warning**: If a suggestion involves extracting code containing |
| 166 | + `.await` points, warn about `Send` bound implications and recommend `cargo check`. |
| 167 | + |
| 168 | +5. **Validation requirement**: Any accepted suggestion must pass `cargo check` + |
| 169 | + `cargo clippy`. Characterization tests alone are insufficient -- they miss |
| 170 | + `Send`/`Sync` violations and lifetime constraint breakages. |
| 171 | + |
| 172 | +--- |
| 173 | + |
| 174 | +## Output Format |
| 175 | + |
| 176 | +Structure the report with these four sections: |
| 177 | + |
| 178 | +### Section 1: Hotspot Summary |
| 179 | + |
| 180 | +A ranked table: |
| 181 | + |
| 182 | +``` |
| 183 | +## Complexity Hotspots |
| 184 | +
|
| 185 | +| # | Function | Location | LOC | Nesting | Params | Flags | Class | |
| 186 | +|---|----------|----------|-----|---------|--------|-------|-------| |
| 187 | +``` |
| 188 | + |
| 189 | +Flags use abbreviated severity: `LOC:High`, `Nest:Mod`, `Params:Mod`. |
| 190 | +Class is ESSENTIAL, ACCIDENTAL, or MIXED. |
| 191 | + |
| 192 | +### Section 2: Per-Function Analysis |
| 193 | + |
| 194 | +One block per flagged function, in rank order: |
| 195 | + |
| 196 | +``` |
| 197 | +### #N: `function_name` (file:line) -- CLASSIFICATION |
| 198 | +
|
| 199 | +**Metrics:** N LOC | max nesting M | K params |
| 200 | +**Flags:** which thresholds triggered |
| 201 | +
|
| 202 | +**Why it is complex:** 2-3 sentences explaining the dominant complexity driver. |
| 203 | +
|
| 204 | +**Essential vs Accidental:** What is inherent to the domain vs what is structural. |
| 205 | +
|
| 206 | +**Suggestions:** (only for ACCIDENTAL/MIXED) |
| 207 | +1. TECHNIQUE (confidence): explanation, before/after sketch, impact estimate |
| 208 | + - Over-abstraction check result if applicable |
| 209 | + - Safety warnings if applicable |
| 210 | +``` |
| 211 | + |
| 212 | +### Section 3: Codebase Health Overview |
| 213 | + |
| 214 | +Aggregate statistics: |
| 215 | + |
| 216 | +``` |
| 217 | +## Codebase Health |
| 218 | +
|
| 219 | +| Metric | Value | Assessment | |
| 220 | +|--------|-------|------------| |
| 221 | +| Functions exceeding LOC threshold | N / total (%) | vs Pareto norm (10-20%) | |
| 222 | +| Functions exceeding nesting threshold | N / total (%) | | |
| 223 | +| Essential complexity ratio | N of M flagged (%) | Higher = more domain-inherent | |
| 224 | +| Dominant complexity pattern | e.g. "sequential orchestration" | | |
| 225 | +
|
| 226 | +**Highest-ROI targets:** Functions with the most accidental complexity and |
| 227 | +simplest extraction boundaries. |
| 228 | +``` |
| 229 | + |
| 230 | +### Section 4: Essential Complexity Warnings |
| 231 | + |
| 232 | +Functions that are complex but should NOT be simplified: |
| 233 | + |
| 234 | +``` |
| 235 | +## Essential Complexity -- Leave Alone |
| 236 | +
|
| 237 | +| Function | Location | Why Essential | |
| 238 | +|----------|----------|---------------| |
| 239 | +``` |
| 240 | + |
| 241 | +Close with: "Complex code takes 124% longer to resolve issues in (CodeScene, 39 |
| 242 | +codebases). This is a cognitive load effect -- the cost is developer time, not |
| 243 | +production failures. Rust's compiler eliminates many defect classes." |
| 244 | + |
| 245 | +--- |
| 246 | + |
| 247 | +## Supplementary Signals |
| 248 | + |
| 249 | +When git history is available, use it to adjust ranking priority (not detection): |
| 250 | + |
| 251 | +| Signal | Command | Effect | |
| 252 | +|--------|---------|--------| |
| 253 | +| Change frequency | `git log --oneline -- <file> \| wc -l` | High-churn functions ranked higher | |
| 254 | +| Author count | `git log --format=%aN -- <file> \| sort -u \| wc -l` | Many-author functions ranked higher | |
| 255 | +| Recency | `git log --since=90d -- <file>` | Recently changed functions ranked higher | |
| 256 | + |
| 257 | +Process metrics outperform all static code metrics for defect prediction (Moser 2008). |
0 commit comments