slopbrick 0.18.4 → 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/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 import_node_module, require2, pkg, VERSION, AI_SECURITY_NUMERIC, REPOSITORY_HEALTH_WEIGHTS;
36
- var init_types = __esm({
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.5";
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 pkg2 = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
314
- if (Array.isArray(pkg2.workspaces)) {
315
- for (const pattern of pkg2.workspaces) {
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 pkg2 = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
427
+ const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf-8"));
374
428
  deps = {
375
- ...pkg2.dependencies,
376
- ...pkg2.devDependencies,
377
- ...pkg2.peerDependencies
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 pkg2 = JSON.parse((0, import_node_fs3.readFileSync)(pkgPath, "utf-8"));
630
+ const pkg = JSON.parse((0, import_node_fs3.readFileSync)(pkgPath, "utf-8"));
577
631
  const deps = {
578
- ...pkg2.dependencies,
579
- ...pkg2.devDependencies,
580
- ...pkg2.peerDependencies
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 pkg2 = spec.startsWith("@/") ? spec : spec.startsWith("@") ? spec.split("/").slice(0, 2).join("/") : spec.split("/")[0];
26217
- if (pkg2) importedPackages.add(pkg2);
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 pkg2 of importedPackages) {
26221
- if (DEFAULT_STACK_PACKAGES.some((p) => p === pkg2 || p.startsWith(pkg2 + "/"))) {
26222
- hits.push(pkg2);
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 pkg2;
28474
+ let pkg;
28222
28475
  try {
28223
- pkg2 = JSON.parse((0, import_node_fs5.readFileSync)(pkgPath, "utf-8"));
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 [pkg2.dependencies, pkg2.devDependencies]) {
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 [pkg2, { field, signal }] of Object.entries(CONSTITUTION_SIGNALS)) {
28245
- if (deps.has(pkg2)) {
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
@@ -29935,9 +30188,9 @@ function declaredPackages(cwd) {
29935
30188
  if (!(0, import_node_fs8.existsSync)(pkgPath)) return out;
29936
30189
  try {
29937
30190
  const raw = (0, import_node_fs8.readFileSync)(pkgPath, "utf-8");
29938
- const pkg2 = JSON.parse(raw);
30191
+ const pkg = JSON.parse(raw);
29939
30192
  for (const k of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
29940
- const v = pkg2[k];
30193
+ const v = pkg[k];
29941
30194
  if (v && typeof v === "object") {
29942
30195
  for (const name of Object.keys(v)) {
29943
30196
  out.add(name);
@@ -30367,7 +30620,7 @@ var init_spacing_grid = __esm({
30367
30620
  "use strict";
30368
30621
  init_rule();
30369
30622
  init_utils();
30370
- init_config();
30623
+ init_config2();
30371
30624
  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
30625
  ARBITRARY_VALUE_RE2 = /^(-?\d+(?:\.\d+)?)(px|rem)$/;
30373
30626
  SKIP_VALUES = /* @__PURE__ */ new Set(["auto", "full", "screen", "min", "max", "fit", "none"]);
@@ -42455,6 +42708,78 @@ function extractStateBinding(node, lineOffsets) {
42455
42708
  setterReferenced: false
42456
42709
  };
42457
42710
  }
42711
+ function findUnreachableStatements(ast, source, lineOffsets) {
42712
+ const out = [];
42713
+ function isTerminator(node) {
42714
+ if (node.type === "ReturnStatement") return "return";
42715
+ if (node.type === "ThrowStatement") return "throw";
42716
+ if (node.type === "BreakStatement") return "break";
42717
+ if (node.type === "ContinueStatement") return "continue";
42718
+ return null;
42719
+ }
42720
+ function snippetFor(node, src) {
42721
+ const span = node.span;
42722
+ if (!span || typeof span.start !== "number" || typeof span.end !== "number") {
42723
+ return "<unreachable>";
42724
+ }
42725
+ const text = src.slice(span.start, Math.min(span.end, span.start + 60));
42726
+ return text.replace(/\s+/g, " ").trim() || "<unreachable>";
42727
+ }
42728
+ function lineColumn(offset) {
42729
+ let lo = 0;
42730
+ let hi = lineOffsets.length - 1;
42731
+ while (lo < hi) {
42732
+ const mid = lo + hi + 1 >>> 1;
42733
+ const midVal = lineOffsets[mid];
42734
+ const loVal = lineOffsets[lo];
42735
+ if (midVal === void 0) break;
42736
+ if (midVal <= offset) lo = mid;
42737
+ else hi = mid - 1;
42738
+ void loVal;
42739
+ }
42740
+ const baseOffset = lineOffsets[lo] ?? 0;
42741
+ return { line: lo + 1, column: offset - baseOffset };
42742
+ }
42743
+ function visitBody(body) {
42744
+ if (!Array.isArray(body)) return;
42745
+ let lastTerminator = null;
42746
+ for (const stmt of body) {
42747
+ if (!isObject(stmt)) continue;
42748
+ if (lastTerminator && stmt.type !== "EmptyStatement") {
42749
+ const span = stmt.span;
42750
+ const offset = typeof span?.start === "number" ? span.start : 0;
42751
+ const { line, column } = lineColumn(offset);
42752
+ out.push({
42753
+ terminator: lastTerminator,
42754
+ line,
42755
+ column,
42756
+ snippet: snippetFor(stmt, source)
42757
+ });
42758
+ }
42759
+ const t = isTerminator(stmt);
42760
+ if (t) lastTerminator = t;
42761
+ }
42762
+ }
42763
+ function walk3(node) {
42764
+ if (!isObject(node)) return;
42765
+ if (node.type === "BlockStatement") {
42766
+ visitBody(node.stmts);
42767
+ } else if (node.type === "Module") {
42768
+ visitBody(node.body);
42769
+ }
42770
+ for (const key of Object.keys(node)) {
42771
+ if (key === "parent" || key === "span" || key === "ctxt") continue;
42772
+ const child = node[key];
42773
+ if (Array.isArray(child)) {
42774
+ for (const c of child) walk3(c);
42775
+ } else {
42776
+ walk3(child);
42777
+ }
42778
+ }
42779
+ }
42780
+ walk3(ast);
42781
+ return out;
42782
+ }
42458
42783
  var init_scan_helpers = __esm({
42459
42784
  "src/engine/visitors/scan-helpers.ts"() {
42460
42785
  "use strict";
@@ -42540,15 +42865,42 @@ function handleImportDeclaration(node, _parent, _path, vctx) {
42540
42865
  if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
42541
42866
  const local = specifier.local;
42542
42867
  if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
42543
- importedNames.push(local.value);
42868
+ const name = local.value;
42869
+ importedNames.push(name);
42870
+ vctx.facts.deadCode.bindings.push({
42871
+ name,
42872
+ kind: specifier.type === "ImportDefaultSpecifier" ? "import-default" : "import-namespace",
42873
+ line,
42874
+ column,
42875
+ source,
42876
+ isReferenced: false
42877
+ });
42544
42878
  }
42545
42879
  } else if (specifier.type === "ImportSpecifier") {
42546
42880
  const imported = specifier.imported;
42547
42881
  const local = specifier.local;
42548
42882
  if (isObject(imported) && typeof imported.value === "string" && imported.value.length > 0) {
42549
- importedNames.push(imported.value);
42883
+ const name = imported.value;
42884
+ importedNames.push(name);
42885
+ vctx.facts.deadCode.bindings.push({
42886
+ name,
42887
+ kind: "import-specifier",
42888
+ line,
42889
+ column,
42890
+ source,
42891
+ isReferenced: false
42892
+ });
42550
42893
  } else if (isObject(local) && local.type === "Identifier" && typeof local.value === "string") {
42551
- importedNames.push(local.value);
42894
+ const name = local.value;
42895
+ importedNames.push(name);
42896
+ vctx.facts.deadCode.bindings.push({
42897
+ name,
42898
+ kind: "import-specifier",
42899
+ line,
42900
+ column,
42901
+ source,
42902
+ isReferenced: false
42903
+ });
42552
42904
  }
42553
42905
  }
42554
42906
  }
@@ -42638,6 +42990,13 @@ function isBindingSite(node, parent) {
42638
42990
  if (params.some((param) => containsNode(param, node))) return true;
42639
42991
  }
42640
42992
  }
42993
+ if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") {
42994
+ if (parent.type === "ImportSpecifier") {
42995
+ if (parent.imported === node || parent.local === node) return true;
42996
+ } else {
42997
+ if (parent.local === node) return true;
42998
+ }
42999
+ }
42641
43000
  return false;
42642
43001
  }
42643
43002
  function isNonComputedMemberProperty(node, parent) {
@@ -42704,6 +43063,9 @@ function handleIdentifier(node, parent, path, vctx) {
42704
43063
  if (typeof node.value === "string" && !isBindingSite(node, parent) && !isNonComputedMemberProperty(node, parent)) {
42705
43064
  markStateReference(node.value, vctx);
42706
43065
  trackPropUsage(node, parent, path, vctx);
43066
+ vctx.facts.referencedNames.add(node.value);
43067
+ const top = vctx.ctx.stack[vctx.ctx.stack.length - 1];
43068
+ if (top) top.references.add(node.value);
42707
43069
  }
42708
43070
  return false;
42709
43071
  }
@@ -42844,6 +43206,20 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
42844
43206
  frame.bindings.add(bindingName);
42845
43207
  }
42846
43208
  }
43209
+ if (bindingNames.length > 0) {
43210
+ const parent = node.parent;
43211
+ const kind = isObject(parent) && parent.type === "VariableDeclaration" ? String(parent.kind ?? "var") : "var";
43212
+ const { line, column } = positionFrom(id, vctx.lineOffsets);
43213
+ for (const bindingName of bindingNames) {
43214
+ vctx.facts.deadCode.bindings.push({
43215
+ name: bindingName,
43216
+ kind,
43217
+ line,
43218
+ column,
43219
+ isReferenced: false
43220
+ });
43221
+ }
43222
+ }
42847
43223
  if (isUseStateDeclarator(node)) {
42848
43224
  const binding = extractStateBinding(node, vctx.lineOffsets);
42849
43225
  if (binding) {
@@ -42863,6 +43239,36 @@ function handleVariableDeclarator(node, _parent, path, vctx) {
42863
43239
  }
42864
43240
  return true;
42865
43241
  }
43242
+ function handleIfStatement(node, _parent, _path, vctx) {
43243
+ if (!isObject(node)) return false;
43244
+ const test = node.test;
43245
+ if (!isObject(test)) return false;
43246
+ if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
43247
+ const { line, column } = positionFrom(test, vctx.lineOffsets);
43248
+ vctx.facts.deadCode.constantConditions.push({
43249
+ kind: test.value ? "if-true" : "if-false",
43250
+ condition: String(test.value),
43251
+ line,
43252
+ column
43253
+ });
43254
+ }
43255
+ return false;
43256
+ }
43257
+ function handleWhileStatement(node, _parent, _path, vctx) {
43258
+ if (!isObject(node)) return false;
43259
+ const test = node.test;
43260
+ if (!isObject(test)) return false;
43261
+ if (test.type === "BooleanLiteral" && typeof test.value === "boolean") {
43262
+ const { line, column } = positionFrom(test, vctx.lineOffsets);
43263
+ vctx.facts.deadCode.constantConditions.push({
43264
+ kind: test.value ? "while-true" : "while-false",
43265
+ condition: String(test.value),
43266
+ line,
43267
+ column
43268
+ });
43269
+ }
43270
+ return false;
43271
+ }
42866
43272
  function dispatchNode(node, parent, path, vctx) {
42867
43273
  if (!isObject(node)) return false;
42868
43274
  const type = getNodeType(node);
@@ -42887,7 +43293,9 @@ var init_dispatch = __esm({
42887
43293
  MemberExpression: handleMemberExpression,
42888
43294
  JSXAttribute: handleJSXAttribute,
42889
43295
  JSXOpeningElement: handleJSXOpeningElement,
42890
- VariableDeclarator: handleVariableDeclarator
43296
+ VariableDeclarator: handleVariableDeclarator,
43297
+ IfStatement: handleIfStatement,
43298
+ WhileStatement: handleWhileStatement
42891
43299
  };
42892
43300
  }
42893
43301
  });
@@ -43038,6 +43446,17 @@ function buildV2Facts(facts, source, ext, framework, config, templateClassNames
43038
43446
  },
43039
43447
  logic: buildLogicBlock(facts),
43040
43448
  designTokens: scanDesignTokens(facts.staticClassNames),
43449
+ // dead-code detector. Copy the internal accumulator
43450
+ // into the v2 shape, marking each binding as referenced
43451
+ // iff the file-level referenced-name set contains its name.
43452
+ deadCode: {
43453
+ bindings: facts.deadCode.bindings.map((b) => ({
43454
+ ...b,
43455
+ isReferenced: facts.referencedNames.has(b.name)
43456
+ })),
43457
+ constantConditions: facts.deadCode.constantConditions,
43458
+ unreachableStatements: facts.deadCode.unreachableStatements
43459
+ },
43041
43460
  componentSizes: facts.componentSizes.map((cs) => ({
43042
43461
  name: cs.name,
43043
43462
  lineCount: cs.lineCount,
@@ -43119,7 +43538,17 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
43119
43538
  componentSizes: [],
43120
43539
  astroComponents: [],
43121
43540
  fetchCalls: [],
43122
- optimisticUpdates: []
43541
+ optimisticUpdates: [],
43542
+ // dead-code detector. The visitor's identifier walk + import/
43543
+ // branch/return handlers populate these. The v2 builder at the
43544
+ // bottom of extractFacts() reads them and produces
43545
+ // `facts.v2.deadCode`.
43546
+ deadCode: {
43547
+ bindings: [],
43548
+ constantConditions: [],
43549
+ unreachableStatements: []
43550
+ },
43551
+ referencedNames: /* @__PURE__ */ new Set()
43123
43552
  };
43124
43553
  const ctx = {
43125
43554
  stack: [],
@@ -43206,6 +43635,16 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
43206
43635
  propBindingSet.add(bindingName);
43207
43636
  }
43208
43637
  }
43638
+ const { line: pLine, column: pCol } = positionFrom(param, lineOffsets);
43639
+ for (const bindingName of collectBindingNames2(param)) {
43640
+ facts.deadCode.bindings.push({
43641
+ name: bindingName,
43642
+ kind: "parameter",
43643
+ line: pLine,
43644
+ column: pCol,
43645
+ isReferenced: false
43646
+ });
43647
+ }
43209
43648
  }
43210
43649
  }
43211
43650
  ctx.stack.push({
@@ -43221,6 +43660,12 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
43221
43660
  propUsages: [],
43222
43661
  isComponent,
43223
43662
  bindings,
43663
+ // dead-code detector: per-frame referenced-name set.
43664
+ // Identifiers encountered inside the frame are added to this
43665
+ // set; the deadCode builder unions it with parent frames at
43666
+ // pop time so a binding is considered used if any reachable
43667
+ // scope references it.
43668
+ references: /* @__PURE__ */ new Set(),
43224
43669
  propBindingSet,
43225
43670
  propUsageSet: /* @__PURE__ */ new Set(),
43226
43671
  node
@@ -43316,6 +43761,11 @@ function extractFacts(filePath, ast, source, supportsRsc = true, framework = "re
43316
43761
  mergeTemplateClassNames(filePath, source, facts, templateClassNames);
43317
43762
  const { ext } = splitFilePath(filePath);
43318
43763
  facts._source = source;
43764
+ facts.deadCode.unreachableStatements = findUnreachableStatements(
43765
+ ast,
43766
+ source,
43767
+ lineOffsets
43768
+ );
43319
43769
  const v2 = buildV2Facts(facts, source, ext, framework, config, templateClassNames);
43320
43770
  return envelopeScanFacts(filePath, v2);
43321
43771
  }
@@ -43998,6 +44448,11 @@ var init_builtins = __esm({
43998
44448
  init_missing_not_null();
43999
44449
  init_naming_inconsistency();
44000
44450
  init_sql_concat();
44451
+ init_dead_branch();
44452
+ init_unreachable();
44453
+ init_unused_import();
44454
+ init_unused_local();
44455
+ init_unused_parameter();
44001
44456
  init_broken_link();
44002
44457
  init_expired_code_example();
44003
44458
  init_stale_function_reference();
@@ -44094,6 +44549,11 @@ var init_builtins = __esm({
44094
44549
  missingNotNullRule,
44095
44550
  namingInconsistencyRule,
44096
44551
  sqlConcatRule,
44552
+ deadBranchRule,
44553
+ unreachableRule,
44554
+ unusedImportRule,
44555
+ unusedLocalRule,
44556
+ unusedParameterRule,
44097
44557
  brokenLinkRule,
44098
44558
  expiredCodeExampleRule,
44099
44559
  staleFunctionReferenceRule,
@@ -44665,8 +45125,8 @@ function detectJsLoader(configPath) {
44665
45125
  const pkgPath = (0, import_node_path10.join)(current, "package.json");
44666
45126
  if ((0, import_node_fs11.existsSync)(pkgPath)) {
44667
45127
  try {
44668
- const pkg2 = JSON.parse((0, import_node_fs11.readFileSync)(pkgPath, "utf-8"));
44669
- return pkg2.type === "module" ? "import" : "require";
45128
+ const pkg = JSON.parse((0, import_node_fs11.readFileSync)(pkgPath, "utf-8"));
45129
+ return pkg.type === "module" ? "import" : "require";
44670
45130
  } catch {
44671
45131
  return "require";
44672
45132
  }
@@ -44680,7 +45140,7 @@ function detectJsLoader(configPath) {
44680
45140
  async function loadConfigFile(path) {
44681
45141
  const loader = detectJsLoader(path);
44682
45142
  if (loader === "require") {
44683
- const req = (0, import_node_module2.createRequire)(__importMetaUrl);
45143
+ const req = (0, import_node_module.createRequire)(__importMetaUrl);
44684
45144
  const mod2 = req(path);
44685
45145
  return mod2.default ?? mod2;
44686
45146
  }
@@ -44712,13 +45172,13 @@ async function loadConfig(cwd) {
44712
45172
  );
44713
45173
  return merged;
44714
45174
  }
44715
- var import_node_fs11, import_node_path10, import_node_module2;
45175
+ var import_node_fs11, import_node_path10, import_node_module;
44716
45176
  var init_load = __esm({
44717
45177
  "src/config/load.ts"() {
44718
45178
  "use strict";
44719
45179
  import_node_fs11 = require("fs");
44720
45180
  import_node_path10 = require("path");
44721
- import_node_module2 = require("module");
45181
+ import_node_module = require("module");
44722
45182
  init_logger();
44723
45183
  init_validation();
44724
45184
  init_defaults();
@@ -44865,7 +45325,7 @@ var init_init = __esm({
44865
45325
  });
44866
45326
 
44867
45327
  // src/config/index.ts
44868
- var init_config = __esm({
45328
+ var init_config2 = __esm({
44869
45329
  "src/config/index.ts"() {
44870
45330
  "use strict";
44871
45331
  init_defaults();
@@ -47012,6 +47472,61 @@ var init_signal_strength = __esm({
47012
47472
  _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
47473
  aiSpecific: true
47014
47474
  },
47475
+ "dead/unused-import": {
47476
+ recall: 0,
47477
+ fpRate: 0,
47478
+ ratio: 0,
47479
+ precision: 0,
47480
+ lastCalibratedAt: "2026-06-30T00:00:00Z",
47481
+ verdict: "DORMANT",
47482
+ defaultOff: true,
47483
+ _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.",
47484
+ aiSpecific: true
47485
+ },
47486
+ "dead/unused-local": {
47487
+ recall: 0,
47488
+ fpRate: 0,
47489
+ ratio: 0,
47490
+ precision: 0,
47491
+ lastCalibratedAt: "2026-06-30T00:00:00Z",
47492
+ verdict: "DORMANT",
47493
+ defaultOff: true,
47494
+ _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).",
47495
+ aiSpecific: true
47496
+ },
47497
+ "dead/unused-parameter": {
47498
+ recall: 0,
47499
+ fpRate: 0,
47500
+ ratio: 0,
47501
+ precision: 0,
47502
+ lastCalibratedAt: "2026-06-30T00:00:00Z",
47503
+ verdict: "DORMANT",
47504
+ defaultOff: true,
47505
+ _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.",
47506
+ aiSpecific: true
47507
+ },
47508
+ "dead/dead-branch": {
47509
+ recall: 0,
47510
+ fpRate: 0,
47511
+ ratio: 0,
47512
+ precision: 0,
47513
+ lastCalibratedAt: "2026-06-30T00:00:00Z",
47514
+ verdict: "DORMANT",
47515
+ defaultOff: true,
47516
+ _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.",
47517
+ aiSpecific: true
47518
+ },
47519
+ "dead/unreachable": {
47520
+ recall: 0,
47521
+ fpRate: 0,
47522
+ ratio: 0,
47523
+ precision: 0,
47524
+ lastCalibratedAt: "2026-06-30T00:00:00Z",
47525
+ verdict: "DORMANT",
47526
+ defaultOff: true,
47527
+ _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.",
47528
+ aiSpecific: true
47529
+ },
47015
47530
  "docs/stale-package-reference": {
47016
47531
  recall: 0,
47017
47532
  fpRate: 0,
@@ -47973,7 +48488,7 @@ var init_cache = __esm({
47973
48488
  import_node_fs16 = require("fs");
47974
48489
  import_node_path17 = require("path");
47975
48490
  init_types();
47976
- init_config();
48491
+ init_config2();
47977
48492
  BASELINE_VERSION = VERSION;
47978
48493
  BASELINE_HASH_KEYS = /* @__PURE__ */ new Set([
47979
48494
  "framework",
@@ -50457,7 +50972,7 @@ var init_finalizeReport = __esm({
50457
50972
  init_dist2();
50458
50973
  init_logger();
50459
50974
  init_memory_io();
50460
- init_config();
50975
+ init_config2();
50461
50976
  init_enrichReport();
50462
50977
  init_assembleScanReport();
50463
50978
  init_persistRun();
@@ -52382,11 +52897,11 @@ var init_watch = __esm({
52382
52897
  init_worker();
52383
52898
  init_threshold();
52384
52899
  init_cache();
52385
- init_config();
52900
+ init_config2();
52386
52901
  init_render();
52387
52902
  init_logger();
52388
52903
  init_error();
52389
- init_scan();
52904
+ init_scan2();
52390
52905
  init_renderOutput();
52391
52906
  init_types();
52392
52907
  }
@@ -52667,14 +53182,14 @@ async function scanProject(options) {
52667
53182
  return report;
52668
53183
  }
52669
53184
  var import_node_fs28, import_node_path30;
52670
- var init_scan = __esm({
53185
+ var init_scan2 = __esm({
52671
53186
  "src/cli/scan.ts"() {
52672
53187
  "use strict";
52673
53188
  import_node_fs28 = require("fs");
52674
53189
  import_node_path30 = require("path");
52675
53190
  init_render();
52676
53191
  init_threshold();
52677
- init_config();
53192
+ init_config2();
52678
53193
  init_discover();
52679
53194
  init_git();
52680
53195
  init_cache_incremental();
@@ -52844,7 +53359,7 @@ async function runSuggest(args, ctx) {
52844
53359
  }
52845
53360
  async function runGovernance(args, ctx) {
52846
53361
  try {
52847
- const { runScan: runScan3 } = await Promise.resolve().then(() => (init_scan(), scan_exports));
53362
+ const { runScan: runScan3 } = await Promise.resolve().then(() => (init_scan2(), scan_exports));
52848
53363
  const maxFiles = typeof args.maxFiles === "number" && Number.isFinite(args.maxFiles) && args.maxFiles > 0 ? Math.floor(args.maxFiles) : 500;
52849
53364
  const { report } = await runScan3({
52850
53365
  workspace: ctx.cwd,
@@ -53326,7 +53841,7 @@ __export(src_exports, {
53326
53841
  });
53327
53842
  module.exports = __toCommonJS(src_exports);
53328
53843
  init_types();
53329
- init_config();
53844
+ init_config2();
53330
53845
  init_dist2();
53331
53846
 
53332
53847
  // src/cli/program.ts
@@ -53370,14 +53885,14 @@ function parseThreshold(value) {
53370
53885
  // src/cli/program.ts
53371
53886
  init_render();
53372
53887
  init_threshold();
53373
- init_scan();
53374
- init_scan();
53888
+ init_scan2();
53889
+ init_scan2();
53375
53890
 
53376
53891
  // src/cli/init.ts
53377
53892
  var import_node_fs30 = require("fs");
53378
53893
  var import_node_path32 = require("path");
53379
53894
  var import_node_readline = require("readline");
53380
- init_config();
53895
+ init_config2();
53381
53896
  init_discover();
53382
53897
  init_git();
53383
53898
  init_cache();
@@ -53867,7 +54382,7 @@ async function runDoctor(cwd) {
53867
54382
  var import_node_path33 = require("path");
53868
54383
  init_render();
53869
54384
  init_logger();
53870
- init_scan();
54385
+ init_scan2();
53871
54386
  function registerBadge(program) {
53872
54387
  program.command("badge").description(
53873
54388
  "print a shields.io slop-index badge. Reads .slopbrick/health.json if present (no re-scan); falls back to a fresh scan."
@@ -53894,7 +54409,7 @@ var import_node_path34 = require("path");
53894
54409
  init_advice();
53895
54410
  init_unified_diff();
53896
54411
  init_logger();
53897
- init_scan();
54412
+ init_scan2();
53898
54413
  function registerSuggest(program) {
53899
54414
  program.command("suggest").description("print remediation advice").action(async (_cmdOptions, command) => {
53900
54415
  const options = command.optsWithGlobals();
@@ -54021,6 +54536,11 @@ var RULE_HINTS = {
54021
54536
  "logic/qwik-hook-leak": "Use Qwik primitives ($state, $effect, useSignal) instead of React hooks (useState, useEffect).",
54022
54537
  "logic/reactive-hook-soup": "Coordinate state via a single derived value (useMemo) or a state machine. Avoid chained useEffects that sync local state.",
54023
54538
  "logic/zombie-state": "Remove unused useState or wire it into the component. Don't leave declared-but-never-read state bindings.",
54539
+ "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.",
54540
+ "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.",
54541
+ "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.",
54542
+ "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.",
54543
+ "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
54544
  "perf/cls-image": "Add width/height attributes or an aspect-ratio utility to prevent layout shift.",
54025
54545
  "perf/css-bloat": "Extract to a CSS variable (`--surface-card`) or a component prop when a class string repeats 5+ times.",
54026
54546
  "perf/halstead-anomaly": "Introduce domain-specific identifiers and varied operations. Low vocabulary per line is a strong AI signature (Halstead 1977 \xA73).",
@@ -54275,7 +54795,7 @@ init_logger();
54275
54795
 
54276
54796
  // src/mcp/server.ts
54277
54797
  init_builtins();
54278
- init_config();
54798
+ init_config2();
54279
54799
  init_tools();
54280
54800
  var SERVER_INFO = {
54281
54801
  name: "slopbrick",
@@ -55705,7 +56225,7 @@ function registerTrend(program) {
55705
56225
  // src/cli/commands/drift.ts
55706
56226
  var import_node_path51 = require("path");
55707
56227
  init_logger();
55708
- init_scan();
56228
+ init_scan2();
55709
56229
 
55710
56230
  // src/cli/drift.ts
55711
56231
  var import_node_fs38 = require("fs");
@@ -55846,7 +56366,7 @@ function registerDrift(program) {
55846
56366
  // src/cli/commands/pr.ts
55847
56367
  var import_node_path53 = require("path");
55848
56368
  init_logger();
55849
- init_scan();
56369
+ init_scan2();
55850
56370
 
55851
56371
  // src/cli/pr.ts
55852
56372
  var import_node_fs39 = require("fs");
@@ -56135,7 +56655,7 @@ function registerPr(program) {
56135
56655
  // src/cli/commands/security.ts
56136
56656
  var import_node_path54 = require("path");
56137
56657
  init_logger();
56138
- init_scan();
56658
+ init_scan2();
56139
56659
  init_ai_security_risk();
56140
56660
  function registerSecurity(program) {
56141
56661
  program.command("security").description(
@@ -56194,11 +56714,11 @@ function registerSecurity(program) {
56194
56714
  // src/cli/commands/test.ts
56195
56715
  var import_node_path56 = require("path");
56196
56716
  init_logger();
56197
- init_scan();
56717
+ init_scan2();
56198
56718
 
56199
56719
  // src/cli/test.ts
56200
56720
  var import_node_path55 = require("path");
56201
- init_scan();
56721
+ init_scan2();
56202
56722
  init_test_quality();
56203
56723
  init_logger();
56204
56724
  var TEST_INCLUDE_GLOBS = [
@@ -56313,7 +56833,7 @@ function registerTest(program) {
56313
56833
  // src/cli/commands/architecture.ts
56314
56834
  var import_node_path57 = require("path");
56315
56835
  init_logger();
56316
- init_scan();
56836
+ init_scan2();
56317
56837
  init_architecture_score();
56318
56838
  function registerArchitecture(program) {
56319
56839
  program.command("architecture").description(
@@ -56341,7 +56861,7 @@ function registerArchitecture(program) {
56341
56861
  // src/cli/commands/business-logic.ts
56342
56862
  var import_node_path59 = require("path");
56343
56863
  init_logger();
56344
- init_scan();
56864
+ init_scan2();
56345
56865
 
56346
56866
  // src/cli/business-logic.ts
56347
56867
  var import_node_fs40 = require("fs");
@@ -56487,10 +57007,10 @@ function registerBusinessLogic(program) {
56487
57007
  // src/cli/commands/maintenance-cost.ts
56488
57008
  var import_node_path60 = require("path");
56489
57009
  init_logger();
56490
- init_scan();
57010
+ init_scan2();
56491
57011
 
56492
57012
  // src/cli/maintenance-cost.ts
56493
- init_scan();
57013
+ init_scan2();
56494
57014
  init_maintenance_cost();
56495
57015
  init_logger();
56496
57016
  async function runMaintenanceCostScan(cwd, config, options = {}) {
@@ -56630,10 +57150,10 @@ function registerMaintenanceCost(program) {
56630
57150
  // src/cli/commands/docs.ts
56631
57151
  var import_node_path61 = require("path");
56632
57152
  init_logger();
56633
- init_scan();
57153
+ init_scan2();
56634
57154
 
56635
57155
  // src/cli/docs.ts
56636
- init_scan();
57156
+ init_scan2();
56637
57157
  init_doc_freshness();
56638
57158
  init_logger();
56639
57159
  async function runDocsScan(cwd, config, options = {}) {
@@ -56779,10 +57299,10 @@ function registerDocs(program) {
56779
57299
  // src/cli/commands/db.ts
56780
57300
  var import_node_path62 = require("path");
56781
57301
  init_logger();
56782
- init_scan();
57302
+ init_scan2();
56783
57303
 
56784
57304
  // src/cli/db.ts
56785
- init_scan();
57305
+ init_scan2();
56786
57306
  init_db_health();
56787
57307
  init_logger();
56788
57308
  async function runDbScan(cwd, config, options = {}) {
@@ -56922,7 +57442,7 @@ function registerDb(program) {
56922
57442
  // src/cli/commands/patterns.ts
56923
57443
  var import_node_path64 = require("path");
56924
57444
  init_logger();
56925
- init_scan();
57445
+ init_scan2();
56926
57446
 
56927
57447
  // src/engine/patterns.ts
56928
57448
  var import_node_fs41 = require("fs");
@@ -57271,7 +57791,7 @@ function registerPatterns(program) {
57271
57791
  var import_node_fs42 = require("fs");
57272
57792
  var import_node_path65 = require("path");
57273
57793
  init_logger();
57274
- init_config();
57794
+ init_config2();
57275
57795
  function registerResearch(program) {
57276
57796
  const research = program.command("research").description("research commands for the AI UI learning loop");
57277
57797
  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 +57872,8 @@ var import_node_fs43 = require("fs");
57352
57872
  var import_node_path67 = require("path");
57353
57873
  init_logger();
57354
57874
  init_builtins();
57355
- init_scan();
57356
- init_config();
57875
+ init_scan2();
57876
+ init_config2();
57357
57877
  init_threshold();
57358
57878
  init_git();
57359
57879
  init_cache();
@@ -57834,7 +58354,7 @@ function registerScan(program, scanAction) {
57834
58354
  }
57835
58355
 
57836
58356
  // src/cli/program.ts
57837
- init_config();
58357
+ init_config2();
57838
58358
  init_git();
57839
58359
  init_logger();
57840
58360
  init_unified_diff();
@@ -58400,7 +58920,7 @@ function formatGroupedHelp(cmd) {
58400
58920
  }
58401
58921
 
58402
58922
  // src/cli/program.ts
58403
- init_scan();
58923
+ init_scan2();
58404
58924
  process.on("uncaughtException", (err) => {
58405
58925
  logger.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
58406
58926
  process.exit(3);