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.cjs
CHANGED
|
@@ -31,15 +31,41 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
));
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
|
-
// src/types.ts
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
"src/types.ts"() {
|
|
34
|
+
// src/types/_header.ts
|
|
35
|
+
var VERSION;
|
|
36
|
+
var init_header = __esm({
|
|
37
|
+
"src/types/_header.ts"() {
|
|
38
|
+
"use strict";
|
|
39
|
+
VERSION = "0.18.7";
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// src/types/primitives.ts
|
|
44
|
+
var init_primitives = __esm({
|
|
45
|
+
"src/types/primitives.ts"() {
|
|
46
|
+
"use strict";
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// src/types/scan.ts
|
|
51
|
+
var init_scan = __esm({
|
|
52
|
+
"src/types/scan.ts"() {
|
|
53
|
+
"use strict";
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// src/types/config.ts
|
|
58
|
+
var init_config = __esm({
|
|
59
|
+
"src/types/config.ts"() {
|
|
60
|
+
"use strict";
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// src/types/report.ts
|
|
65
|
+
var AI_SECURITY_NUMERIC, REPOSITORY_HEALTH_WEIGHTS;
|
|
66
|
+
var init_report = __esm({
|
|
67
|
+
"src/types/report.ts"() {
|
|
38
68
|
"use strict";
|
|
39
|
-
import_node_module = require("module");
|
|
40
|
-
require2 = (0, import_node_module.createRequire)(__importMetaUrl);
|
|
41
|
-
pkg = require2("../package.json");
|
|
42
|
-
VERSION = pkg.version;
|
|
43
69
|
AI_SECURITY_NUMERIC = {
|
|
44
70
|
low: 100,
|
|
45
71
|
medium: 75,
|
|
@@ -59,6 +85,34 @@ var init_types = __esm({
|
|
|
59
85
|
}
|
|
60
86
|
});
|
|
61
87
|
|
|
88
|
+
// src/types/project-report.ts
|
|
89
|
+
var init_project_report = __esm({
|
|
90
|
+
"src/types/project-report.ts"() {
|
|
91
|
+
"use strict";
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// src/types/baseline.ts
|
|
96
|
+
var init_baseline = __esm({
|
|
97
|
+
"src/types/baseline.ts"() {
|
|
98
|
+
"use strict";
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// src/types/index.ts
|
|
103
|
+
var init_types = __esm({
|
|
104
|
+
"src/types/index.ts"() {
|
|
105
|
+
"use strict";
|
|
106
|
+
init_header();
|
|
107
|
+
init_primitives();
|
|
108
|
+
init_scan();
|
|
109
|
+
init_config();
|
|
110
|
+
init_report();
|
|
111
|
+
init_project_report();
|
|
112
|
+
init_baseline();
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
62
116
|
// src/config/defaults.ts
|
|
63
117
|
var DEFAULT_SPACING_SCALE, DEFAULT_RADIUS_SCALE, DEFAULT_RULE_CONFIG, DEFAULT_CONFIG;
|
|
64
118
|
var init_defaults = __esm({
|
|
@@ -310,9 +364,9 @@ function findWorkspacePackages(cwd) {
|
|
|
310
364
|
const pkgPath = (0, import_node_path.join)(root, "package.json");
|
|
311
365
|
if ((0, import_node_fs.existsSync)(pkgPath)) {
|
|
312
366
|
try {
|
|
313
|
-
const
|
|
314
|
-
if (Array.isArray(
|
|
315
|
-
for (const pattern of
|
|
367
|
+
const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
|
|
368
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
369
|
+
for (const pattern of pkg.workspaces) {
|
|
316
370
|
packages.push(...expandWorkspacePattern(root, pattern));
|
|
317
371
|
}
|
|
318
372
|
}
|
|
@@ -370,11 +424,11 @@ function detectStylingSolution(cwd) {
|
|
|
370
424
|
let deps = {};
|
|
371
425
|
if ((0, import_node_fs2.existsSync)(pkgPath)) {
|
|
372
426
|
try {
|
|
373
|
-
const
|
|
427
|
+
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
|
|
374
428
|
deps = {
|
|
375
|
-
...
|
|
376
|
-
...
|
|
377
|
-
...
|
|
429
|
+
...pkg.dependencies,
|
|
430
|
+
...pkg.devDependencies,
|
|
431
|
+
...pkg.peerDependencies
|
|
378
432
|
};
|
|
379
433
|
} catch {
|
|
380
434
|
}
|
|
@@ -573,11 +627,11 @@ function detectStack(cwd) {
|
|
|
573
627
|
return {};
|
|
574
628
|
}
|
|
575
629
|
try {
|
|
576
|
-
const
|
|
630
|
+
const pkg = JSON.parse((0, import_node_fs3.readFileSync)(pkgPath, "utf-8"));
|
|
577
631
|
const deps = {
|
|
578
|
-
...
|
|
579
|
-
...
|
|
580
|
-
...
|
|
632
|
+
...pkg.dependencies,
|
|
633
|
+
...pkg.devDependencies,
|
|
634
|
+
...pkg.peerDependencies
|
|
581
635
|
};
|
|
582
636
|
const names = Object.keys(deps).map((name) => name.toLowerCase());
|
|
583
637
|
const result = {};
|
|
@@ -26213,13 +26267,13 @@ var init_default_react_stack = __esm({
|
|
|
26213
26267
|
for (const m of source.matchAll(IMPORT_LINE_RE)) {
|
|
26214
26268
|
const spec = m[1];
|
|
26215
26269
|
if (!spec) continue;
|
|
26216
|
-
const
|
|
26217
|
-
if (
|
|
26270
|
+
const pkg = spec.startsWith("@/") ? spec : spec.startsWith("@") ? spec.split("/").slice(0, 2).join("/") : spec.split("/")[0];
|
|
26271
|
+
if (pkg) importedPackages.add(pkg);
|
|
26218
26272
|
}
|
|
26219
26273
|
const hits = [];
|
|
26220
|
-
for (const
|
|
26221
|
-
if (DEFAULT_STACK_PACKAGES.some((p) => p ===
|
|
26222
|
-
hits.push(
|
|
26274
|
+
for (const pkg of importedPackages) {
|
|
26275
|
+
if (DEFAULT_STACK_PACKAGES.some((p) => p === pkg || p.startsWith(pkg + "/"))) {
|
|
26276
|
+
hits.push(pkg);
|
|
26223
26277
|
}
|
|
26224
26278
|
}
|
|
26225
26279
|
if (hits.length < MIN_HITS) return [];
|
|
@@ -28109,6 +28163,205 @@ var init_sql_concat = __esm({
|
|
|
28109
28163
|
}
|
|
28110
28164
|
});
|
|
28111
28165
|
|
|
28166
|
+
// src/rules/dead/dead-branch.ts
|
|
28167
|
+
var deadBranchRule;
|
|
28168
|
+
var init_dead_branch = __esm({
|
|
28169
|
+
"src/rules/dead/dead-branch.ts"() {
|
|
28170
|
+
"use strict";
|
|
28171
|
+
init_rule();
|
|
28172
|
+
deadBranchRule = createRule({
|
|
28173
|
+
id: "dead/dead-branch",
|
|
28174
|
+
category: "logic",
|
|
28175
|
+
severity: "medium",
|
|
28176
|
+
aiSpecific: true,
|
|
28177
|
+
description: "Literal boolean condition makes one branch statically dead",
|
|
28178
|
+
create(_context) {
|
|
28179
|
+
return {};
|
|
28180
|
+
},
|
|
28181
|
+
analyze(_context, facts) {
|
|
28182
|
+
const issues = [];
|
|
28183
|
+
if (!facts.v2) return issues;
|
|
28184
|
+
for (const cond of facts.v2.deadCode.constantConditions) {
|
|
28185
|
+
const isWhileTrue = cond.kind === "while-true";
|
|
28186
|
+
issues.push({
|
|
28187
|
+
ruleId: "dead/dead-branch",
|
|
28188
|
+
category: "logic",
|
|
28189
|
+
severity: isWhileTrue ? "low" : "medium",
|
|
28190
|
+
aiSpecific: true,
|
|
28191
|
+
message: isWhileTrue ? `Infinite loop with literal condition (${cond.kind})` : `Dead branch: condition is always ${cond.condition}`,
|
|
28192
|
+
line: cond.line,
|
|
28193
|
+
column: cond.column,
|
|
28194
|
+
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.`
|
|
28195
|
+
});
|
|
28196
|
+
}
|
|
28197
|
+
return issues;
|
|
28198
|
+
}
|
|
28199
|
+
});
|
|
28200
|
+
}
|
|
28201
|
+
});
|
|
28202
|
+
|
|
28203
|
+
// src/rules/dead/unreachable.ts
|
|
28204
|
+
var unreachableRule;
|
|
28205
|
+
var init_unreachable = __esm({
|
|
28206
|
+
"src/rules/dead/unreachable.ts"() {
|
|
28207
|
+
"use strict";
|
|
28208
|
+
init_rule();
|
|
28209
|
+
unreachableRule = createRule({
|
|
28210
|
+
id: "dead/unreachable",
|
|
28211
|
+
category: "logic",
|
|
28212
|
+
severity: "high",
|
|
28213
|
+
aiSpecific: true,
|
|
28214
|
+
description: "Statement is unreachable after an unconditional return/throw/break/continue",
|
|
28215
|
+
create(_context) {
|
|
28216
|
+
return {};
|
|
28217
|
+
},
|
|
28218
|
+
analyze(_context, facts) {
|
|
28219
|
+
const issues = [];
|
|
28220
|
+
if (!facts.v2) return issues;
|
|
28221
|
+
for (const u of facts.v2.deadCode.unreachableStatements) {
|
|
28222
|
+
if (u.snippet === "<unreachable>") continue;
|
|
28223
|
+
issues.push({
|
|
28224
|
+
ruleId: "dead/unreachable",
|
|
28225
|
+
category: "logic",
|
|
28226
|
+
severity: "high",
|
|
28227
|
+
aiSpecific: true,
|
|
28228
|
+
message: `Unreachable after ${u.terminator}: ${u.snippet}`,
|
|
28229
|
+
line: u.line,
|
|
28230
|
+
column: u.column,
|
|
28231
|
+
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.`
|
|
28232
|
+
});
|
|
28233
|
+
}
|
|
28234
|
+
return issues;
|
|
28235
|
+
}
|
|
28236
|
+
});
|
|
28237
|
+
}
|
|
28238
|
+
});
|
|
28239
|
+
|
|
28240
|
+
// src/rules/dead/unused-import.ts
|
|
28241
|
+
var unusedImportRule;
|
|
28242
|
+
var init_unused_import = __esm({
|
|
28243
|
+
"src/rules/dead/unused-import.ts"() {
|
|
28244
|
+
"use strict";
|
|
28245
|
+
init_rule();
|
|
28246
|
+
unusedImportRule = createRule({
|
|
28247
|
+
id: "dead/unused-import",
|
|
28248
|
+
category: "logic",
|
|
28249
|
+
severity: "low",
|
|
28250
|
+
aiSpecific: true,
|
|
28251
|
+
description: "ES module import is never referenced in the file",
|
|
28252
|
+
create(_context) {
|
|
28253
|
+
return {};
|
|
28254
|
+
},
|
|
28255
|
+
analyze(_context, facts) {
|
|
28256
|
+
const issues = [];
|
|
28257
|
+
if (!facts.v2) return issues;
|
|
28258
|
+
for (const binding of facts.v2.deadCode.bindings) {
|
|
28259
|
+
if (binding.kind !== "import-specifier" && binding.kind !== "import-default" && binding.kind !== "import-namespace") {
|
|
28260
|
+
continue;
|
|
28261
|
+
}
|
|
28262
|
+
if (binding.isReferenced) continue;
|
|
28263
|
+
if (!binding.name) continue;
|
|
28264
|
+
const source = binding.source ? ` from '${binding.source}'` : "";
|
|
28265
|
+
issues.push({
|
|
28266
|
+
ruleId: "dead/unused-import",
|
|
28267
|
+
category: "logic",
|
|
28268
|
+
severity: "low",
|
|
28269
|
+
aiSpecific: true,
|
|
28270
|
+
message: `Unused import: '${binding.name}'${source}`,
|
|
28271
|
+
line: binding.line,
|
|
28272
|
+
column: binding.column,
|
|
28273
|
+
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.`
|
|
28274
|
+
});
|
|
28275
|
+
}
|
|
28276
|
+
return issues;
|
|
28277
|
+
}
|
|
28278
|
+
});
|
|
28279
|
+
}
|
|
28280
|
+
});
|
|
28281
|
+
|
|
28282
|
+
// src/rules/dead/unused-local.ts
|
|
28283
|
+
var SKIP_NAMES, unusedLocalRule;
|
|
28284
|
+
var init_unused_local = __esm({
|
|
28285
|
+
"src/rules/dead/unused-local.ts"() {
|
|
28286
|
+
"use strict";
|
|
28287
|
+
init_rule();
|
|
28288
|
+
SKIP_NAMES = /* @__PURE__ */ new Set(["React", "_"]);
|
|
28289
|
+
unusedLocalRule = createRule({
|
|
28290
|
+
id: "dead/unused-local",
|
|
28291
|
+
category: "logic",
|
|
28292
|
+
severity: "low",
|
|
28293
|
+
aiSpecific: true,
|
|
28294
|
+
description: "Variable is declared but never read after declaration",
|
|
28295
|
+
create(_context) {
|
|
28296
|
+
return {};
|
|
28297
|
+
},
|
|
28298
|
+
analyze(_context, facts) {
|
|
28299
|
+
const issues = [];
|
|
28300
|
+
if (!facts.v2) return issues;
|
|
28301
|
+
for (const binding of facts.v2.deadCode.bindings) {
|
|
28302
|
+
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") {
|
|
28303
|
+
continue;
|
|
28304
|
+
}
|
|
28305
|
+
if (binding.isReferenced) continue;
|
|
28306
|
+
if (SKIP_NAMES.has(binding.name)) continue;
|
|
28307
|
+
if (binding.name.startsWith("_")) continue;
|
|
28308
|
+
issues.push({
|
|
28309
|
+
ruleId: "dead/unused-local",
|
|
28310
|
+
category: "logic",
|
|
28311
|
+
severity: "low",
|
|
28312
|
+
aiSpecific: true,
|
|
28313
|
+
message: `Unused ${binding.kind}: '${binding.name}'`,
|
|
28314
|
+
line: binding.line,
|
|
28315
|
+
column: binding.column,
|
|
28316
|
+
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.`
|
|
28317
|
+
});
|
|
28318
|
+
}
|
|
28319
|
+
return issues;
|
|
28320
|
+
}
|
|
28321
|
+
});
|
|
28322
|
+
}
|
|
28323
|
+
});
|
|
28324
|
+
|
|
28325
|
+
// src/rules/dead/unused-parameter.ts
|
|
28326
|
+
var unusedParameterRule;
|
|
28327
|
+
var init_unused_parameter = __esm({
|
|
28328
|
+
"src/rules/dead/unused-parameter.ts"() {
|
|
28329
|
+
"use strict";
|
|
28330
|
+
init_rule();
|
|
28331
|
+
unusedParameterRule = createRule({
|
|
28332
|
+
id: "dead/unused-parameter",
|
|
28333
|
+
category: "logic",
|
|
28334
|
+
severity: "low",
|
|
28335
|
+
aiSpecific: true,
|
|
28336
|
+
description: "Function parameter is declared but never read",
|
|
28337
|
+
create(_context) {
|
|
28338
|
+
return {};
|
|
28339
|
+
},
|
|
28340
|
+
analyze(_context, facts) {
|
|
28341
|
+
const issues = [];
|
|
28342
|
+
if (!facts.v2) return issues;
|
|
28343
|
+
for (const binding of facts.v2.deadCode.bindings) {
|
|
28344
|
+
if (binding.kind !== "parameter") continue;
|
|
28345
|
+
if (binding.isReferenced) continue;
|
|
28346
|
+
if (binding.name.startsWith("_")) continue;
|
|
28347
|
+
if (binding.name === "props") continue;
|
|
28348
|
+
issues.push({
|
|
28349
|
+
ruleId: "dead/unused-parameter",
|
|
28350
|
+
category: "logic",
|
|
28351
|
+
severity: "low",
|
|
28352
|
+
aiSpecific: true,
|
|
28353
|
+
message: `Unused parameter: '${binding.name}'`,
|
|
28354
|
+
line: binding.line,
|
|
28355
|
+
column: binding.column,
|
|
28356
|
+
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.`
|
|
28357
|
+
});
|
|
28358
|
+
}
|
|
28359
|
+
return issues;
|
|
28360
|
+
}
|
|
28361
|
+
});
|
|
28362
|
+
}
|
|
28363
|
+
});
|
|
28364
|
+
|
|
28112
28365
|
// src/engine/discover.ts
|
|
28113
28366
|
var discover_exports = {};
|
|
28114
28367
|
__export(discover_exports, {
|
|
@@ -28218,14 +28471,14 @@ var init_discover = __esm({
|
|
|
28218
28471
|
function readDeps(cwd) {
|
|
28219
28472
|
const pkgPath = (0, import_node_path5.join)(cwd, "package.json");
|
|
28220
28473
|
if (!(0, import_node_fs5.existsSync)(pkgPath)) return /* @__PURE__ */ new Set();
|
|
28221
|
-
let
|
|
28474
|
+
let pkg;
|
|
28222
28475
|
try {
|
|
28223
|
-
|
|
28476
|
+
pkg = JSON.parse((0, import_node_fs5.readFileSync)(pkgPath, "utf-8"));
|
|
28224
28477
|
} catch {
|
|
28225
28478
|
return /* @__PURE__ */ new Set();
|
|
28226
28479
|
}
|
|
28227
28480
|
const out = /* @__PURE__ */ new Set();
|
|
28228
|
-
for (const source of [
|
|
28481
|
+
for (const source of [pkg.dependencies, pkg.devDependencies]) {
|
|
28229
28482
|
if (source && typeof source === "object") {
|
|
28230
28483
|
for (const name of Object.keys(source)) out.add(name);
|
|
28231
28484
|
}
|
|
@@ -28241,8 +28494,8 @@ function detectConstitution(cwd) {
|
|
|
28241
28494
|
const deps = readDeps(cwd);
|
|
28242
28495
|
if (deps.size === 0) return {};
|
|
28243
28496
|
const out = {};
|
|
28244
|
-
for (const [
|
|
28245
|
-
if (deps.has(
|
|
28497
|
+
for (const [pkg, { field, signal }] of Object.entries(CONSTITUTION_SIGNALS)) {
|
|
28498
|
+
if (deps.has(pkg)) {
|
|
28246
28499
|
out[field] = pushUnique(
|
|
28247
28500
|
out[field],
|
|
28248
28501
|
signal
|
|
@@ -29512,6 +29765,9 @@ var init_expired_code_example = __esm({
|
|
|
29512
29765
|
const issues = [];
|
|
29513
29766
|
const source = facts.v2?._source;
|
|
29514
29767
|
if (!source) return issues;
|
|
29768
|
+
const packages = declaredPackages(context.cwd);
|
|
29769
|
+
const packageName = context.packageName;
|
|
29770
|
+
if (packageName) packages.add(packageName);
|
|
29515
29771
|
const blocks = extractFencedCodeBlocks(source);
|
|
29516
29772
|
for (const block of blocks) {
|
|
29517
29773
|
if (!CODE_LANGS.has(block.lang)) continue;
|
|
@@ -29519,7 +29775,7 @@ var init_expired_code_example = __esm({
|
|
|
29519
29775
|
const imports = extractImports(block.body);
|
|
29520
29776
|
for (const imp of imports) {
|
|
29521
29777
|
const pkgName = stripSubpath(imp);
|
|
29522
|
-
if (
|
|
29778
|
+
if (packages.has(pkgName)) continue;
|
|
29523
29779
|
issues.push({
|
|
29524
29780
|
ruleId: "docs/expired-code-example",
|
|
29525
29781
|
category: "docs",
|
|
@@ -29572,7 +29828,12 @@ function collectExports(cwd) {
|
|
|
29572
29828
|
/\bexport\s+class\s+([A-Za-z_$][\w$]*)/g,
|
|
29573
29829
|
/\bexport\s+interface\s+([A-Za-z_$][\w$]*)/g,
|
|
29574
29830
|
/\bexport\s+type\s+([A-Za-z_$][\w$]*)/g,
|
|
29575
|
-
/\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g
|
|
29831
|
+
/\bexport\s+default\s+(?:function\s+|class\s+)?([A-Za-z_$][\w$]*)/g,
|
|
29832
|
+
// v0.18.6: also collect field names from `export interface` and
|
|
29833
|
+
// `export type` declarations. Without this, fields like
|
|
29834
|
+
// `crossFileDrift`, `aiQuality`, `engineeringHygiene` are
|
|
29835
|
+
// flagged as stale even though they're valid type fields.
|
|
29836
|
+
/^\s*(?:readonly\s+)?([A-Za-z_$][\w$]*)\s*[?:]/gm
|
|
29576
29837
|
]) {
|
|
29577
29838
|
let m;
|
|
29578
29839
|
while ((m = re.exec(source)) !== null) {
|
|
@@ -29583,6 +29844,21 @@ function collectExports(cwd) {
|
|
|
29583
29844
|
}
|
|
29584
29845
|
return out;
|
|
29585
29846
|
}
|
|
29847
|
+
function looksLikeProseLabel(inside) {
|
|
29848
|
+
const trimmed = inside.trim();
|
|
29849
|
+
if (trimmed.length === 0) return false;
|
|
29850
|
+
if (trimmed.startsWith("`") || trimmed.startsWith("/")) return true;
|
|
29851
|
+
if (trimmed.includes("`")) return true;
|
|
29852
|
+
if (/\d+\s+[a-z]/i.test(trimmed)) return true;
|
|
29853
|
+
const parts = trimmed.split(",").map((s) => s.trim());
|
|
29854
|
+
if (parts.length >= 3) {
|
|
29855
|
+
const allNumeric = parts.every((p) => /^\d+\.?\d*$/.test(p));
|
|
29856
|
+
if (!allNumeric) return true;
|
|
29857
|
+
}
|
|
29858
|
+
if (trimmed.length > 40 && !trimmed.includes(",")) return true;
|
|
29859
|
+
if (trimmed.includes("\u2014") || trimmed.includes("\u2013")) return true;
|
|
29860
|
+
return false;
|
|
29861
|
+
}
|
|
29586
29862
|
var import_node_fs7, import_node_path7, RESERVED, SOURCE_EXTS, SOURCE_ROOTS, CAP, staleFunctionReferenceRule;
|
|
29587
29863
|
var init_stale_function_reference = __esm({
|
|
29588
29864
|
"src/rules/docs/stale-function-reference.ts"() {
|
|
@@ -29592,6 +29868,7 @@ var init_stale_function_reference = __esm({
|
|
|
29592
29868
|
init_rule();
|
|
29593
29869
|
init_doc_freshness();
|
|
29594
29870
|
RESERVED = /* @__PURE__ */ new Set([
|
|
29871
|
+
// JS reserved words
|
|
29595
29872
|
"true",
|
|
29596
29873
|
"false",
|
|
29597
29874
|
"null",
|
|
@@ -29691,7 +29968,472 @@ var init_stale_function_reference = __esm({
|
|
|
29691
29968
|
"next",
|
|
29692
29969
|
"vue",
|
|
29693
29970
|
"angular",
|
|
29694
|
-
"svelte"
|
|
29971
|
+
"svelte",
|
|
29972
|
+
// Framework / runtime names
|
|
29973
|
+
"html",
|
|
29974
|
+
"astro",
|
|
29975
|
+
"python",
|
|
29976
|
+
"jvm",
|
|
29977
|
+
"kotlin",
|
|
29978
|
+
"swift",
|
|
29979
|
+
"dart",
|
|
29980
|
+
"ruby",
|
|
29981
|
+
"rust",
|
|
29982
|
+
"cpp",
|
|
29983
|
+
"go",
|
|
29984
|
+
"java",
|
|
29985
|
+
"php",
|
|
29986
|
+
"php-html",
|
|
29987
|
+
"csharp",
|
|
29988
|
+
"typescript",
|
|
29989
|
+
"javascript",
|
|
29990
|
+
"jsx",
|
|
29991
|
+
"tsx",
|
|
29992
|
+
"mjs",
|
|
29993
|
+
"cjs",
|
|
29994
|
+
"esnext",
|
|
29995
|
+
"es6",
|
|
29996
|
+
"es2022",
|
|
29997
|
+
"es2023",
|
|
29998
|
+
"esm",
|
|
29999
|
+
"cjs",
|
|
30000
|
+
"umd",
|
|
30001
|
+
"amd",
|
|
30002
|
+
"commonjs",
|
|
30003
|
+
"require",
|
|
30004
|
+
"module",
|
|
30005
|
+
"exports",
|
|
30006
|
+
"define",
|
|
30007
|
+
"global",
|
|
30008
|
+
"window",
|
|
30009
|
+
"document",
|
|
30010
|
+
"process",
|
|
30011
|
+
"console",
|
|
30012
|
+
"buffer",
|
|
30013
|
+
"stream",
|
|
30014
|
+
"fetch",
|
|
30015
|
+
"axios",
|
|
30016
|
+
"express",
|
|
30017
|
+
"fastify",
|
|
30018
|
+
"koa",
|
|
30019
|
+
"hapi",
|
|
30020
|
+
"nextjs",
|
|
30021
|
+
"nuxt",
|
|
30022
|
+
"remix",
|
|
30023
|
+
"gatsby",
|
|
30024
|
+
"sveltekit",
|
|
30025
|
+
"solid",
|
|
30026
|
+
"preact",
|
|
30027
|
+
"qwik",
|
|
30028
|
+
"lit",
|
|
30029
|
+
"stencil",
|
|
30030
|
+
"marko",
|
|
30031
|
+
"alpine",
|
|
30032
|
+
"stimulus",
|
|
30033
|
+
"turbo",
|
|
30034
|
+
"hotwire",
|
|
30035
|
+
// Models / providers
|
|
30036
|
+
"gpt",
|
|
30037
|
+
"claude",
|
|
30038
|
+
"gpt-3",
|
|
30039
|
+
"gpt-3.5",
|
|
30040
|
+
"gpt-4",
|
|
30041
|
+
"gpt-oss",
|
|
30042
|
+
"haiku",
|
|
30043
|
+
"sonnet",
|
|
30044
|
+
"opus",
|
|
30045
|
+
"aider",
|
|
30046
|
+
"tabby",
|
|
30047
|
+
"copilot",
|
|
30048
|
+
"cursor",
|
|
30049
|
+
"windsurf",
|
|
30050
|
+
"devin",
|
|
30051
|
+
"claude-code",
|
|
30052
|
+
// LLM-detection lingo
|
|
30053
|
+
"heuristic",
|
|
30054
|
+
"heuristics",
|
|
30055
|
+
"calibrate",
|
|
30056
|
+
"calibration",
|
|
30057
|
+
"calibrator",
|
|
30058
|
+
"corpus",
|
|
30059
|
+
"baseline",
|
|
30060
|
+
"baselines",
|
|
30061
|
+
"corpus-baselines",
|
|
30062
|
+
"lift",
|
|
30063
|
+
"recall",
|
|
30064
|
+
"precision",
|
|
30065
|
+
"fpRate",
|
|
30066
|
+
"ratio",
|
|
30067
|
+
"verdict",
|
|
30068
|
+
"USEFUL",
|
|
30069
|
+
"NOISY",
|
|
30070
|
+
"INVERTED",
|
|
30071
|
+
"HYGIENE",
|
|
30072
|
+
"DORMANT",
|
|
30073
|
+
"OK",
|
|
30074
|
+
"aiSpecific",
|
|
30075
|
+
"defaultOff",
|
|
30076
|
+
// Common slop-audit verbs/nouns
|
|
30077
|
+
"commit",
|
|
30078
|
+
"push",
|
|
30079
|
+
"reset",
|
|
30080
|
+
"rebase",
|
|
30081
|
+
"merge",
|
|
30082
|
+
"cherry-pick",
|
|
30083
|
+
"revert",
|
|
30084
|
+
"scan",
|
|
30085
|
+
"parse",
|
|
30086
|
+
"build",
|
|
30087
|
+
"test",
|
|
30088
|
+
"lint",
|
|
30089
|
+
"format",
|
|
30090
|
+
"check",
|
|
30091
|
+
"audit",
|
|
30092
|
+
"fix",
|
|
30093
|
+
"patch",
|
|
30094
|
+
"diff",
|
|
30095
|
+
"pr",
|
|
30096
|
+
"ci",
|
|
30097
|
+
"cd",
|
|
30098
|
+
"gh",
|
|
30099
|
+
"npm",
|
|
30100
|
+
"npx",
|
|
30101
|
+
"pnpm",
|
|
30102
|
+
"yaml",
|
|
30103
|
+
"json",
|
|
30104
|
+
"toml",
|
|
30105
|
+
"csv",
|
|
30106
|
+
"md",
|
|
30107
|
+
"mdx",
|
|
30108
|
+
"sh",
|
|
30109
|
+
"bash",
|
|
30110
|
+
"zsh",
|
|
30111
|
+
"fish",
|
|
30112
|
+
"ascii",
|
|
30113
|
+
"utf8",
|
|
30114
|
+
"utf-8",
|
|
30115
|
+
"base64",
|
|
30116
|
+
"hex",
|
|
30117
|
+
"binary",
|
|
30118
|
+
"text",
|
|
30119
|
+
// Common design / ui terms
|
|
30120
|
+
"flex",
|
|
30121
|
+
"grid",
|
|
30122
|
+
"auto",
|
|
30123
|
+
"min",
|
|
30124
|
+
"max",
|
|
30125
|
+
"fill",
|
|
30126
|
+
"stretch",
|
|
30127
|
+
"wrap",
|
|
30128
|
+
"nowrap",
|
|
30129
|
+
"inline",
|
|
30130
|
+
"block",
|
|
30131
|
+
"hidden",
|
|
30132
|
+
"visible",
|
|
30133
|
+
"static",
|
|
30134
|
+
"fixed",
|
|
30135
|
+
"absolute",
|
|
30136
|
+
"relative",
|
|
30137
|
+
"sticky",
|
|
30138
|
+
"pointer",
|
|
30139
|
+
"cursor",
|
|
30140
|
+
"focus",
|
|
30141
|
+
"hover",
|
|
30142
|
+
"active",
|
|
30143
|
+
"disabled",
|
|
30144
|
+
"readonly",
|
|
30145
|
+
"primary",
|
|
30146
|
+
"secondary",
|
|
30147
|
+
"tertiary",
|
|
30148
|
+
"success",
|
|
30149
|
+
"warning",
|
|
30150
|
+
"danger",
|
|
30151
|
+
"info",
|
|
30152
|
+
"muted",
|
|
30153
|
+
"sm",
|
|
30154
|
+
"md",
|
|
30155
|
+
"lg",
|
|
30156
|
+
"xl",
|
|
30157
|
+
"xxl",
|
|
30158
|
+
"xs",
|
|
30159
|
+
"2xl",
|
|
30160
|
+
"3xl",
|
|
30161
|
+
"4xl",
|
|
30162
|
+
// Math / types
|
|
30163
|
+
"array",
|
|
30164
|
+
"map",
|
|
30165
|
+
"set",
|
|
30166
|
+
"weakmap",
|
|
30167
|
+
"weakset",
|
|
30168
|
+
"object",
|
|
30169
|
+
"string",
|
|
30170
|
+
"number",
|
|
30171
|
+
"boolean",
|
|
30172
|
+
"bigint",
|
|
30173
|
+
"symbol",
|
|
30174
|
+
"null",
|
|
30175
|
+
"undefined",
|
|
30176
|
+
"any",
|
|
30177
|
+
"unknown",
|
|
30178
|
+
"never",
|
|
30179
|
+
"void",
|
|
30180
|
+
"readonly",
|
|
30181
|
+
"private",
|
|
30182
|
+
"public",
|
|
30183
|
+
"protected",
|
|
30184
|
+
"static",
|
|
30185
|
+
"abstract",
|
|
30186
|
+
"async",
|
|
30187
|
+
"generator",
|
|
30188
|
+
"iterator",
|
|
30189
|
+
"iterable",
|
|
30190
|
+
"promise",
|
|
30191
|
+
"observable",
|
|
30192
|
+
// Auth / domain
|
|
30193
|
+
"admin",
|
|
30194
|
+
"user",
|
|
30195
|
+
"guest",
|
|
30196
|
+
"anonymous",
|
|
30197
|
+
"authenticated",
|
|
30198
|
+
"unauthenticated",
|
|
30199
|
+
"jwt",
|
|
30200
|
+
"oauth",
|
|
30201
|
+
"oidc",
|
|
30202
|
+
"saml",
|
|
30203
|
+
"csrf",
|
|
30204
|
+
"xss",
|
|
30205
|
+
"sql",
|
|
30206
|
+
"nosql",
|
|
30207
|
+
"orm",
|
|
30208
|
+
"prisma",
|
|
30209
|
+
"drizzle",
|
|
30210
|
+
"sequelize",
|
|
30211
|
+
"mongoose",
|
|
30212
|
+
"redis",
|
|
30213
|
+
"postgres",
|
|
30214
|
+
"mysql",
|
|
30215
|
+
"sqlite",
|
|
30216
|
+
"kafka",
|
|
30217
|
+
"rabbitmq",
|
|
30218
|
+
"graphql",
|
|
30219
|
+
"rest",
|
|
30220
|
+
"grpc",
|
|
30221
|
+
"websocket",
|
|
30222
|
+
// slop-audit specific
|
|
30223
|
+
"slopbrick",
|
|
30224
|
+
"usebrick",
|
|
30225
|
+
"deadcode",
|
|
30226
|
+
"unused",
|
|
30227
|
+
"orphan",
|
|
30228
|
+
"zombie",
|
|
30229
|
+
"blocker",
|
|
30230
|
+
"warning",
|
|
30231
|
+
"info",
|
|
30232
|
+
"error",
|
|
30233
|
+
"verbose",
|
|
30234
|
+
"debug",
|
|
30235
|
+
"silly",
|
|
30236
|
+
"p50",
|
|
30237
|
+
"p90",
|
|
30238
|
+
"p95",
|
|
30239
|
+
"p99",
|
|
30240
|
+
"min",
|
|
30241
|
+
"max",
|
|
30242
|
+
"avg",
|
|
30243
|
+
"mean",
|
|
30244
|
+
"median",
|
|
30245
|
+
"ratchet",
|
|
30246
|
+
"tier",
|
|
30247
|
+
"composite",
|
|
30248
|
+
"fitness",
|
|
30249
|
+
"fpr",
|
|
30250
|
+
"tpr",
|
|
30251
|
+
"roc",
|
|
30252
|
+
"should",
|
|
30253
|
+
"could",
|
|
30254
|
+
"would",
|
|
30255
|
+
"might",
|
|
30256
|
+
"must",
|
|
30257
|
+
"shall",
|
|
30258
|
+
"may",
|
|
30259
|
+
"can",
|
|
30260
|
+
"todo",
|
|
30261
|
+
"fixme",
|
|
30262
|
+
"xxx",
|
|
30263
|
+
"hack",
|
|
30264
|
+
"note",
|
|
30265
|
+
"warning",
|
|
30266
|
+
"attention",
|
|
30267
|
+
"h1",
|
|
30268
|
+
"h2",
|
|
30269
|
+
"h3",
|
|
30270
|
+
"h4",
|
|
30271
|
+
"h5",
|
|
30272
|
+
"h6",
|
|
30273
|
+
"strong",
|
|
30274
|
+
"em",
|
|
30275
|
+
"b",
|
|
30276
|
+
"i",
|
|
30277
|
+
"u",
|
|
30278
|
+
"true",
|
|
30279
|
+
"false",
|
|
30280
|
+
"yes",
|
|
30281
|
+
"no",
|
|
30282
|
+
"on",
|
|
30283
|
+
"off",
|
|
30284
|
+
"enable",
|
|
30285
|
+
"disable",
|
|
30286
|
+
"ltr",
|
|
30287
|
+
"rtl",
|
|
30288
|
+
"auto",
|
|
30289
|
+
"start",
|
|
30290
|
+
"end",
|
|
30291
|
+
"center",
|
|
30292
|
+
"baseline",
|
|
30293
|
+
"stretch",
|
|
30294
|
+
"rounded",
|
|
30295
|
+
"sharp",
|
|
30296
|
+
"outline",
|
|
30297
|
+
"ghost",
|
|
30298
|
+
"link",
|
|
30299
|
+
"filled",
|
|
30300
|
+
"row",
|
|
30301
|
+
"col",
|
|
30302
|
+
"gap",
|
|
30303
|
+
"pad",
|
|
30304
|
+
"margin",
|
|
30305
|
+
"padding",
|
|
30306
|
+
"border",
|
|
30307
|
+
"shadow",
|
|
30308
|
+
"transparent",
|
|
30309
|
+
"currentcolor",
|
|
30310
|
+
"inherit",
|
|
30311
|
+
"initial",
|
|
30312
|
+
"unset",
|
|
30313
|
+
"revert",
|
|
30314
|
+
"hover",
|
|
30315
|
+
"focus",
|
|
30316
|
+
"active",
|
|
30317
|
+
"disabled",
|
|
30318
|
+
"checked",
|
|
30319
|
+
"indeterminate",
|
|
30320
|
+
"open",
|
|
30321
|
+
"close",
|
|
30322
|
+
"expanded",
|
|
30323
|
+
"collapsed",
|
|
30324
|
+
"selected",
|
|
30325
|
+
"pressed",
|
|
30326
|
+
// Web/CSS
|
|
30327
|
+
"div",
|
|
30328
|
+
"span",
|
|
30329
|
+
"p",
|
|
30330
|
+
"a",
|
|
30331
|
+
"img",
|
|
30332
|
+
"ul",
|
|
30333
|
+
"ol",
|
|
30334
|
+
"li",
|
|
30335
|
+
"table",
|
|
30336
|
+
"tr",
|
|
30337
|
+
"td",
|
|
30338
|
+
"th",
|
|
30339
|
+
"thead",
|
|
30340
|
+
"tbody",
|
|
30341
|
+
"tfoot",
|
|
30342
|
+
"caption",
|
|
30343
|
+
"figure",
|
|
30344
|
+
"figcaption",
|
|
30345
|
+
"main",
|
|
30346
|
+
"section",
|
|
30347
|
+
"article",
|
|
30348
|
+
"aside",
|
|
30349
|
+
"header",
|
|
30350
|
+
"footer",
|
|
30351
|
+
"nav",
|
|
30352
|
+
"form",
|
|
30353
|
+
"input",
|
|
30354
|
+
"button",
|
|
30355
|
+
"select",
|
|
30356
|
+
"option",
|
|
30357
|
+
"textarea",
|
|
30358
|
+
"label",
|
|
30359
|
+
"fieldset",
|
|
30360
|
+
"legend",
|
|
30361
|
+
"details",
|
|
30362
|
+
"summary",
|
|
30363
|
+
"dialog",
|
|
30364
|
+
"menu",
|
|
30365
|
+
"menuitem",
|
|
30366
|
+
"template",
|
|
30367
|
+
"slot",
|
|
30368
|
+
"picture",
|
|
30369
|
+
"source",
|
|
30370
|
+
"track",
|
|
30371
|
+
"video",
|
|
30372
|
+
"audio",
|
|
30373
|
+
"canvas",
|
|
30374
|
+
"svg",
|
|
30375
|
+
"iframe",
|
|
30376
|
+
"embed",
|
|
30377
|
+
"object",
|
|
30378
|
+
"portal",
|
|
30379
|
+
// Common business terms
|
|
30380
|
+
"api",
|
|
30381
|
+
"cli",
|
|
30382
|
+
"ui",
|
|
30383
|
+
"ux",
|
|
30384
|
+
"sdk",
|
|
30385
|
+
"ide",
|
|
30386
|
+
"cli",
|
|
30387
|
+
"docs",
|
|
30388
|
+
"doc",
|
|
30389
|
+
"blog",
|
|
30390
|
+
"post",
|
|
30391
|
+
"page",
|
|
30392
|
+
"view",
|
|
30393
|
+
"tab",
|
|
30394
|
+
"panel",
|
|
30395
|
+
"card",
|
|
30396
|
+
"list",
|
|
30397
|
+
"grid",
|
|
30398
|
+
"form",
|
|
30399
|
+
"modal",
|
|
30400
|
+
"menu",
|
|
30401
|
+
"button",
|
|
30402
|
+
"icon",
|
|
30403
|
+
"avatar",
|
|
30404
|
+
"badge",
|
|
30405
|
+
"chip",
|
|
30406
|
+
"tooltip",
|
|
30407
|
+
"popover",
|
|
30408
|
+
"dropdown",
|
|
30409
|
+
"banner",
|
|
30410
|
+
"alert",
|
|
30411
|
+
"toast",
|
|
30412
|
+
"notification",
|
|
30413
|
+
"drawer",
|
|
30414
|
+
"sidebar",
|
|
30415
|
+
"navbar",
|
|
30416
|
+
"header",
|
|
30417
|
+
"footer",
|
|
30418
|
+
"hero",
|
|
30419
|
+
"cta",
|
|
30420
|
+
"cta-primary",
|
|
30421
|
+
"cta-secondary",
|
|
30422
|
+
"pricing",
|
|
30423
|
+
"price",
|
|
30424
|
+
"cost",
|
|
30425
|
+
"rate",
|
|
30426
|
+
"percent",
|
|
30427
|
+
"pct",
|
|
30428
|
+
"count",
|
|
30429
|
+
"total",
|
|
30430
|
+
"small",
|
|
30431
|
+
"medium",
|
|
30432
|
+
"large",
|
|
30433
|
+
"xl",
|
|
30434
|
+
"xxl",
|
|
30435
|
+
"tiny",
|
|
30436
|
+
"huge"
|
|
29695
30437
|
]);
|
|
29696
30438
|
SOURCE_EXTS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
29697
30439
|
SOURCE_ROOTS = ["src", "lib", "app", "components"];
|
|
@@ -29715,8 +30457,39 @@ var init_stale_function_reference = __esm({
|
|
|
29715
30457
|
if (text.length < 3) continue;
|
|
29716
30458
|
if (RESERVED.has(text.toLowerCase())) continue;
|
|
29717
30459
|
if (context.exports.has(text)) continue;
|
|
29718
|
-
const
|
|
29719
|
-
|
|
30460
|
+
const lineEnd = source.indexOf("\n", span.index);
|
|
30461
|
+
const restOfLine = source.slice(
|
|
30462
|
+
span.index,
|
|
30463
|
+
lineEnd === -1 ? source.length : lineEnd
|
|
30464
|
+
);
|
|
30465
|
+
const closeTick = restOfLine.indexOf("`", 1);
|
|
30466
|
+
if (closeTick === -1) continue;
|
|
30467
|
+
const afterTick = restOfLine.slice(closeTick + 1);
|
|
30468
|
+
const directCall = /^\s*\(/.test(afterTick);
|
|
30469
|
+
let identifierRepeats = false;
|
|
30470
|
+
if (!directCall) {
|
|
30471
|
+
const afterSpan = restOfLine.slice(closeTick + 1);
|
|
30472
|
+
const needle = text + "(";
|
|
30473
|
+
identifierRepeats = afterSpan.indexOf(needle) !== -1;
|
|
30474
|
+
}
|
|
30475
|
+
if (!directCall && !identifierRepeats) continue;
|
|
30476
|
+
const beforeTickIdx = span.index - 1;
|
|
30477
|
+
const beforeChar = beforeTickIdx >= 0 ? source[beforeTickIdx] : "";
|
|
30478
|
+
if (beforeChar === "." || beforeChar === "|") continue;
|
|
30479
|
+
const parenStart = restOfLine.indexOf("(", closeTick);
|
|
30480
|
+
const parenEnd = restOfLine.indexOf(")", parenStart);
|
|
30481
|
+
if (parenStart !== -1 && parenEnd !== -1) {
|
|
30482
|
+
const inside = restOfLine.slice(parenStart + 1, parenEnd);
|
|
30483
|
+
const trimmed = inside.trim();
|
|
30484
|
+
if (looksLikeProseLabel(inside)) continue;
|
|
30485
|
+
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(
|
|
30486
|
+
inside
|
|
30487
|
+
) || // Short single-word label (≤ 24 chars, no `,`,
|
|
30488
|
+
// doesn't look like a function arg). Real function
|
|
30489
|
+
// calls are usually longer or contain commas.
|
|
30490
|
+
trimmed.length > 0 && trimmed.length <= 24 && !trimmed.includes(",") && /[a-zA-Z]/.test(trimmed));
|
|
30491
|
+
if (looksLikeTypeAnnotation) continue;
|
|
30492
|
+
}
|
|
29720
30493
|
issues.push({
|
|
29721
30494
|
ruleId: "docs/stale-function-reference",
|
|
29722
30495
|
category: "docs",
|
|
@@ -29796,7 +30569,33 @@ var init_stale_package_reference = __esm({
|
|
|
29796
30569
|
"jsx",
|
|
29797
30570
|
"ok",
|
|
29798
30571
|
"no",
|
|
29799
|
-
"yes"
|
|
30572
|
+
"yes",
|
|
30573
|
+
// v0.18.6: common English adjectives / adverbs that frequently
|
|
30574
|
+
// appear in backticked prose but are not package names.
|
|
30575
|
+
"aspirational",
|
|
30576
|
+
"concrete",
|
|
30577
|
+
"abstract",
|
|
30578
|
+
"inline",
|
|
30579
|
+
"exposed",
|
|
30580
|
+
"deprecated",
|
|
30581
|
+
"experimental",
|
|
30582
|
+
"stable",
|
|
30583
|
+
"beta",
|
|
30584
|
+
"alpha",
|
|
30585
|
+
"wip",
|
|
30586
|
+
"draft",
|
|
30587
|
+
"final",
|
|
30588
|
+
"shim",
|
|
30589
|
+
"polyfill",
|
|
30590
|
+
"stub",
|
|
30591
|
+
"mock",
|
|
30592
|
+
"fake",
|
|
30593
|
+
"real",
|
|
30594
|
+
"false",
|
|
30595
|
+
"true",
|
|
30596
|
+
"optional",
|
|
30597
|
+
"required",
|
|
30598
|
+
"default"
|
|
29800
30599
|
]);
|
|
29801
30600
|
stalePackageReferenceRule = createRule({
|
|
29802
30601
|
id: "docs/stale-package-reference",
|
|
@@ -29935,9 +30734,9 @@ function declaredPackages(cwd) {
|
|
|
29935
30734
|
if (!(0, import_node_fs8.existsSync)(pkgPath)) return out;
|
|
29936
30735
|
try {
|
|
29937
30736
|
const raw = (0, import_node_fs8.readFileSync)(pkgPath, "utf-8");
|
|
29938
|
-
const
|
|
30737
|
+
const pkg = JSON.parse(raw);
|
|
29939
30738
|
for (const k of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
29940
|
-
const v =
|
|
30739
|
+
const v = pkg[k];
|
|
29941
30740
|
if (v && typeof v === "object") {
|
|
29942
30741
|
for (const name of Object.keys(v)) {
|
|
29943
30742
|
out.add(name);
|
|
@@ -30018,7 +30817,15 @@ async function buildDocFreshness(cwd, config, options = {}) {
|
|
|
30018
30817
|
continue;
|
|
30019
30818
|
}
|
|
30020
30819
|
const relPath = (0, import_node_path8.relative)(cwd, abs);
|
|
30021
|
-
|
|
30820
|
+
let packageName;
|
|
30821
|
+
try {
|
|
30822
|
+
const pkg = JSON.parse(
|
|
30823
|
+
(0, import_node_fs8.readFileSync)((0, import_node_path8.join)(cwd, "package.json"), "utf-8")
|
|
30824
|
+
);
|
|
30825
|
+
packageName = pkg.name;
|
|
30826
|
+
} catch {
|
|
30827
|
+
}
|
|
30828
|
+
const context = { config, filePath: relPath, cwd, packageName };
|
|
30022
30829
|
const facts = { filePath: relPath, v2: { _source: source } };
|
|
30023
30830
|
const ruleConfigs = [
|
|
30024
30831
|
{ rule: stalePackageReferenceRule, ruleId: "docs/stale-package-reference" },
|
|
@@ -30134,7 +30941,9 @@ var init_broken_link = __esm({
|
|
|
30134
30941
|
if (target.startsWith("#")) continue;
|
|
30135
30942
|
if (target.startsWith("//")) continue;
|
|
30136
30943
|
if (target.startsWith("/")) continue;
|
|
30137
|
-
const
|
|
30944
|
+
const filePart = target.split("#")[0] ?? target;
|
|
30945
|
+
if (filePart === "") continue;
|
|
30946
|
+
const resolved = (0, import_node_path9.join)(docDir, filePart);
|
|
30138
30947
|
if ((0, import_node_fs9.existsSync)(resolved)) continue;
|
|
30139
30948
|
issues.push({
|
|
30140
30949
|
ruleId: "docs/broken-link",
|
|
@@ -30367,7 +31176,7 @@ var init_spacing_grid = __esm({
|
|
|
30367
31176
|
"use strict";
|
|
30368
31177
|
init_rule();
|
|
30369
31178
|
init_utils();
|
|
30370
|
-
|
|
31179
|
+
init_config2();
|
|
30371
31180
|
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)-(.+)$/;
|
|
30372
31181
|
ARBITRARY_VALUE_RE2 = /^(-?\d+(?:\.\d+)?)(px|rem)$/;
|
|
30373
31182
|
SKIP_VALUES = /* @__PURE__ */ new Set(["auto", "full", "screen", "min", "max", "fit", "none"]);
|
|
@@ -42455,6 +43264,78 @@ function extractStateBinding(node, lineOffsets) {
|
|
|
42455
43264
|
setterReferenced: false
|
|
42456
43265
|
};
|
|
42457
43266
|
}
|
|
43267
|
+
function findUnreachableStatements(ast, source, lineOffsets) {
|
|
43268
|
+
const out = [];
|
|
43269
|
+
function isTerminator(node) {
|
|
43270
|
+
if (node.type === "ReturnStatement") return "return";
|
|
43271
|
+
if (node.type === "ThrowStatement") return "throw";
|
|
43272
|
+
if (node.type === "BreakStatement") return "break";
|
|
43273
|
+
if (node.type === "ContinueStatement") return "continue";
|
|
43274
|
+
return null;
|
|
43275
|
+
}
|
|
43276
|
+
function snippetFor(node, src) {
|
|
43277
|
+
const span = node.span;
|
|
43278
|
+
if (!span || typeof span.start !== "number" || typeof span.end !== "number") {
|
|
43279
|
+
return "<unreachable>";
|
|
43280
|
+
}
|
|
43281
|
+
const text = src.slice(span.start, Math.min(span.end, span.start + 60));
|
|
43282
|
+
return text.replace(/\s+/g, " ").trim() || "<unreachable>";
|
|
43283
|
+
}
|
|
43284
|
+
function lineColumn(offset) {
|
|
43285
|
+
let lo = 0;
|
|
43286
|
+
let hi = lineOffsets.length - 1;
|
|
43287
|
+
while (lo < hi) {
|
|
43288
|
+
const mid = lo + hi + 1 >>> 1;
|
|
43289
|
+
const midVal = lineOffsets[mid];
|
|
43290
|
+
const loVal = lineOffsets[lo];
|
|
43291
|
+
if (midVal === void 0) break;
|
|
43292
|
+
if (midVal <= offset) lo = mid;
|
|
43293
|
+
else hi = mid - 1;
|
|
43294
|
+
void loVal;
|
|
43295
|
+
}
|
|
43296
|
+
const baseOffset = lineOffsets[lo] ?? 0;
|
|
43297
|
+
return { line: lo + 1, column: offset - baseOffset };
|
|
43298
|
+
}
|
|
43299
|
+
function visitBody(body) {
|
|
43300
|
+
if (!Array.isArray(body)) return;
|
|
43301
|
+
let lastTerminator = null;
|
|
43302
|
+
for (const stmt of body) {
|
|
43303
|
+
if (!isObject(stmt)) continue;
|
|
43304
|
+
if (lastTerminator && stmt.type !== "EmptyStatement") {
|
|
43305
|
+
const span = stmt.span;
|
|
43306
|
+
const offset = typeof span?.start === "number" ? span.start : 0;
|
|
43307
|
+
const { line, column } = lineColumn(offset);
|
|
43308
|
+
out.push({
|
|
43309
|
+
terminator: lastTerminator,
|
|
43310
|
+
line,
|
|
43311
|
+
column,
|
|
43312
|
+
snippet: snippetFor(stmt, source)
|
|
43313
|
+
});
|
|
43314
|
+
}
|
|
43315
|
+
const t = isTerminator(stmt);
|
|
43316
|
+
if (t) lastTerminator = t;
|
|
43317
|
+
}
|
|
43318
|
+
}
|
|
43319
|
+
function walk3(node) {
|
|
43320
|
+
if (!isObject(node)) return;
|
|
43321
|
+
if (node.type === "BlockStatement") {
|
|
43322
|
+
visitBody(node.stmts);
|
|
43323
|
+
} else if (node.type === "Module") {
|
|
43324
|
+
visitBody(node.body);
|
|
43325
|
+
}
|
|
43326
|
+
for (const key of Object.keys(node)) {
|
|
43327
|
+
if (key === "parent" || key === "span" || key === "ctxt") continue;
|
|
43328
|
+
const child = node[key];
|
|
43329
|
+
if (Array.isArray(child)) {
|
|
43330
|
+
for (const c of child) walk3(c);
|
|
43331
|
+
} else {
|
|
43332
|
+
walk3(child);
|
|
43333
|
+
}
|
|
43334
|
+
}
|
|
43335
|
+
}
|
|
43336
|
+
walk3(ast);
|
|
43337
|
+
return out;
|
|
43338
|
+
}
|
|
42458
43339
|
var init_scan_helpers = __esm({
|
|
42459
43340
|
"src/engine/visitors/scan-helpers.ts"() {
|
|
42460
43341
|
"use strict";
|
|
@@ -42540,15 +43421,42 @@ function handleImportDeclaration(node, _parent, _path, vctx) {
|
|
|
42540
43421
|
if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
|
|
42541
43422
|
const local = specifier.local;
|
|
42542
43423
|
if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
|
|
42543
|
-
|
|
43424
|
+
const name = local.value;
|
|
43425
|
+
importedNames.push(name);
|
|
43426
|
+
vctx.facts.deadCode.bindings.push({
|
|
43427
|
+
name,
|
|
43428
|
+
kind: specifier.type === "ImportDefaultSpecifier" ? "import-default" : "import-namespace",
|
|
43429
|
+
line,
|
|
43430
|
+
column,
|
|
43431
|
+
source,
|
|
43432
|
+
isReferenced: false
|
|
43433
|
+
});
|
|
42544
43434
|
}
|
|
42545
43435
|
} else if (specifier.type === "ImportSpecifier") {
|
|
42546
43436
|
const imported = specifier.imported;
|
|
42547
43437
|
const local = specifier.local;
|
|
42548
43438
|
if (isObject(imported) && typeof imported.value === "string" && imported.value.length > 0) {
|
|
42549
|
-
|
|
43439
|
+
const name = imported.value;
|
|
43440
|
+
importedNames.push(name);
|
|
43441
|
+
vctx.facts.deadCode.bindings.push({
|
|
43442
|
+
name,
|
|
43443
|
+
kind: "import-specifier",
|
|
43444
|
+
line,
|
|
43445
|
+
column,
|
|
43446
|
+
source,
|
|
43447
|
+
isReferenced: false
|
|
43448
|
+
});
|
|
42550
43449
|
} else if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
|
|
42551
|
-
|
|
43450
|
+
const name = local.value;
|
|
43451
|
+
importedNames.push(name);
|
|
43452
|
+
vctx.facts.deadCode.bindings.push({
|
|
43453
|
+
name,
|
|
43454
|
+
kind: "import-specifier",
|
|
43455
|
+
line,
|
|
43456
|
+
column,
|
|
43457
|
+
source,
|
|
43458
|
+
isReferenced: false
|
|
43459
|
+
});
|
|
42552
43460
|
}
|
|
42553
43461
|
}
|
|
42554
43462
|
}
|
|
@@ -42638,6 +43546,13 @@ function isBindingSite(node, parent) {
|
|
|
42638
43546
|
if (params.some((param) => containsNode(param, node))) return true;
|
|
42639
43547
|
}
|
|
42640
43548
|
}
|
|
43549
|
+
if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") {
|
|
43550
|
+
if (parent.type === "ImportSpecifier") {
|
|
43551
|
+
if (parent.imported === node || parent.local === node) return true;
|
|
43552
|
+
} else {
|
|
43553
|
+
if (parent.local === node) return true;
|
|
43554
|
+
}
|
|
43555
|
+
}
|
|
42641
43556
|
return false;
|
|
42642
43557
|
}
|
|
42643
43558
|
function isNonComputedMemberProperty(node, parent) {
|
|
@@ -42704,6 +43619,9 @@ function handleIdentifier(node, parent, path, vctx) {
|
|
|
42704
43619
|
if (typeof node.value === "string" && !isBindingSite(node, parent) && !isNonComputedMemberProperty(node, parent)) {
|
|
42705
43620
|
markStateReference(node.value, vctx);
|
|
42706
43621
|
trackPropUsage(node, parent, path, vctx);
|
|
43622
|
+
vctx.facts.referencedNames.add(node.value);
|
|
43623
|
+
const top = vctx.ctx.stack[vctx.ctx.stack.length - 1];
|
|
43624
|
+
if (top) top.references.add(node.value);
|
|
42707
43625
|
}
|
|
42708
43626
|
return false;
|
|
42709
43627
|
}
|
|
@@ -42844,6 +43762,20 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
|
|
|
42844
43762
|
frame.bindings.add(bindingName);
|
|
42845
43763
|
}
|
|
42846
43764
|
}
|
|
43765
|
+
if (bindingNames.length > 0) {
|
|
43766
|
+
const parent = node.parent;
|
|
43767
|
+
const kind = isObject(parent) && parent.type === "VariableDeclaration" ? String(parent.kind ?? "var") : "var";
|
|
43768
|
+
const { line, column } = positionFrom(id, vctx.lineOffsets);
|
|
43769
|
+
for (const bindingName of bindingNames) {
|
|
43770
|
+
vctx.facts.deadCode.bindings.push({
|
|
43771
|
+
name: bindingName,
|
|
43772
|
+
kind,
|
|
43773
|
+
line,
|
|
43774
|
+
column,
|
|
43775
|
+
isReferenced: false
|
|
43776
|
+
});
|
|
43777
|
+
}
|
|
43778
|
+
}
|
|
42847
43779
|
if (isUseStateDeclarator(node)) {
|
|
42848
43780
|
const binding = extractStateBinding(node, vctx.lineOffsets);
|
|
42849
43781
|
if (binding) {
|
|
@@ -42863,6 +43795,36 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
|
|
|
42863
43795
|
}
|
|
42864
43796
|
return true;
|
|
42865
43797
|
}
|
|
43798
|
+
function handleIfStatement(node, _parent, _path, vctx) {
|
|
43799
|
+
if (!isObject(node)) return false;
|
|
43800
|
+
const test = node.test;
|
|
43801
|
+
if (!isObject(test)) return false;
|
|
43802
|
+
if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
|
|
43803
|
+
const { line, column } = positionFrom(test, vctx.lineOffsets);
|
|
43804
|
+
vctx.facts.deadCode.constantConditions.push({
|
|
43805
|
+
kind: test.value ? "if-true" : "if-false",
|
|
43806
|
+
condition: String(test.value),
|
|
43807
|
+
line,
|
|
43808
|
+
column
|
|
43809
|
+
});
|
|
43810
|
+
}
|
|
43811
|
+
return false;
|
|
43812
|
+
}
|
|
43813
|
+
function handleWhileStatement(node, _parent, _path, vctx) {
|
|
43814
|
+
if (!isObject(node)) return false;
|
|
43815
|
+
const test = node.test;
|
|
43816
|
+
if (!isObject(test)) return false;
|
|
43817
|
+
if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
|
|
43818
|
+
const { line, column } = positionFrom(test, vctx.lineOffsets);
|
|
43819
|
+
vctx.facts.deadCode.constantConditions.push({
|
|
43820
|
+
kind: test.value ? "while-true" : "while-false",
|
|
43821
|
+
condition: String(test.value),
|
|
43822
|
+
line,
|
|
43823
|
+
column
|
|
43824
|
+
});
|
|
43825
|
+
}
|
|
43826
|
+
return false;
|
|
43827
|
+
}
|
|
42866
43828
|
function dispatchNode(node, parent, path, vctx) {
|
|
42867
43829
|
if (!isObject(node)) return false;
|
|
42868
43830
|
const type = getNodeType(node);
|
|
@@ -42887,7 +43849,9 @@ var init_dispatch = __esm({
|
|
|
42887
43849
|
MemberExpression: handleMemberExpression,
|
|
42888
43850
|
JSXAttribute: handleJSXAttribute,
|
|
42889
43851
|
JSXOpeningElement: handleJSXOpeningElement,
|
|
42890
|
-
VariableDeclarator: handleVariableDeclarator
|
|
43852
|
+
VariableDeclarator: handleVariableDeclarator,
|
|
43853
|
+
IfStatement: handleIfStatement,
|
|
43854
|
+
WhileStatement: handleWhileStatement
|
|
42891
43855
|
};
|
|
42892
43856
|
}
|
|
42893
43857
|
});
|
|
@@ -43038,6 +44002,17 @@ function buildV2Facts(facts, source, ext, framework, config, templateClassNames
|
|
|
43038
44002
|
},
|
|
43039
44003
|
logic: buildLogicBlock(facts),
|
|
43040
44004
|
designTokens: scanDesignTokens(facts.staticClassNames),
|
|
44005
|
+
// dead-code detector. Copy the internal accumulator
|
|
44006
|
+
// into the v2 shape, marking each binding as referenced
|
|
44007
|
+
// iff the file-level referenced-name set contains its name.
|
|
44008
|
+
deadCode: {
|
|
44009
|
+
bindings: facts.deadCode.bindings.map((b) => ({
|
|
44010
|
+
...b,
|
|
44011
|
+
isReferenced: facts.referencedNames.has(b.name)
|
|
44012
|
+
})),
|
|
44013
|
+
constantConditions: facts.deadCode.constantConditions,
|
|
44014
|
+
unreachableStatements: facts.deadCode.unreachableStatements
|
|
44015
|
+
},
|
|
43041
44016
|
componentSizes: facts.componentSizes.map((cs) => ({
|
|
43042
44017
|
name: cs.name,
|
|
43043
44018
|
lineCount: cs.lineCount,
|
|
@@ -43119,7 +44094,17 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43119
44094
|
componentSizes: [],
|
|
43120
44095
|
astroComponents: [],
|
|
43121
44096
|
fetchCalls: [],
|
|
43122
|
-
optimisticUpdates: []
|
|
44097
|
+
optimisticUpdates: [],
|
|
44098
|
+
// dead-code detector. The visitor's identifier walk + import/
|
|
44099
|
+
// branch/return handlers populate these. The v2 builder at the
|
|
44100
|
+
// bottom of extractFacts() reads them and produces
|
|
44101
|
+
// `facts.v2.deadCode`.
|
|
44102
|
+
deadCode: {
|
|
44103
|
+
bindings: [],
|
|
44104
|
+
constantConditions: [],
|
|
44105
|
+
unreachableStatements: []
|
|
44106
|
+
},
|
|
44107
|
+
referencedNames: /* @__PURE__ */ new Set()
|
|
43123
44108
|
};
|
|
43124
44109
|
const ctx = {
|
|
43125
44110
|
stack: [],
|
|
@@ -43206,6 +44191,16 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43206
44191
|
propBindingSet.add(bindingName);
|
|
43207
44192
|
}
|
|
43208
44193
|
}
|
|
44194
|
+
const { line: pLine, column: pCol } = positionFrom(param, lineOffsets);
|
|
44195
|
+
for (const bindingName of collectBindingNames2(param)) {
|
|
44196
|
+
facts.deadCode.bindings.push({
|
|
44197
|
+
name: bindingName,
|
|
44198
|
+
kind: "parameter",
|
|
44199
|
+
line: pLine,
|
|
44200
|
+
column: pCol,
|
|
44201
|
+
isReferenced: false
|
|
44202
|
+
});
|
|
44203
|
+
}
|
|
43209
44204
|
}
|
|
43210
44205
|
}
|
|
43211
44206
|
ctx.stack.push({
|
|
@@ -43221,6 +44216,12 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43221
44216
|
propUsages: [],
|
|
43222
44217
|
isComponent,
|
|
43223
44218
|
bindings,
|
|
44219
|
+
// dead-code detector: per-frame referenced-name set.
|
|
44220
|
+
// Identifiers encountered inside the frame are added to this
|
|
44221
|
+
// set; the deadCode builder unions it with parent frames at
|
|
44222
|
+
// pop time so a binding is considered used if any reachable
|
|
44223
|
+
// scope references it.
|
|
44224
|
+
references: /* @__PURE__ */ new Set(),
|
|
43224
44225
|
propBindingSet,
|
|
43225
44226
|
propUsageSet: /* @__PURE__ */ new Set(),
|
|
43226
44227
|
node
|
|
@@ -43316,6 +44317,11 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43316
44317
|
mergeTemplateClassNames(filePath, source, facts, templateClassNames);
|
|
43317
44318
|
const { ext } = splitFilePath(filePath);
|
|
43318
44319
|
facts._source = source;
|
|
44320
|
+
facts.deadCode.unreachableStatements = findUnreachableStatements(
|
|
44321
|
+
ast,
|
|
44322
|
+
source,
|
|
44323
|
+
lineOffsets
|
|
44324
|
+
);
|
|
43319
44325
|
const v2 = buildV2Facts(facts, source, ext, framework, config, templateClassNames);
|
|
43320
44326
|
return envelopeScanFacts(filePath, v2);
|
|
43321
44327
|
}
|
|
@@ -43998,6 +45004,11 @@ var init_builtins = __esm({
|
|
|
43998
45004
|
init_missing_not_null();
|
|
43999
45005
|
init_naming_inconsistency();
|
|
44000
45006
|
init_sql_concat();
|
|
45007
|
+
init_dead_branch();
|
|
45008
|
+
init_unreachable();
|
|
45009
|
+
init_unused_import();
|
|
45010
|
+
init_unused_local();
|
|
45011
|
+
init_unused_parameter();
|
|
44001
45012
|
init_broken_link();
|
|
44002
45013
|
init_expired_code_example();
|
|
44003
45014
|
init_stale_function_reference();
|
|
@@ -44094,6 +45105,11 @@ var init_builtins = __esm({
|
|
|
44094
45105
|
missingNotNullRule,
|
|
44095
45106
|
namingInconsistencyRule,
|
|
44096
45107
|
sqlConcatRule,
|
|
45108
|
+
deadBranchRule,
|
|
45109
|
+
unreachableRule,
|
|
45110
|
+
unusedImportRule,
|
|
45111
|
+
unusedLocalRule,
|
|
45112
|
+
unusedParameterRule,
|
|
44097
45113
|
brokenLinkRule,
|
|
44098
45114
|
expiredCodeExampleRule,
|
|
44099
45115
|
staleFunctionReferenceRule,
|
|
@@ -44665,8 +45681,8 @@ function detectJsLoader(configPath) {
|
|
|
44665
45681
|
const pkgPath = (0, import_node_path10.join)(current, "package.json");
|
|
44666
45682
|
if ((0, import_node_fs11.existsSync)(pkgPath)) {
|
|
44667
45683
|
try {
|
|
44668
|
-
const
|
|
44669
|
-
return
|
|
45684
|
+
const pkg = JSON.parse((0, import_node_fs11.readFileSync)(pkgPath, "utf-8"));
|
|
45685
|
+
return pkg.type === "module" ? "import" : "require";
|
|
44670
45686
|
} catch {
|
|
44671
45687
|
return "require";
|
|
44672
45688
|
}
|
|
@@ -44680,7 +45696,7 @@ function detectJsLoader(configPath) {
|
|
|
44680
45696
|
async function loadConfigFile(path) {
|
|
44681
45697
|
const loader = detectJsLoader(path);
|
|
44682
45698
|
if (loader === "require") {
|
|
44683
|
-
const req = (0,
|
|
45699
|
+
const req = (0, import_node_module.createRequire)(__importMetaUrl);
|
|
44684
45700
|
const mod2 = req(path);
|
|
44685
45701
|
return mod2.default ?? mod2;
|
|
44686
45702
|
}
|
|
@@ -44712,13 +45728,13 @@ async function loadConfig(cwd) {
|
|
|
44712
45728
|
);
|
|
44713
45729
|
return merged;
|
|
44714
45730
|
}
|
|
44715
|
-
var import_node_fs11, import_node_path10,
|
|
45731
|
+
var import_node_fs11, import_node_path10, import_node_module;
|
|
44716
45732
|
var init_load = __esm({
|
|
44717
45733
|
"src/config/load.ts"() {
|
|
44718
45734
|
"use strict";
|
|
44719
45735
|
import_node_fs11 = require("fs");
|
|
44720
45736
|
import_node_path10 = require("path");
|
|
44721
|
-
|
|
45737
|
+
import_node_module = require("module");
|
|
44722
45738
|
init_logger();
|
|
44723
45739
|
init_validation();
|
|
44724
45740
|
init_defaults();
|
|
@@ -44865,7 +45881,7 @@ var init_init = __esm({
|
|
|
44865
45881
|
});
|
|
44866
45882
|
|
|
44867
45883
|
// src/config/index.ts
|
|
44868
|
-
var
|
|
45884
|
+
var init_config2 = __esm({
|
|
44869
45885
|
"src/config/index.ts"() {
|
|
44870
45886
|
"use strict";
|
|
44871
45887
|
init_defaults();
|
|
@@ -47012,6 +48028,61 @@ var init_signal_strength = __esm({
|
|
|
47012
48028
|
_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.)",
|
|
47013
48029
|
aiSpecific: true
|
|
47014
48030
|
},
|
|
48031
|
+
"dead/unused-import": {
|
|
48032
|
+
recall: 0,
|
|
48033
|
+
fpRate: 0,
|
|
48034
|
+
ratio: 0,
|
|
48035
|
+
precision: 0,
|
|
48036
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48037
|
+
verdict: "DORMANT",
|
|
48038
|
+
defaultOff: true,
|
|
48039
|
+
_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.",
|
|
48040
|
+
aiSpecific: true
|
|
48041
|
+
},
|
|
48042
|
+
"dead/unused-local": {
|
|
48043
|
+
recall: 0,
|
|
48044
|
+
fpRate: 0,
|
|
48045
|
+
ratio: 0,
|
|
48046
|
+
precision: 0,
|
|
48047
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48048
|
+
verdict: "DORMANT",
|
|
48049
|
+
defaultOff: true,
|
|
48050
|
+
_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).",
|
|
48051
|
+
aiSpecific: true
|
|
48052
|
+
},
|
|
48053
|
+
"dead/unused-parameter": {
|
|
48054
|
+
recall: 0,
|
|
48055
|
+
fpRate: 0,
|
|
48056
|
+
ratio: 0,
|
|
48057
|
+
precision: 0,
|
|
48058
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48059
|
+
verdict: "DORMANT",
|
|
48060
|
+
defaultOff: true,
|
|
48061
|
+
_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.",
|
|
48062
|
+
aiSpecific: true
|
|
48063
|
+
},
|
|
48064
|
+
"dead/dead-branch": {
|
|
48065
|
+
recall: 0,
|
|
48066
|
+
fpRate: 0,
|
|
48067
|
+
ratio: 0,
|
|
48068
|
+
precision: 0,
|
|
48069
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48070
|
+
verdict: "DORMANT",
|
|
48071
|
+
defaultOff: true,
|
|
48072
|
+
_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.",
|
|
48073
|
+
aiSpecific: true
|
|
48074
|
+
},
|
|
48075
|
+
"dead/unreachable": {
|
|
48076
|
+
recall: 0,
|
|
48077
|
+
fpRate: 0,
|
|
48078
|
+
ratio: 0,
|
|
48079
|
+
precision: 0,
|
|
48080
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
48081
|
+
verdict: "DORMANT",
|
|
48082
|
+
defaultOff: true,
|
|
48083
|
+
_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.",
|
|
48084
|
+
aiSpecific: true
|
|
48085
|
+
},
|
|
47015
48086
|
"docs/stale-package-reference": {
|
|
47016
48087
|
recall: 0,
|
|
47017
48088
|
fpRate: 0,
|
|
@@ -47973,7 +49044,7 @@ var init_cache = __esm({
|
|
|
47973
49044
|
import_node_fs16 = require("fs");
|
|
47974
49045
|
import_node_path17 = require("path");
|
|
47975
49046
|
init_types();
|
|
47976
|
-
|
|
49047
|
+
init_config2();
|
|
47977
49048
|
BASELINE_VERSION = VERSION;
|
|
47978
49049
|
BASELINE_HASH_KEYS = /* @__PURE__ */ new Set([
|
|
47979
49050
|
"framework",
|
|
@@ -50457,7 +51528,7 @@ var init_finalizeReport = __esm({
|
|
|
50457
51528
|
init_dist2();
|
|
50458
51529
|
init_logger();
|
|
50459
51530
|
init_memory_io();
|
|
50460
|
-
|
|
51531
|
+
init_config2();
|
|
50461
51532
|
init_enrichReport();
|
|
50462
51533
|
init_assembleScanReport();
|
|
50463
51534
|
init_persistRun();
|
|
@@ -52382,11 +53453,11 @@ var init_watch = __esm({
|
|
|
52382
53453
|
init_worker();
|
|
52383
53454
|
init_threshold();
|
|
52384
53455
|
init_cache();
|
|
52385
|
-
|
|
53456
|
+
init_config2();
|
|
52386
53457
|
init_render();
|
|
52387
53458
|
init_logger();
|
|
52388
53459
|
init_error();
|
|
52389
|
-
|
|
53460
|
+
init_scan2();
|
|
52390
53461
|
init_renderOutput();
|
|
52391
53462
|
init_types();
|
|
52392
53463
|
}
|
|
@@ -52667,14 +53738,14 @@ async function scanProject(options) {
|
|
|
52667
53738
|
return report;
|
|
52668
53739
|
}
|
|
52669
53740
|
var import_node_fs28, import_node_path30;
|
|
52670
|
-
var
|
|
53741
|
+
var init_scan2 = __esm({
|
|
52671
53742
|
"src/cli/scan.ts"() {
|
|
52672
53743
|
"use strict";
|
|
52673
53744
|
import_node_fs28 = require("fs");
|
|
52674
53745
|
import_node_path30 = require("path");
|
|
52675
53746
|
init_render();
|
|
52676
53747
|
init_threshold();
|
|
52677
|
-
|
|
53748
|
+
init_config2();
|
|
52678
53749
|
init_discover();
|
|
52679
53750
|
init_git();
|
|
52680
53751
|
init_cache_incremental();
|
|
@@ -52844,7 +53915,7 @@ async function runSuggest(args, ctx) {
|
|
|
52844
53915
|
}
|
|
52845
53916
|
async function runGovernance(args, ctx) {
|
|
52846
53917
|
try {
|
|
52847
|
-
const { runScan: runScan3 } = await Promise.resolve().then(() => (
|
|
53918
|
+
const { runScan: runScan3 } = await Promise.resolve().then(() => (init_scan2(), scan_exports));
|
|
52848
53919
|
const maxFiles = typeof args.maxFiles === "number" && Number.isFinite(args.maxFiles) && args.maxFiles > 0 ? Math.floor(args.maxFiles) : 500;
|
|
52849
53920
|
const { report } = await runScan3({
|
|
52850
53921
|
workspace: ctx.cwd,
|
|
@@ -53326,7 +54397,7 @@ __export(src_exports, {
|
|
|
53326
54397
|
});
|
|
53327
54398
|
module.exports = __toCommonJS(src_exports);
|
|
53328
54399
|
init_types();
|
|
53329
|
-
|
|
54400
|
+
init_config2();
|
|
53330
54401
|
init_dist2();
|
|
53331
54402
|
|
|
53332
54403
|
// src/cli/program.ts
|
|
@@ -53370,14 +54441,14 @@ function parseThreshold(value) {
|
|
|
53370
54441
|
// src/cli/program.ts
|
|
53371
54442
|
init_render();
|
|
53372
54443
|
init_threshold();
|
|
53373
|
-
|
|
53374
|
-
|
|
54444
|
+
init_scan2();
|
|
54445
|
+
init_scan2();
|
|
53375
54446
|
|
|
53376
54447
|
// src/cli/init.ts
|
|
53377
54448
|
var import_node_fs30 = require("fs");
|
|
53378
54449
|
var import_node_path32 = require("path");
|
|
53379
54450
|
var import_node_readline = require("readline");
|
|
53380
|
-
|
|
54451
|
+
init_config2();
|
|
53381
54452
|
init_discover();
|
|
53382
54453
|
init_git();
|
|
53383
54454
|
init_cache();
|
|
@@ -53867,7 +54938,7 @@ async function runDoctor(cwd) {
|
|
|
53867
54938
|
var import_node_path33 = require("path");
|
|
53868
54939
|
init_render();
|
|
53869
54940
|
init_logger();
|
|
53870
|
-
|
|
54941
|
+
init_scan2();
|
|
53871
54942
|
function registerBadge(program) {
|
|
53872
54943
|
program.command("badge").description(
|
|
53873
54944
|
"print a shields.io slop-index badge. Reads .slopbrick/health.json if present (no re-scan); falls back to a fresh scan."
|
|
@@ -53894,7 +54965,7 @@ var import_node_path34 = require("path");
|
|
|
53894
54965
|
init_advice();
|
|
53895
54966
|
init_unified_diff();
|
|
53896
54967
|
init_logger();
|
|
53897
|
-
|
|
54968
|
+
init_scan2();
|
|
53898
54969
|
function registerSuggest(program) {
|
|
53899
54970
|
program.command("suggest").description("print remediation advice").action(async (_cmdOptions, command) => {
|
|
53900
54971
|
const options = command.optsWithGlobals();
|
|
@@ -54021,6 +55092,11 @@ var RULE_HINTS = {
|
|
|
54021
55092
|
"logic/qwik-hook-leak": "Use Qwik primitives ($state, $effect, useSignal) instead of React hooks (useState, useEffect).",
|
|
54022
55093
|
"logic/reactive-hook-soup": "Coordinate state via a single derived value (useMemo) or a state machine. Avoid chained useEffects that sync local state.",
|
|
54023
55094
|
"logic/zombie-state": "Remove unused useState or wire it into the component. Don't leave declared-but-never-read state bindings.",
|
|
55095
|
+
"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.",
|
|
55096
|
+
"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.",
|
|
55097
|
+
"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.",
|
|
55098
|
+
"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.",
|
|
55099
|
+
"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.",
|
|
54024
55100
|
"perf/cls-image": "Add width/height attributes or an aspect-ratio utility to prevent layout shift.",
|
|
54025
55101
|
"perf/css-bloat": "Extract to a CSS variable (`--surface-card`) or a component prop when a class string repeats 5+ times.",
|
|
54026
55102
|
"perf/halstead-anomaly": "Introduce domain-specific identifiers and varied operations. Low vocabulary per line is a strong AI signature (Halstead 1977 \xA73).",
|
|
@@ -54275,7 +55351,7 @@ init_logger();
|
|
|
54275
55351
|
|
|
54276
55352
|
// src/mcp/server.ts
|
|
54277
55353
|
init_builtins();
|
|
54278
|
-
|
|
55354
|
+
init_config2();
|
|
54279
55355
|
init_tools();
|
|
54280
55356
|
var SERVER_INFO = {
|
|
54281
55357
|
name: "slopbrick",
|
|
@@ -55705,7 +56781,7 @@ function registerTrend(program) {
|
|
|
55705
56781
|
// src/cli/commands/drift.ts
|
|
55706
56782
|
var import_node_path51 = require("path");
|
|
55707
56783
|
init_logger();
|
|
55708
|
-
|
|
56784
|
+
init_scan2();
|
|
55709
56785
|
|
|
55710
56786
|
// src/cli/drift.ts
|
|
55711
56787
|
var import_node_fs38 = require("fs");
|
|
@@ -55846,7 +56922,7 @@ function registerDrift(program) {
|
|
|
55846
56922
|
// src/cli/commands/pr.ts
|
|
55847
56923
|
var import_node_path53 = require("path");
|
|
55848
56924
|
init_logger();
|
|
55849
|
-
|
|
56925
|
+
init_scan2();
|
|
55850
56926
|
|
|
55851
56927
|
// src/cli/pr.ts
|
|
55852
56928
|
var import_node_fs39 = require("fs");
|
|
@@ -56135,7 +57211,7 @@ function registerPr(program) {
|
|
|
56135
57211
|
// src/cli/commands/security.ts
|
|
56136
57212
|
var import_node_path54 = require("path");
|
|
56137
57213
|
init_logger();
|
|
56138
|
-
|
|
57214
|
+
init_scan2();
|
|
56139
57215
|
init_ai_security_risk();
|
|
56140
57216
|
function registerSecurity(program) {
|
|
56141
57217
|
program.command("security").description(
|
|
@@ -56194,11 +57270,11 @@ function registerSecurity(program) {
|
|
|
56194
57270
|
// src/cli/commands/test.ts
|
|
56195
57271
|
var import_node_path56 = require("path");
|
|
56196
57272
|
init_logger();
|
|
56197
|
-
|
|
57273
|
+
init_scan2();
|
|
56198
57274
|
|
|
56199
57275
|
// src/cli/test.ts
|
|
56200
57276
|
var import_node_path55 = require("path");
|
|
56201
|
-
|
|
57277
|
+
init_scan2();
|
|
56202
57278
|
init_test_quality();
|
|
56203
57279
|
init_logger();
|
|
56204
57280
|
var TEST_INCLUDE_GLOBS = [
|
|
@@ -56313,7 +57389,7 @@ function registerTest(program) {
|
|
|
56313
57389
|
// src/cli/commands/architecture.ts
|
|
56314
57390
|
var import_node_path57 = require("path");
|
|
56315
57391
|
init_logger();
|
|
56316
|
-
|
|
57392
|
+
init_scan2();
|
|
56317
57393
|
init_architecture_score();
|
|
56318
57394
|
function registerArchitecture(program) {
|
|
56319
57395
|
program.command("architecture").description(
|
|
@@ -56341,7 +57417,7 @@ function registerArchitecture(program) {
|
|
|
56341
57417
|
// src/cli/commands/business-logic.ts
|
|
56342
57418
|
var import_node_path59 = require("path");
|
|
56343
57419
|
init_logger();
|
|
56344
|
-
|
|
57420
|
+
init_scan2();
|
|
56345
57421
|
|
|
56346
57422
|
// src/cli/business-logic.ts
|
|
56347
57423
|
var import_node_fs40 = require("fs");
|
|
@@ -56487,10 +57563,10 @@ function registerBusinessLogic(program) {
|
|
|
56487
57563
|
// src/cli/commands/maintenance-cost.ts
|
|
56488
57564
|
var import_node_path60 = require("path");
|
|
56489
57565
|
init_logger();
|
|
56490
|
-
|
|
57566
|
+
init_scan2();
|
|
56491
57567
|
|
|
56492
57568
|
// src/cli/maintenance-cost.ts
|
|
56493
|
-
|
|
57569
|
+
init_scan2();
|
|
56494
57570
|
init_maintenance_cost();
|
|
56495
57571
|
init_logger();
|
|
56496
57572
|
async function runMaintenanceCostScan(cwd, config, options = {}) {
|
|
@@ -56630,10 +57706,10 @@ function registerMaintenanceCost(program) {
|
|
|
56630
57706
|
// src/cli/commands/docs.ts
|
|
56631
57707
|
var import_node_path61 = require("path");
|
|
56632
57708
|
init_logger();
|
|
56633
|
-
|
|
57709
|
+
init_scan2();
|
|
56634
57710
|
|
|
56635
57711
|
// src/cli/docs.ts
|
|
56636
|
-
|
|
57712
|
+
init_scan2();
|
|
56637
57713
|
init_doc_freshness();
|
|
56638
57714
|
init_logger();
|
|
56639
57715
|
async function runDocsScan(cwd, config, options = {}) {
|
|
@@ -56779,10 +57855,10 @@ function registerDocs(program) {
|
|
|
56779
57855
|
// src/cli/commands/db.ts
|
|
56780
57856
|
var import_node_path62 = require("path");
|
|
56781
57857
|
init_logger();
|
|
56782
|
-
|
|
57858
|
+
init_scan2();
|
|
56783
57859
|
|
|
56784
57860
|
// src/cli/db.ts
|
|
56785
|
-
|
|
57861
|
+
init_scan2();
|
|
56786
57862
|
init_db_health();
|
|
56787
57863
|
init_logger();
|
|
56788
57864
|
async function runDbScan(cwd, config, options = {}) {
|
|
@@ -56922,7 +57998,7 @@ function registerDb(program) {
|
|
|
56922
57998
|
// src/cli/commands/patterns.ts
|
|
56923
57999
|
var import_node_path64 = require("path");
|
|
56924
58000
|
init_logger();
|
|
56925
|
-
|
|
58001
|
+
init_scan2();
|
|
56926
58002
|
|
|
56927
58003
|
// src/engine/patterns.ts
|
|
56928
58004
|
var import_node_fs41 = require("fs");
|
|
@@ -57271,7 +58347,7 @@ function registerPatterns(program) {
|
|
|
57271
58347
|
var import_node_fs42 = require("fs");
|
|
57272
58348
|
var import_node_path65 = require("path");
|
|
57273
58349
|
init_logger();
|
|
57274
|
-
|
|
58350
|
+
init_config2();
|
|
57275
58351
|
function registerResearch(program) {
|
|
57276
58352
|
const research = program.command("research").description("research commands for the AI UI learning loop");
|
|
57277
58353
|
research.command("generate").description("generate synthetic UI samples").requiredOption("--count <n>", "number of samples", parseCount).requiredOption("--framework <name>", "target framework").requiredOption("--component-type <type>", "component type").requiredOption("--provider <name>", "AI provider (openai)").option("--api-key <key>", "API key for provider").option("--model <name>", "model name").option("--temperature <n>", "sampling temperature", parseFloat, 0.7).option("--output-dir <path>", "output directory", ".slopbrick/corpus/generated").action(async (cmdOptions) => {
|
|
@@ -57352,8 +58428,8 @@ var import_node_fs43 = require("fs");
|
|
|
57352
58428
|
var import_node_path67 = require("path");
|
|
57353
58429
|
init_logger();
|
|
57354
58430
|
init_builtins();
|
|
57355
|
-
|
|
57356
|
-
|
|
58431
|
+
init_scan2();
|
|
58432
|
+
init_config2();
|
|
57357
58433
|
init_threshold();
|
|
57358
58434
|
init_git();
|
|
57359
58435
|
init_cache();
|
|
@@ -57834,7 +58910,7 @@ function registerScan(program, scanAction) {
|
|
|
57834
58910
|
}
|
|
57835
58911
|
|
|
57836
58912
|
// src/cli/program.ts
|
|
57837
|
-
|
|
58913
|
+
init_config2();
|
|
57838
58914
|
init_git();
|
|
57839
58915
|
init_logger();
|
|
57840
58916
|
init_unified_diff();
|
|
@@ -58400,7 +59476,7 @@ function formatGroupedHelp(cmd) {
|
|
|
58400
59476
|
}
|
|
58401
59477
|
|
|
58402
59478
|
// src/cli/program.ts
|
|
58403
|
-
|
|
59479
|
+
init_scan2();
|
|
58404
59480
|
process.on("uncaughtException", (err) => {
|
|
58405
59481
|
logger.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
58406
59482
|
process.exit(3);
|