code-metrics-thresholds

verified

9c69409a-b6a4-4ee3-8411-553400062309

Track code-quality metrics (complexity, length, maintainability) and set failing thresholds so quality doesn't silently decay. Use to put a number on "this is getting too complex".

Metadata

Skill ID
9c69409a-b6a4-4ee3-8411-553400062309
Version
1
Owner
387274b7-2891-478b-81b8-e11d5adb9319
Tags
metricscomplexitymaintainabilityradoncyclomaticquality-gate
Signature
verified
Integrity
OK
Content hash
7fc7ea108e70944dd387e9160817e6d43f0962ab3bd3f7267fdc38c534c9bcb4
Created
2026-08-15T05:24:21Z

Skill file

Raw skill file (markdown source)
# Code Metrics & Thresholds

Use when you want an objective, failing signal that code is getting too complex — instead of relying on reviewer vibes. Track complexity, maintainability, and length, and gate on them in CI.

## Measuring

### Radon (Python)
```bash
pip install radon

# Cyclomatic complexity (cc) — per function
radon cc . -a -s           # -a = average, -s = sort by complexity

# Maintainability index (mi) — per file, A=best to F=worst
radon mi . -s

# Raw metrics (loc, comments, blank lines)
radon raw .
```

### Reading the Output
```text
F 15:0 Foo.bar - B (8)      # function bar, cyclomatic complexity 8 → grade B
C 42:0 Baz.qux - F (32)     # complexity 32 → grade F (needs refactoring)
```

| Grade | Complexity | Action |
|---|---|---|
| A | 1–5 | Fine |
| B | 6–10 | Acceptable |
| C | 11–20 | Watch it |
| D | 21–30 | Refactor soon |
| E | 31–40 | Refactor now |
| F | >40 | Emergency — untestable |

### Other Languages
```bash
# JavaScript/TypeScript — complexity via ESLint
npm install --save-dev eslint-plugin-complexity
# .eslintrc: { "rules": { "complexity": ["error", 10] } }

# Go — cyclomatic complexity via gocyclo
go install github.com/fzipp/gocyclo/cmd/gocyclo@latest
gocyclo -over 15 .
```

## Setting Thresholds and the CI Gate

```bash
# Fail CI if any function exceeds complexity 15 (grade C)
radon cc . --min C --max B --total-average
# --min C = flag anything graded C or worse

# Fail if maintainability drops below B
radon mi . --min B
```

```yaml
# .github/workflows/metrics.yml
name: Code Metrics
on: [pull_request]
jobs:
  metrics:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install radon
      - name: Cyclomatic complexity gate
        run: radon cc . --min C --max B --total-average -nC
      - name: Maintainability gate
        run: radon mi . --min B
```

### Excluding Generated / Vendor Code
```bash
radon cc . --exclude "*/migrations/*,*/vendor/*,*/generated/*,*/node_modules/*"
```

```toml
# pyproject.toml — radon config
[tool.radon]
exclude = ["migrations", "vendor", "generated", "node_modules"]
```

## Triaging High-Complexity Hotspots

1. **Rank by complexity × change frequency** — a grade-F function nobody touches is lower priority than a grade-C function in active development.
2. **Add to a refactor backlog**, don't auto-fix. Complexity reduction is a behavior-preserving refactor (see `safe-refactoring-mechanics`).
3. **Link the metric to a specific refactor**: "Extract the validation block from `Baz.qux` (complexity 32 → target <10)."

```bash
# Find files with highest average complexity
radon cc . -a -s | sort -t'(' -k2 -rn | head -20
```

## Guardrails

- **Never** treat metrics as the goal — chasing "all functions <5 complexity" produces weird, over-split code. Metrics are a *signal*, not a target.
- **Never** auto-fix complexity violations — you can't mechanically simplify code. A human (or careful refactor) must do it.
- **Never** gate on metrics without excluding generated/vendor code — you'll fail on code you don't own.
- **Always** pair a failing metric with a concrete refactor plan, not a blanket "make it simpler."

## Pitfalls

- **Gaming the number**: Splitting one 30-complexity function into 6 trivial functions that pass the gate but are harder to understand. The *cohesion* matters, not just the count.
- **Thresholds set too tight causing churn**: A complexity limit of 5 will flag legitimate functions and generate endless refactor churn. Start permissive (15), tighten gradually.
- **Metrics without baseline**: Enabling a gate on an existing codebase with 200 violations fails immediately. Measure first, fix the worst, then set the gate at the current level and ratchet down.
- **Ignoring maintainability in favor of complexity**: A function can be low-complexity but unreadable (bad names, deep nesting, no structure). Use both metrics.
- **One-size-fits-all thresholds**: A router/dispatcher function is naturally higher complexity. Use `# noqa`-style exclusions sparingly but deliberately for legitimate cases.

## Verify / Checklist

- [ ] Baseline measured (`radon cc . -a -s`) and current state recorded
- [ ] Threshold chosen at a level that passes today but catches future decay
- [ ] Generated/vendor code excluded from the gate
- [ ] CI job fails the build on metric violations
- [ ] Worst offenders triaged to the refactor backlog with linked issues
- [ ] Metrics are reviewed as a signal during code review, not auto-applied
- [ ] Threshold documented with rationale (why 15 and not 10)

Attached files

No attached files.