slopbrick 0.18.4 → 0.18.7
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/dist/engine/worker.cjs +981 -12
- package/dist/engine/worker.js +981 -12
- package/dist/index.cjs +1160 -84
- package/dist/index.d.cts +611 -511
- package/dist/index.d.ts +611 -511
- package/dist/index.js +1159 -83
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,15 +14,41 @@ var __export = (target, all) => {
|
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
// src/types.ts
|
|
18
|
-
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
// src/types/_header.ts
|
|
18
|
+
var VERSION;
|
|
19
|
+
var init_header = __esm({
|
|
20
|
+
"src/types/_header.ts"() {
|
|
21
|
+
"use strict";
|
|
22
|
+
VERSION = "0.18.7";
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// src/types/primitives.ts
|
|
27
|
+
var init_primitives = __esm({
|
|
28
|
+
"src/types/primitives.ts"() {
|
|
29
|
+
"use strict";
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// src/types/scan.ts
|
|
34
|
+
var init_scan = __esm({
|
|
35
|
+
"src/types/scan.ts"() {
|
|
36
|
+
"use strict";
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// src/types/config.ts
|
|
41
|
+
var init_config = __esm({
|
|
42
|
+
"src/types/config.ts"() {
|
|
43
|
+
"use strict";
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// src/types/report.ts
|
|
48
|
+
var AI_SECURITY_NUMERIC, REPOSITORY_HEALTH_WEIGHTS;
|
|
49
|
+
var init_report = __esm({
|
|
50
|
+
"src/types/report.ts"() {
|
|
22
51
|
"use strict";
|
|
23
|
-
require2 = createRequire(import.meta.url);
|
|
24
|
-
pkg = require2("../package.json");
|
|
25
|
-
VERSION = pkg.version;
|
|
26
52
|
AI_SECURITY_NUMERIC = {
|
|
27
53
|
low: 100,
|
|
28
54
|
medium: 75,
|
|
@@ -42,6 +68,34 @@ var init_types = __esm({
|
|
|
42
68
|
}
|
|
43
69
|
});
|
|
44
70
|
|
|
71
|
+
// src/types/project-report.ts
|
|
72
|
+
var init_project_report = __esm({
|
|
73
|
+
"src/types/project-report.ts"() {
|
|
74
|
+
"use strict";
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// src/types/baseline.ts
|
|
79
|
+
var init_baseline = __esm({
|
|
80
|
+
"src/types/baseline.ts"() {
|
|
81
|
+
"use strict";
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// src/types/index.ts
|
|
86
|
+
var init_types = __esm({
|
|
87
|
+
"src/types/index.ts"() {
|
|
88
|
+
"use strict";
|
|
89
|
+
init_header();
|
|
90
|
+
init_primitives();
|
|
91
|
+
init_scan();
|
|
92
|
+
init_config();
|
|
93
|
+
init_report();
|
|
94
|
+
init_project_report();
|
|
95
|
+
init_baseline();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
45
99
|
// src/config/defaults.ts
|
|
46
100
|
var DEFAULT_SPACING_SCALE, DEFAULT_RADIUS_SCALE, DEFAULT_RULE_CONFIG, DEFAULT_CONFIG;
|
|
47
101
|
var init_defaults = __esm({
|
|
@@ -295,9 +349,9 @@ function findWorkspacePackages(cwd) {
|
|
|
295
349
|
const pkgPath = join(root, "package.json");
|
|
296
350
|
if (existsSync(pkgPath)) {
|
|
297
351
|
try {
|
|
298
|
-
const
|
|
299
|
-
if (Array.isArray(
|
|
300
|
-
for (const pattern of
|
|
352
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
353
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
354
|
+
for (const pattern of pkg.workspaces) {
|
|
301
355
|
packages.push(...expandWorkspacePattern(root, pattern));
|
|
302
356
|
}
|
|
303
357
|
}
|
|
@@ -355,11 +409,11 @@ function detectStylingSolution(cwd) {
|
|
|
355
409
|
let deps = {};
|
|
356
410
|
if (existsSync2(pkgPath)) {
|
|
357
411
|
try {
|
|
358
|
-
const
|
|
412
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
359
413
|
deps = {
|
|
360
|
-
...
|
|
361
|
-
...
|
|
362
|
-
...
|
|
414
|
+
...pkg.dependencies,
|
|
415
|
+
...pkg.devDependencies,
|
|
416
|
+
...pkg.peerDependencies
|
|
363
417
|
};
|
|
364
418
|
} catch {
|
|
365
419
|
}
|
|
@@ -558,11 +612,11 @@ function detectStack(cwd) {
|
|
|
558
612
|
return {};
|
|
559
613
|
}
|
|
560
614
|
try {
|
|
561
|
-
const
|
|
615
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
562
616
|
const deps = {
|
|
563
|
-
...
|
|
564
|
-
...
|
|
565
|
-
...
|
|
617
|
+
...pkg.dependencies,
|
|
618
|
+
...pkg.devDependencies,
|
|
619
|
+
...pkg.peerDependencies
|
|
566
620
|
};
|
|
567
621
|
const names = Object.keys(deps).map((name) => name.toLowerCase());
|
|
568
622
|
const result = {};
|
|
@@ -26195,13 +26249,13 @@ var init_default_react_stack = __esm({
|
|
|
26195
26249
|
for (const m of source.matchAll(IMPORT_LINE_RE)) {
|
|
26196
26250
|
const spec = m[1];
|
|
26197
26251
|
if (!spec) continue;
|
|
26198
|
-
const
|
|
26199
|
-
if (
|
|
26252
|
+
const pkg = spec.startsWith("@/") ? spec : spec.startsWith("@") ? spec.split("/").slice(0, 2).join("/") : spec.split("/")[0];
|
|
26253
|
+
if (pkg) importedPackages.add(pkg);
|
|
26200
26254
|
}
|
|
26201
26255
|
const hits = [];
|
|
26202
|
-
for (const
|
|
26203
|
-
if (DEFAULT_STACK_PACKAGES.some((p) => p ===
|
|
26204
|
-
hits.push(
|
|
26256
|
+
for (const pkg of importedPackages) {
|
|
26257
|
+
if (DEFAULT_STACK_PACKAGES.some((p) => p === pkg || p.startsWith(pkg + "/"))) {
|
|
26258
|
+
hits.push(pkg);
|
|
26205
26259
|
}
|
|
26206
26260
|
}
|
|
26207
26261
|
if (hits.length < MIN_HITS) return [];
|
|
@@ -28091,6 +28145,205 @@ var init_sql_concat = __esm({
|
|
|
28091
28145
|
}
|
|
28092
28146
|
});
|
|
28093
28147
|
|
|
28148
|
+
// src/rules/dead/dead-branch.ts
|
|
28149
|
+
var deadBranchRule;
|
|
28150
|
+
var init_dead_branch = __esm({
|
|
28151
|
+
"src/rules/dead/dead-branch.ts"() {
|
|
28152
|
+
"use strict";
|
|
28153
|
+
init_rule();
|
|
28154
|
+
deadBranchRule = createRule({
|
|
28155
|
+
id: "dead/dead-branch",
|
|
28156
|
+
category: "logic",
|
|
28157
|
+
severity: "medium",
|
|
28158
|
+
aiSpecific: true,
|
|
28159
|
+
description: "Literal boolean condition makes one branch statically dead",
|
|
28160
|
+
create(_context) {
|
|
28161
|
+
return {};
|
|
28162
|
+
},
|
|
28163
|
+
analyze(_context, facts) {
|
|
28164
|
+
const issues = [];
|
|
28165
|
+
if (!facts.v2) return issues;
|
|
28166
|
+
for (const cond of facts.v2.deadCode.constantConditions) {
|
|
28167
|
+
const isWhileTrue = cond.kind === "while-true";
|
|
28168
|
+
issues.push({
|
|
28169
|
+
ruleId: "dead/dead-branch",
|
|
28170
|
+
category: "logic",
|
|
28171
|
+
severity: isWhileTrue ? "low" : "medium",
|
|
28172
|
+
aiSpecific: true,
|
|
28173
|
+
message: isWhileTrue ? `Infinite loop with literal condition (${cond.kind})` : `Dead branch: condition is always ${cond.condition}`,
|
|
28174
|
+
line: cond.line,
|
|
28175
|
+
column: cond.column,
|
|
28176
|
+
advice: isWhileTrue ? `If this is an intentional infinite loop (event loop, hot loop with explicit \`break\`), add a \`// slopbrick-disable\` comment. Otherwise, replace the literal with a real condition.` : `Replace the literal with a real condition, or remove the dead branch entirely. This is the AI-iteration signature: the model toggled a feature flag to a constant or left a wrapper from a previous refactor.`
|
|
28177
|
+
});
|
|
28178
|
+
}
|
|
28179
|
+
return issues;
|
|
28180
|
+
}
|
|
28181
|
+
});
|
|
28182
|
+
}
|
|
28183
|
+
});
|
|
28184
|
+
|
|
28185
|
+
// src/rules/dead/unreachable.ts
|
|
28186
|
+
var unreachableRule;
|
|
28187
|
+
var init_unreachable = __esm({
|
|
28188
|
+
"src/rules/dead/unreachable.ts"() {
|
|
28189
|
+
"use strict";
|
|
28190
|
+
init_rule();
|
|
28191
|
+
unreachableRule = createRule({
|
|
28192
|
+
id: "dead/unreachable",
|
|
28193
|
+
category: "logic",
|
|
28194
|
+
severity: "high",
|
|
28195
|
+
aiSpecific: true,
|
|
28196
|
+
description: "Statement is unreachable after an unconditional return/throw/break/continue",
|
|
28197
|
+
create(_context) {
|
|
28198
|
+
return {};
|
|
28199
|
+
},
|
|
28200
|
+
analyze(_context, facts) {
|
|
28201
|
+
const issues = [];
|
|
28202
|
+
if (!facts.v2) return issues;
|
|
28203
|
+
for (const u of facts.v2.deadCode.unreachableStatements) {
|
|
28204
|
+
if (u.snippet === "<unreachable>") continue;
|
|
28205
|
+
issues.push({
|
|
28206
|
+
ruleId: "dead/unreachable",
|
|
28207
|
+
category: "logic",
|
|
28208
|
+
severity: "high",
|
|
28209
|
+
aiSpecific: true,
|
|
28210
|
+
message: `Unreachable after ${u.terminator}: ${u.snippet}`,
|
|
28211
|
+
line: u.line,
|
|
28212
|
+
column: u.column,
|
|
28213
|
+
advice: `Remove this statement \u2014 code after a ${u.terminator} is unreachable. This is the AI-iteration signature: the model added an early ${u.terminator} for a new error path, then forgot the rest of the function body was still sitting below it.`
|
|
28214
|
+
});
|
|
28215
|
+
}
|
|
28216
|
+
return issues;
|
|
28217
|
+
}
|
|
28218
|
+
});
|
|
28219
|
+
}
|
|
28220
|
+
});
|
|
28221
|
+
|
|
28222
|
+
// src/rules/dead/unused-import.ts
|
|
28223
|
+
var unusedImportRule;
|
|
28224
|
+
var init_unused_import = __esm({
|
|
28225
|
+
"src/rules/dead/unused-import.ts"() {
|
|
28226
|
+
"use strict";
|
|
28227
|
+
init_rule();
|
|
28228
|
+
unusedImportRule = createRule({
|
|
28229
|
+
id: "dead/unused-import",
|
|
28230
|
+
category: "logic",
|
|
28231
|
+
severity: "low",
|
|
28232
|
+
aiSpecific: true,
|
|
28233
|
+
description: "ES module import is never referenced in the file",
|
|
28234
|
+
create(_context) {
|
|
28235
|
+
return {};
|
|
28236
|
+
},
|
|
28237
|
+
analyze(_context, facts) {
|
|
28238
|
+
const issues = [];
|
|
28239
|
+
if (!facts.v2) return issues;
|
|
28240
|
+
for (const binding of facts.v2.deadCode.bindings) {
|
|
28241
|
+
if (binding.kind !== "import-specifier" && binding.kind !== "import-default" && binding.kind !== "import-namespace") {
|
|
28242
|
+
continue;
|
|
28243
|
+
}
|
|
28244
|
+
if (binding.isReferenced) continue;
|
|
28245
|
+
if (!binding.name) continue;
|
|
28246
|
+
const source = binding.source ? ` from '${binding.source}'` : "";
|
|
28247
|
+
issues.push({
|
|
28248
|
+
ruleId: "dead/unused-import",
|
|
28249
|
+
category: "logic",
|
|
28250
|
+
severity: "low",
|
|
28251
|
+
aiSpecific: true,
|
|
28252
|
+
message: `Unused import: '${binding.name}'${source}`,
|
|
28253
|
+
line: binding.line,
|
|
28254
|
+
column: binding.column,
|
|
28255
|
+
advice: `Remove the import or use '${binding.name}' somewhere in the file. This is the most common AI-iteration rot \u2014 the model added the import when it introduced a feature, then rewrote the function without cleaning up.`
|
|
28256
|
+
});
|
|
28257
|
+
}
|
|
28258
|
+
return issues;
|
|
28259
|
+
}
|
|
28260
|
+
});
|
|
28261
|
+
}
|
|
28262
|
+
});
|
|
28263
|
+
|
|
28264
|
+
// src/rules/dead/unused-local.ts
|
|
28265
|
+
var SKIP_NAMES, unusedLocalRule;
|
|
28266
|
+
var init_unused_local = __esm({
|
|
28267
|
+
"src/rules/dead/unused-local.ts"() {
|
|
28268
|
+
"use strict";
|
|
28269
|
+
init_rule();
|
|
28270
|
+
SKIP_NAMES = /* @__PURE__ */ new Set(["React", "_"]);
|
|
28271
|
+
unusedLocalRule = createRule({
|
|
28272
|
+
id: "dead/unused-local",
|
|
28273
|
+
category: "logic",
|
|
28274
|
+
severity: "low",
|
|
28275
|
+
aiSpecific: true,
|
|
28276
|
+
description: "Variable is declared but never read after declaration",
|
|
28277
|
+
create(_context) {
|
|
28278
|
+
return {};
|
|
28279
|
+
},
|
|
28280
|
+
analyze(_context, facts) {
|
|
28281
|
+
const issues = [];
|
|
28282
|
+
if (!facts.v2) return issues;
|
|
28283
|
+
for (const binding of facts.v2.deadCode.bindings) {
|
|
28284
|
+
if (binding.kind !== "var" && binding.kind !== "let" && binding.kind !== "const" && binding.kind !== "function" && binding.kind !== "class" && binding.kind !== "type" && binding.kind !== "interface" && binding.kind !== "enum") {
|
|
28285
|
+
continue;
|
|
28286
|
+
}
|
|
28287
|
+
if (binding.isReferenced) continue;
|
|
28288
|
+
if (SKIP_NAMES.has(binding.name)) continue;
|
|
28289
|
+
if (binding.name.startsWith("_")) continue;
|
|
28290
|
+
issues.push({
|
|
28291
|
+
ruleId: "dead/unused-local",
|
|
28292
|
+
category: "logic",
|
|
28293
|
+
severity: "low",
|
|
28294
|
+
aiSpecific: true,
|
|
28295
|
+
message: `Unused ${binding.kind}: '${binding.name}'`,
|
|
28296
|
+
line: binding.line,
|
|
28297
|
+
column: binding.column,
|
|
28298
|
+
advice: `Remove the declaration or use '${binding.name}' somewhere in the file. This is the second-most-common AI-iteration signature \u2014 the model declared the binding when it introduced a feature, then rewrote the function without cleaning up.`
|
|
28299
|
+
});
|
|
28300
|
+
}
|
|
28301
|
+
return issues;
|
|
28302
|
+
}
|
|
28303
|
+
});
|
|
28304
|
+
}
|
|
28305
|
+
});
|
|
28306
|
+
|
|
28307
|
+
// src/rules/dead/unused-parameter.ts
|
|
28308
|
+
var unusedParameterRule;
|
|
28309
|
+
var init_unused_parameter = __esm({
|
|
28310
|
+
"src/rules/dead/unused-parameter.ts"() {
|
|
28311
|
+
"use strict";
|
|
28312
|
+
init_rule();
|
|
28313
|
+
unusedParameterRule = createRule({
|
|
28314
|
+
id: "dead/unused-parameter",
|
|
28315
|
+
category: "logic",
|
|
28316
|
+
severity: "low",
|
|
28317
|
+
aiSpecific: true,
|
|
28318
|
+
description: "Function parameter is declared but never read",
|
|
28319
|
+
create(_context) {
|
|
28320
|
+
return {};
|
|
28321
|
+
},
|
|
28322
|
+
analyze(_context, facts) {
|
|
28323
|
+
const issues = [];
|
|
28324
|
+
if (!facts.v2) return issues;
|
|
28325
|
+
for (const binding of facts.v2.deadCode.bindings) {
|
|
28326
|
+
if (binding.kind !== "parameter") continue;
|
|
28327
|
+
if (binding.isReferenced) continue;
|
|
28328
|
+
if (binding.name.startsWith("_")) continue;
|
|
28329
|
+
if (binding.name === "props") continue;
|
|
28330
|
+
issues.push({
|
|
28331
|
+
ruleId: "dead/unused-parameter",
|
|
28332
|
+
category: "logic",
|
|
28333
|
+
severity: "low",
|
|
28334
|
+
aiSpecific: true,
|
|
28335
|
+
message: `Unused parameter: '${binding.name}'`,
|
|
28336
|
+
line: binding.line,
|
|
28337
|
+
column: binding.column,
|
|
28338
|
+
advice: `Remove the parameter (and update every call site) or use '${binding.name}' in the function body. This is the AI-iteration signature: the model added the parameter when it introduced a feature, then rewrote the function without removing parameters the new code does not need.`
|
|
28339
|
+
});
|
|
28340
|
+
}
|
|
28341
|
+
return issues;
|
|
28342
|
+
}
|
|
28343
|
+
});
|
|
28344
|
+
}
|
|
28345
|
+
});
|
|
28346
|
+
|
|
28094
28347
|
// src/engine/discover.ts
|
|
28095
28348
|
var discover_exports = {};
|
|
28096
28349
|
__export(discover_exports, {
|
|
@@ -28202,14 +28455,14 @@ import { join as join5 } from "path";
|
|
|
28202
28455
|
function readDeps(cwd) {
|
|
28203
28456
|
const pkgPath = join5(cwd, "package.json");
|
|
28204
28457
|
if (!existsSync4(pkgPath)) return /* @__PURE__ */ new Set();
|
|
28205
|
-
let
|
|
28458
|
+
let pkg;
|
|
28206
28459
|
try {
|
|
28207
|
-
|
|
28460
|
+
pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
28208
28461
|
} catch {
|
|
28209
28462
|
return /* @__PURE__ */ new Set();
|
|
28210
28463
|
}
|
|
28211
28464
|
const out = /* @__PURE__ */ new Set();
|
|
28212
|
-
for (const source of [
|
|
28465
|
+
for (const source of [pkg.dependencies, pkg.devDependencies]) {
|
|
28213
28466
|
if (source && typeof source === "object") {
|
|
28214
28467
|
for (const name of Object.keys(source)) out.add(name);
|
|
28215
28468
|
}
|
|
@@ -28225,8 +28478,8 @@ function detectConstitution(cwd) {
|
|
|
28225
28478
|
const deps = readDeps(cwd);
|
|
28226
28479
|
if (deps.size === 0) return {};
|
|
28227
28480
|
const out = {};
|
|
28228
|
-
for (const [
|
|
28229
|
-
if (deps.has(
|
|
28481
|
+
for (const [pkg, { field, signal }] of Object.entries(CONSTITUTION_SIGNALS)) {
|
|
28482
|
+
if (deps.has(pkg)) {
|
|
28230
28483
|
out[field] = pushUnique(
|
|
28231
28484
|
out[field],
|
|
28232
28485
|
signal
|
|
@@ -29494,6 +29747,9 @@ var init_expired_code_example = __esm({
|
|
|
29494
29747
|
const issues = [];
|
|
29495
29748
|
const source = facts.v2?._source;
|
|
29496
29749
|
if (!source) return issues;
|
|
29750
|
+
const packages = declaredPackages(context.cwd);
|
|
29751
|
+
const packageName = context.packageName;
|
|
29752
|
+
if (packageName) packages.add(packageName);
|
|
29497
29753
|
const blocks = extractFencedCodeBlocks(source);
|
|
29498
29754
|
for (const block of blocks) {
|
|
29499
29755
|
if (!CODE_LANGS.has(block.lang)) continue;
|
|
@@ -29501,7 +29757,7 @@ var init_expired_code_example = __esm({
|
|
|
29501
29757
|
const imports = extractImports(block.body);
|
|
29502
29758
|
for (const imp of imports) {
|
|
29503
29759
|
const pkgName = stripSubpath(imp);
|
|
29504
|
-
if (
|
|
29760
|
+
if (packages.has(pkgName)) continue;
|
|
29505
29761
|
issues.push({
|
|
29506
29762
|
ruleId: "docs/expired-code-example",
|
|
29507
29763
|
category: "docs",
|
|
@@ -29556,7 +29812,12 @@ function collectExports(cwd) {
|
|
|
29556
29812
|
/\bexport\s+class\s+([A-Za-z_$][\w$]*)/g,
|
|
29557
29813
|
/\bexport\s+interface\s+([A-Za-z_$][\w$]*)/g,
|
|
29558
29814
|
/\bexport\s+type\s+([A-Za-z_$][\w$]*)/g,
|
|
29559
|
-
/\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g
|
|
29815
|
+
/\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g,
|
|
29816
|
+
// v0.18.6: also collect field names from `export interface` and
|
|
29817
|
+
// `export type` declarations. Without this, fields like
|
|
29818
|
+
// `crossFileDrift`, `aiQuality`, `engineeringHygiene` are
|
|
29819
|
+
// flagged as stale even though they're valid type fields.
|
|
29820
|
+
/^\s*(?:readonly\s+)?([A-Za-z_$][\w$]*)\s*[?:]/gm
|
|
29560
29821
|
]) {
|
|
29561
29822
|
let m;
|
|
29562
29823
|
while ((m = re.exec(source)) !== null) {
|
|
@@ -29567,6 +29828,21 @@ function collectExports(cwd) {
|
|
|
29567
29828
|
}
|
|
29568
29829
|
return out;
|
|
29569
29830
|
}
|
|
29831
|
+
function looksLikeProseLabel(inside) {
|
|
29832
|
+
const trimmed = inside.trim();
|
|
29833
|
+
if (trimmed.length === 0) return false;
|
|
29834
|
+
if (trimmed.startsWith("`") || trimmed.startsWith("/")) return true;
|
|
29835
|
+
if (trimmed.includes("`")) return true;
|
|
29836
|
+
if (/\d+\s+[a-z]/i.test(trimmed)) return true;
|
|
29837
|
+
const parts = trimmed.split(",").map((s) => s.trim());
|
|
29838
|
+
if (parts.length >= 3) {
|
|
29839
|
+
const allNumeric = parts.every((p) => /^\d+\.?\d*$/.test(p));
|
|
29840
|
+
if (!allNumeric) return true;
|
|
29841
|
+
}
|
|
29842
|
+
if (trimmed.length > 40 && !trimmed.includes(",")) return true;
|
|
29843
|
+
if (trimmed.includes("\u2014") || trimmed.includes("\u2013")) return true;
|
|
29844
|
+
return false;
|
|
29845
|
+
}
|
|
29570
29846
|
var RESERVED, SOURCE_EXTS, SOURCE_ROOTS, CAP, staleFunctionReferenceRule;
|
|
29571
29847
|
var init_stale_function_reference = __esm({
|
|
29572
29848
|
"src/rules/docs/stale-function-reference.ts"() {
|
|
@@ -29574,6 +29850,7 @@ var init_stale_function_reference = __esm({
|
|
|
29574
29850
|
init_rule();
|
|
29575
29851
|
init_doc_freshness();
|
|
29576
29852
|
RESERVED = /* @__PURE__ */ new Set([
|
|
29853
|
+
// JS reserved words
|
|
29577
29854
|
"true",
|
|
29578
29855
|
"false",
|
|
29579
29856
|
"null",
|
|
@@ -29673,7 +29950,472 @@ var init_stale_function_reference = __esm({
|
|
|
29673
29950
|
"next",
|
|
29674
29951
|
"vue",
|
|
29675
29952
|
"angular",
|
|
29676
|
-
"svelte"
|
|
29953
|
+
"svelte",
|
|
29954
|
+
// Framework / runtime names
|
|
29955
|
+
"html",
|
|
29956
|
+
"astro",
|
|
29957
|
+
"python",
|
|
29958
|
+
"jvm",
|
|
29959
|
+
"kotlin",
|
|
29960
|
+
"swift",
|
|
29961
|
+
"dart",
|
|
29962
|
+
"ruby",
|
|
29963
|
+
"rust",
|
|
29964
|
+
"cpp",
|
|
29965
|
+
"go",
|
|
29966
|
+
"java",
|
|
29967
|
+
"php",
|
|
29968
|
+
"php-html",
|
|
29969
|
+
"csharp",
|
|
29970
|
+
"typescript",
|
|
29971
|
+
"javascript",
|
|
29972
|
+
"jsx",
|
|
29973
|
+
"tsx",
|
|
29974
|
+
"mjs",
|
|
29975
|
+
"cjs",
|
|
29976
|
+
"esnext",
|
|
29977
|
+
"es6",
|
|
29978
|
+
"es2022",
|
|
29979
|
+
"es2023",
|
|
29980
|
+
"esm",
|
|
29981
|
+
"cjs",
|
|
29982
|
+
"umd",
|
|
29983
|
+
"amd",
|
|
29984
|
+
"commonjs",
|
|
29985
|
+
"require",
|
|
29986
|
+
"module",
|
|
29987
|
+
"exports",
|
|
29988
|
+
"define",
|
|
29989
|
+
"global",
|
|
29990
|
+
"window",
|
|
29991
|
+
"document",
|
|
29992
|
+
"process",
|
|
29993
|
+
"console",
|
|
29994
|
+
"buffer",
|
|
29995
|
+
"stream",
|
|
29996
|
+
"fetch",
|
|
29997
|
+
"axios",
|
|
29998
|
+
"express",
|
|
29999
|
+
"fastify",
|
|
30000
|
+
"koa",
|
|
30001
|
+
"hapi",
|
|
30002
|
+
"nextjs",
|
|
30003
|
+
"nuxt",
|
|
30004
|
+
"remix",
|
|
30005
|
+
"gatsby",
|
|
30006
|
+
"sveltekit",
|
|
30007
|
+
"solid",
|
|
30008
|
+
"preact",
|
|
30009
|
+
"qwik",
|
|
30010
|
+
"lit",
|
|
30011
|
+
"stencil",
|
|
30012
|
+
"marko",
|
|
30013
|
+
"alpine",
|
|
30014
|
+
"stimulus",
|
|
30015
|
+
"turbo",
|
|
30016
|
+
"hotwire",
|
|
30017
|
+
// Models / providers
|
|
30018
|
+
"gpt",
|
|
30019
|
+
"claude",
|
|
30020
|
+
"gpt-3",
|
|
30021
|
+
"gpt-3.5",
|
|
30022
|
+
"gpt-4",
|
|
30023
|
+
"gpt-oss",
|
|
30024
|
+
"haiku",
|
|
30025
|
+
"sonnet",
|
|
30026
|
+
"opus",
|
|
30027
|
+
"aider",
|
|
30028
|
+
"tabby",
|
|
30029
|
+
"copilot",
|
|
30030
|
+
"cursor",
|
|
30031
|
+
"windsurf",
|
|
30032
|
+
"devin",
|
|
30033
|
+
"claude-code",
|
|
30034
|
+
// LLM-detection lingo
|
|
30035
|
+
"heuristic",
|
|
30036
|
+
"heuristics",
|
|
30037
|
+
"calibrate",
|
|
30038
|
+
"calibration",
|
|
30039
|
+
"calibrator",
|
|
30040
|
+
"corpus",
|
|
30041
|
+
"baseline",
|
|
30042
|
+
"baselines",
|
|
30043
|
+
"corpus-baselines",
|
|
30044
|
+
"lift",
|
|
30045
|
+
"recall",
|
|
30046
|
+
"precision",
|
|
30047
|
+
"fpRate",
|
|
30048
|
+
"ratio",
|
|
30049
|
+
"verdict",
|
|
30050
|
+
"USEFUL",
|
|
30051
|
+
"NOISY",
|
|
30052
|
+
"INVERTED",
|
|
30053
|
+
"HYGIENE",
|
|
30054
|
+
"DORMANT",
|
|
30055
|
+
"OK",
|
|
30056
|
+
"aiSpecific",
|
|
30057
|
+
"defaultOff",
|
|
30058
|
+
// Common slop-audit verbs/nouns
|
|
30059
|
+
"commit",
|
|
30060
|
+
"push",
|
|
30061
|
+
"reset",
|
|
30062
|
+
"rebase",
|
|
30063
|
+
"merge",
|
|
30064
|
+
"cherry-pick",
|
|
30065
|
+
"revert",
|
|
30066
|
+
"scan",
|
|
30067
|
+
"parse",
|
|
30068
|
+
"build",
|
|
30069
|
+
"test",
|
|
30070
|
+
"lint",
|
|
30071
|
+
"format",
|
|
30072
|
+
"check",
|
|
30073
|
+
"audit",
|
|
30074
|
+
"fix",
|
|
30075
|
+
"patch",
|
|
30076
|
+
"diff",
|
|
30077
|
+
"pr",
|
|
30078
|
+
"ci",
|
|
30079
|
+
"cd",
|
|
30080
|
+
"gh",
|
|
30081
|
+
"npm",
|
|
30082
|
+
"npx",
|
|
30083
|
+
"pnpm",
|
|
30084
|
+
"yaml",
|
|
30085
|
+
"json",
|
|
30086
|
+
"toml",
|
|
30087
|
+
"csv",
|
|
30088
|
+
"md",
|
|
30089
|
+
"mdx",
|
|
30090
|
+
"sh",
|
|
30091
|
+
"bash",
|
|
30092
|
+
"zsh",
|
|
30093
|
+
"fish",
|
|
30094
|
+
"ascii",
|
|
30095
|
+
"utf8",
|
|
30096
|
+
"utf-8",
|
|
30097
|
+
"base64",
|
|
30098
|
+
"hex",
|
|
30099
|
+
"binary",
|
|
30100
|
+
"text",
|
|
30101
|
+
// Common design / ui terms
|
|
30102
|
+
"flex",
|
|
30103
|
+
"grid",
|
|
30104
|
+
"auto",
|
|
30105
|
+
"min",
|
|
30106
|
+
"max",
|
|
30107
|
+
"fill",
|
|
30108
|
+
"stretch",
|
|
30109
|
+
"wrap",
|
|
30110
|
+
"nowrap",
|
|
30111
|
+
"inline",
|
|
30112
|
+
"block",
|
|
30113
|
+
"hidden",
|
|
30114
|
+
"visible",
|
|
30115
|
+
"static",
|
|
30116
|
+
"fixed",
|
|
30117
|
+
"absolute",
|
|
30118
|
+
"relative",
|
|
30119
|
+
"sticky",
|
|
30120
|
+
"pointer",
|
|
30121
|
+
"cursor",
|
|
30122
|
+
"focus",
|
|
30123
|
+
"hover",
|
|
30124
|
+
"active",
|
|
30125
|
+
"disabled",
|
|
30126
|
+
"readonly",
|
|
30127
|
+
"primary",
|
|
30128
|
+
"secondary",
|
|
30129
|
+
"tertiary",
|
|
30130
|
+
"success",
|
|
30131
|
+
"warning",
|
|
30132
|
+
"danger",
|
|
30133
|
+
"info",
|
|
30134
|
+
"muted",
|
|
30135
|
+
"sm",
|
|
30136
|
+
"md",
|
|
30137
|
+
"lg",
|
|
30138
|
+
"xl",
|
|
30139
|
+
"xxl",
|
|
30140
|
+
"xs",
|
|
30141
|
+
"2xl",
|
|
30142
|
+
"3xl",
|
|
30143
|
+
"4xl",
|
|
30144
|
+
// Math / types
|
|
30145
|
+
"array",
|
|
30146
|
+
"map",
|
|
30147
|
+
"set",
|
|
30148
|
+
"weakmap",
|
|
30149
|
+
"weakset",
|
|
30150
|
+
"object",
|
|
30151
|
+
"string",
|
|
30152
|
+
"number",
|
|
30153
|
+
"boolean",
|
|
30154
|
+
"bigint",
|
|
30155
|
+
"symbol",
|
|
30156
|
+
"null",
|
|
30157
|
+
"undefined",
|
|
30158
|
+
"any",
|
|
30159
|
+
"unknown",
|
|
30160
|
+
"never",
|
|
30161
|
+
"void",
|
|
30162
|
+
"readonly",
|
|
30163
|
+
"private",
|
|
30164
|
+
"public",
|
|
30165
|
+
"protected",
|
|
30166
|
+
"static",
|
|
30167
|
+
"abstract",
|
|
30168
|
+
"async",
|
|
30169
|
+
"generator",
|
|
30170
|
+
"iterator",
|
|
30171
|
+
"iterable",
|
|
30172
|
+
"promise",
|
|
30173
|
+
"observable",
|
|
30174
|
+
// Auth / domain
|
|
30175
|
+
"admin",
|
|
30176
|
+
"user",
|
|
30177
|
+
"guest",
|
|
30178
|
+
"anonymous",
|
|
30179
|
+
"authenticated",
|
|
30180
|
+
"unauthenticated",
|
|
30181
|
+
"jwt",
|
|
30182
|
+
"oauth",
|
|
30183
|
+
"oidc",
|
|
30184
|
+
"saml",
|
|
30185
|
+
"csrf",
|
|
30186
|
+
"xss",
|
|
30187
|
+
"sql",
|
|
30188
|
+
"nosql",
|
|
30189
|
+
"orm",
|
|
30190
|
+
"prisma",
|
|
30191
|
+
"drizzle",
|
|
30192
|
+
"sequelize",
|
|
30193
|
+
"mongoose",
|
|
30194
|
+
"redis",
|
|
30195
|
+
"postgres",
|
|
30196
|
+
"mysql",
|
|
30197
|
+
"sqlite",
|
|
30198
|
+
"kafka",
|
|
30199
|
+
"rabbitmq",
|
|
30200
|
+
"graphql",
|
|
30201
|
+
"rest",
|
|
30202
|
+
"grpc",
|
|
30203
|
+
"websocket",
|
|
30204
|
+
// slop-audit specific
|
|
30205
|
+
"slopbrick",
|
|
30206
|
+
"usebrick",
|
|
30207
|
+
"deadcode",
|
|
30208
|
+
"unused",
|
|
30209
|
+
"orphan",
|
|
30210
|
+
"zombie",
|
|
30211
|
+
"blocker",
|
|
30212
|
+
"warning",
|
|
30213
|
+
"info",
|
|
30214
|
+
"error",
|
|
30215
|
+
"verbose",
|
|
30216
|
+
"debug",
|
|
30217
|
+
"silly",
|
|
30218
|
+
"p50",
|
|
30219
|
+
"p90",
|
|
30220
|
+
"p95",
|
|
30221
|
+
"p99",
|
|
30222
|
+
"min",
|
|
30223
|
+
"max",
|
|
30224
|
+
"avg",
|
|
30225
|
+
"mean",
|
|
30226
|
+
"median",
|
|
30227
|
+
"ratchet",
|
|
30228
|
+
"tier",
|
|
30229
|
+
"composite",
|
|
30230
|
+
"fitness",
|
|
30231
|
+
"fpr",
|
|
30232
|
+
"tpr",
|
|
30233
|
+
"roc",
|
|
30234
|
+
"should",
|
|
30235
|
+
"could",
|
|
30236
|
+
"would",
|
|
30237
|
+
"might",
|
|
30238
|
+
"must",
|
|
30239
|
+
"shall",
|
|
30240
|
+
"may",
|
|
30241
|
+
"can",
|
|
30242
|
+
"todo",
|
|
30243
|
+
"fixme",
|
|
30244
|
+
"xxx",
|
|
30245
|
+
"hack",
|
|
30246
|
+
"note",
|
|
30247
|
+
"warning",
|
|
30248
|
+
"attention",
|
|
30249
|
+
"h1",
|
|
30250
|
+
"h2",
|
|
30251
|
+
"h3",
|
|
30252
|
+
"h4",
|
|
30253
|
+
"h5",
|
|
30254
|
+
"h6",
|
|
30255
|
+
"strong",
|
|
30256
|
+
"em",
|
|
30257
|
+
"b",
|
|
30258
|
+
"i",
|
|
30259
|
+
"u",
|
|
30260
|
+
"true",
|
|
30261
|
+
"false",
|
|
30262
|
+
"yes",
|
|
30263
|
+
"no",
|
|
30264
|
+
"on",
|
|
30265
|
+
"off",
|
|
30266
|
+
"enable",
|
|
30267
|
+
"disable",
|
|
30268
|
+
"ltr",
|
|
30269
|
+
"rtl",
|
|
30270
|
+
"auto",
|
|
30271
|
+
"start",
|
|
30272
|
+
"end",
|
|
30273
|
+
"center",
|
|
30274
|
+
"baseline",
|
|
30275
|
+
"stretch",
|
|
30276
|
+
"rounded",
|
|
30277
|
+
"sharp",
|
|
30278
|
+
"outline",
|
|
30279
|
+
"ghost",
|
|
30280
|
+
"link",
|
|
30281
|
+
"filled",
|
|
30282
|
+
"row",
|
|
30283
|
+
"col",
|
|
30284
|
+
"gap",
|
|
30285
|
+
"pad",
|
|
30286
|
+
"margin",
|
|
30287
|
+
"padding",
|
|
30288
|
+
"border",
|
|
30289
|
+
"shadow",
|
|
30290
|
+
"transparent",
|
|
30291
|
+
"currentcolor",
|
|
30292
|
+
"inherit",
|
|
30293
|
+
"initial",
|
|
30294
|
+
"unset",
|
|
30295
|
+
"revert",
|
|
30296
|
+
"hover",
|
|
30297
|
+
"focus",
|
|
30298
|
+
"active",
|
|
30299
|
+
"disabled",
|
|
30300
|
+
"checked",
|
|
30301
|
+
"indeterminate",
|
|
30302
|
+
"open",
|
|
30303
|
+
"close",
|
|
30304
|
+
"expanded",
|
|
30305
|
+
"collapsed",
|
|
30306
|
+
"selected",
|
|
30307
|
+
"pressed",
|
|
30308
|
+
// Web/CSS
|
|
30309
|
+
"div",
|
|
30310
|
+
"span",
|
|
30311
|
+
"p",
|
|
30312
|
+
"a",
|
|
30313
|
+
"img",
|
|
30314
|
+
"ul",
|
|
30315
|
+
"ol",
|
|
30316
|
+
"li",
|
|
30317
|
+
"table",
|
|
30318
|
+
"tr",
|
|
30319
|
+
"td",
|
|
30320
|
+
"th",
|
|
30321
|
+
"thead",
|
|
30322
|
+
"tbody",
|
|
30323
|
+
"tfoot",
|
|
30324
|
+
"caption",
|
|
30325
|
+
"figure",
|
|
30326
|
+
"figcaption",
|
|
30327
|
+
"main",
|
|
30328
|
+
"section",
|
|
30329
|
+
"article",
|
|
30330
|
+
"aside",
|
|
30331
|
+
"header",
|
|
30332
|
+
"footer",
|
|
30333
|
+
"nav",
|
|
30334
|
+
"form",
|
|
30335
|
+
"input",
|
|
30336
|
+
"button",
|
|
30337
|
+
"select",
|
|
30338
|
+
"option",
|
|
30339
|
+
"textarea",
|
|
30340
|
+
"label",
|
|
30341
|
+
"fieldset",
|
|
30342
|
+
"legend",
|
|
30343
|
+
"details",
|
|
30344
|
+
"summary",
|
|
30345
|
+
"dialog",
|
|
30346
|
+
"menu",
|
|
30347
|
+
"menuitem",
|
|
30348
|
+
"template",
|
|
30349
|
+
"slot",
|
|
30350
|
+
"picture",
|
|
30351
|
+
"source",
|
|
30352
|
+
"track",
|
|
30353
|
+
"video",
|
|
30354
|
+
"audio",
|
|
30355
|
+
"canvas",
|
|
30356
|
+
"svg",
|
|
30357
|
+
"iframe",
|
|
30358
|
+
"embed",
|
|
30359
|
+
"object",
|
|
30360
|
+
"portal",
|
|
30361
|
+
// Common business terms
|
|
30362
|
+
"api",
|
|
30363
|
+
"cli",
|
|
30364
|
+
"ui",
|
|
30365
|
+
"ux",
|
|
30366
|
+
"sdk",
|
|
30367
|
+
"ide",
|
|
30368
|
+
"cli",
|
|
30369
|
+
"docs",
|
|
30370
|
+
"doc",
|
|
30371
|
+
"blog",
|
|
30372
|
+
"post",
|
|
30373
|
+
"page",
|
|
30374
|
+
"view",
|
|
30375
|
+
"tab",
|
|
30376
|
+
"panel",
|
|
30377
|
+
"card",
|
|
30378
|
+
"list",
|
|
30379
|
+
"grid",
|
|
30380
|
+
"form",
|
|
30381
|
+
"modal",
|
|
30382
|
+
"menu",
|
|
30383
|
+
"button",
|
|
30384
|
+
"icon",
|
|
30385
|
+
"avatar",
|
|
30386
|
+
"badge",
|
|
30387
|
+
"chip",
|
|
30388
|
+
"tooltip",
|
|
30389
|
+
"popover",
|
|
30390
|
+
"dropdown",
|
|
30391
|
+
"banner",
|
|
30392
|
+
"alert",
|
|
30393
|
+
"toast",
|
|
30394
|
+
"notification",
|
|
30395
|
+
"drawer",
|
|
30396
|
+
"sidebar",
|
|
30397
|
+
"navbar",
|
|
30398
|
+
"header",
|
|
30399
|
+
"footer",
|
|
30400
|
+
"hero",
|
|
30401
|
+
"cta",
|
|
30402
|
+
"cta-primary",
|
|
30403
|
+
"cta-secondary",
|
|
30404
|
+
"pricing",
|
|
30405
|
+
"price",
|
|
30406
|
+
"cost",
|
|
30407
|
+
"rate",
|
|
30408
|
+
"percent",
|
|
30409
|
+
"pct",
|
|
30410
|
+
"count",
|
|
30411
|
+
"total",
|
|
30412
|
+
"small",
|
|
30413
|
+
"medium",
|
|
30414
|
+
"large",
|
|
30415
|
+
"xl",
|
|
30416
|
+
"xxl",
|
|
30417
|
+
"tiny",
|
|
30418
|
+
"huge"
|
|
29677
30419
|
]);
|
|
29678
30420
|
SOURCE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
29679
30421
|
SOURCE_ROOTS = ["src", "lib", "app", "components"];
|
|
@@ -29697,8 +30439,39 @@ var init_stale_function_reference = __esm({
|
|
|
29697
30439
|
if (text.length < 3) continue;
|
|
29698
30440
|
if (RESERVED.has(text.toLowerCase())) continue;
|
|
29699
30441
|
if (context.exports.has(text)) continue;
|
|
29700
|
-
const
|
|
29701
|
-
|
|
30442
|
+
const lineEnd = source.indexOf("\n", span.index);
|
|
30443
|
+
const restOfLine = source.slice(
|
|
30444
|
+
span.index,
|
|
30445
|
+
lineEnd === -1 ? source.length : lineEnd
|
|
30446
|
+
);
|
|
30447
|
+
const closeTick = restOfLine.indexOf("`", 1);
|
|
30448
|
+
if (closeTick === -1) continue;
|
|
30449
|
+
const afterTick = restOfLine.slice(closeTick + 1);
|
|
30450
|
+
const directCall = /^\s*\(/.test(afterTick);
|
|
30451
|
+
let identifierRepeats = false;
|
|
30452
|
+
if (!directCall) {
|
|
30453
|
+
const afterSpan = restOfLine.slice(closeTick + 1);
|
|
30454
|
+
const needle = text + "(";
|
|
30455
|
+
identifierRepeats = afterSpan.indexOf(needle) !== -1;
|
|
30456
|
+
}
|
|
30457
|
+
if (!directCall && !identifierRepeats) continue;
|
|
30458
|
+
const beforeTickIdx = span.index - 1;
|
|
30459
|
+
const beforeChar = beforeTickIdx >= 0 ? source[beforeTickIdx] : "";
|
|
30460
|
+
if (beforeChar === "." || beforeChar === "|") continue;
|
|
30461
|
+
const parenStart = restOfLine.indexOf("(", closeTick);
|
|
30462
|
+
const parenEnd = restOfLine.indexOf(")", parenStart);
|
|
30463
|
+
if (parenStart !== -1 && parenEnd !== -1) {
|
|
30464
|
+
const inside = restOfLine.slice(parenStart + 1, parenEnd);
|
|
30465
|
+
const trimmed = inside.trim();
|
|
30466
|
+
if (looksLikeProseLabel(inside)) continue;
|
|
30467
|
+
const looksLikeTypeAnnotation = !inside.includes(":") && (/\b(string|number|boolean|null|undefined|object|array|required|optional|categorical|direct|n\/a|\bmapped\b|0[\-–][0-9]+|v[0-9]|higher is better|lower is better|added in|deprecated|pr-[0-9])\b/i.test(
|
|
30468
|
+
inside
|
|
30469
|
+
) || // Short single-word label (≤ 24 chars, no `,`,
|
|
30470
|
+
// doesn't look like a function arg). Real function
|
|
30471
|
+
// calls are usually longer or contain commas.
|
|
30472
|
+
trimmed.length > 0 && trimmed.length <= 24 && !trimmed.includes(",") && /[a-zA-Z]/.test(trimmed));
|
|
30473
|
+
if (looksLikeTypeAnnotation) continue;
|
|
30474
|
+
}
|
|
29702
30475
|
issues.push({
|
|
29703
30476
|
ruleId: "docs/stale-function-reference",
|
|
29704
30477
|
category: "docs",
|
|
@@ -29778,7 +30551,33 @@ var init_stale_package_reference = __esm({
|
|
|
29778
30551
|
"jsx",
|
|
29779
30552
|
"ok",
|
|
29780
30553
|
"no",
|
|
29781
|
-
"yes"
|
|
30554
|
+
"yes",
|
|
30555
|
+
// v0.18.6: common English adjectives / adverbs that frequently
|
|
30556
|
+
// appear in backticked prose but are not package names.
|
|
30557
|
+
"aspirational",
|
|
30558
|
+
"concrete",
|
|
30559
|
+
"abstract",
|
|
30560
|
+
"inline",
|
|
30561
|
+
"exposed",
|
|
30562
|
+
"deprecated",
|
|
30563
|
+
"experimental",
|
|
30564
|
+
"stable",
|
|
30565
|
+
"beta",
|
|
30566
|
+
"alpha",
|
|
30567
|
+
"wip",
|
|
30568
|
+
"draft",
|
|
30569
|
+
"final",
|
|
30570
|
+
"shim",
|
|
30571
|
+
"polyfill",
|
|
30572
|
+
"stub",
|
|
30573
|
+
"mock",
|
|
30574
|
+
"fake",
|
|
30575
|
+
"real",
|
|
30576
|
+
"false",
|
|
30577
|
+
"true",
|
|
30578
|
+
"optional",
|
|
30579
|
+
"required",
|
|
30580
|
+
"default"
|
|
29782
30581
|
]);
|
|
29783
30582
|
stalePackageReferenceRule = createRule({
|
|
29784
30583
|
id: "docs/stale-package-reference",
|
|
@@ -29920,9 +30719,9 @@ function declaredPackages(cwd) {
|
|
|
29920
30719
|
if (!existsSync6(pkgPath)) return out;
|
|
29921
30720
|
try {
|
|
29922
30721
|
const raw = readFileSync8(pkgPath, "utf-8");
|
|
29923
|
-
const
|
|
30722
|
+
const pkg = JSON.parse(raw);
|
|
29924
30723
|
for (const k of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
29925
|
-
const v =
|
|
30724
|
+
const v = pkg[k];
|
|
29926
30725
|
if (v && typeof v === "object") {
|
|
29927
30726
|
for (const name of Object.keys(v)) {
|
|
29928
30727
|
out.add(name);
|
|
@@ -30003,7 +30802,15 @@ async function buildDocFreshness(cwd, config, options = {}) {
|
|
|
30003
30802
|
continue;
|
|
30004
30803
|
}
|
|
30005
30804
|
const relPath = relative2(cwd, abs);
|
|
30006
|
-
|
|
30805
|
+
let packageName;
|
|
30806
|
+
try {
|
|
30807
|
+
const pkg = JSON.parse(
|
|
30808
|
+
readFileSync8(join7(cwd, "package.json"), "utf-8")
|
|
30809
|
+
);
|
|
30810
|
+
packageName = pkg.name;
|
|
30811
|
+
} catch {
|
|
30812
|
+
}
|
|
30813
|
+
const context = { config, filePath: relPath, cwd, packageName };
|
|
30007
30814
|
const facts = { filePath: relPath, v2: { _source: source } };
|
|
30008
30815
|
const ruleConfigs = [
|
|
30009
30816
|
{ rule: stalePackageReferenceRule, ruleId: "docs/stale-package-reference" },
|
|
@@ -30116,7 +30923,9 @@ var init_broken_link = __esm({
|
|
|
30116
30923
|
if (target.startsWith("#")) continue;
|
|
30117
30924
|
if (target.startsWith("//")) continue;
|
|
30118
30925
|
if (target.startsWith("/")) continue;
|
|
30119
|
-
const
|
|
30926
|
+
const filePart = target.split("#")[0] ?? target;
|
|
30927
|
+
if (filePart === "") continue;
|
|
30928
|
+
const resolved = join8(docDir, filePart);
|
|
30120
30929
|
if (existsSync7(resolved)) continue;
|
|
30121
30930
|
issues.push({
|
|
30122
30931
|
ruleId: "docs/broken-link",
|
|
@@ -30349,7 +31158,7 @@ var init_spacing_grid = __esm({
|
|
|
30349
31158
|
"use strict";
|
|
30350
31159
|
init_rule();
|
|
30351
31160
|
init_utils();
|
|
30352
|
-
|
|
31161
|
+
init_config2();
|
|
30353
31162
|
SPACING_PREFIX_RE = /^-?(p|px|py|pt|pr|pb|pl|m|mx|my|mt|mr|mb|ml|gap|gap-x|gap-y|space-x|space-y)-(.+)$/;
|
|
30354
31163
|
ARBITRARY_VALUE_RE2 = /^(-?\d+(?:\.\d+)?)(px|rem)$/;
|
|
30355
31164
|
SKIP_VALUES = /* @__PURE__ */ new Set(["auto", "full", "screen", "min", "max", "fit", "none"]);
|
|
@@ -42437,6 +43246,78 @@ function extractStateBinding(node, lineOffsets) {
|
|
|
42437
43246
|
setterReferenced: false
|
|
42438
43247
|
};
|
|
42439
43248
|
}
|
|
43249
|
+
function findUnreachableStatements(ast, source, lineOffsets) {
|
|
43250
|
+
const out = [];
|
|
43251
|
+
function isTerminator(node) {
|
|
43252
|
+
if (node.type === "ReturnStatement") return "return";
|
|
43253
|
+
if (node.type === "ThrowStatement") return "throw";
|
|
43254
|
+
if (node.type === "BreakStatement") return "break";
|
|
43255
|
+
if (node.type === "ContinueStatement") return "continue";
|
|
43256
|
+
return null;
|
|
43257
|
+
}
|
|
43258
|
+
function snippetFor(node, src) {
|
|
43259
|
+
const span = node.span;
|
|
43260
|
+
if (!span || typeof span.start !== "number" || typeof span.end !== "number") {
|
|
43261
|
+
return "<unreachable>";
|
|
43262
|
+
}
|
|
43263
|
+
const text = src.slice(span.start, Math.min(span.end, span.start + 60));
|
|
43264
|
+
return text.replace(/\s+/g, " ").trim() || "<unreachable>";
|
|
43265
|
+
}
|
|
43266
|
+
function lineColumn(offset) {
|
|
43267
|
+
let lo = 0;
|
|
43268
|
+
let hi = lineOffsets.length - 1;
|
|
43269
|
+
while (lo < hi) {
|
|
43270
|
+
const mid = lo + hi + 1 >>> 1;
|
|
43271
|
+
const midVal = lineOffsets[mid];
|
|
43272
|
+
const loVal = lineOffsets[lo];
|
|
43273
|
+
if (midVal === void 0) break;
|
|
43274
|
+
if (midVal <= offset) lo = mid;
|
|
43275
|
+
else hi = mid - 1;
|
|
43276
|
+
void loVal;
|
|
43277
|
+
}
|
|
43278
|
+
const baseOffset = lineOffsets[lo] ?? 0;
|
|
43279
|
+
return { line: lo + 1, column: offset - baseOffset };
|
|
43280
|
+
}
|
|
43281
|
+
function visitBody(body) {
|
|
43282
|
+
if (!Array.isArray(body)) return;
|
|
43283
|
+
let lastTerminator = null;
|
|
43284
|
+
for (const stmt of body) {
|
|
43285
|
+
if (!isObject(stmt)) continue;
|
|
43286
|
+
if (lastTerminator && stmt.type !== "EmptyStatement") {
|
|
43287
|
+
const span = stmt.span;
|
|
43288
|
+
const offset = typeof span?.start === "number" ? span.start : 0;
|
|
43289
|
+
const { line, column } = lineColumn(offset);
|
|
43290
|
+
out.push({
|
|
43291
|
+
terminator: lastTerminator,
|
|
43292
|
+
line,
|
|
43293
|
+
column,
|
|
43294
|
+
snippet: snippetFor(stmt, source)
|
|
43295
|
+
});
|
|
43296
|
+
}
|
|
43297
|
+
const t = isTerminator(stmt);
|
|
43298
|
+
if (t) lastTerminator = t;
|
|
43299
|
+
}
|
|
43300
|
+
}
|
|
43301
|
+
function walk3(node) {
|
|
43302
|
+
if (!isObject(node)) return;
|
|
43303
|
+
if (node.type === "BlockStatement") {
|
|
43304
|
+
visitBody(node.stmts);
|
|
43305
|
+
} else if (node.type === "Module") {
|
|
43306
|
+
visitBody(node.body);
|
|
43307
|
+
}
|
|
43308
|
+
for (const key of Object.keys(node)) {
|
|
43309
|
+
if (key === "parent" || key === "span" || key === "ctxt") continue;
|
|
43310
|
+
const child = node[key];
|
|
43311
|
+
if (Array.isArray(child)) {
|
|
43312
|
+
for (const c of child) walk3(c);
|
|
43313
|
+
} else {
|
|
43314
|
+
walk3(child);
|
|
43315
|
+
}
|
|
43316
|
+
}
|
|
43317
|
+
}
|
|
43318
|
+
walk3(ast);
|
|
43319
|
+
return out;
|
|
43320
|
+
}
|
|
42440
43321
|
var init_scan_helpers = __esm({
|
|
42441
43322
|
"src/engine/visitors/scan-helpers.ts"() {
|
|
42442
43323
|
"use strict";
|
|
@@ -42522,15 +43403,42 @@ function handleImportDeclaration(node, _parent, _path, vctx) {
|
|
|
42522
43403
|
if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
|
|
42523
43404
|
const local = specifier.local;
|
|
42524
43405
|
if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
|
|
42525
|
-
|
|
43406
|
+
const name = local.value;
|
|
43407
|
+
importedNames.push(name);
|
|
43408
|
+
vctx.facts.deadCode.bindings.push({
|
|
43409
|
+
name,
|
|
43410
|
+
kind: specifier.type === "ImportDefaultSpecifier" ? "import-default" : "import-namespace",
|
|
43411
|
+
line,
|
|
43412
|
+
column,
|
|
43413
|
+
source,
|
|
43414
|
+
isReferenced: false
|
|
43415
|
+
});
|
|
42526
43416
|
}
|
|
42527
43417
|
} else if (specifier.type === "ImportSpecifier") {
|
|
42528
43418
|
const imported = specifier.imported;
|
|
42529
43419
|
const local = specifier.local;
|
|
42530
43420
|
if (isObject(imported) && typeof imported.value === "string" && imported.value.length > 0) {
|
|
42531
|
-
|
|
43421
|
+
const name = imported.value;
|
|
43422
|
+
importedNames.push(name);
|
|
43423
|
+
vctx.facts.deadCode.bindings.push({
|
|
43424
|
+
name,
|
|
43425
|
+
kind: "import-specifier",
|
|
43426
|
+
line,
|
|
43427
|
+
column,
|
|
43428
|
+
source,
|
|
43429
|
+
isReferenced: false
|
|
43430
|
+
});
|
|
42532
43431
|
} else if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
|
|
42533
|
-
|
|
43432
|
+
const name = local.value;
|
|
43433
|
+
importedNames.push(name);
|
|
43434
|
+
vctx.facts.deadCode.bindings.push({
|
|
43435
|
+
name,
|
|
43436
|
+
kind: "import-specifier",
|
|
43437
|
+
line,
|
|
43438
|
+
column,
|
|
43439
|
+
source,
|
|
43440
|
+
isReferenced: false
|
|
43441
|
+
});
|
|
42534
43442
|
}
|
|
42535
43443
|
}
|
|
42536
43444
|
}
|
|
@@ -42620,6 +43528,13 @@ function isBindingSite(node, parent) {
|
|
|
42620
43528
|
if (params.some((param) => containsNode(param, node))) return true;
|
|
42621
43529
|
}
|
|
42622
43530
|
}
|
|
43531
|
+
if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") {
|
|
43532
|
+
if (parent.type === "ImportSpecifier") {
|
|
43533
|
+
if (parent.imported === node || parent.local === node) return true;
|
|
43534
|
+
} else {
|
|
43535
|
+
if (parent.local === node) return true;
|
|
43536
|
+
}
|
|
43537
|
+
}
|
|
42623
43538
|
return false;
|
|
42624
43539
|
}
|
|
42625
43540
|
function isNonComputedMemberProperty(node, parent) {
|
|
@@ -42686,6 +43601,9 @@ function handleIdentifier(node, parent, path, vctx) {
|
|
|
42686
43601
|
if (typeof node.value === "string" && !isBindingSite(node, parent) && !isNonComputedMemberProperty(node, parent)) {
|
|
42687
43602
|
markStateReference(node.value, vctx);
|
|
42688
43603
|
trackPropUsage(node, parent, path, vctx);
|
|
43604
|
+
vctx.facts.referencedNames.add(node.value);
|
|
43605
|
+
const top = vctx.ctx.stack[vctx.ctx.stack.length - 1];
|
|
43606
|
+
if (top) top.references.add(node.value);
|
|
42689
43607
|
}
|
|
42690
43608
|
return false;
|
|
42691
43609
|
}
|
|
@@ -42826,6 +43744,20 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
|
|
|
42826
43744
|
frame.bindings.add(bindingName);
|
|
42827
43745
|
}
|
|
42828
43746
|
}
|
|
43747
|
+
if (bindingNames.length > 0) {
|
|
43748
|
+
const parent = node.parent;
|
|
43749
|
+
const kind = isObject(parent) && parent.type === "VariableDeclaration" ? String(parent.kind ?? "var") : "var";
|
|
43750
|
+
const { line, column } = positionFrom(id, vctx.lineOffsets);
|
|
43751
|
+
for (const bindingName of bindingNames) {
|
|
43752
|
+
vctx.facts.deadCode.bindings.push({
|
|
43753
|
+
name: bindingName,
|
|
43754
|
+
kind,
|
|
43755
|
+
line,
|
|
43756
|
+
column,
|
|
43757
|
+
isReferenced: false
|
|
43758
|
+
});
|
|
43759
|
+
}
|
|
43760
|
+
}
|
|
42829
43761
|
if (isUseStateDeclarator(node)) {
|
|
42830
43762
|
const binding = extractStateBinding(node, vctx.lineOffsets);
|
|
42831
43763
|
if (binding) {
|
|
@@ -42845,6 +43777,36 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
|
|
|
42845
43777
|
}
|
|
42846
43778
|
return true;
|
|
42847
43779
|
}
|
|
43780
|
+
function handleIfStatement(node, _parent, _path, vctx) {
|
|
43781
|
+
if (!isObject(node)) return false;
|
|
43782
|
+
const test = node.test;
|
|
43783
|
+
if (!isObject(test)) return false;
|
|
43784
|
+
if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
|
|
43785
|
+
const { line, column } = positionFrom(test, vctx.lineOffsets);
|
|
43786
|
+
vctx.facts.deadCode.constantConditions.push({
|
|
43787
|
+
kind: test.value ? "if-true" : "if-false",
|
|
43788
|
+
condition: String(test.value),
|
|
43789
|
+
line,
|
|
43790
|
+
column
|
|
43791
|
+
});
|
|
43792
|
+
}
|
|
43793
|
+
return false;
|
|
43794
|
+
}
|
|
43795
|
+
function handleWhileStatement(node, _parent, _path, vctx) {
|
|
43796
|
+
if (!isObject(node)) return false;
|
|
43797
|
+
const test = node.test;
|
|
43798
|
+
if (!isObject(test)) return false;
|
|
43799
|
+
if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
|
|
43800
|
+
const { line, column } = positionFrom(test, vctx.lineOffsets);
|
|
43801
|
+
vctx.facts.deadCode.constantConditions.push({
|
|
43802
|
+
kind: test.value ? "while-true" : "while-false",
|
|
43803
|
+
condition: String(test.value),
|
|
43804
|
+
line,
|
|
43805
|
+
column
|
|
43806
|
+
});
|
|
43807
|
+
}
|
|
43808
|
+
return false;
|
|
43809
|
+
}
|
|
42848
43810
|
function dispatchNode(node, parent, path, vctx) {
|
|
42849
43811
|
if (!isObject(node)) return false;
|
|
42850
43812
|
const type = getNodeType(node);
|
|
@@ -42869,7 +43831,9 @@ var init_dispatch = __esm({
|
|
|
42869
43831
|
MemberExpression: handleMemberExpression,
|
|
42870
43832
|
JSXAttribute: handleJSXAttribute,
|
|
42871
43833
|
JSXOpeningElement: handleJSXOpeningElement,
|
|
42872
|
-
VariableDeclarator: handleVariableDeclarator
|
|
43834
|
+
VariableDeclarator: handleVariableDeclarator,
|
|
43835
|
+
IfStatement: handleIfStatement,
|
|
43836
|
+
WhileStatement: handleWhileStatement
|
|
42873
43837
|
};
|
|
42874
43838
|
}
|
|
42875
43839
|
});
|
|
@@ -43020,6 +43984,17 @@ function buildV2Facts(facts, source, ext, framework, config, templateClassNames
|
|
|
43020
43984
|
},
|
|
43021
43985
|
logic: buildLogicBlock(facts),
|
|
43022
43986
|
designTokens: scanDesignTokens(facts.staticClassNames),
|
|
43987
|
+
// dead-code detector. Copy the internal accumulator
|
|
43988
|
+
// into the v2 shape, marking each binding as referenced
|
|
43989
|
+
// iff the file-level referenced-name set contains its name.
|
|
43990
|
+
deadCode: {
|
|
43991
|
+
bindings: facts.deadCode.bindings.map((b) => ({
|
|
43992
|
+
...b,
|
|
43993
|
+
isReferenced: facts.referencedNames.has(b.name)
|
|
43994
|
+
})),
|
|
43995
|
+
constantConditions: facts.deadCode.constantConditions,
|
|
43996
|
+
unreachableStatements: facts.deadCode.unreachableStatements
|
|
43997
|
+
},
|
|
43023
43998
|
componentSizes: facts.componentSizes.map((cs) => ({
|
|
43024
43999
|
name: cs.name,
|
|
43025
44000
|
lineCount: cs.lineCount,
|
|
@@ -43101,7 +44076,17 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43101
44076
|
componentSizes: [],
|
|
43102
44077
|
astroComponents: [],
|
|
43103
44078
|
fetchCalls: [],
|
|
43104
|
-
optimisticUpdates: []
|
|
44079
|
+
optimisticUpdates: [],
|
|
44080
|
+
// dead-code detector. The visitor's identifier walk + import/
|
|
44081
|
+
// branch/return handlers populate these. The v2 builder at the
|
|
44082
|
+
// bottom of extractFacts() reads them and produces
|
|
44083
|
+
// `facts.v2.deadCode`.
|
|
44084
|
+
deadCode: {
|
|
44085
|
+
bindings: [],
|
|
44086
|
+
constantConditions: [],
|
|
44087
|
+
unreachableStatements: []
|
|
44088
|
+
},
|
|
44089
|
+
referencedNames: /* @__PURE__ */ new Set()
|
|
43105
44090
|
};
|
|
43106
44091
|
const ctx = {
|
|
43107
44092
|
stack: [],
|
|
@@ -43188,6 +44173,16 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43188
44173
|
propBindingSet.add(bindingName);
|
|
43189
44174
|
}
|
|
43190
44175
|
}
|
|
44176
|
+
const { line: pLine, column: pCol } = positionFrom(param, lineOffsets);
|
|
44177
|
+
for (const bindingName of collectBindingNames2(param)) {
|
|
44178
|
+
facts.deadCode.bindings.push({
|
|
44179
|
+
name: bindingName,
|
|
44180
|
+
kind: "parameter",
|
|
44181
|
+
line: pLine,
|
|
44182
|
+
column: pCol,
|
|
44183
|
+
isReferenced: false
|
|
44184
|
+
});
|
|
44185
|
+
}
|
|
43191
44186
|
}
|
|
43192
44187
|
}
|
|
43193
44188
|
ctx.stack.push({
|
|
@@ -43203,6 +44198,12 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43203
44198
|
propUsages: [],
|
|
43204
44199
|
isComponent,
|
|
43205
44200
|
bindings,
|
|
44201
|
+
// dead-code detector: per-frame referenced-name set.
|
|
44202
|
+
// Identifiers encountered inside the frame are added to this
|
|
44203
|
+
// set; the deadCode builder unions it with parent frames at
|
|
44204
|
+
// pop time so a binding is considered used if any reachable
|
|
44205
|
+
// scope references it.
|
|
44206
|
+
references: /* @__PURE__ */ new Set(),
|
|
43206
44207
|
propBindingSet,
|
|
43207
44208
|
propUsageSet: /* @__PURE__ */ new Set(),
|
|
43208
44209
|
node
|
|
@@ -43298,6 +44299,11 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43298
44299
|
mergeTemplateClassNames(filePath, source, facts, templateClassNames);
|
|
43299
44300
|
const { ext } = splitFilePath(filePath);
|
|
43300
44301
|
facts._source = source;
|
|
44302
|
+
facts.deadCode.unreachableStatements = findUnreachableStatements(
|
|
44303
|
+
ast,
|
|
44304
|
+
source,
|
|
44305
|
+
lineOffsets
|
|
44306
|
+
);
|
|
43301
44307
|
const v2 = buildV2Facts(facts, source, ext, framework, config, templateClassNames);
|
|
43302
44308
|
return envelopeScanFacts(filePath, v2);
|
|
43303
44309
|
}
|
|
@@ -43980,6 +44986,11 @@ var init_builtins = __esm({
|
|
|
43980
44986
|
init_missing_not_null();
|
|
43981
44987
|
init_naming_inconsistency();
|
|
43982
44988
|
init_sql_concat();
|
|
44989
|
+
init_dead_branch();
|
|
44990
|
+
init_unreachable();
|
|
44991
|
+
init_unused_import();
|
|
44992
|
+
init_unused_local();
|
|
44993
|
+
init_unused_parameter();
|
|
43983
44994
|
init_broken_link();
|
|
43984
44995
|
init_expired_code_example();
|
|
43985
44996
|
init_stale_function_reference();
|
|
@@ -44076,6 +45087,11 @@ var init_builtins = __esm({
|
|
|
44076
45087
|
missingNotNullRule,
|
|
44077
45088
|
namingInconsistencyRule,
|
|
44078
45089
|
sqlConcatRule,
|
|
45090
|
+
deadBranchRule,
|
|
45091
|
+
unreachableRule,
|
|
45092
|
+
unusedImportRule,
|
|
45093
|
+
unusedLocalRule,
|
|
45094
|
+
unusedParameterRule,
|
|
44079
45095
|
brokenLinkRule,
|
|
44080
45096
|
expiredCodeExampleRule,
|
|
44081
45097
|
staleFunctionReferenceRule,
|
|
@@ -44614,7 +45630,7 @@ var init_validation = __esm({
|
|
|
44614
45630
|
// src/config/load.ts
|
|
44615
45631
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
|
|
44616
45632
|
import { dirname as dirname7, extname as extname5, join as join11, resolve as resolve6 } from "path";
|
|
44617
|
-
import { createRequire
|
|
45633
|
+
import { createRequire } from "module";
|
|
44618
45634
|
function deepMerge(target, source) {
|
|
44619
45635
|
const out = { ...target };
|
|
44620
45636
|
for (const key of Object.keys(source)) {
|
|
@@ -44650,8 +45666,8 @@ function detectJsLoader(configPath) {
|
|
|
44650
45666
|
const pkgPath = join11(current, "package.json");
|
|
44651
45667
|
if (existsSync10(pkgPath)) {
|
|
44652
45668
|
try {
|
|
44653
|
-
const
|
|
44654
|
-
return
|
|
45669
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
45670
|
+
return pkg.type === "module" ? "import" : "require";
|
|
44655
45671
|
} catch {
|
|
44656
45672
|
return "require";
|
|
44657
45673
|
}
|
|
@@ -44665,7 +45681,7 @@ function detectJsLoader(configPath) {
|
|
|
44665
45681
|
async function loadConfigFile(path) {
|
|
44666
45682
|
const loader = detectJsLoader(path);
|
|
44667
45683
|
if (loader === "require") {
|
|
44668
|
-
const req =
|
|
45684
|
+
const req = createRequire(import.meta.url);
|
|
44669
45685
|
const mod2 = req(path);
|
|
44670
45686
|
return mod2.default ?? mod2;
|
|
44671
45687
|
}
|
|
@@ -44846,7 +45862,7 @@ var init_init = __esm({
|
|
|
44846
45862
|
});
|
|
44847
45863
|
|
|
44848
45864
|
// src/config/index.ts
|
|
44849
|
-
var
|
|
45865
|
+
var init_config2 = __esm({
|
|
44850
45866
|
"src/config/index.ts"() {
|
|
44851
45867
|
"use strict";
|
|
44852
45868
|
init_defaults();
|
|
@@ -46991,6 +48007,61 @@ var init_signal_strength = __esm({
|
|
|
46991
48007
|
_calibrationNote: "v0.17.0 ship \u2014 not in v7 per-rule table. Default-off until calibration data lands. Backed by: OWASP Foundation (2021), *OWASP Top 10 \u2014 A03:2021 Injection*, https://owasp.org/Top10/A03_2021-Injection/; OWASP Foundation (2017), *SQL Injection Prevention Cheat Sheet*. (Template-literal SQL with ${...} interpolation is the #1 SQL injection vector in AI-generated TypeScript code.)",
|
|
46992
48008
|
aiSpecific: true
|
|
46993
48009
|
},
|
|
48010
|
+
"dead/unused-import": {
|
|
48011
|
+
recall: 0,
|
|
48012
|
+
fpRate: 0,
|
|
48013
|
+
ratio: 0,
|
|
48014
|
+
precision: 0,
|
|
48015
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48016
|
+
verdict: "DORMANT",
|
|
48017
|
+
defaultOff: true,
|
|
48018
|
+
_calibrationNote: "v0.18.5 ship \u2014 not in v7 per-rule table. Default-off until v8 calibration data lands. The first of 5 planned `dead/*` rules (this one + dead/unused-local + dead/unused-parameter + dead/dead-branch + dead/unreachable). The pattern is the canonical AI-iteration rot: the model adds an import when introducing a feature, then rewrites the function later without cleaning up. Most real-world tsconfig.json files have `noUnusedLocals: false`, so tsc never fires.",
|
|
48019
|
+
aiSpecific: true
|
|
48020
|
+
},
|
|
48021
|
+
"dead/unused-local": {
|
|
48022
|
+
recall: 0,
|
|
48023
|
+
fpRate: 0,
|
|
48024
|
+
ratio: 0,
|
|
48025
|
+
precision: 0,
|
|
48026
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48027
|
+
verdict: "DORMANT",
|
|
48028
|
+
defaultOff: true,
|
|
48029
|
+
_calibrationNote: "v0.18.5b ship \u2014 not in v7 per-rule table. Default-off until v8 calibration data lands. The second of 5 planned `dead/*` rules. Muchnick 1997 Ch. 13 'liveness analysis' (textbook compiler optimization).",
|
|
48030
|
+
aiSpecific: true
|
|
48031
|
+
},
|
|
48032
|
+
"dead/unused-parameter": {
|
|
48033
|
+
recall: 0,
|
|
48034
|
+
fpRate: 0,
|
|
48035
|
+
ratio: 0,
|
|
48036
|
+
precision: 0,
|
|
48037
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48038
|
+
verdict: "DORMANT",
|
|
48039
|
+
defaultOff: true,
|
|
48040
|
+
_calibrationNote: "v0.18.5b ship \u2014 not in v7 per-rule table. Default-off until v8 calibration data lands. The third of 5 planned `dead/*` rules. AI agents add parameters when introducing features, then rewrite the function without removing parameters the new code does not need.",
|
|
48041
|
+
aiSpecific: true
|
|
48042
|
+
},
|
|
48043
|
+
"dead/dead-branch": {
|
|
48044
|
+
recall: 0,
|
|
48045
|
+
fpRate: 0,
|
|
48046
|
+
ratio: 0,
|
|
48047
|
+
precision: 0,
|
|
48048
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48049
|
+
verdict: "DORMANT",
|
|
48050
|
+
defaultOff: true,
|
|
48051
|
+
_calibrationNote: "v0.18.5b ship \u2014 not in v7 per-rule table. Default-off until v8 calibration data lands. The fourth of 5 planned `dead/*` rules. AI-iteration signature: feature flag toggled to a constant, or wrapper from a previous refactor.",
|
|
48052
|
+
aiSpecific: true
|
|
48053
|
+
},
|
|
48054
|
+
"dead/unreachable": {
|
|
48055
|
+
recall: 0,
|
|
48056
|
+
fpRate: 0,
|
|
48057
|
+
ratio: 0,
|
|
48058
|
+
precision: 0,
|
|
48059
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48060
|
+
verdict: "DORMANT",
|
|
48061
|
+
defaultOff: true,
|
|
48062
|
+
_calibrationNote: "v0.18.5b ship \u2014 not in v7 per-rule table. Default-off until v8 calibration data lands. The fifth of 5 planned `dead/*` rules. AI-iteration signature: model added an early return for a new error path, then forgot the rest of the function body was still sitting below it.",
|
|
48063
|
+
aiSpecific: true
|
|
48064
|
+
},
|
|
46994
48065
|
"docs/stale-package-reference": {
|
|
46995
48066
|
recall: 0,
|
|
46996
48067
|
fpRate: 0,
|
|
@@ -47951,7 +49022,7 @@ var init_cache = __esm({
|
|
|
47951
49022
|
"src/engine/cache.ts"() {
|
|
47952
49023
|
"use strict";
|
|
47953
49024
|
init_types();
|
|
47954
|
-
|
|
49025
|
+
init_config2();
|
|
47955
49026
|
BASELINE_VERSION = VERSION;
|
|
47956
49027
|
BASELINE_HASH_KEYS = /* @__PURE__ */ new Set([
|
|
47957
49028
|
"framework",
|
|
@@ -50442,7 +51513,7 @@ var init_finalizeReport = __esm({
|
|
|
50442
51513
|
init_dist2();
|
|
50443
51514
|
init_logger();
|
|
50444
51515
|
init_memory_io();
|
|
50445
|
-
|
|
51516
|
+
init_config2();
|
|
50446
51517
|
init_enrichReport();
|
|
50447
51518
|
init_assembleScanReport();
|
|
50448
51519
|
init_persistRun();
|
|
@@ -52366,11 +53437,11 @@ var init_watch = __esm({
|
|
|
52366
53437
|
init_worker();
|
|
52367
53438
|
init_threshold();
|
|
52368
53439
|
init_cache();
|
|
52369
|
-
|
|
53440
|
+
init_config2();
|
|
52370
53441
|
init_render();
|
|
52371
53442
|
init_logger();
|
|
52372
53443
|
init_error();
|
|
52373
|
-
|
|
53444
|
+
init_scan2();
|
|
52374
53445
|
init_renderOutput();
|
|
52375
53446
|
init_types();
|
|
52376
53447
|
}
|
|
@@ -52652,12 +53723,12 @@ async function scanProject(options) {
|
|
|
52652
53723
|
const { report } = await runScan({ ...options, workspace: options.cwd });
|
|
52653
53724
|
return report;
|
|
52654
53725
|
}
|
|
52655
|
-
var
|
|
53726
|
+
var init_scan2 = __esm({
|
|
52656
53727
|
"src/cli/scan.ts"() {
|
|
52657
53728
|
"use strict";
|
|
52658
53729
|
init_render();
|
|
52659
53730
|
init_threshold();
|
|
52660
|
-
|
|
53731
|
+
init_config2();
|
|
52661
53732
|
init_discover();
|
|
52662
53733
|
init_git();
|
|
52663
53734
|
init_cache_incremental();
|
|
@@ -52829,7 +53900,7 @@ async function runSuggest(args, ctx) {
|
|
|
52829
53900
|
}
|
|
52830
53901
|
async function runGovernance(args, ctx) {
|
|
52831
53902
|
try {
|
|
52832
|
-
const { runScan: runScan3 } = await Promise.resolve().then(() => (
|
|
53903
|
+
const { runScan: runScan3 } = await Promise.resolve().then(() => (init_scan2(), scan_exports));
|
|
52833
53904
|
const maxFiles = typeof args.maxFiles === "number" && Number.isFinite(args.maxFiles) && args.maxFiles > 0 ? Math.floor(args.maxFiles) : 500;
|
|
52834
53905
|
const { report } = await runScan3({
|
|
52835
53906
|
workspace: ctx.cwd,
|
|
@@ -53229,7 +54300,7 @@ var init_tools = __esm({
|
|
|
53229
54300
|
|
|
53230
54301
|
// src/index.ts
|
|
53231
54302
|
init_types();
|
|
53232
|
-
|
|
54303
|
+
init_config2();
|
|
53233
54304
|
init_dist2();
|
|
53234
54305
|
|
|
53235
54306
|
// src/cli/program.ts
|
|
@@ -53273,11 +54344,11 @@ function parseThreshold(value) {
|
|
|
53273
54344
|
// src/cli/program.ts
|
|
53274
54345
|
init_render();
|
|
53275
54346
|
init_threshold();
|
|
53276
|
-
|
|
53277
|
-
|
|
54347
|
+
init_scan2();
|
|
54348
|
+
init_scan2();
|
|
53278
54349
|
|
|
53279
54350
|
// src/cli/init.ts
|
|
53280
|
-
|
|
54351
|
+
init_config2();
|
|
53281
54352
|
init_discover();
|
|
53282
54353
|
init_git();
|
|
53283
54354
|
init_cache();
|
|
@@ -53769,7 +54840,7 @@ async function runDoctor(cwd) {
|
|
|
53769
54840
|
// src/cli/commands/badge.ts
|
|
53770
54841
|
init_render();
|
|
53771
54842
|
init_logger();
|
|
53772
|
-
|
|
54843
|
+
init_scan2();
|
|
53773
54844
|
import { resolve as resolve13 } from "path";
|
|
53774
54845
|
function registerBadge(program) {
|
|
53775
54846
|
program.command("badge").description(
|
|
@@ -53796,7 +54867,7 @@ function registerBadge(program) {
|
|
|
53796
54867
|
init_advice();
|
|
53797
54868
|
init_unified_diff();
|
|
53798
54869
|
init_logger();
|
|
53799
|
-
|
|
54870
|
+
init_scan2();
|
|
53800
54871
|
import { resolve as resolve14 } from "path";
|
|
53801
54872
|
function registerSuggest(program) {
|
|
53802
54873
|
program.command("suggest").description("print remediation advice").action(async (_cmdOptions, command) => {
|
|
@@ -53924,6 +54995,11 @@ var RULE_HINTS = {
|
|
|
53924
54995
|
"logic/qwik-hook-leak": "Use Qwik primitives ($state, $effect, useSignal) instead of React hooks (useState, useEffect).",
|
|
53925
54996
|
"logic/reactive-hook-soup": "Coordinate state via a single derived value (useMemo) or a state machine. Avoid chained useEffects that sync local state.",
|
|
53926
54997
|
"logic/zombie-state": "Remove unused useState or wire it into the component. Don't leave declared-but-never-read state bindings.",
|
|
54998
|
+
"dead/unused-import": "Remove the import or use the symbol somewhere. Unused imports are the most common AI-iteration signature \u2014 the model added it for a feature, then rewrote the function without cleaning up.",
|
|
54999
|
+
"dead/unused-local": "Remove the declaration or use the variable. AI-iteration signature: the model declared a binding for a feature, then rewrote the function without cleaning up.",
|
|
55000
|
+
"dead/unused-parameter": "Remove the parameter (and update every call site) or use it in the function body. AI-iteration signature: the model added a parameter for a feature, then rewrote the function without removing parameters the new code does not need.",
|
|
55001
|
+
"dead/dead-branch": "Replace the literal boolean with a real condition, or remove the dead branch. AI-iteration signature: a feature flag toggled to a constant, or a wrapper from a previous refactor that was never cleaned up.",
|
|
55002
|
+
"dead/unreachable": "Remove this statement \u2014 code after a return/throw/break/continue is unreachable. AI-iteration signature: the model added an early return for a new error path, then forgot the rest of the function body was still sitting below it.",
|
|
53927
55003
|
"perf/cls-image": "Add width/height attributes or an aspect-ratio utility to prevent layout shift.",
|
|
53928
55004
|
"perf/css-bloat": "Extract to a CSS variable (`--surface-card`) or a component prop when a class string repeats 5+ times.",
|
|
53929
55005
|
"perf/halstead-anomaly": "Introduce domain-specific identifiers and varied operations. Low vocabulary per line is a strong AI signature (Halstead 1977 \xA73).",
|
|
@@ -54184,7 +55260,7 @@ init_logger();
|
|
|
54184
55260
|
|
|
54185
55261
|
// src/mcp/server.ts
|
|
54186
55262
|
init_builtins();
|
|
54187
|
-
|
|
55263
|
+
init_config2();
|
|
54188
55264
|
init_tools();
|
|
54189
55265
|
var SERVER_INFO = {
|
|
54190
55266
|
name: "slopbrick",
|
|
@@ -55613,7 +56689,7 @@ function registerTrend(program) {
|
|
|
55613
56689
|
|
|
55614
56690
|
// src/cli/commands/drift.ts
|
|
55615
56691
|
init_logger();
|
|
55616
|
-
|
|
56692
|
+
init_scan2();
|
|
55617
56693
|
import { resolve as resolve26 } from "path";
|
|
55618
56694
|
|
|
55619
56695
|
// src/cli/drift.ts
|
|
@@ -55754,7 +56830,7 @@ function registerDrift(program) {
|
|
|
55754
56830
|
|
|
55755
56831
|
// src/cli/commands/pr.ts
|
|
55756
56832
|
init_logger();
|
|
55757
|
-
|
|
56833
|
+
init_scan2();
|
|
55758
56834
|
import { resolve as resolve28 } from "path";
|
|
55759
56835
|
|
|
55760
56836
|
// src/cli/pr.ts
|
|
@@ -56043,7 +57119,7 @@ function registerPr(program) {
|
|
|
56043
57119
|
|
|
56044
57120
|
// src/cli/commands/security.ts
|
|
56045
57121
|
init_logger();
|
|
56046
|
-
|
|
57122
|
+
init_scan2();
|
|
56047
57123
|
init_ai_security_risk();
|
|
56048
57124
|
import { resolve as resolve29 } from "path";
|
|
56049
57125
|
function registerSecurity(program) {
|
|
@@ -56102,11 +57178,11 @@ function registerSecurity(program) {
|
|
|
56102
57178
|
|
|
56103
57179
|
// src/cli/commands/test.ts
|
|
56104
57180
|
init_logger();
|
|
56105
|
-
|
|
57181
|
+
init_scan2();
|
|
56106
57182
|
import { resolve as resolve31 } from "path";
|
|
56107
57183
|
|
|
56108
57184
|
// src/cli/test.ts
|
|
56109
|
-
|
|
57185
|
+
init_scan2();
|
|
56110
57186
|
init_test_quality();
|
|
56111
57187
|
init_logger();
|
|
56112
57188
|
import { resolve as resolve30 } from "path";
|
|
@@ -56221,7 +57297,7 @@ function registerTest(program) {
|
|
|
56221
57297
|
|
|
56222
57298
|
// src/cli/commands/architecture.ts
|
|
56223
57299
|
init_logger();
|
|
56224
|
-
|
|
57300
|
+
init_scan2();
|
|
56225
57301
|
init_architecture_score();
|
|
56226
57302
|
import { resolve as resolve32 } from "path";
|
|
56227
57303
|
function registerArchitecture(program) {
|
|
@@ -56249,7 +57325,7 @@ function registerArchitecture(program) {
|
|
|
56249
57325
|
|
|
56250
57326
|
// src/cli/commands/business-logic.ts
|
|
56251
57327
|
init_logger();
|
|
56252
|
-
|
|
57328
|
+
init_scan2();
|
|
56253
57329
|
import { resolve as resolve33 } from "path";
|
|
56254
57330
|
|
|
56255
57331
|
// src/cli/business-logic.ts
|
|
@@ -56395,11 +57471,11 @@ function registerBusinessLogic(program) {
|
|
|
56395
57471
|
|
|
56396
57472
|
// src/cli/commands/maintenance-cost.ts
|
|
56397
57473
|
init_logger();
|
|
56398
|
-
|
|
57474
|
+
init_scan2();
|
|
56399
57475
|
import { resolve as resolve34 } from "path";
|
|
56400
57476
|
|
|
56401
57477
|
// src/cli/maintenance-cost.ts
|
|
56402
|
-
|
|
57478
|
+
init_scan2();
|
|
56403
57479
|
init_maintenance_cost();
|
|
56404
57480
|
init_logger();
|
|
56405
57481
|
async function runMaintenanceCostScan(cwd, config, options = {}) {
|
|
@@ -56538,11 +57614,11 @@ function registerMaintenanceCost(program) {
|
|
|
56538
57614
|
|
|
56539
57615
|
// src/cli/commands/docs.ts
|
|
56540
57616
|
init_logger();
|
|
56541
|
-
|
|
57617
|
+
init_scan2();
|
|
56542
57618
|
import { resolve as resolve35 } from "path";
|
|
56543
57619
|
|
|
56544
57620
|
// src/cli/docs.ts
|
|
56545
|
-
|
|
57621
|
+
init_scan2();
|
|
56546
57622
|
init_doc_freshness();
|
|
56547
57623
|
init_logger();
|
|
56548
57624
|
async function runDocsScan(cwd, config, options = {}) {
|
|
@@ -56687,11 +57763,11 @@ function registerDocs(program) {
|
|
|
56687
57763
|
|
|
56688
57764
|
// src/cli/commands/db.ts
|
|
56689
57765
|
init_logger();
|
|
56690
|
-
|
|
57766
|
+
init_scan2();
|
|
56691
57767
|
import { resolve as resolve36 } from "path";
|
|
56692
57768
|
|
|
56693
57769
|
// src/cli/db.ts
|
|
56694
|
-
|
|
57770
|
+
init_scan2();
|
|
56695
57771
|
init_db_health();
|
|
56696
57772
|
init_logger();
|
|
56697
57773
|
async function runDbScan(cwd, config, options = {}) {
|
|
@@ -56830,7 +57906,7 @@ function registerDb(program) {
|
|
|
56830
57906
|
|
|
56831
57907
|
// src/cli/commands/patterns.ts
|
|
56832
57908
|
init_logger();
|
|
56833
|
-
|
|
57909
|
+
init_scan2();
|
|
56834
57910
|
import { resolve as resolve37 } from "path";
|
|
56835
57911
|
|
|
56836
57912
|
// src/engine/patterns.ts
|
|
@@ -57178,7 +58254,7 @@ function registerPatterns(program) {
|
|
|
57178
58254
|
|
|
57179
58255
|
// src/cli/commands/research.ts
|
|
57180
58256
|
init_logger();
|
|
57181
|
-
|
|
58257
|
+
init_config2();
|
|
57182
58258
|
import { existsSync as existsSync27, mkdirSync as mkdirSync14, readFileSync as readFileSync34, writeFileSync as writeFileSync17 } from "fs";
|
|
57183
58259
|
import { dirname as dirname18, resolve as resolve38 } from "path";
|
|
57184
58260
|
function registerResearch(program) {
|
|
@@ -57261,8 +58337,8 @@ init_logger();
|
|
|
57261
58337
|
init_builtins();
|
|
57262
58338
|
import { existsSync as existsSync28, mkdirSync as mkdirSync15, readFileSync as readFileSync35, writeFileSync as writeFileSync18 } from "fs";
|
|
57263
58339
|
import { dirname as dirname19, join as join29, resolve as resolve39 } from "path";
|
|
57264
|
-
|
|
57265
|
-
|
|
58340
|
+
init_scan2();
|
|
58341
|
+
init_config2();
|
|
57266
58342
|
init_threshold();
|
|
57267
58343
|
init_git();
|
|
57268
58344
|
init_cache();
|
|
@@ -57743,7 +58819,7 @@ function registerScan(program, scanAction) {
|
|
|
57743
58819
|
}
|
|
57744
58820
|
|
|
57745
58821
|
// src/cli/program.ts
|
|
57746
|
-
|
|
58822
|
+
init_config2();
|
|
57747
58823
|
init_git();
|
|
57748
58824
|
init_logger();
|
|
57749
58825
|
init_unified_diff();
|
|
@@ -58309,7 +59385,7 @@ function formatGroupedHelp(cmd) {
|
|
|
58309
59385
|
}
|
|
58310
59386
|
|
|
58311
59387
|
// src/cli/program.ts
|
|
58312
|
-
|
|
59388
|
+
init_scan2();
|
|
58313
59389
|
process.on("uncaughtException", (err) => {
|
|
58314
59390
|
logger.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
58315
59391
|
process.exit(3);
|