slopbrick 0.18.3 → 0.18.5
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 +426 -5
- package/dist/engine/worker.js +426 -5
- package/dist/index.cjs +735 -76
- package/dist/index.d.cts +611 -511
- package/dist/index.d.ts +611 -511
- package/dist/index.js +734 -75
- 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.5";
|
|
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
|
|
@@ -29920,9 +30173,9 @@ function declaredPackages(cwd) {
|
|
|
29920
30173
|
if (!existsSync6(pkgPath)) return out;
|
|
29921
30174
|
try {
|
|
29922
30175
|
const raw = readFileSync8(pkgPath, "utf-8");
|
|
29923
|
-
const
|
|
30176
|
+
const pkg = JSON.parse(raw);
|
|
29924
30177
|
for (const k of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
29925
|
-
const v =
|
|
30178
|
+
const v = pkg[k];
|
|
29926
30179
|
if (v && typeof v === "object") {
|
|
29927
30180
|
for (const name of Object.keys(v)) {
|
|
29928
30181
|
out.add(name);
|
|
@@ -30349,7 +30602,7 @@ var init_spacing_grid = __esm({
|
|
|
30349
30602
|
"use strict";
|
|
30350
30603
|
init_rule();
|
|
30351
30604
|
init_utils();
|
|
30352
|
-
|
|
30605
|
+
init_config2();
|
|
30353
30606
|
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
30607
|
ARBITRARY_VALUE_RE2 = /^(-?\d+(?:\.\d+)?)(px|rem)$/;
|
|
30355
30608
|
SKIP_VALUES = /* @__PURE__ */ new Set(["auto", "full", "screen", "min", "max", "fit", "none"]);
|
|
@@ -42437,6 +42690,78 @@ function extractStateBinding(node, lineOffsets) {
|
|
|
42437
42690
|
setterReferenced: false
|
|
42438
42691
|
};
|
|
42439
42692
|
}
|
|
42693
|
+
function findUnreachableStatements(ast, source, lineOffsets) {
|
|
42694
|
+
const out = [];
|
|
42695
|
+
function isTerminator(node) {
|
|
42696
|
+
if (node.type === "ReturnStatement") return "return";
|
|
42697
|
+
if (node.type === "ThrowStatement") return "throw";
|
|
42698
|
+
if (node.type === "BreakStatement") return "break";
|
|
42699
|
+
if (node.type === "ContinueStatement") return "continue";
|
|
42700
|
+
return null;
|
|
42701
|
+
}
|
|
42702
|
+
function snippetFor(node, src) {
|
|
42703
|
+
const span = node.span;
|
|
42704
|
+
if (!span || typeof span.start !== "number" || typeof span.end !== "number") {
|
|
42705
|
+
return "<unreachable>";
|
|
42706
|
+
}
|
|
42707
|
+
const text = src.slice(span.start, Math.min(span.end, span.start + 60));
|
|
42708
|
+
return text.replace(/\s+/g, " ").trim() || "<unreachable>";
|
|
42709
|
+
}
|
|
42710
|
+
function lineColumn(offset) {
|
|
42711
|
+
let lo = 0;
|
|
42712
|
+
let hi = lineOffsets.length - 1;
|
|
42713
|
+
while (lo < hi) {
|
|
42714
|
+
const mid = lo + hi + 1 >>> 1;
|
|
42715
|
+
const midVal = lineOffsets[mid];
|
|
42716
|
+
const loVal = lineOffsets[lo];
|
|
42717
|
+
if (midVal === void 0) break;
|
|
42718
|
+
if (midVal <= offset) lo = mid;
|
|
42719
|
+
else hi = mid - 1;
|
|
42720
|
+
void loVal;
|
|
42721
|
+
}
|
|
42722
|
+
const baseOffset = lineOffsets[lo] ?? 0;
|
|
42723
|
+
return { line: lo + 1, column: offset - baseOffset };
|
|
42724
|
+
}
|
|
42725
|
+
function visitBody(body) {
|
|
42726
|
+
if (!Array.isArray(body)) return;
|
|
42727
|
+
let lastTerminator = null;
|
|
42728
|
+
for (const stmt of body) {
|
|
42729
|
+
if (!isObject(stmt)) continue;
|
|
42730
|
+
if (lastTerminator && stmt.type !== "EmptyStatement") {
|
|
42731
|
+
const span = stmt.span;
|
|
42732
|
+
const offset = typeof span?.start === "number" ? span.start : 0;
|
|
42733
|
+
const { line, column } = lineColumn(offset);
|
|
42734
|
+
out.push({
|
|
42735
|
+
terminator: lastTerminator,
|
|
42736
|
+
line,
|
|
42737
|
+
column,
|
|
42738
|
+
snippet: snippetFor(stmt, source)
|
|
42739
|
+
});
|
|
42740
|
+
}
|
|
42741
|
+
const t = isTerminator(stmt);
|
|
42742
|
+
if (t) lastTerminator = t;
|
|
42743
|
+
}
|
|
42744
|
+
}
|
|
42745
|
+
function walk3(node) {
|
|
42746
|
+
if (!isObject(node)) return;
|
|
42747
|
+
if (node.type === "BlockStatement") {
|
|
42748
|
+
visitBody(node.stmts);
|
|
42749
|
+
} else if (node.type === "Module") {
|
|
42750
|
+
visitBody(node.body);
|
|
42751
|
+
}
|
|
42752
|
+
for (const key of Object.keys(node)) {
|
|
42753
|
+
if (key === "parent" || key === "span" || key === "ctxt") continue;
|
|
42754
|
+
const child = node[key];
|
|
42755
|
+
if (Array.isArray(child)) {
|
|
42756
|
+
for (const c of child) walk3(c);
|
|
42757
|
+
} else {
|
|
42758
|
+
walk3(child);
|
|
42759
|
+
}
|
|
42760
|
+
}
|
|
42761
|
+
}
|
|
42762
|
+
walk3(ast);
|
|
42763
|
+
return out;
|
|
42764
|
+
}
|
|
42440
42765
|
var init_scan_helpers = __esm({
|
|
42441
42766
|
"src/engine/visitors/scan-helpers.ts"() {
|
|
42442
42767
|
"use strict";
|
|
@@ -42522,15 +42847,42 @@ function handleImportDeclaration(node, _parent, _path, vctx) {
|
|
|
42522
42847
|
if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
|
|
42523
42848
|
const local = specifier.local;
|
|
42524
42849
|
if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
|
|
42525
|
-
|
|
42850
|
+
const name = local.value;
|
|
42851
|
+
importedNames.push(name);
|
|
42852
|
+
vctx.facts.deadCode.bindings.push({
|
|
42853
|
+
name,
|
|
42854
|
+
kind: specifier.type === "ImportDefaultSpecifier" ? "import-default" : "import-namespace",
|
|
42855
|
+
line,
|
|
42856
|
+
column,
|
|
42857
|
+
source,
|
|
42858
|
+
isReferenced: false
|
|
42859
|
+
});
|
|
42526
42860
|
}
|
|
42527
42861
|
} else if (specifier.type === "ImportSpecifier") {
|
|
42528
42862
|
const imported = specifier.imported;
|
|
42529
42863
|
const local = specifier.local;
|
|
42530
42864
|
if (isObject(imported) && typeof imported.value === "string" && imported.value.length > 0) {
|
|
42531
|
-
|
|
42865
|
+
const name = imported.value;
|
|
42866
|
+
importedNames.push(name);
|
|
42867
|
+
vctx.facts.deadCode.bindings.push({
|
|
42868
|
+
name,
|
|
42869
|
+
kind: "import-specifier",
|
|
42870
|
+
line,
|
|
42871
|
+
column,
|
|
42872
|
+
source,
|
|
42873
|
+
isReferenced: false
|
|
42874
|
+
});
|
|
42532
42875
|
} else if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
|
|
42533
|
-
|
|
42876
|
+
const name = local.value;
|
|
42877
|
+
importedNames.push(name);
|
|
42878
|
+
vctx.facts.deadCode.bindings.push({
|
|
42879
|
+
name,
|
|
42880
|
+
kind: "import-specifier",
|
|
42881
|
+
line,
|
|
42882
|
+
column,
|
|
42883
|
+
source,
|
|
42884
|
+
isReferenced: false
|
|
42885
|
+
});
|
|
42534
42886
|
}
|
|
42535
42887
|
}
|
|
42536
42888
|
}
|
|
@@ -42620,6 +42972,13 @@ function isBindingSite(node, parent) {
|
|
|
42620
42972
|
if (params.some((param) => containsNode(param, node))) return true;
|
|
42621
42973
|
}
|
|
42622
42974
|
}
|
|
42975
|
+
if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") {
|
|
42976
|
+
if (parent.type === "ImportSpecifier") {
|
|
42977
|
+
if (parent.imported === node || parent.local === node) return true;
|
|
42978
|
+
} else {
|
|
42979
|
+
if (parent.local === node) return true;
|
|
42980
|
+
}
|
|
42981
|
+
}
|
|
42623
42982
|
return false;
|
|
42624
42983
|
}
|
|
42625
42984
|
function isNonComputedMemberProperty(node, parent) {
|
|
@@ -42686,6 +43045,9 @@ function handleIdentifier(node, parent, path, vctx) {
|
|
|
42686
43045
|
if (typeof node.value === "string" && !isBindingSite(node, parent) && !isNonComputedMemberProperty(node, parent)) {
|
|
42687
43046
|
markStateReference(node.value, vctx);
|
|
42688
43047
|
trackPropUsage(node, parent, path, vctx);
|
|
43048
|
+
vctx.facts.referencedNames.add(node.value);
|
|
43049
|
+
const top = vctx.ctx.stack[vctx.ctx.stack.length - 1];
|
|
43050
|
+
if (top) top.references.add(node.value);
|
|
42689
43051
|
}
|
|
42690
43052
|
return false;
|
|
42691
43053
|
}
|
|
@@ -42826,6 +43188,20 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
|
|
|
42826
43188
|
frame.bindings.add(bindingName);
|
|
42827
43189
|
}
|
|
42828
43190
|
}
|
|
43191
|
+
if (bindingNames.length > 0) {
|
|
43192
|
+
const parent = node.parent;
|
|
43193
|
+
const kind = isObject(parent) && parent.type === "VariableDeclaration" ? String(parent.kind ?? "var") : "var";
|
|
43194
|
+
const { line, column } = positionFrom(id, vctx.lineOffsets);
|
|
43195
|
+
for (const bindingName of bindingNames) {
|
|
43196
|
+
vctx.facts.deadCode.bindings.push({
|
|
43197
|
+
name: bindingName,
|
|
43198
|
+
kind,
|
|
43199
|
+
line,
|
|
43200
|
+
column,
|
|
43201
|
+
isReferenced: false
|
|
43202
|
+
});
|
|
43203
|
+
}
|
|
43204
|
+
}
|
|
42829
43205
|
if (isUseStateDeclarator(node)) {
|
|
42830
43206
|
const binding = extractStateBinding(node, vctx.lineOffsets);
|
|
42831
43207
|
if (binding) {
|
|
@@ -42845,6 +43221,36 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
|
|
|
42845
43221
|
}
|
|
42846
43222
|
return true;
|
|
42847
43223
|
}
|
|
43224
|
+
function handleIfStatement(node, _parent, _path, vctx) {
|
|
43225
|
+
if (!isObject(node)) return false;
|
|
43226
|
+
const test = node.test;
|
|
43227
|
+
if (!isObject(test)) return false;
|
|
43228
|
+
if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
|
|
43229
|
+
const { line, column } = positionFrom(test, vctx.lineOffsets);
|
|
43230
|
+
vctx.facts.deadCode.constantConditions.push({
|
|
43231
|
+
kind: test.value ? "if-true" : "if-false",
|
|
43232
|
+
condition: String(test.value),
|
|
43233
|
+
line,
|
|
43234
|
+
column
|
|
43235
|
+
});
|
|
43236
|
+
}
|
|
43237
|
+
return false;
|
|
43238
|
+
}
|
|
43239
|
+
function handleWhileStatement(node, _parent, _path, vctx) {
|
|
43240
|
+
if (!isObject(node)) return false;
|
|
43241
|
+
const test = node.test;
|
|
43242
|
+
if (!isObject(test)) return false;
|
|
43243
|
+
if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
|
|
43244
|
+
const { line, column } = positionFrom(test, vctx.lineOffsets);
|
|
43245
|
+
vctx.facts.deadCode.constantConditions.push({
|
|
43246
|
+
kind: test.value ? "while-true" : "while-false",
|
|
43247
|
+
condition: String(test.value),
|
|
43248
|
+
line,
|
|
43249
|
+
column
|
|
43250
|
+
});
|
|
43251
|
+
}
|
|
43252
|
+
return false;
|
|
43253
|
+
}
|
|
42848
43254
|
function dispatchNode(node, parent, path, vctx) {
|
|
42849
43255
|
if (!isObject(node)) return false;
|
|
42850
43256
|
const type = getNodeType(node);
|
|
@@ -42869,7 +43275,9 @@ var init_dispatch = __esm({
|
|
|
42869
43275
|
MemberExpression: handleMemberExpression,
|
|
42870
43276
|
JSXAttribute: handleJSXAttribute,
|
|
42871
43277
|
JSXOpeningElement: handleJSXOpeningElement,
|
|
42872
|
-
VariableDeclarator: handleVariableDeclarator
|
|
43278
|
+
VariableDeclarator: handleVariableDeclarator,
|
|
43279
|
+
IfStatement: handleIfStatement,
|
|
43280
|
+
WhileStatement: handleWhileStatement
|
|
42873
43281
|
};
|
|
42874
43282
|
}
|
|
42875
43283
|
});
|
|
@@ -43020,6 +43428,17 @@ function buildV2Facts(facts, source, ext, framework, config, templateClassNames
|
|
|
43020
43428
|
},
|
|
43021
43429
|
logic: buildLogicBlock(facts),
|
|
43022
43430
|
designTokens: scanDesignTokens(facts.staticClassNames),
|
|
43431
|
+
// dead-code detector. Copy the internal accumulator
|
|
43432
|
+
// into the v2 shape, marking each binding as referenced
|
|
43433
|
+
// iff the file-level referenced-name set contains its name.
|
|
43434
|
+
deadCode: {
|
|
43435
|
+
bindings: facts.deadCode.bindings.map((b) => ({
|
|
43436
|
+
...b,
|
|
43437
|
+
isReferenced: facts.referencedNames.has(b.name)
|
|
43438
|
+
})),
|
|
43439
|
+
constantConditions: facts.deadCode.constantConditions,
|
|
43440
|
+
unreachableStatements: facts.deadCode.unreachableStatements
|
|
43441
|
+
},
|
|
43023
43442
|
componentSizes: facts.componentSizes.map((cs) => ({
|
|
43024
43443
|
name: cs.name,
|
|
43025
43444
|
lineCount: cs.lineCount,
|
|
@@ -43101,7 +43520,17 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43101
43520
|
componentSizes: [],
|
|
43102
43521
|
astroComponents: [],
|
|
43103
43522
|
fetchCalls: [],
|
|
43104
|
-
optimisticUpdates: []
|
|
43523
|
+
optimisticUpdates: [],
|
|
43524
|
+
// dead-code detector. The visitor's identifier walk + import/
|
|
43525
|
+
// branch/return handlers populate these. The v2 builder at the
|
|
43526
|
+
// bottom of extractFacts() reads them and produces
|
|
43527
|
+
// `facts.v2.deadCode`.
|
|
43528
|
+
deadCode: {
|
|
43529
|
+
bindings: [],
|
|
43530
|
+
constantConditions: [],
|
|
43531
|
+
unreachableStatements: []
|
|
43532
|
+
},
|
|
43533
|
+
referencedNames: /* @__PURE__ */ new Set()
|
|
43105
43534
|
};
|
|
43106
43535
|
const ctx = {
|
|
43107
43536
|
stack: [],
|
|
@@ -43188,6 +43617,16 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43188
43617
|
propBindingSet.add(bindingName);
|
|
43189
43618
|
}
|
|
43190
43619
|
}
|
|
43620
|
+
const { line: pLine, column: pCol } = positionFrom(param, lineOffsets);
|
|
43621
|
+
for (const bindingName of collectBindingNames2(param)) {
|
|
43622
|
+
facts.deadCode.bindings.push({
|
|
43623
|
+
name: bindingName,
|
|
43624
|
+
kind: "parameter",
|
|
43625
|
+
line: pLine,
|
|
43626
|
+
column: pCol,
|
|
43627
|
+
isReferenced: false
|
|
43628
|
+
});
|
|
43629
|
+
}
|
|
43191
43630
|
}
|
|
43192
43631
|
}
|
|
43193
43632
|
ctx.stack.push({
|
|
@@ -43203,6 +43642,12 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43203
43642
|
propUsages: [],
|
|
43204
43643
|
isComponent,
|
|
43205
43644
|
bindings,
|
|
43645
|
+
// dead-code detector: per-frame referenced-name set.
|
|
43646
|
+
// Identifiers encountered inside the frame are added to this
|
|
43647
|
+
// set; the deadCode builder unions it with parent frames at
|
|
43648
|
+
// pop time so a binding is considered used if any reachable
|
|
43649
|
+
// scope references it.
|
|
43650
|
+
references: /* @__PURE__ */ new Set(),
|
|
43206
43651
|
propBindingSet,
|
|
43207
43652
|
propUsageSet: /* @__PURE__ */ new Set(),
|
|
43208
43653
|
node
|
|
@@ -43298,6 +43743,11 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
|
|
|
43298
43743
|
mergeTemplateClassNames(filePath, source, facts, templateClassNames);
|
|
43299
43744
|
const { ext } = splitFilePath(filePath);
|
|
43300
43745
|
facts._source = source;
|
|
43746
|
+
facts.deadCode.unreachableStatements = findUnreachableStatements(
|
|
43747
|
+
ast,
|
|
43748
|
+
source,
|
|
43749
|
+
lineOffsets
|
|
43750
|
+
);
|
|
43301
43751
|
const v2 = buildV2Facts(facts, source, ext, framework, config, templateClassNames);
|
|
43302
43752
|
return envelopeScanFacts(filePath, v2);
|
|
43303
43753
|
}
|
|
@@ -43980,6 +44430,11 @@ var init_builtins = __esm({
|
|
|
43980
44430
|
init_missing_not_null();
|
|
43981
44431
|
init_naming_inconsistency();
|
|
43982
44432
|
init_sql_concat();
|
|
44433
|
+
init_dead_branch();
|
|
44434
|
+
init_unreachable();
|
|
44435
|
+
init_unused_import();
|
|
44436
|
+
init_unused_local();
|
|
44437
|
+
init_unused_parameter();
|
|
43983
44438
|
init_broken_link();
|
|
43984
44439
|
init_expired_code_example();
|
|
43985
44440
|
init_stale_function_reference();
|
|
@@ -44076,6 +44531,11 @@ var init_builtins = __esm({
|
|
|
44076
44531
|
missingNotNullRule,
|
|
44077
44532
|
namingInconsistencyRule,
|
|
44078
44533
|
sqlConcatRule,
|
|
44534
|
+
deadBranchRule,
|
|
44535
|
+
unreachableRule,
|
|
44536
|
+
unusedImportRule,
|
|
44537
|
+
unusedLocalRule,
|
|
44538
|
+
unusedParameterRule,
|
|
44079
44539
|
brokenLinkRule,
|
|
44080
44540
|
expiredCodeExampleRule,
|
|
44081
44541
|
staleFunctionReferenceRule,
|
|
@@ -44614,7 +45074,7 @@ var init_validation = __esm({
|
|
|
44614
45074
|
// src/config/load.ts
|
|
44615
45075
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
|
|
44616
45076
|
import { dirname as dirname7, extname as extname5, join as join11, resolve as resolve6 } from "path";
|
|
44617
|
-
import { createRequire
|
|
45077
|
+
import { createRequire } from "module";
|
|
44618
45078
|
function deepMerge(target, source) {
|
|
44619
45079
|
const out = { ...target };
|
|
44620
45080
|
for (const key of Object.keys(source)) {
|
|
@@ -44650,8 +45110,8 @@ function detectJsLoader(configPath) {
|
|
|
44650
45110
|
const pkgPath = join11(current, "package.json");
|
|
44651
45111
|
if (existsSync10(pkgPath)) {
|
|
44652
45112
|
try {
|
|
44653
|
-
const
|
|
44654
|
-
return
|
|
45113
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
45114
|
+
return pkg.type === "module" ? "import" : "require";
|
|
44655
45115
|
} catch {
|
|
44656
45116
|
return "require";
|
|
44657
45117
|
}
|
|
@@ -44665,7 +45125,7 @@ function detectJsLoader(configPath) {
|
|
|
44665
45125
|
async function loadConfigFile(path) {
|
|
44666
45126
|
const loader = detectJsLoader(path);
|
|
44667
45127
|
if (loader === "require") {
|
|
44668
|
-
const req =
|
|
45128
|
+
const req = createRequire(import.meta.url);
|
|
44669
45129
|
const mod2 = req(path);
|
|
44670
45130
|
return mod2.default ?? mod2;
|
|
44671
45131
|
}
|
|
@@ -44846,7 +45306,7 @@ var init_init = __esm({
|
|
|
44846
45306
|
});
|
|
44847
45307
|
|
|
44848
45308
|
// src/config/index.ts
|
|
44849
|
-
var
|
|
45309
|
+
var init_config2 = __esm({
|
|
44850
45310
|
"src/config/index.ts"() {
|
|
44851
45311
|
"use strict";
|
|
44852
45312
|
init_defaults();
|
|
@@ -46991,6 +47451,61 @@ var init_signal_strength = __esm({
|
|
|
46991
47451
|
_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
47452
|
aiSpecific: true
|
|
46993
47453
|
},
|
|
47454
|
+
"dead/unused-import": {
|
|
47455
|
+
recall: 0,
|
|
47456
|
+
fpRate: 0,
|
|
47457
|
+
ratio: 0,
|
|
47458
|
+
precision: 0,
|
|
47459
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
47460
|
+
verdict: "DORMANT",
|
|
47461
|
+
defaultOff: true,
|
|
47462
|
+
_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.",
|
|
47463
|
+
aiSpecific: true
|
|
47464
|
+
},
|
|
47465
|
+
"dead/unused-local": {
|
|
47466
|
+
recall: 0,
|
|
47467
|
+
fpRate: 0,
|
|
47468
|
+
ratio: 0,
|
|
47469
|
+
precision: 0,
|
|
47470
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
47471
|
+
verdict: "DORMANT",
|
|
47472
|
+
defaultOff: true,
|
|
47473
|
+
_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).",
|
|
47474
|
+
aiSpecific: true
|
|
47475
|
+
},
|
|
47476
|
+
"dead/unused-parameter": {
|
|
47477
|
+
recall: 0,
|
|
47478
|
+
fpRate: 0,
|
|
47479
|
+
ratio: 0,
|
|
47480
|
+
precision: 0,
|
|
47481
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
47482
|
+
verdict: "DORMANT",
|
|
47483
|
+
defaultOff: true,
|
|
47484
|
+
_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.",
|
|
47485
|
+
aiSpecific: true
|
|
47486
|
+
},
|
|
47487
|
+
"dead/dead-branch": {
|
|
47488
|
+
recall: 0,
|
|
47489
|
+
fpRate: 0,
|
|
47490
|
+
ratio: 0,
|
|
47491
|
+
precision: 0,
|
|
47492
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
47493
|
+
verdict: "DORMANT",
|
|
47494
|
+
defaultOff: true,
|
|
47495
|
+
_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.",
|
|
47496
|
+
aiSpecific: true
|
|
47497
|
+
},
|
|
47498
|
+
"dead/unreachable": {
|
|
47499
|
+
recall: 0,
|
|
47500
|
+
fpRate: 0,
|
|
47501
|
+
ratio: 0,
|
|
47502
|
+
precision: 0,
|
|
47503
|
+
lastCalibratedAt: "2026-06-30T00:00:00Z",
|
|
47504
|
+
verdict: "DORMANT",
|
|
47505
|
+
defaultOff: true,
|
|
47506
|
+
_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.",
|
|
47507
|
+
aiSpecific: true
|
|
47508
|
+
},
|
|
46994
47509
|
"docs/stale-package-reference": {
|
|
46995
47510
|
recall: 0,
|
|
46996
47511
|
fpRate: 0,
|
|
@@ -47951,7 +48466,7 @@ var init_cache = __esm({
|
|
|
47951
48466
|
"src/engine/cache.ts"() {
|
|
47952
48467
|
"use strict";
|
|
47953
48468
|
init_types();
|
|
47954
|
-
|
|
48469
|
+
init_config2();
|
|
47955
48470
|
BASELINE_VERSION = VERSION;
|
|
47956
48471
|
BASELINE_HASH_KEYS = /* @__PURE__ */ new Set([
|
|
47957
48472
|
"framework",
|
|
@@ -50442,7 +50957,7 @@ var init_finalizeReport = __esm({
|
|
|
50442
50957
|
init_dist2();
|
|
50443
50958
|
init_logger();
|
|
50444
50959
|
init_memory_io();
|
|
50445
|
-
|
|
50960
|
+
init_config2();
|
|
50446
50961
|
init_enrichReport();
|
|
50447
50962
|
init_assembleScanReport();
|
|
50448
50963
|
init_persistRun();
|
|
@@ -52366,11 +52881,11 @@ var init_watch = __esm({
|
|
|
52366
52881
|
init_worker();
|
|
52367
52882
|
init_threshold();
|
|
52368
52883
|
init_cache();
|
|
52369
|
-
|
|
52884
|
+
init_config2();
|
|
52370
52885
|
init_render();
|
|
52371
52886
|
init_logger();
|
|
52372
52887
|
init_error();
|
|
52373
|
-
|
|
52888
|
+
init_scan2();
|
|
52374
52889
|
init_renderOutput();
|
|
52375
52890
|
init_types();
|
|
52376
52891
|
}
|
|
@@ -52652,12 +53167,12 @@ async function scanProject(options) {
|
|
|
52652
53167
|
const { report } = await runScan({ ...options, workspace: options.cwd });
|
|
52653
53168
|
return report;
|
|
52654
53169
|
}
|
|
52655
|
-
var
|
|
53170
|
+
var init_scan2 = __esm({
|
|
52656
53171
|
"src/cli/scan.ts"() {
|
|
52657
53172
|
"use strict";
|
|
52658
53173
|
init_render();
|
|
52659
53174
|
init_threshold();
|
|
52660
|
-
|
|
53175
|
+
init_config2();
|
|
52661
53176
|
init_discover();
|
|
52662
53177
|
init_git();
|
|
52663
53178
|
init_cache_incremental();
|
|
@@ -52829,7 +53344,7 @@ async function runSuggest(args, ctx) {
|
|
|
52829
53344
|
}
|
|
52830
53345
|
async function runGovernance(args, ctx) {
|
|
52831
53346
|
try {
|
|
52832
|
-
const { runScan: runScan3 } = await Promise.resolve().then(() => (
|
|
53347
|
+
const { runScan: runScan3 } = await Promise.resolve().then(() => (init_scan2(), scan_exports));
|
|
52833
53348
|
const maxFiles = typeof args.maxFiles === "number" && Number.isFinite(args.maxFiles) && args.maxFiles > 0 ? Math.floor(args.maxFiles) : 500;
|
|
52834
53349
|
const { report } = await runScan3({
|
|
52835
53350
|
workspace: ctx.cwd,
|
|
@@ -53229,7 +53744,7 @@ var init_tools = __esm({
|
|
|
53229
53744
|
|
|
53230
53745
|
// src/index.ts
|
|
53231
53746
|
init_types();
|
|
53232
|
-
|
|
53747
|
+
init_config2();
|
|
53233
53748
|
init_dist2();
|
|
53234
53749
|
|
|
53235
53750
|
// src/cli/program.ts
|
|
@@ -53273,11 +53788,11 @@ function parseThreshold(value) {
|
|
|
53273
53788
|
// src/cli/program.ts
|
|
53274
53789
|
init_render();
|
|
53275
53790
|
init_threshold();
|
|
53276
|
-
|
|
53277
|
-
|
|
53791
|
+
init_scan2();
|
|
53792
|
+
init_scan2();
|
|
53278
53793
|
|
|
53279
53794
|
// src/cli/init.ts
|
|
53280
|
-
|
|
53795
|
+
init_config2();
|
|
53281
53796
|
init_discover();
|
|
53282
53797
|
init_git();
|
|
53283
53798
|
init_cache();
|
|
@@ -53769,7 +54284,7 @@ async function runDoctor(cwd) {
|
|
|
53769
54284
|
// src/cli/commands/badge.ts
|
|
53770
54285
|
init_render();
|
|
53771
54286
|
init_logger();
|
|
53772
|
-
|
|
54287
|
+
init_scan2();
|
|
53773
54288
|
import { resolve as resolve13 } from "path";
|
|
53774
54289
|
function registerBadge(program) {
|
|
53775
54290
|
program.command("badge").description(
|
|
@@ -53796,7 +54311,7 @@ function registerBadge(program) {
|
|
|
53796
54311
|
init_advice();
|
|
53797
54312
|
init_unified_diff();
|
|
53798
54313
|
init_logger();
|
|
53799
|
-
|
|
54314
|
+
init_scan2();
|
|
53800
54315
|
import { resolve as resolve14 } from "path";
|
|
53801
54316
|
function registerSuggest(program) {
|
|
53802
54317
|
program.command("suggest").description("print remediation advice").action(async (_cmdOptions, command) => {
|
|
@@ -53924,6 +54439,11 @@ var RULE_HINTS = {
|
|
|
53924
54439
|
"logic/qwik-hook-leak": "Use Qwik primitives ($state, $effect, useSignal) instead of React hooks (useState, useEffect).",
|
|
53925
54440
|
"logic/reactive-hook-soup": "Coordinate state via a single derived value (useMemo) or a state machine. Avoid chained useEffects that sync local state.",
|
|
53926
54441
|
"logic/zombie-state": "Remove unused useState or wire it into the component. Don't leave declared-but-never-read state bindings.",
|
|
54442
|
+
"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.",
|
|
54443
|
+
"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.",
|
|
54444
|
+
"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.",
|
|
54445
|
+
"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.",
|
|
54446
|
+
"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
54447
|
"perf/cls-image": "Add width/height attributes or an aspect-ratio utility to prevent layout shift.",
|
|
53928
54448
|
"perf/css-bloat": "Extract to a CSS variable (`--surface-card`) or a component prop when a class string repeats 5+ times.",
|
|
53929
54449
|
"perf/halstead-anomaly": "Introduce domain-specific identifiers and varied operations. Low vocabulary per line is a strong AI signature (Halstead 1977 \xA73).",
|
|
@@ -54184,7 +54704,7 @@ init_logger();
|
|
|
54184
54704
|
|
|
54185
54705
|
// src/mcp/server.ts
|
|
54186
54706
|
init_builtins();
|
|
54187
|
-
|
|
54707
|
+
init_config2();
|
|
54188
54708
|
init_tools();
|
|
54189
54709
|
var SERVER_INFO = {
|
|
54190
54710
|
name: "slopbrick",
|
|
@@ -55613,7 +56133,7 @@ function registerTrend(program) {
|
|
|
55613
56133
|
|
|
55614
56134
|
// src/cli/commands/drift.ts
|
|
55615
56135
|
init_logger();
|
|
55616
|
-
|
|
56136
|
+
init_scan2();
|
|
55617
56137
|
import { resolve as resolve26 } from "path";
|
|
55618
56138
|
|
|
55619
56139
|
// src/cli/drift.ts
|
|
@@ -55754,7 +56274,7 @@ function registerDrift(program) {
|
|
|
55754
56274
|
|
|
55755
56275
|
// src/cli/commands/pr.ts
|
|
55756
56276
|
init_logger();
|
|
55757
|
-
|
|
56277
|
+
init_scan2();
|
|
55758
56278
|
import { resolve as resolve28 } from "path";
|
|
55759
56279
|
|
|
55760
56280
|
// src/cli/pr.ts
|
|
@@ -56043,7 +56563,7 @@ function registerPr(program) {
|
|
|
56043
56563
|
|
|
56044
56564
|
// src/cli/commands/security.ts
|
|
56045
56565
|
init_logger();
|
|
56046
|
-
|
|
56566
|
+
init_scan2();
|
|
56047
56567
|
init_ai_security_risk();
|
|
56048
56568
|
import { resolve as resolve29 } from "path";
|
|
56049
56569
|
function registerSecurity(program) {
|
|
@@ -56102,11 +56622,11 @@ function registerSecurity(program) {
|
|
|
56102
56622
|
|
|
56103
56623
|
// src/cli/commands/test.ts
|
|
56104
56624
|
init_logger();
|
|
56105
|
-
|
|
56625
|
+
init_scan2();
|
|
56106
56626
|
import { resolve as resolve31 } from "path";
|
|
56107
56627
|
|
|
56108
56628
|
// src/cli/test.ts
|
|
56109
|
-
|
|
56629
|
+
init_scan2();
|
|
56110
56630
|
init_test_quality();
|
|
56111
56631
|
init_logger();
|
|
56112
56632
|
import { resolve as resolve30 } from "path";
|
|
@@ -56221,7 +56741,7 @@ function registerTest(program) {
|
|
|
56221
56741
|
|
|
56222
56742
|
// src/cli/commands/architecture.ts
|
|
56223
56743
|
init_logger();
|
|
56224
|
-
|
|
56744
|
+
init_scan2();
|
|
56225
56745
|
init_architecture_score();
|
|
56226
56746
|
import { resolve as resolve32 } from "path";
|
|
56227
56747
|
function registerArchitecture(program) {
|
|
@@ -56249,7 +56769,7 @@ function registerArchitecture(program) {
|
|
|
56249
56769
|
|
|
56250
56770
|
// src/cli/commands/business-logic.ts
|
|
56251
56771
|
init_logger();
|
|
56252
|
-
|
|
56772
|
+
init_scan2();
|
|
56253
56773
|
import { resolve as resolve33 } from "path";
|
|
56254
56774
|
|
|
56255
56775
|
// src/cli/business-logic.ts
|
|
@@ -56395,11 +56915,11 @@ function registerBusinessLogic(program) {
|
|
|
56395
56915
|
|
|
56396
56916
|
// src/cli/commands/maintenance-cost.ts
|
|
56397
56917
|
init_logger();
|
|
56398
|
-
|
|
56918
|
+
init_scan2();
|
|
56399
56919
|
import { resolve as resolve34 } from "path";
|
|
56400
56920
|
|
|
56401
56921
|
// src/cli/maintenance-cost.ts
|
|
56402
|
-
|
|
56922
|
+
init_scan2();
|
|
56403
56923
|
init_maintenance_cost();
|
|
56404
56924
|
init_logger();
|
|
56405
56925
|
async function runMaintenanceCostScan(cwd, config, options = {}) {
|
|
@@ -56538,11 +57058,11 @@ function registerMaintenanceCost(program) {
|
|
|
56538
57058
|
|
|
56539
57059
|
// src/cli/commands/docs.ts
|
|
56540
57060
|
init_logger();
|
|
56541
|
-
|
|
57061
|
+
init_scan2();
|
|
56542
57062
|
import { resolve as resolve35 } from "path";
|
|
56543
57063
|
|
|
56544
57064
|
// src/cli/docs.ts
|
|
56545
|
-
|
|
57065
|
+
init_scan2();
|
|
56546
57066
|
init_doc_freshness();
|
|
56547
57067
|
init_logger();
|
|
56548
57068
|
async function runDocsScan(cwd, config, options = {}) {
|
|
@@ -56687,11 +57207,11 @@ function registerDocs(program) {
|
|
|
56687
57207
|
|
|
56688
57208
|
// src/cli/commands/db.ts
|
|
56689
57209
|
init_logger();
|
|
56690
|
-
|
|
57210
|
+
init_scan2();
|
|
56691
57211
|
import { resolve as resolve36 } from "path";
|
|
56692
57212
|
|
|
56693
57213
|
// src/cli/db.ts
|
|
56694
|
-
|
|
57214
|
+
init_scan2();
|
|
56695
57215
|
init_db_health();
|
|
56696
57216
|
init_logger();
|
|
56697
57217
|
async function runDbScan(cwd, config, options = {}) {
|
|
@@ -56830,7 +57350,7 @@ function registerDb(program) {
|
|
|
56830
57350
|
|
|
56831
57351
|
// src/cli/commands/patterns.ts
|
|
56832
57352
|
init_logger();
|
|
56833
|
-
|
|
57353
|
+
init_scan2();
|
|
56834
57354
|
import { resolve as resolve37 } from "path";
|
|
56835
57355
|
|
|
56836
57356
|
// src/engine/patterns.ts
|
|
@@ -57178,7 +57698,7 @@ function registerPatterns(program) {
|
|
|
57178
57698
|
|
|
57179
57699
|
// src/cli/commands/research.ts
|
|
57180
57700
|
init_logger();
|
|
57181
|
-
|
|
57701
|
+
init_config2();
|
|
57182
57702
|
import { existsSync as existsSync27, mkdirSync as mkdirSync14, readFileSync as readFileSync34, writeFileSync as writeFileSync17 } from "fs";
|
|
57183
57703
|
import { dirname as dirname18, resolve as resolve38 } from "path";
|
|
57184
57704
|
function registerResearch(program) {
|
|
@@ -57261,8 +57781,8 @@ init_logger();
|
|
|
57261
57781
|
init_builtins();
|
|
57262
57782
|
import { existsSync as existsSync28, mkdirSync as mkdirSync15, readFileSync as readFileSync35, writeFileSync as writeFileSync18 } from "fs";
|
|
57263
57783
|
import { dirname as dirname19, join as join29, resolve as resolve39 } from "path";
|
|
57264
|
-
|
|
57265
|
-
|
|
57784
|
+
init_scan2();
|
|
57785
|
+
init_config2();
|
|
57266
57786
|
init_threshold();
|
|
57267
57787
|
init_git();
|
|
57268
57788
|
init_cache();
|
|
@@ -57743,7 +58263,7 @@ function registerScan(program, scanAction) {
|
|
|
57743
58263
|
}
|
|
57744
58264
|
|
|
57745
58265
|
// src/cli/program.ts
|
|
57746
|
-
|
|
58266
|
+
init_config2();
|
|
57747
58267
|
init_git();
|
|
57748
58268
|
init_logger();
|
|
57749
58269
|
init_unified_diff();
|
|
@@ -58176,7 +58696,140 @@ async function applyFixes(report, config, scannedFiles) {
|
|
|
58176
58696
|
// src/cli/program.ts
|
|
58177
58697
|
init_cache();
|
|
58178
58698
|
init_types();
|
|
58179
|
-
|
|
58699
|
+
|
|
58700
|
+
// src/cli/help.ts
|
|
58701
|
+
var CATEGORY_LABELS3 = {
|
|
58702
|
+
file: "File selection",
|
|
58703
|
+
filter: "Filter",
|
|
58704
|
+
output: "Output & display",
|
|
58705
|
+
perf: "Performance",
|
|
58706
|
+
fix: "Auto-fix",
|
|
58707
|
+
ci: "CI / threshold",
|
|
58708
|
+
watch: "Watch & diagnose",
|
|
58709
|
+
tokens: "Tokens",
|
|
58710
|
+
telemetry: "Telemetry",
|
|
58711
|
+
other: "Other"
|
|
58712
|
+
};
|
|
58713
|
+
var OPTION_CATEGORY = {
|
|
58714
|
+
// File selection
|
|
58715
|
+
"--include": "file",
|
|
58716
|
+
"--exclude": "file",
|
|
58717
|
+
"--since": "file",
|
|
58718
|
+
"--diff": "file",
|
|
58719
|
+
"--staged": "file",
|
|
58720
|
+
"--changed": "file",
|
|
58721
|
+
"--workspace": "file",
|
|
58722
|
+
// Filter
|
|
58723
|
+
"--ai-only": "filter",
|
|
58724
|
+
"--human-only": "filter",
|
|
58725
|
+
"--security-only": "filter",
|
|
58726
|
+
"--ignore-wcag22": "filter",
|
|
58727
|
+
"--framework": "filter",
|
|
58728
|
+
// Output & display
|
|
58729
|
+
"--format": "output",
|
|
58730
|
+
"--brief": "output",
|
|
58731
|
+
"--full": "output",
|
|
58732
|
+
"--json": "output",
|
|
58733
|
+
"--html": "output",
|
|
58734
|
+
"--no-color": "output",
|
|
58735
|
+
"--quiet": "output",
|
|
58736
|
+
"--verbose": "output",
|
|
58737
|
+
"--heatmap": "output",
|
|
58738
|
+
"--trend": "output",
|
|
58739
|
+
"--why-failing": "output",
|
|
58740
|
+
// Performance
|
|
58741
|
+
"--threads": "perf",
|
|
58742
|
+
"--incremental": "perf",
|
|
58743
|
+
"--cache": "perf",
|
|
58744
|
+
"--cache-path": "perf",
|
|
58745
|
+
// Auto-fix
|
|
58746
|
+
"--fix": "fix",
|
|
58747
|
+
"--dry-run": "fix",
|
|
58748
|
+
"--show-fixes-diff": "fix",
|
|
58749
|
+
// CI / threshold
|
|
58750
|
+
"--strict": "ci",
|
|
58751
|
+
"--no-increase": "ci",
|
|
58752
|
+
"--baseline": "ci",
|
|
58753
|
+
"--threshold": "ci",
|
|
58754
|
+
// Watch & diagnose
|
|
58755
|
+
"--watch": "watch",
|
|
58756
|
+
"--doctor": "watch",
|
|
58757
|
+
"--suggest": "watch",
|
|
58758
|
+
"--tighten": "watch",
|
|
58759
|
+
// Tokens
|
|
58760
|
+
"--tokens": "tokens",
|
|
58761
|
+
// Telemetry
|
|
58762
|
+
"--no-telemetry": "telemetry"
|
|
58763
|
+
};
|
|
58764
|
+
var CATEGORY_ORDER2 = [
|
|
58765
|
+
"file",
|
|
58766
|
+
"filter",
|
|
58767
|
+
"output",
|
|
58768
|
+
"perf",
|
|
58769
|
+
"fix",
|
|
58770
|
+
"ci",
|
|
58771
|
+
"watch",
|
|
58772
|
+
"tokens",
|
|
58773
|
+
"telemetry",
|
|
58774
|
+
"other"
|
|
58775
|
+
];
|
|
58776
|
+
function groupOptions(cmd) {
|
|
58777
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
58778
|
+
for (const category of CATEGORY_ORDER2) {
|
|
58779
|
+
grouped.set(category, []);
|
|
58780
|
+
}
|
|
58781
|
+
for (const opt of cmd.options) {
|
|
58782
|
+
if (opt.hidden) continue;
|
|
58783
|
+
const longFlag = opt.long ?? opt.short ?? "";
|
|
58784
|
+
const category = longFlag ? OPTION_CATEGORY[longFlag] ?? "other" : "other";
|
|
58785
|
+
grouped.get(category).push({
|
|
58786
|
+
category,
|
|
58787
|
+
flags: opt.flags,
|
|
58788
|
+
description: opt.description ?? ""
|
|
58789
|
+
});
|
|
58790
|
+
}
|
|
58791
|
+
return grouped;
|
|
58792
|
+
}
|
|
58793
|
+
function renderOption(opt, flagWidth) {
|
|
58794
|
+
const padded = opt.flags.padEnd(flagWidth, " ");
|
|
58795
|
+
return ` ${padded} ${opt.description}`;
|
|
58796
|
+
}
|
|
58797
|
+
function formatGroupedHelp(cmd) {
|
|
58798
|
+
const lines = [];
|
|
58799
|
+
const usage = cmd.usage ? cmd.usage() : `Usage: ${cmd.name()} [options]`;
|
|
58800
|
+
lines.push(usage);
|
|
58801
|
+
lines.push("");
|
|
58802
|
+
if (cmd.description()) {
|
|
58803
|
+
lines.push(cmd.description());
|
|
58804
|
+
lines.push("");
|
|
58805
|
+
}
|
|
58806
|
+
const grouped = groupOptions(cmd);
|
|
58807
|
+
let flagWidth = 0;
|
|
58808
|
+
for (const options of grouped.values()) {
|
|
58809
|
+
for (const opt of options) {
|
|
58810
|
+
if (opt.flags.length > flagWidth) flagWidth = opt.flags.length;
|
|
58811
|
+
}
|
|
58812
|
+
}
|
|
58813
|
+
let firstCategory = true;
|
|
58814
|
+
for (const category of CATEGORY_ORDER2) {
|
|
58815
|
+
const options = grouped.get(category);
|
|
58816
|
+
if (options.length === 0) continue;
|
|
58817
|
+
if (!firstCategory) lines.push("");
|
|
58818
|
+
firstCategory = false;
|
|
58819
|
+
lines.push(` ${CATEGORY_LABELS3[category]}:`);
|
|
58820
|
+
for (const opt of options) {
|
|
58821
|
+
lines.push(renderOption(opt, flagWidth));
|
|
58822
|
+
}
|
|
58823
|
+
}
|
|
58824
|
+
lines.push("");
|
|
58825
|
+
lines.push(
|
|
58826
|
+
"Use `--help-flat` for the standard un-grouped list. See `https://usebrick.dev/docs/scan-options` for full docs."
|
|
58827
|
+
);
|
|
58828
|
+
return lines.join("\n");
|
|
58829
|
+
}
|
|
58830
|
+
|
|
58831
|
+
// src/cli/program.ts
|
|
58832
|
+
init_scan2();
|
|
58180
58833
|
process.on("uncaughtException", (err) => {
|
|
58181
58834
|
logger.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
|
|
58182
58835
|
process.exit(3);
|
|
@@ -58184,6 +58837,7 @@ process.on("uncaughtException", (err) => {
|
|
|
58184
58837
|
async function runCli({ start }) {
|
|
58185
58838
|
try {
|
|
58186
58839
|
const program = new Command().name("slopbrick").description("Repository Coherence Scanner \u2014 surface AI-induced pattern drift, secret leaks, and design-token violations").version(VERSION).option("--framework <name>", "framework multiplier to apply").option("--include <glob>", "include pattern (repeatable)", collectGlob, []).option("--exclude <glob>", "exclude pattern (repeatable)", collectGlob, []).option("--ai-only", "only report AI-specific issues").option("--human-only", "only report human-facing issues").option("--ignore-wcag22", "ignore WCAG 2.2 related issues").option("--format <pretty|json|sarif|html>", "output format", "pretty").option("--threads <n>", "number of worker threads", parseThreads).option("--since <ref>", "only scan files changed since git ref").option("--diff <ref>", "alias for --since <ref>; also adds PR Slop Score to the report").option("--workspace <path>", "workspace/project path", process.cwd()).option("--tighten", "tighten baseline allowances").option("--fix", "apply auto-fixes").option("--dry-run", "with --fix: print what would change without writing").option("--show-fixes-diff", "print unified diff of proposed auto-fixes").option("--doctor", "run diagnostics").option("--watch", "watch files and re-run").option("--suggest", "print remediation advice").option("--why-failing", "print the top 5 rules dragging the score down").option("--brief", "terse output (verdict + headline + threshold + delta only)").option("--heatmap", "print migration ROI heatmap").option("--quiet", "suppress non-error output").option("--verbose", "enable debug logging (file paths, timings, rule-fire counts)").option("--strict", "exit 2 if any high-severity issue remains").option("--no-increase", "exit 2 if slop index increased since last run").option("--baseline", "save a baseline after this scan").option("--trend [n]", "print a sparkline of the last n runs", parseTrend).option("--json [path]", "write JSON report to path or stdout").option("--html [path]", "write HTML report to path or stdout").option("--staged", "scan only changed files (staged and unstaged)").option("--changed", "scan working-tree changes (staged + unstaged + untracked)").option("--incremental", "skip unchanged files using the persisted hash cache").option("--cache-path <path>", "path to the incremental-scan cache (default: .slopbrick-cache.json)").option("--tokens <path>", "merge tokens.json layout values into the arbitrary-value allowlist").option("--cache", "cache parsed AST results locally").option("--no-color", "suppress ANSI color codes in output").option("--security-only", "run only the security/* rules").option("--full", "show the complete report (all issues, all categories)");
|
|
58840
|
+
program.helpInformation = () => formatGroupedHelp(program);
|
|
58187
58841
|
registerInit(program);
|
|
58188
58842
|
registerInstall(program);
|
|
58189
58843
|
registerUninstall(program);
|
|
@@ -58347,6 +59001,11 @@ async function runCli({ start }) {
|
|
|
58347
59001
|
registerTokens(program);
|
|
58348
59002
|
registerReport(program);
|
|
58349
59003
|
registerScan(program, scanAction);
|
|
59004
|
+
if (process.argv.includes("--help-flat")) {
|
|
59005
|
+
delete program.helpInformation;
|
|
59006
|
+
program.outputHelp();
|
|
59007
|
+
process.exit(0);
|
|
59008
|
+
}
|
|
58350
59009
|
await program.parseAsync(process.argv);
|
|
58351
59010
|
} catch (err) {
|
|
58352
59011
|
if (err instanceof ConfigValidationError) {
|