Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ All notable changes to DebtLens are documented here. This project adheres to

### Added

- **Code smell detectors** for silent failures and dead code: `empty-catch`, `swallowed-error`,
`floating-promise`, and `commented-out-code` in the core TS/JS pack; `python-error-handling`
in the Python pack; and `kotlin-empty-catch` in the Kotlin pack
([#257](https://github.com/ColumbusLabs/DebtLens/issues/257),
[#258](https://github.com/ColumbusLabs/DebtLens/issues/258),
[#259](https://github.com/ColumbusLabs/DebtLens/issues/259)).
- **Swift core pack** (`--pack swift`) with `swift-todo-comment`, `swift-large-function`,
`swift-dead-abstraction`, and `swift-duplicate-logic` for `.swift` files ([#194](https://github.com/ColumbusLabs/DebtLens/issues/194)).
- **SwiftUI pack** (`--pack swiftui`) with `swiftui-large-view` and `swiftui-state-sprawl`
Expand Down
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,28 @@ language packs. Full taxonomy: [`docs/rule-packs.md`](./docs/rule-packs.md).
| --- | --- | --- | --- |
| `duplicate-logic` | core | Near-duplicate functions/components using normalized AST/text similarity | Medium |
| `test-duplication` | core | Structurally identical test cases across test files | Medium |
| `large-function` | core | Non-component functions over line or branch budgets | Medium |
| `import-cycle` | core | Circular relative import graphs | Medium |
| `complex-control-flow` | core | Branch-heavy or deeply nested functions | Medium |
| `config-drift` | core | Conflicting repeated values across JSON config files | Medium |
| `dead-abstraction` | core | Thin wrappers that add little behavior | Low |
| `duplicated-literal` | core | Repeated string/number literals across files | Low |
| `todo-comment` | core | TODO/FIXME/HACK/temporary implementation comments | Low |
| `naming-drift` | core | Files with multiple competing names for the same domain concept | Info |
| `barrel-file` | core | Re-export-only barrels that obscure import graphs | Low |
| `weak-test-boundary` | core | Production imports from test-only modules | Medium |
| `api-surface-sprawl` | core | Files exporting too many public symbols | Medium |
| `empty-catch` | core | Empty or comment-only catch blocks that silently ignore errors | Medium |
| `swallowed-error` | core | Catch blocks that only log without rethrowing or returning | Medium |
| `floating-promise` | core | Unawaited promise-returning calls and effect fire-and-forget | Medium |
| `commented-out-code` | core | Contiguous comment lines that look like dead code | Low |
| `large-component` | react | React-style components with too many lines, hooks, or branch points | Medium |
| `state-sprawl` | react | Components/hooks with many local stateful hooks | Medium |
| `effect-complexity` | react | Long or overloaded React effect hooks | Medium |
| `hook-dependency-smell` | react | Inline object/array/function literals in hook dependency arrays | Low |
| `context-provider-sprawl` | react | Components wrapping many unrelated Context providers | Medium |
| `prop-drilling` | react | Components that forward many props to children | Medium |
| `story-only-component` | react | Exported components whose known consumers are only Storybook stories | Low |
| `rn-host-forwarding` | react-native | RN wrappers forwarding many props into host primitives | Medium |
| `server-client-boundary` | next | App Router server/client boundary mistakes | High |
| `route-handler-size` | next | Oversized Next route/page modules | Medium |
Expand All @@ -107,6 +119,7 @@ language packs. Full taxonomy: [`docs/rule-packs.md`](./docs/rule-packs.md).
| `python-complex-control-flow` | python | Branch-heavy or deeply nested Python functions | Medium |
| `python-dead-abstraction` | python | Thin Python pass-through functions | Low |
| `python-todo-comment` | python | TODO/FIXME/HACK comments in Python files | Low |
| `python-error-handling` | python | Empty/bare except blocks and log-only Python error handlers | Medium |
| `python-route-sprawl` | python-web | Flask/Blueprint or Django URL modules registering too many routes | Medium |
| `vue-todo-comment` | vue | TODO/FIXME/HACK comments inside Vue script blocks | Low |
| `vue-large-script` | vue | Oversized Vue SFC scripts or script functions | Medium |
Expand All @@ -118,6 +131,7 @@ language packs. Full taxonomy: [`docs/rule-packs.md`](./docs/rule-packs.md).
| `kotlin-large-function` | kotlin | Oversized or branch-heavy Kotlin functions | Medium |
| `kotlin-dead-abstraction` | kotlin | Thin Kotlin pass-through functions | Low |
| `kotlin-todo-comment` | kotlin | TODO/FIXME/HACK comments in Kotlin files | Low |
| `kotlin-empty-catch` | kotlin | Empty or comment-only Kotlin catch blocks | Medium |
| `compose-large-composable` | compose | Oversized or branch-heavy Jetpack Compose functions | Medium |
| `compose-state-hoisting` | compose | Composables owning too many local state holders | Medium |

Expand Down Expand Up @@ -459,23 +473,23 @@ also declare their discovery metadata, so selecting `python`, `vue`, `svelte`, `

| Pack | Rules |
| --- | --- |
| `core` | framework-neutral maintainability rules: duplication, large functions, barrels, test boundaries, API surface, TODOs, naming drift |
| `core` | framework-neutral maintainability rules: duplication, large functions, barrels, test boundaries, API surface, TODOs, naming drift, silent failures, floating promises, and dead commented code |
| `react` | core + component, hook, provider, prop, and Storybook signals |
| `react-native` | react + RN host primitive forwarding |
| `next` | react + App Router boundary, route size, and data-loader checks |
| `node` | core + Express/Fastify handler depth and route sprawl |
| `python` | Python duplicate functions, large and branch-heavy functions, thin wrappers, and TODO comments |
| `python` | Python duplicate functions, large and branch-heavy functions, thin wrappers, TODO comments, and error-handling smells |
| `python-web` | python + Flask/Blueprint and Django URL route sprawl |
| `vue` | Vue SFC script TODO, large-script, and duplicate-logic signals |
| `svelte` | Svelte SFC script TODO, large-script, and duplicate-logic signals |
| `kotlin` | Kotlin duplicate functions, large functions, thin wrappers, and TODO comments |
| `kotlin` | Kotlin duplicate functions, large functions, thin wrappers, TODO comments, and empty catch blocks |
| `swift` | Swift duplicate functions, large functions, thin wrappers, and TODO comments |
| `ruby` | Ruby duplicate methods, large methods, thin wrappers, and TODO comments |
| `rails` | Ruby core rules plus Rails route and controller sprawl checks |
| `compose` | Jetpack Compose oversized composables and local state-hoisting smells |
| `swiftui` | SwiftUI oversized views and local state-sprawl checks |
| `expo` | React Native tuning for Expo Router projects |
| `ai-assisted-maintainer` | high-signal maintainability checks for assistant-heavy codebases; no authorship claims |
| `ai-assisted-maintainer` | high-signal maintainability checks for assistant-heavy codebases, including silent failures and commented-out code but excluding floating-promise; no authorship claims |
| `oss-maintainer` | library API surface, barrels, duplication, tests, and TODO debt |
| `ai-workflow-drift` | duplicated or contradictory AI assistant instruction files; no AI-authorship claims |

Expand Down
41 changes: 36 additions & 5 deletions docs/example-report.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# DebtLens Report

Scanned **3** files with **28** rules in **174ms**.
Scanned **3** files with **32** rules in **162ms**.

## Summary

- Total issues: **8**
- Total issues: **9**
- High: **2**
- Medium: **2**
- Medium: **3**
- Low: **4**
- Info: **0**

## Fix these first

| File | Why | Top rules |
| --- | --- | --- |
| `src/Dashboard.tsx` | 1 high-severity finding; 2 medium-severity findings; 5 distinct rules | dead-abstraction (3), effect-complexity (1), prop-drilling (1) |
| `src/Dashboard.tsx` | 1 high-severity finding; 3 medium-severity findings; 6 distinct rules | dead-abstraction (3), effect-complexity (1), floating-promise (1) |
| `src/duplicateOne.ts` | 1 high-severity finding; 1 duplicate cluster | duplicate-logic (1) |

## High severity
Expand All @@ -32,6 +32,8 @@ Evidence:

Suggestion: Consider colocating the data owner closer to consumers, using a composition slot, or extracting a focused context for stable cross-cutting values.

Review prompt: Can data ownership move closer to consumers via composition, context, or a colocated hook?

### Duplicate logic — `src/duplicateOne.ts:1`

normalizeMovieRelease is 100% structurally similar to normalizeGameRelease.
Expand All @@ -44,6 +46,8 @@ Evidence:

Suggestion: Compare the two implementations. Extract shared behavior only if the variation is intentional and stable; otherwise delete the weaker duplicate.

Review prompt: Are both copies intentional? If not, which copy should become canonical and what breaks if you merge them?


## Medium severity

Expand All @@ -58,6 +62,8 @@ Evidence:

Suggestion: Group related state in a reducer, extract state machines into a hook, or move server/cache state out of component state.

Review prompt: Which state variables change together? Could a reducer or domain hook replace independent useState calls?

### Effect complexity — `src/Dashboard.tsx:23`

This useEffect spans 26 lines, has 9 dependencies, 3 branches, and 14 nested calls.
Expand All @@ -72,6 +78,23 @@ Evidence:

Suggestion: Split unrelated effects, move imperative workflows into named functions, or replace derived state effects with memoized values.

Review prompt: Does this effect do one job? If not, what is the smallest split that preserves behavior?

### Floating promise — `src/Dashboard.tsx:47`

Promise work inside useEffect is not awaited or error-handled.

Confidence: **88%**

Evidence:
- Expression: load()
- Not awaited, returned, assigned, void-marked, or passed as an argument
- Inside React effect without cleanup or error handling
- Calls async function
- Type checker reports Promise<void>

Suggestion: Await the promise inside the effect, chain .catch(), or move async work into a named helper with explicit error handling.


## Low severity

Expand All @@ -86,6 +109,8 @@ Evidence:

Suggestion: Convert the marker into a tracked issue, add a removal condition, or fix it before more code depends on it.

Review prompt: Is there a tracked issue and removal condition? If not, create one or fix the debt now.

### Dead abstraction — `src/Dashboard.tsx:67`

ReleaseHero looks like a thin wrapper: it only forwards to a single JSX element.
Expand All @@ -97,6 +122,8 @@ Evidence:

Suggestion: Keep the wrapper only if it creates a stable domain boundary. Otherwise inline it or add the missing behavior where this abstraction belongs.

Review prompt: Does this wrapper enforce a boundary today? If not, inline it or add the missing behavior.

### Dead abstraction — `src/Dashboard.tsx:71`

ReleaseGrid looks like a thin wrapper: it only forwards to a single JSX element.
Expand All @@ -108,6 +135,8 @@ Evidence:

Suggestion: Keep the wrapper only if it creates a stable domain boundary. Otherwise inline it or add the missing behavior where this abstraction belongs.

Review prompt: Does this wrapper enforce a boundary today? If not, inline it or add the missing behavior.

### Dead abstraction — `src/Dashboard.tsx:75`

ReleaseFooter looks like a thin wrapper: it only forwards to a single JSX element.
Expand All @@ -119,12 +148,14 @@ Evidence:

Suggestion: Keep the wrapper only if it creates a stable domain boundary. Otherwise inline it or add the missing behavior where this abstraction belongs.

Review prompt: Does this wrapper enforce a boundary today? If not, inline it or add the missing behavior.


## Rule correlations

| File | Rules | Issues |
| --- | --- | ---: |
| `src/Dashboard.tsx` | dead-abstraction (3), effect-complexity (1), prop-drilling (1), state-sprawl (1), todo-comment (1) | 7 |
| `src/Dashboard.tsx` | dead-abstraction (3), effect-complexity (1), floating-promise (1), prop-drilling (1), state-sprawl (1), todo-comment (1) | 8 |

## Duplicate logic clusters

Expand Down
4 changes: 2 additions & 2 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ these commands when evaluating output, writing docs, or checking a reporter chan
| Next.js App Router | `debtlens scan examples/next --pack next --min-severity info` | Server/client boundary and route/data-loader rules. |
| React Native screen | `debtlens scan examples/react-native --pack react-native --min-severity info` | RN host-forwarding and React-family rules. |
| Node API | `debtlens scan examples/node-api --pack node --min-severity info` | Route and handler-depth signals for server code. |
| Python service | `debtlens scan examples/python --pack python --min-severity info` | Python duplicate, large-function, control-flow, thin-wrapper, and TODO rules. |
| Python service | `debtlens scan examples/python --pack python --min-severity info` | Python duplicate, large-function, control-flow, thin-wrapper, TODO, and error-handling rules. |
| Python web routes | `debtlens scan examples/python-web --pack python-web --min-severity info` | Flask/Blueprint route-sprawl signals plus core Python rules. |
| Vue SFC scripts | `debtlens scan examples/vue --pack vue --min-severity info` | Vue script TODO and duplicate-logic signals with `.vue` line mapping. |
| Svelte SFC scripts | `debtlens scan examples/svelte --pack svelte --min-severity info` | Svelte script TODO and duplicate-logic signals without React rules. |
| Kotlin service | `debtlens scan examples/kotlin --pack kotlin --min-severity info` | Kotlin duplicate, large-function, thin-wrapper, and TODO rules. |
| Kotlin service | `debtlens scan examples/kotlin --pack kotlin --min-severity info` | Kotlin duplicate, large-function, thin-wrapper, TODO, and empty-catch rules. |
| Swift service | `debtlens scan examples/swift --pack swift --min-severity info` | Swift duplicate, large-function, thin-wrapper, and TODO rules. |
| SwiftUI screen | `debtlens scan examples/swiftui --pack swiftui --min-severity info` | SwiftUI large-view and state-sprawl rules. |
| Ruby service | `debtlens scan examples/ruby --pack ruby --min-severity info` | Ruby duplicate, large-method, thin-wrapper, and TODO rules. |
Expand Down
2 changes: 2 additions & 0 deletions docs/language-pack-rfc.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ Current implementation:
nesting depth for review-heavy functions.
- `python-dead-abstraction` flags single-statement pass-through functions such as
`def f(x): return g(x)`.
- `python-error-handling` flags bare/empty except blocks and broad log-only handlers
while ignoring examples inside comments and strings.
- `--pack python` widens discovery to `.py` files. Use `--pack core,python` for one merged TS/JS + Python scan.

Possible future sidecar command:
Expand Down
Loading