tl-complexity-assessment
tl-complexity-assessment
Find the files that need to be split up. Get a ranked, evidence-based list of complexity hotspots with specific refactoring recommendations.
Quick Start
For experienced users — run the scanner and get a report:
# Bash
./scripts/complexity-scan.sh src/
# PowerShell
.\scripts\complexity-scan.ps1 -TargetDir src/
For guided assessment — follow the phases below.
When to Use
- "find complex files"
- "what needs to be split up"
- "assess complexity" / "code health check"
- "find monoliths" / "find god files"
- "identify refactoring candidates"
- "this file is too big"
- Before major refactoring efforts
- When onboarding to a new codebase
- Sprint planning for tech debt reduction
Do Not Use When
- Looking for bugs (use debugging skills instead)
- Assessing security vulnerabilities (use security audit)
- Reviewing code style (use linting/formatting tools)
- File is already small and focused (<150 lines, single responsibility)
Outcomes
- Analysis: Ranked list of complexity hotspots with evidence and recommendations
- Decision: Which files/modules to refactor first (ROI-based prioritization)
- Artifact: Optional findings register (markdown) for tracking remediation
- Next Steps: Clear refactoring recommendations for each finding
The Iron Law
NO COMPLEXITY CLAIMS WITHOUT EVIDENCE
Every finding must include file path, line count or metric, and specific observation.
What Good Looks Like
⌠BAD: "UserService.ts is too complex and should be refactored"
✅ GOOD: "UserService.ts (847 lines, 23 exports) mixes 4 concerns:
- Authentication (lines 1-150)
- Validation (lines 151-320)
- API calls (lines 321-600)
- Formatting (lines 601-847)
Recommendation: Split into auth.ts, validation.ts, api.ts, formatters.ts
Effort: E2 (4-8 hours) | Impact: High (imported by 12 files)"
Assessment Categories
Category 1: Size Indicators
| Indicator | Threshold | Severity |
|---|---|---|
| File lines | >500 | High |
| File lines | 300-500 | Medium |
| Function lines | >50 | High |
| Function lines | 30-50 | Medium |
| Component lines | >300 | High |
| Component lines | 150-300 | Medium |
Category 2: Responsibility Indicators
| Indicator | Threshold | Severity |
|---|---|---|
| Exports per file | >10 | High |
| Exports per file | 6-10 | Medium |
| Classes per file | >2 | High |
| Functions per file | >15 | Medium |
Category 3: Coupling Indicators
| Indicator | Threshold | Severity |
|---|---|---|
| Import statements | >20 | High |
| Import statements | 10-20 | Medium |
| Cross-domain imports | >5 distinct domains | High |
| Circular dependencies | Any | Critical |
Category 4: Cyclomatic Complexity Proxies
| Indicator | Threshold | Severity |
|---|---|---|
| Nested conditionals | >3 levels deep | High |
| Switch cases | >7 cases | Medium |
| Ternary chains | >2 chained | Medium |
| Callback depth | >3 levels | High |
Category 5: React-Specific Smells
| Indicator | Threshold | Severity |
|---|---|---|
| useEffect hooks | >3 per component | High |
| useEffect hooks | 2-3 per component | Medium |
| useState hooks | >5 per component | Medium |
| Inline sub-components | Any | Medium |
| Props count | >7 props | Medium |
| Business logic in page | Non-trivial | High |
Category 6: Structural Smells
| Indicator | Pattern | Severity |
|---|---|---|
| God files | utils.ts, helpers.ts, common.ts, shared.ts |
High |
| Catch-all routers | >10 routes inline | High |
| Mega schemas | >10 unrelated tables | High |
| Mixed concerns | API + UI in same file | Medium |
| Barrel bloat | index.ts >50 re-exports |
Medium |
Assessment Phases
Phase 1: Automated Discovery
Run these commands to gather metrics. Adapt paths to your project structure.
Find large files:
find src/ -name "*.ts" -o -name "*.tsx" | xargs wc -l 2>/dev/null | sort -rn | head -30
Count exports per file:
rg "^export " --type ts -c | sort -t: -k2 -rn | head -20
Count imports per file:
rg "^import " --type ts -c | sort -t: -k2 -rn | head -20
Find god files:
rg -l "utils|helpers|common|shared" --type ts --glob "!node_modules" | head -20
Find React components with many hooks:
rg "useEffect\(" --type tsx -c | sort -t: -k2 -rn | head -20
Find deeply nested conditionals:
rg "if.*if.*if" --type ts -l | head -20
Find files with many functions:
rg "^(export )?(async )?(function |const \w+ = )" --type ts -c | sort -t: -k2 -rn | head -20
Phase 2: Manual Analysis
For each candidate file from Phase 1:
- Read the file - Understand what it does
- Identify responsibilities - List distinct concerns
- Check coupling - What does it import from? What imports it?
- Assess cohesion - Do all parts serve a single purpose?
- Document evidence - File path, line count, specific observations
Phase 3: Scoring
Score each finding 0-10:
| Score | Meaning |
|---|---|
| 0-2 | Acceptable - monitor only |
| 3-4 | Low priority - refactor when convenient |
| 5-6 | Medium priority - plan for refactor |
| 7-8 | High priority - refactor soon |
| 9-10 | Critical - blocking quality/velocity |
Score Formula:
Score = (Severity × 2) + (Impact × 2) + (Effort_Inverse)
Where:
- Severity: 1 (Low) to 3 (Critical)
- Impact: 1 (isolated) to 3 (affects many files)
- Effort_Inverse: 3 (easy fix) to 1 (hard fix)
Phase 4: Report
For each finding, report:
### [Rank] File: `path/to/file.ts`
**Score:** 8/10 | **Severity:** High | **Effort:** Medium
**Metrics:**
- Lines: 847
- Exports: 23
- Imports: 18 (from 6 domains)
**Observations:**
- Contains 4 unrelated responsibilities: auth, validation, API calls, formatting
- 3 useEffect hooks managing different concerns
- Imported by 12 other files
**Recommendation:**
Split into:
- `auth.ts` - Authentication utilities
- `validation.ts` - Form validation
- `api.ts` - API client functions
- `formatters.ts` - Display formatting
**Evidence:**
Lines 1-150: Auth functions
Lines 151-320: Validation schemas
Lines 321-600: API calls
Lines 601-847: Formatting utilities
Priority Matrix
ROI = Severity × (4 - Effort)
| Severity | E0 (<1h) | E1 (1-4h) | E2 (4-8h) | E3 (>8h) |
|---|---|---|---|---|
| Critical | 12 🔥 | 9 🔥 | 6 | 3 |
| High | 8 | 6 | 4 | 2 |
| Medium | 4 | 3 | 2 | 1 |
🔥 = Address first (ROI ≥ 9)
Red Flags - Stop and Reassess
If you catch yourself:
- Claiming "this file is complex" without metrics
- Recommending splits without identifying responsibilities
- Skipping files because they "look fine"
- Using vague terms like "too big" or "messy"
- Recommending refactors without considering import impact
Return to Phase 1. Gather evidence.
Rationalizations (Do Not Skip)
| Rationalization | Why It's Wrong | Required Action |
|---|---|---|
| "File is large but organized" | Organization doesn't fix responsibility sprawl | Identify distinct responsibilities, recommend splits |
| "It's a utility file, expected to be big" | Utility files are complexity magnets | Break into domain-specific utilities |
| "Would take too long to refactor" | Note effort, still report finding | Document with E3 effort, let prioritization decide |
| "Tests would break" | Tests prove the split points | Note as consideration, not blocker |
| "Team knows this code" | Tribal knowledge is tech debt | Document for bus factor mitigation |
Time-Boxing Guidelines
| Codebase Size | Discovery | Analysis | Total |
|---|---|---|---|
| Small (<10k LOC) | 30 min | 30 min | 1 hour |
| Medium (10-50k LOC) | 1 hour | 1 hour | 2 hours |
| Large (50k+ LOC) | 2 hours | 2 hours | 4 hours |
When time expires: Document what you found. Mark incomplete areas with next actions.
Output Format
Provide a summary table followed by detailed findings:
## Complexity Assessment Summary
| Rank | File | Score | Severity | Recommendation |
|------|------|-------|----------|----------------|
| 1 | `src/utils/helpers.ts` | 9 | Critical | Split into 4 domain files |
| 2 | `src/components/Dashboard.tsx` | 8 | High | Extract 3 sub-components |
| 3 | `src/api/client.ts` | 7 | High | Separate by API domain |
### Top Finding Details
[Detailed findings for top 5-10 items]
Example Real Output
See Example Output for a worked-through assessment report (summary table, per-file score, observations, recommendations, evidence).
What To Do After Assessment
Once you have findings, here's how to act on them:
Immediate (This Sprint)
- Fix 🔥 Critical findings (ROI ≥ 9) - These block velocity
- Run
tl-knipto remove dead exports before splitting - Add tests for files you're about to split
Plan (Next Sprint)
- Create tickets for High-priority findings (score 7-8)
- Group related splits (e.g., all API files together)
- Estimate using the Effort column
Monitor (Ongoing)
- Re-run assessment monthly to catch new complexity
- Add complexity checks to PR reviews
- Set team threshold: "No new files over 300 lines without review"
Cognitive vs Cyclomatic Complexity
See Cognitive Complexity for the difference between cyclomatic and cognitive complexity, scoring rules, and ESLint/SonarJS integration.
Code Review Metrics
See Code Review Metrics for optimal PR size thresholds, review time budgets, and a CI complexity-gate workflow example.
Verification Checklist
Before completing assessment:
- Ran automated discovery commands
- Every finding has file path and line count
- Every finding has specific observations (not vague)
- Responsibilities identified for each split recommendation
- Effort estimated for each recommendation
- Priority calculated using ROI formula
- Time-boxing respected
- Summary table provided with top findings
Skill Resources
Automated Discovery
Run the scanner script for quick assessment:
# Bash
./scripts/complexity-scan.sh src/
# PowerShell
.\scripts\complexity-scan.ps1 -TargetDir src/
Reference Documentation
| Document | Purpose |
|---|---|
references/react-patterns.md |
React hook limits, component size, inline sub-components |
references/coupling-analysis.md |
Import analysis, circular deps, dependency direction |
references/refactoring-strategies.md |
Extract function/module/component patterns |
Load these references when deeper analysis is needed for a specific category.
Related Skills
tl-knip- Find unused exports (reduces false positives in export counts)codebase-audit- Broader code health assessmentui-audit- UI-specific complexity and drift detectionsemgrep/skills/code-security- Security vulnerability detection (complementary to structural complexity)
References
Quilted Sources
- trailofbits/skills/code-maturity-assessor — Assessment framework
- obra/superpowers/systematic-debugging — Iron Law pattern
- obra/superpowers/verification-before-completion — Evidence principles
- rmyndharis/antigravity-skills/code-refactoring-refactor-clean — SOLID assessment
Official Skills
- semgrep/skills/semgrep — Static analysis and custom rule creation
- semgrep/skills/code-security — Security vulnerability patterns
- jwynia/agent-skills/code-review — Review metrics
First-Party Documentation
- ESLint Complexity Rule — Cyclomatic complexity linting
- SonarQube Cognitive Complexity — Cognitive complexity definition
- Semgrep Rule Writing — Custom complexity rules
- TypeScript Compiler API — AST analysis
Academic/Industry
- Cognitive Complexity Paper — Original SonarSource definition
- Code Complete 2 — McConnell complexity guidance
More from toddlevy/tl-agent-skills
tl-openmeter-api
Works with the OpenMeter REST API for usage metering, billing, and entitlements. Covers CloudEvents ingestion, meters, features, plans, customers, subscriptions, entitlements, notifications, billing profiles, invoices, apps, addons, grants, and the Stripe marketplace. Use when integrating OpenMeter, debugging metering, building catalog sync scripts, or when the user mentions OpenMeter API.
13tl-first-principles
Foundational software design principles traced to their intellectual origins. Covers information hiding, separation of concerns, abstraction, SSOT/DRY, conceptual integrity, and composition. Use when making architectural decisions, evaluating trade-offs, or understanding *why* best practices exist.
13tl-knip
Find and remove unused files, dependencies, and exports in TypeScript/JavaScript projects using Knip. Covers configuration-first workflow, plugin system, barrel file handling, CI integration, monorepo support, and agent-specific cleanup guidance.
12tl-docs-create
Create documentation from scratch for codebases. Covers SSOT-driven generation, writing standards, and templates for README/AGENTS.md/CHANGELOG. Use when creating new docs or documenting an undocumented codebase.
12tl-devlog
Maintain a structured development changelog (DEVLOG.md) capturing architectural decisions, milestones, incidents, and insights. Use when the user says "log this", "devlog", "archive this", or at natural pause points after significant decisions. Trigger on changelog, decision log, work log, or progress tracking.
12tl-docs-audit
Audit existing documentation for gaps, staleness, and sync issues. Generates sync reports with actionable findings. Use when reviewing doc coverage, finding outdated docs, or syncing docs with code.
12