CUPID — methodology

how each grew → fixed → stayed case is confirmed

Each evidence case is found by a deterministic check over a function's per-release history — no LLM, identical every run. A code smell must have grown (over the published threshold for ≥ 2 releases), been fixed (the criterion below), and stayed fixed (survived to the latest observed release). Each family's “fixed” rule and the research behind it:

How findings are ranked

Complexity findings are ordered by three explicit axes (never collapsed into one opaque number, so a ranking is always explainable):

So: the most cognitively/cyclomatically complex code leads; among similarly complex functions, many callers + worsening over time rises (higher payoff, marked “touches N callers”), while never cleaned across releases sinks — likely essential or chronically deferred, not worth refactoring for its own sake unless you are already in that code.

A · Performance (the moat)

implemented
quadratic-scan, membership-in-loop, linear-search-in-loop, regex-in-loop, n-plus-one-query, repeated-allocation/work-in-loop

How a fix is confirmed (deterministic, no LLM): The offending site count in the function falls from > 0 to 0 — the x in list leaves the loop, the nested input-scaling loop collapses, the query or allocation is hoisted or batched — while the function survives (a removal, not a deletion).

Confidence: high

B · Error handling

implemented
broad-except

How a fix is confirmed (deterministic, no LLM): The bare/broad+silent handler is narrowed to a specific exception type, or stops being silent (logging or a re-raise is added) — either clears the offending-handler count.

Research backing
Confidence: high

C · Type contracts

implemented
missing-type-contract, bare-generic, type-escape-hatch

How a fix is confirmed (deterministic, no LLM): Annotation coverage rises — unannotated parameters and a missing return type get annotated, a bare list/dict gains type args, or an Any/cast/type: ignore is removed — driving the “weak/missing” count to 0.

Research backing
Confidence: high

D · Duplication

implemented
duplicate-function

How a fix is confirmed (deterministic, no LLM): A function's clone group shrinks — the near-identical copies are consolidated into one shared implementation, so the count of other copies falls to 0.

Research backing
Confidence: high (with nuance)

E · Architecture

implemented
dependency-cycle, soft-dependency-cycle, barrel-back-reference-cycle; hub-function and instability trend evidence are next

How a fix is confirmed (deterministic, no LLM): A strongly-connected import cycle is no longer an SCC at a later release (an edge was removed — the cycle broke). The current-version report also classifies lazy/re-export cycles and package barrel back-references separately from import-time cycles. Hub and instability trend confirmation are still roadmap items.

Research backing
Confidence: cycles: high · hubs/instability trends: planned

F · Resources

planned
alloc-without-free, unbalanced-resource

How a fix is confirmed (deterministic, no LLM): The acquire/release balance stops being positive — a free/close/unlock is added, or the acquisition becomes context-managed (with) — while the function survives.

Confidence: medium-high

G · Dead code & debt

planned
unused-static-function, unused-parameter, magic-number, todo-comment, missing-doc-comment

How a fix is confirmed (deterministic, no LLM): The flagged item simply disappears — the dead function/parameter is removed, the literal is named as a constant, the TODO is resolved, the docstring is added.

Research backing
  • Fowler, Refactoring; general maintainability guidance — these are conventions with limited dedicated empirical backing, reported honestly at low confidence
Confidence: low