@reidbuilds/slop 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +11 -0
- package/.firebaserc +5 -0
- package/README.md +73 -0
- package/cli/analyzer.js +150 -0
- package/cli/index.js +182 -0
- package/cli/learner.js +156 -0
- package/cli/reporter.js +126 -0
- package/cli/scanner.js +45 -0
- package/ff-slop.md +27 -0
- package/firebase.json +16 -0
- package/functions/index.js +30 -0
- package/functions/package-lock.json +2755 -0
- package/functions/package.json +12 -0
- package/hardcoresyn-slop.md +1887 -0
- package/package.json +17 -0
- package/slop-index/catches.jsonl +590 -0
- package/slop-index/patterns/001-hallucinated-imports.md +39 -0
- package/slop-index/patterns/002-comment-restatement.md +53 -0
- package/slop-index/patterns/003-unnecessary-abstraction.md +56 -0
- package/slop-index/patterns/004-unused-imports.md +41 -0
- package/slop-index/patterns/005-hardcoded-config.md +49 -0
- package/slop-index/patterns/006-deprecated-api-confidence.md +52 -0
- package/slop-index/patterns/007-try-catch-everything.md +63 -0
- package/slop-index/patterns/008-generic-variable-names.md +49 -0
- package/slop-index/patterns/009-stub-with-shell.md +61 -0
- package/slop-index/patterns/010-async-misuse.md +64 -0
- package/slop-index/patterns/011-console-log-left-in.md +53 -0
- package/slop-index/patterns/012-over-engineered-simple.md +64 -0
- package/slop-index/patterns/013-emoji-debugging.md +44 -0
- package/slop-index/patterns/014-fake-async-simulation.md +71 -0
- package/slop-index/patterns/015-credential-fallbacks.md +51 -0
- package/slop-index/patterns/016-mock-data-pollution.md +75 -0
- package/slop-index/proposed/.gitkeep +0 -0
- package/slop-index/proposed/017-emoji-progress-logging.md +44 -0
- package/slop-index/proposed/018-test-credentials-in-fallbacks.md +54 -0
- package/slop-index/proposed/019-fake-loading-simulation.md +75 -0
- package/slop-index/proposed/020-configuration-debugging-left-in.md +53 -0
- package/slop-index/proposed/021-emoji-production-logging.md +42 -0
- package/slop-index/proposed/022-fake-delay-simulation.md +70 -0
- package/slop-index/proposed/023-credential-hardcoding-with-fallbacks.md +57 -0
- package/slop-index/proposed/024-repetitive-error-pattern.md +76 -0
- package/slop-index/proposed/025-environment-specific-fallbacks.md +55 -0
- package/slop-index/proposed/026-emoji-production-logs.md +46 -0
- package/slop-index/proposed/027-credentials-in-debug-logs.md +48 -0
- package/slop-index/proposed/028-repetitive-service-wrappers.md +59 -0
- package/slop-index/proposed/029-forced-non-null-assertions.md +59 -0
- package/slop-index/proposed/030-production-credential-fallbacks.md +51 -0
- package/slop-index/proposed/031-fake-version-confidence.md +50 -0
- package/slop-index/proposed/032-forced-non-null-assertions.md +53 -0
- package/slop-index/proposed/033-emoji-production-logs.md +44 -0
- package/slop-index/proposed/034-realistic-mock-data-leakage.md +62 -0
- package/slop-index/proposed/035-production-credential-exposure.md +43 -0
- package/slop-index/proposed/036-identical-wrapper-proliferation.md +53 -0
- package/slop-index/proposed/037-forced-null-assertions.md +50 -0
- package/slop-index/proposed/038-emoji-production-logging.md +42 -0
- package/slop-index/proposed/039-fake-delay-operations.md +52 -0
- package/slop-index/proposed/040-forced-null-assertion-chains.md +45 -0
- package/slop-index/proposed/041-production-debug-configuration.md +45 -0
- package/slop-index/proposed/042-repetitive-firebase-wrappers.md +51 -0
- package/slop-index/proposed/043-hardcoded-process-timeouts.md +48 -0
- package/slop-index/proposed/044-fictional-package-versions.md +37 -0
- package/test-sample.js +89 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 001
|
|
3
|
+
name: hallucinated-imports
|
|
4
|
+
severity: high
|
|
5
|
+
languages: [javascript, typescript, python]
|
|
6
|
+
tags: [imports, runtime-error]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Hallucinated Imports
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
AI generates import statements for packages or named exports that do not exist, using names that plausibly sound like they should.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
import { useAsyncCallback } from 'react-use-async'
|
|
18
|
+
import { formatCurrency } from 'lodash'
|
|
19
|
+
from utils import smart_retry
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Why AI Does This
|
|
23
|
+
Training data contains thousands of similar-looking import patterns. The model autocompletes the most statistically likely package name without verifying it exists or that the named export is part of that package's actual API surface.
|
|
24
|
+
|
|
25
|
+
## Catch Signal
|
|
26
|
+
- Package name almost-matches a real one with subtle differences
|
|
27
|
+
- Named export doesn't appear in the package's documented API
|
|
28
|
+
- Package exists but the specific export was removed in a major version
|
|
29
|
+
- Utility functions imported from general-purpose libraries that don't include them (e.g. `formatCurrency` from lodash)
|
|
30
|
+
|
|
31
|
+
## Fix Template
|
|
32
|
+
```js
|
|
33
|
+
// Verify on npm before trusting. Replace with:
|
|
34
|
+
import { useAsync } from 'react-async' // verified equivalent
|
|
35
|
+
// OR remove and use built-in alternatives
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Severity Rationale
|
|
39
|
+
High — fails immediately at runtime with a module not found or undefined export error. No graceful degradation.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 002
|
|
3
|
+
name: comment-restatement
|
|
4
|
+
severity: low
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [readability, comments]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Comment Restatement
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Comments that simply translate the code into English, adding no context, intent, or reasoning that isn't already obvious from reading the code itself.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
// Loop through users
|
|
18
|
+
for (const user of users) {
|
|
19
|
+
// Check if user is active
|
|
20
|
+
if (user.isActive) {
|
|
21
|
+
// Add user to result array
|
|
22
|
+
result.push(user)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Return the result
|
|
27
|
+
return result
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Why AI Does This
|
|
31
|
+
AI is trained to produce "well-commented" code. Without understanding what constitutes a useful comment, it defaults to narrating every line — which satisfies the surface pattern of commented code without providing actual value.
|
|
32
|
+
|
|
33
|
+
## Catch Signal
|
|
34
|
+
- Comment is a direct English translation of the line(s) below it
|
|
35
|
+
- Comment contains no information about WHY, only WHAT
|
|
36
|
+
- Removing the comment would lose zero information for any developer who can read the language
|
|
37
|
+
- Phrases like "// Check if", "// Loop through", "// Return the", "// Set the"
|
|
38
|
+
|
|
39
|
+
## Fix Template
|
|
40
|
+
```js
|
|
41
|
+
// Comments should explain intent, not mechanics:
|
|
42
|
+
|
|
43
|
+
// Exclude suspended accounts from billing cycle
|
|
44
|
+
for (const user of users) {
|
|
45
|
+
if (user.isActive) {
|
|
46
|
+
result.push(user)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Severity Rationale
|
|
53
|
+
Low — doesn't break anything but adds noise, signals AI generation, and trains junior devs to write bad comments.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 003
|
|
3
|
+
name: unnecessary-abstraction
|
|
4
|
+
severity: medium
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [architecture, readability, over-engineering]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Unnecessary Abstraction
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
AI wraps simple, single-use logic in helper functions, classes, or utilities that will never be reused and add indirection without reducing complexity.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
// AI creates this helper...
|
|
18
|
+
function addItemToArray(array, item) {
|
|
19
|
+
array.push(item)
|
|
20
|
+
return array
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ...to use it exactly once
|
|
24
|
+
addItemToArray(results, newUser)
|
|
25
|
+
|
|
26
|
+
// Or wraps a one-liner fetch in an unnecessary class
|
|
27
|
+
class ApiClient {
|
|
28
|
+
constructor(baseUrl) { this.baseUrl = baseUrl }
|
|
29
|
+
async get(endpoint) {
|
|
30
|
+
return fetch(`${this.baseUrl}${endpoint}`).then(r => r.json())
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Why AI Does This
|
|
36
|
+
Training data rewards patterns that look "architecturally mature." Abstracting logic into named helpers and classes is a strong signal of professional code, so the model applies it indiscriminately regardless of whether the abstraction carries weight.
|
|
37
|
+
|
|
38
|
+
## Catch Signal
|
|
39
|
+
- Helper function used exactly once
|
|
40
|
+
- Function body is one or two lines that could inline trivially
|
|
41
|
+
- Class with a single method and no state
|
|
42
|
+
- Abstraction that doesn't reduce parameters, complexity, or repetition
|
|
43
|
+
- Function name is generic rather than domain-specific (`handleData`, `processItem`, `doOperation`)
|
|
44
|
+
|
|
45
|
+
## Fix Template
|
|
46
|
+
```js
|
|
47
|
+
// Before (unnecessary abstraction):
|
|
48
|
+
function addItemToArray(array, item) { return [...array, item] }
|
|
49
|
+
const results = addItemToArray(results, newUser)
|
|
50
|
+
|
|
51
|
+
// After (just write it):
|
|
52
|
+
results.push(newUser)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Severity Rationale
|
|
56
|
+
Medium — doesn't break at runtime but actively degrades maintainability. Future developers chase function definitions expecting complexity they won't find.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 004
|
|
3
|
+
name: unused-imports
|
|
4
|
+
severity: low
|
|
5
|
+
languages: [javascript, typescript, python]
|
|
6
|
+
tags: [imports, readability, bundle-size]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Unused Imports
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Import statements for modules, functions, or types that are never referenced in the file body. Often leftovers from a generation that pivoted mid-way.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react'
|
|
18
|
+
import { formatDate, formatCurrency, formatPhone } from './utils'
|
|
19
|
+
import axios from 'axios'
|
|
20
|
+
|
|
21
|
+
// File only uses useState and formatDate. Everything else is dead weight.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Why AI Does This
|
|
25
|
+
When generating code, the model front-loads imports based on what it anticipates using. When the implementation diverges from the plan, the unused imports remain. The model doesn't backtrack to clean up.
|
|
26
|
+
|
|
27
|
+
## Catch Signal
|
|
28
|
+
- Imported name never appears after the import block
|
|
29
|
+
- Destructured imports where only some members are used
|
|
30
|
+
- Type imports that are never referenced in type annotations
|
|
31
|
+
- Multiple utility imports where only one is used
|
|
32
|
+
|
|
33
|
+
## Fix Template
|
|
34
|
+
```js
|
|
35
|
+
// Only import what you use
|
|
36
|
+
import { useState } from 'react'
|
|
37
|
+
import { formatDate } from './utils'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Severity Rationale
|
|
41
|
+
Low in small projects. Medium in large apps — unused imports increase bundle size, slow tree-shaking analysis, and are a reliable signal of unreviewed AI output.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 005
|
|
3
|
+
name: hardcoded-config
|
|
4
|
+
severity: high
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [security, config, environment]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Hardcoded Config
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Configuration values, credentials, URLs, limits, or environment-specific constants embedded directly in source code instead of environment variables or config files.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
const API_URL = 'https://api.myapp.com/v1'
|
|
18
|
+
const MAX_RETRIES = 3
|
|
19
|
+
const DB_HOST = 'prod-db.internal.myapp.com'
|
|
20
|
+
const SECRET_KEY = 'sk_live_abc123xyz'
|
|
21
|
+
|
|
22
|
+
fetch('https://api.stripe.com/v1/charges', {
|
|
23
|
+
headers: { Authorization: 'Bearer sk_live_abc123xyz' }
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Why AI Does This
|
|
28
|
+
The model needs concrete values to make the code syntactically complete and runnable-looking. Placeholder values feel incomplete, so it fills them with plausible-looking real values. It doesn't model the operational risk of those values landing in version control.
|
|
29
|
+
|
|
30
|
+
## Catch Signal
|
|
31
|
+
- URL strings with real-looking domain names hardcoded inline
|
|
32
|
+
- Numeric thresholds (retries, timeouts, limits) with no explanation or config reference
|
|
33
|
+
- Any string that looks like an API key, token, password, or secret
|
|
34
|
+
- Environment-specific hostnames (prod-, staging-, db., api.) in source
|
|
35
|
+
- Magic numbers used more than once without being named constants
|
|
36
|
+
|
|
37
|
+
## Fix Template
|
|
38
|
+
```js
|
|
39
|
+
// Move to environment variables
|
|
40
|
+
const API_URL = process.env.API_URL
|
|
41
|
+
const MAX_RETRIES = parseInt(process.env.MAX_RETRIES ?? '3')
|
|
42
|
+
const SECRET_KEY = process.env.STRIPE_SECRET_KEY
|
|
43
|
+
|
|
44
|
+
// Or a config module that reads from env
|
|
45
|
+
import { config } from './config'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Severity Rationale
|
|
49
|
+
High — secrets in source code leak via git history, logs, and error messages. Even non-secret config hardcoding creates deployment fragility and environment coupling.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 006
|
|
3
|
+
name: deprecated-api-confidence
|
|
4
|
+
severity: high
|
|
5
|
+
languages: [javascript, typescript, python]
|
|
6
|
+
tags: [runtime-error, versioning, dependencies]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Deprecated API Confidence
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
AI uses deprecated, removed, or version-specific APIs with full syntactic confidence, as if they are current best practice.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
// React — class components and old lifecycle methods
|
|
18
|
+
componentWillMount() { }
|
|
19
|
+
componentWillReceiveProps(nextProps) { }
|
|
20
|
+
|
|
21
|
+
// Node.js — removed APIs
|
|
22
|
+
const { parse } = require('url')
|
|
23
|
+
require('sys').puts('hello')
|
|
24
|
+
|
|
25
|
+
// Express — removed in v5
|
|
26
|
+
app.del('/route', handler)
|
|
27
|
+
|
|
28
|
+
// Python requests — old patterns
|
|
29
|
+
requests.get(url, verify=False) // used as if safe
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Why AI Does This
|
|
33
|
+
Training data contains massive amounts of older code. Deprecated APIs are statistically overrepresented because they existed for longer. The model has no reliable signal for "this was correct in 2019 but not now."
|
|
34
|
+
|
|
35
|
+
## Catch Signal
|
|
36
|
+
- Lifecycle methods prefixed with `componentWill` in React
|
|
37
|
+
- `require()` for modules moved to core or removed in modern Node
|
|
38
|
+
- Framework methods that have documented replacements in current major versions
|
|
39
|
+
- Python 2-style patterns appearing in Python 3 code
|
|
40
|
+
- Any method call that produces a runtime deprecation warning when executed
|
|
41
|
+
|
|
42
|
+
## Fix Template
|
|
43
|
+
```js
|
|
44
|
+
// Instead of componentWillMount:
|
|
45
|
+
useEffect(() => { /* setup */ }, [])
|
|
46
|
+
|
|
47
|
+
// Instead of app.del (Express v5+):
|
|
48
|
+
app.delete('/route', handler)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Severity Rationale
|
|
52
|
+
High — deprecated APIs often still work in current versions but break on the next major upgrade. Removed APIs fail immediately. Both create maintenance debt that compounds.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 007
|
|
3
|
+
name: try-catch-everything
|
|
4
|
+
severity: medium
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [error-handling, architecture]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Try-Catch Everything
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Blanket try/catch blocks wrapped around entire function bodies with generic error handling, silencing specific errors that should propagate or be handled distinctly.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
async function processOrder(orderId) {
|
|
18
|
+
try {
|
|
19
|
+
const order = await getOrder(orderId)
|
|
20
|
+
const inventory = await checkInventory(order.items)
|
|
21
|
+
const payment = await chargeCard(order.paymentMethod)
|
|
22
|
+
await fulfillOrder(order, inventory)
|
|
23
|
+
await sendConfirmationEmail(order)
|
|
24
|
+
return { success: true }
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Something went wrong:', error)
|
|
27
|
+
return { success: false }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Why AI Does This
|
|
33
|
+
Error handling is a strong signal of "production-ready" code. The model wraps everything in try/catch to satisfy that pattern without reasoning about which errors are recoverable, which should propagate, and which need distinct handling.
|
|
34
|
+
|
|
35
|
+
## Catch Signal
|
|
36
|
+
- Single try/catch wrapping 5+ distinct async operations
|
|
37
|
+
- Catch block that only logs and returns a generic failure
|
|
38
|
+
- No differentiation between network errors, validation errors, and business logic errors
|
|
39
|
+
- Errors swallowed with `console.error` and no rethrow or structured response
|
|
40
|
+
- `catch (e) {}` — empty catch that silences everything
|
|
41
|
+
|
|
42
|
+
## Fix Template
|
|
43
|
+
```js
|
|
44
|
+
async function processOrder(orderId) {
|
|
45
|
+
const order = await getOrder(orderId) // let not-found propagate
|
|
46
|
+
const inventory = await checkInventory(order.items)
|
|
47
|
+
|
|
48
|
+
let payment
|
|
49
|
+
try {
|
|
50
|
+
payment = await chargeCard(order.paymentMethod)
|
|
51
|
+
} catch (err) {
|
|
52
|
+
if (err.code === 'card_declined') return { success: false, reason: 'payment_failed' }
|
|
53
|
+
throw err // unexpected errors propagate
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await fulfillOrder(order, inventory)
|
|
57
|
+
await sendConfirmationEmail(order).catch(() => {}) // email failure is non-critical
|
|
58
|
+
return { success: true }
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Severity Rationale
|
|
63
|
+
Medium — doesn't break immediately but masks bugs, makes debugging extremely difficult, and creates silent failure modes that are hard to detect in production.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 008
|
|
3
|
+
name: generic-variable-names
|
|
4
|
+
severity: low
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [readability, maintainability]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Generic Variable Names
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Variables named with generic, context-free identifiers in non-trivial code where domain-specific names would communicate intent.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
const data = await fetchUserOrders(userId)
|
|
18
|
+
const result = data.filter(item => item.status === 'pending')
|
|
19
|
+
const temp = result.map(item => ({ ...item, flagged: true }))
|
|
20
|
+
const final = await Promise.all(temp.map(item => updateOrder(item)))
|
|
21
|
+
|
|
22
|
+
// Or in a function:
|
|
23
|
+
function process(input) {
|
|
24
|
+
const obj = transform(input)
|
|
25
|
+
const val = calculate(obj)
|
|
26
|
+
return val
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Why AI Does This
|
|
31
|
+
Generic names (`data`, `result`, `temp`, `item`, `obj`, `val`) are maximally reusable in training data. The model defaults to these because they statistically appear next to nearly every operation, making them high-probability completions.
|
|
32
|
+
|
|
33
|
+
## Catch Signal
|
|
34
|
+
- Variables named: `data`, `result`, `temp`, `final`, `obj`, `val`, `info`, `thing`, `output`, `input` in non-trivial contexts
|
|
35
|
+
- Loop variables named `item` when iterating over a typed collection
|
|
36
|
+
- Function parameters named `input`, `param`, `arg` with no type annotation to compensate
|
|
37
|
+
- Multiple generic names in the same function making it impossible to track which is which
|
|
38
|
+
|
|
39
|
+
## Fix Template
|
|
40
|
+
```js
|
|
41
|
+
// Name for what it IS, not what it does generically:
|
|
42
|
+
const pendingOrders = await fetchUserOrders(userId)
|
|
43
|
+
const unfulfilled = pendingOrders.filter(order => order.status === 'pending')
|
|
44
|
+
const flaggedForReview = unfulfilled.map(order => ({ ...order, flagged: true }))
|
|
45
|
+
const updateResults = await Promise.all(flaggedForReview.map(order => updateOrder(order)))
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Severity Rationale
|
|
49
|
+
Low individually. Medium when compounded — a function with five generic variable names is actively hostile to debugging and code review.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 009
|
|
3
|
+
name: stub-with-shell
|
|
4
|
+
severity: high
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [completeness, runtime-error]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Stub With Shell
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Functions where the outer structure (signature, error handling, return shape) is fully implemented but the core business logic is a placeholder, stub, or TODO.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
async function calculateShippingRate(order, destination) {
|
|
18
|
+
try {
|
|
19
|
+
// TODO: implement actual shipping calculation
|
|
20
|
+
const rate = 0
|
|
21
|
+
return {
|
|
22
|
+
success: true,
|
|
23
|
+
rate,
|
|
24
|
+
estimatedDays: 5
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
return { success: false, error: error.message }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Or more subtle:
|
|
32
|
+
function validateCreditCard(cardNumber) {
|
|
33
|
+
// Basic validation
|
|
34
|
+
if (!cardNumber) return false
|
|
35
|
+
return true // Always returns true — no actual validation
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Why AI Does This
|
|
40
|
+
The model is trained to produce structurally complete code. It can generate the scaffolding (signature, error handling, return type) from context, but the business logic requires domain knowledge the model doesn't have. Rather than omitting the function, it ships a shell that looks complete.
|
|
41
|
+
|
|
42
|
+
## Catch Signal
|
|
43
|
+
- `// TODO:` or `// FIXME:` inside otherwise complete-looking functions
|
|
44
|
+
- Return values that are hardcoded zeros, empty arrays, or empty strings where real computation is expected
|
|
45
|
+
- Functions that always return `true` or `null` regardless of input
|
|
46
|
+
- Suspiciously short function bodies for complex-sounding function names
|
|
47
|
+
- `throw new Error('Not implemented')` inside a function that the rest of the code calls as if it works
|
|
48
|
+
|
|
49
|
+
## Fix Template
|
|
50
|
+
```js
|
|
51
|
+
// Option 1: Make the stub explicit at the call site
|
|
52
|
+
// Option 2: Throw immediately so it fails loudly
|
|
53
|
+
function calculateShippingRate(order, destination) {
|
|
54
|
+
throw new Error('calculateShippingRate: not yet implemented — see issue #42')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Option 3: Implement it properly
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Severity Rationale
|
|
61
|
+
High — stub functions compile and pass static analysis. They fail silently in production, returning wrong values that propagate through the system before anyone notices.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 010
|
|
3
|
+
name: async-misuse
|
|
4
|
+
severity: high
|
|
5
|
+
languages: [javascript, typescript, python]
|
|
6
|
+
tags: [async, runtime-error, performance]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Async Misuse
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Incorrect application of async/await — either bolted onto synchronous operations, creating unnecessary promise chains, or used incorrectly in ways that break execution order.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
// async on a synchronous function for no reason
|
|
18
|
+
async function formatName(first, last) {
|
|
19
|
+
return `${first} ${last}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// await on a non-promise
|
|
23
|
+
const name = await formatName('John', 'Doe')
|
|
24
|
+
|
|
25
|
+
// Sequential awaits that should be parallel
|
|
26
|
+
async function loadDashboard(userId) {
|
|
27
|
+
const user = await getUser(userId)
|
|
28
|
+
const orders = await getOrders(userId) // these don't depend on each other
|
|
29
|
+
const notifications = await getNotifications(userId) // but run sequentially
|
|
30
|
+
return { user, orders, notifications }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Missing await causing unhandled promise
|
|
34
|
+
function saveUser(user) {
|
|
35
|
+
db.save(user) // returns a promise, no await, no .catch
|
|
36
|
+
return { success: true } // lies
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Why AI Does This
|
|
41
|
+
async/await is statistically associated with "modern, correct" JavaScript in training data. The model applies it broadly as a quality signal without modeling the actual execution semantics of the event loop.
|
|
42
|
+
|
|
43
|
+
## Catch Signal
|
|
44
|
+
- `async` functions whose entire body contains no `await`
|
|
45
|
+
- `await` called on functions that don't return promises
|
|
46
|
+
- Sequential `await` chains where operations are independent (missing `Promise.all`)
|
|
47
|
+
- Promise-returning functions called without `await` or `.then()` in contexts where the result matters
|
|
48
|
+
- `async` in array callbacks where it creates unhandled promises (`arr.forEach(async () => {})`)
|
|
49
|
+
|
|
50
|
+
## Fix Template
|
|
51
|
+
```js
|
|
52
|
+
// Parallel independent async operations:
|
|
53
|
+
async function loadDashboard(userId) {
|
|
54
|
+
const [user, orders, notifications] = await Promise.all([
|
|
55
|
+
getUser(userId),
|
|
56
|
+
getOrders(userId),
|
|
57
|
+
getNotifications(userId)
|
|
58
|
+
])
|
|
59
|
+
return { user, orders, notifications }
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Severity Rationale
|
|
64
|
+
High — async misuse causes race conditions, silent failures, and performance problems that are extremely difficult to debug because they're non-deterministic.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 011
|
|
3
|
+
name: console-log-left-in
|
|
4
|
+
severity: medium
|
|
5
|
+
languages: [javascript, typescript]
|
|
6
|
+
tags: [debugging, security, readability]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Console Log Left In
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Debug console.log statements left in production code, often logging sensitive data, internal state, or development-only context.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
async function authenticateUser(email, password) {
|
|
18
|
+
console.log('Authenticating user:', email, password) // logs credentials
|
|
19
|
+
const user = await findUser(email)
|
|
20
|
+
console.log('Found user:', user) // logs full user object including hashed password
|
|
21
|
+
const valid = await bcrypt.compare(password, user.passwordHash)
|
|
22
|
+
console.log('Password valid:', valid)
|
|
23
|
+
return valid ? generateToken(user) : null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Or the carpet-bomb approach:
|
|
27
|
+
console.log('data:', data)
|
|
28
|
+
console.log('result:', result)
|
|
29
|
+
console.log('here')
|
|
30
|
+
console.log('HERE')
|
|
31
|
+
console.log('===========')
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Why AI Does This
|
|
35
|
+
AI adds console.log statements during code generation as scaffolding — the same way a human would when building something locally. It doesn't model the concept of "this code will run in production" vs "this is debug scaffolding."
|
|
36
|
+
|
|
37
|
+
## Catch Signal
|
|
38
|
+
- `console.log` statements in non-error paths of production functions
|
|
39
|
+
- Any `console.log` that logs a variable containing `password`, `token`, `secret`, `key`, `auth`
|
|
40
|
+
- Multiple consecutive `console.log` calls suggesting a debugging session
|
|
41
|
+
- `console.log('here')` or similar navigation logs
|
|
42
|
+
- `console.log` inside loops (performance issue at scale)
|
|
43
|
+
|
|
44
|
+
## Fix Template
|
|
45
|
+
```js
|
|
46
|
+
// Remove debug logs. For intentional logging use a logger:
|
|
47
|
+
import { logger } from './logger'
|
|
48
|
+
logger.info('User authentication attempted', { email }) // never log passwords
|
|
49
|
+
logger.debug('Auth result', { success: valid }) // filtered in production
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Severity Rationale
|
|
53
|
+
Medium-to-high when sensitive data is involved (credentials, tokens, PII). Medium otherwise — leaks implementation details, clutters production logs, and creates noise that obscures real errors.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: 012
|
|
3
|
+
name: over-engineered-simple
|
|
4
|
+
severity: medium
|
|
5
|
+
languages: [all]
|
|
6
|
+
tags: [architecture, readability, over-engineering]
|
|
7
|
+
added: 2024-01-01
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pattern: Over-Engineered Simple
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Applying enterprise-scale architectural patterns (factories, registries, strategy pattern, dependency injection) to problems that could be solved with a function or a plain object.
|
|
14
|
+
|
|
15
|
+
## What It Looks Like
|
|
16
|
+
```js
|
|
17
|
+
// Needed: format a date
|
|
18
|
+
// AI produces: a formatting framework
|
|
19
|
+
|
|
20
|
+
class FormatterRegistry {
|
|
21
|
+
constructor() { this.formatters = new Map() }
|
|
22
|
+
register(name, formatter) { this.formatters.set(name, formatter) }
|
|
23
|
+
get(name) { return this.formatters.get(name) }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class DateFormatter {
|
|
27
|
+
constructor(locale) { this.locale = locale }
|
|
28
|
+
format(date) { return new Intl.DateTimeFormat(this.locale).format(date) }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const registry = new FormatterRegistry()
|
|
32
|
+
registry.register('date', new DateFormatter('en-US'))
|
|
33
|
+
const formatted = registry.get('date').format(new Date())
|
|
34
|
+
|
|
35
|
+
// Should have been:
|
|
36
|
+
const formatted = new Intl.DateTimeFormat('en-US').format(new Date())
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Why AI Does This
|
|
40
|
+
Enterprise patterns score highly in training data as signals of "good architecture." The model applies them as quality indicators without evaluating whether the problem warrants the complexity. More layers = more "professional" in the training signal.
|
|
41
|
+
|
|
42
|
+
## Catch Signal
|
|
43
|
+
- Factory or registry pattern for a fixed set of 2-3 things that never changes
|
|
44
|
+
- Strategy pattern where there's only one strategy
|
|
45
|
+
- Dependency injection into a function that's called from one place
|
|
46
|
+
- Abstract base class with a single concrete implementation
|
|
47
|
+
- Configuration objects for functions with one or two settings
|
|
48
|
+
- Interface/type definitions for objects used exactly once
|
|
49
|
+
|
|
50
|
+
## Fix Template
|
|
51
|
+
```js
|
|
52
|
+
// Match the solution scale to the problem scale.
|
|
53
|
+
// If it's used once and never changes, inline it.
|
|
54
|
+
// If it has 2-3 variants, use a plain object or switch.
|
|
55
|
+
// Reach for patterns only when the problem actually has the shape they solve.
|
|
56
|
+
|
|
57
|
+
const formatters = {
|
|
58
|
+
date: (d) => new Intl.DateTimeFormat('en-US').format(d),
|
|
59
|
+
currency: (n) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(n)
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Severity Rationale
|
|
64
|
+
Medium — doesn't break at runtime but creates a maintenance burden where future developers must understand unnecessary abstraction layers before making simple changes.
|