title
Complexity hotspots - detect, backlog, reduce
kind
sop
triggers
tools

Standard Operating Procedure: Complexity Hotspots

Reduce structural complexity in small, test-backed batches. Detection belongs to agent-arch-drift; execution belongs to agent-prune (complexity track). Align with CODING_PHILOSOPHY.md §4 (minimal change): simplify before adding layers.

1. What counts as a hotspot

A complexity hotspot is code that is hard to change safely because of shape, not because it is unused (that is dead code).

SignalTypical thresholdNotes
Cognitive / cyclomatic complexityAbove project linter default or > 15 per functionPrefer repo-configured rules (ESLint, Sonar, Checkstyle)
Function length> 40–60 lines without clear structureDomain logic may be longer if cohesive
File length> 300–400 lines mixing concernsSplit by vertical slice, not arbitrary chunking
Nesting depth> 3–4 levelsExtract guard clauses or early returns
Parameter count> 3 positional argsUse a parameter object at the boundary
God moduleMany unrelated exports in one fileSplit slice or extract shared domain
Duplicate logicSame branch/business rule in 2+ placesConsolidate or extract shared domain function
Shotgun couplingOne story forces edits across unrelated slicesRe-home behavior into the owning slice

When metrics and judgment disagree, trust change friction: if reviewers consistently miss edge cases in a module, treat it as a hotspot even if metrics are borderline.

2. Backlog location

Per project, maintain:

~/.agents/handover/<project>/complexity-backlog.md

Do not commit backlog files to the app repo. Template:

# Complexity backlog

| ID | Location | Signal | Class | Status | Notes |
|----|----------|--------|-------|--------|-------|
| C-001 | src/features/foo/Handler.ts | cognitive 22 | extract | ready | split validation block |

Status values: candidatereadydone | blocked | wontfix

Class values: extract | inline | split-slice | consolidate | defer

3. Detection (audit / drift)

During agent-arch-drift reviews or when the user asks for a complexity pass:

  1. Run project metrics when documented (see §5).
  2. Walk changed files and top churn modules from recent PRs.
  3. For each hotspot, open a backlog row with signal, class, and a one-line remediation hypothesis.
  4. Do not refactor inline during a feature PR unless the user scoped simplification in the same change.

Route execution to agent-prune when rows are ready.

4. Reduction (prune - complexity track)

agent-prune complexity track:

  1. Load complexity-backlog.md; process only ready rows (confirm with user if backlog was auto-generated).
  2. One batch = one hotspot cluster (one function family or one slice folder).
  3. Prefer behavior-preserving refactors: extract function, guard clauses, move code into owning slice, consolidate duplicates.
  4. Run tests for touched slices; run agent-pre-commit before marking done.
  5. If simplification needs a lasting boundary change, route to agent-adr and set row blocked.

Reject during prune:

  • Rewrites that change behavior without catalog/test alignment.
  • New abstractions with a single call site (inline instead).
  • Splitting files without moving toward vertical-slice cohesion.

5. Tooling (use what the repo already has)

StackExamples
TypeScripteslint complexity rules, typescript-eslint, optional ts-complexity / Sonar
JavaCheckstyle, PMD, Sonar cognitive complexity
C#Roslyn analyzers, Sonar, NDepend if present
Generalrg for duplicate strings/branches; git log --stat for churn

Do not add new analysis tools without user alignment. Document the command used in the handover.

6. Orchestration routes

RequestRoute
"Simplify X" / complexity cleanupagent-arch-drift (scan) → backlog → agent-pruneagent-pre-commit
Post-audit remediationRows already in backlog → agent-prune
Feature work touching a known hotspotNote backlog ID in handover; optional small extract-only fix in scope

Not part of the default feature lifecycle unless the user requests it or audit rows are ready.

7. Handover

Complexity work uses phase maintenance in handover_prune.md (same artifact as dead-code prune). Include:

  • Backlog IDs completed
  • Metrics before/after when available
  • Tests run
  • Rows left blocked or defer with reason

Markdown source