sickbay 1.4.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Header
3
- } from "./chunk-C6CDVDZ2.js";
3
+ } from "./chunk-YBVU46HP.js";
4
4
 
5
5
  // src/components/DiffApp.tsx
6
6
  import React, { useState, useEffect } from "react";
@@ -119,7 +119,7 @@ function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }) {
119
119
  useEffect(() => {
120
120
  (async () => {
121
121
  try {
122
- const { runSickbay } = await import("./dist-YIK3YE5B.js");
122
+ const { runSickbay } = await import("./dist-ESNXUFHV.js");
123
123
  const currentReport = await runSickbay({
124
124
  projectPath,
125
125
  checks,
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  Header
3
- } from "./chunk-C6CDVDZ2.js";
3
+ } from "./chunk-YBVU46HP.js";
4
4
  import {
5
5
  shortName
6
- } from "./chunk-7CHSSJZH.js";
6
+ } from "./chunk-PMGLCTYQ.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  detectProject
10
- } from "./chunk-WNCDYCPO.js";
10
+ } from "./chunk-T552XMJO.js";
11
11
 
12
12
  // src/components/DoctorApp.tsx
13
13
  import React, { useState, useEffect } from "react";
@@ -3,13 +3,13 @@ import {
3
3
  } from "./chunk-MBVA75EM.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-C6CDVDZ2.js";
6
+ } from "./chunk-YBVU46HP.js";
7
7
  import {
8
8
  shortName
9
- } from "./chunk-7CHSSJZH.js";
9
+ } from "./chunk-PMGLCTYQ.js";
10
10
  import {
11
11
  runSickbay
12
- } from "./chunk-WNCDYCPO.js";
12
+ } from "./chunk-T552XMJO.js";
13
13
 
14
14
  // src/components/FixApp.tsx
15
15
  import React, { useState, useEffect, useCallback } from "react";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  Header
3
- } from "./chunk-C6CDVDZ2.js";
3
+ } from "./chunk-YBVU46HP.js";
4
4
  import {
5
5
  shortName
6
- } from "./chunk-7CHSSJZH.js";
6
+ } from "./chunk-PMGLCTYQ.js";
7
7
  import {
8
8
  detectProject
9
- } from "./chunk-WNCDYCPO.js";
9
+ } from "./chunk-T552XMJO.js";
10
10
 
11
11
  // src/components/StatsApp.tsx
12
12
  import React, { useState, useEffect } from "react";
@@ -4,15 +4,15 @@ import {
4
4
  } from "./chunk-SHO3ZXTH.js";
5
5
  import {
6
6
  Header
7
- } from "./chunk-C6CDVDZ2.js";
7
+ } from "./chunk-YBVU46HP.js";
8
8
  import {
9
9
  detectRegressions,
10
10
  loadHistory
11
11
  } from "./chunk-3OR2GFVE.js";
12
12
  import {
13
13
  shortName
14
- } from "./chunk-7CHSSJZH.js";
15
- import "./chunk-WNCDYCPO.js";
14
+ } from "./chunk-PMGLCTYQ.js";
15
+ import "./chunk-T552XMJO.js";
16
16
 
17
17
  // src/components/TrendApp.tsx
18
18
  import React, { useState, useEffect } from "react";
@@ -17,7 +17,7 @@ import {
17
17
  detectMonorepo,
18
18
  runSickbay,
19
19
  runSickbayMonorepo
20
- } from "./chunk-WNCDYCPO.js";
20
+ } from "./chunk-T552XMJO.js";
21
21
 
22
22
  // src/components/tui/TuiApp.tsx
23
23
  import React11, { useState as useState8, useEffect as useEffect7, useCallback as useCallback2, useRef as useRef5 } from "react";
@@ -689,7 +689,7 @@ function TuiApp({
689
689
  return () => timers.forEach(clearTimeout);
690
690
  }, []);
691
691
  useEffect7(() => {
692
- checkForUpdate("1.4.1").then((info) => {
692
+ checkForUpdate("1.4.2").then((info) => {
693
693
  if (info) setUpdateInfo(info);
694
694
  });
695
695
  }, []);
@@ -715,7 +715,7 @@ function TuiApp({
715
715
  } catch {
716
716
  }
717
717
  try {
718
- const { getDependencyTree } = await import("./dist-YIK3YE5B.js");
718
+ const { getDependencyTree } = await import("./dist-ESNXUFHV.js");
719
719
  const { saveDepTree } = await import("./history-XLNVZEDI.js");
720
720
  const tree = await getDependencyTree(projectPath, result.projectInfo.packageManager);
721
721
  saveDepTree(projectPath, tree);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  detectMonorepo
3
- } from "./chunk-WNCDYCPO.js";
3
+ } from "./chunk-T552XMJO.js";
4
4
 
5
5
  // src/lib/resolve-package.ts
6
6
  import { readFileSync } from "fs";
@@ -15,7 +15,8 @@ import { join as join5 } from "path";
15
15
  import { readdirSync as readdirSync4, statSync as statSync4 } from "fs";
16
16
  import { join as join6, extname } from "path";
17
17
  import { readFileSync as readFileSync6, readdirSync as readdirSync5, statSync as statSync5, existsSync as existsSync3 } from "fs";
18
- import { join as join7, extname as extname2 } from "path";
18
+ import { join as join7, extname as extname3 } from "path";
19
+ import { basename, extname as extname2 } from "path";
19
20
  import { readFileSync as readFileSync8, existsSync as existsSync5, unlinkSync } from "fs";
20
21
  import { tmpdir } from "os";
21
22
  import { join as join9, dirname as dirname3 } from "path";
@@ -50,7 +51,7 @@ import { join as join18 } from "path";
50
51
  import { existsSync as existsSync11, readFileSync as readFileSync15 } from "fs";
51
52
  import { join as join19 } from "path";
52
53
  import { readFileSync as readFileSync16, existsSync as existsSync12, readdirSync as readdirSync10, statSync as statSync10 } from "fs";
53
- import { join as join20, extname as extname3 } from "path";
54
+ import { join as join20, extname as extname4 } from "path";
54
55
  import { readFileSync as readFileSync17, existsSync as existsSync13 } from "fs";
55
56
  import { join as join21 } from "path";
56
57
  import { readFileSync as readFileSync18, existsSync as existsSync14 } from "fs";
@@ -58,15 +59,15 @@ import { join as join22 } from "path";
58
59
  import { execa as execa10 } from "execa";
59
60
  import { execa as execa11 } from "execa";
60
61
  import { readFileSync as readFileSync19, readdirSync as readdirSync11, statSync as statSync11 } from "fs";
61
- import { join as join23, extname as extname4 } from "path";
62
+ import { join as join23, extname as extname5 } from "path";
62
63
  import { readFileSync as readFileSync20, readdirSync as readdirSync12, statSync as statSync12, existsSync as existsSync15 } from "fs";
63
- import { join as join24, extname as extname5, basename } from "path";
64
+ import { join as join24, extname as extname6, basename as basename2 } from "path";
64
65
  import { statSync as statSync13, readFileSync as readFileSync21 } from "fs";
65
66
  import { join as join25 } from "path";
66
67
  import { execa as execa12 } from "execa";
67
68
  import { globby } from "globby";
68
69
  import { readFileSync as readFileSync22, readdirSync as readdirSync13, statSync as statSync14, existsSync as existsSync16 } from "fs";
69
- import { join as join26, extname as extname6 } from "path";
70
+ import { join as join26, extname as extname7 } from "path";
70
71
  import { existsSync as existsSync17 } from "fs";
71
72
  import { join as join27 } from "path";
72
73
  import { execa as execa13 } from "execa";
@@ -699,6 +700,74 @@ function scanAssets(dir, projectRoot, assets) {
699
700
  } catch {
700
701
  }
701
702
  }
703
+ var FILE_TYPE_THRESHOLDS = {
704
+ "react-component": { warn: 300, critical: 500 },
705
+ "custom-hook": { warn: 150, critical: 250 },
706
+ "node-service": { warn: 500, critical: 800 },
707
+ "route-file": { warn: 250, critical: 400 },
708
+ "ts-utility": { warn: 600, critical: 1e3 },
709
+ config: { warn: Infinity, critical: Infinity },
710
+ test: { warn: Infinity, critical: Infinity },
711
+ general: { warn: 400, critical: 600 }
712
+ };
713
+ var TEST_PATTERN = /\.(test|spec)\.(ts|tsx|js|jsx|mts|cts)$/;
714
+ var CONFIG_PATTERN = /\.(config|rc)\.(ts|js|mjs|cjs|json)$/;
715
+ var CONFIG_NAMES = /* @__PURE__ */ new Set([
716
+ ".eslintrc.js",
717
+ ".eslintrc.cjs",
718
+ ".prettierrc.js",
719
+ "tailwind.config.js",
720
+ "tailwind.config.ts",
721
+ "postcss.config.js",
722
+ "postcss.config.ts",
723
+ "next.config.js",
724
+ "next.config.ts",
725
+ "next.config.mjs",
726
+ "tsconfig.json"
727
+ ]);
728
+ var HOOK_PATTERN = /^use[A-Z]/;
729
+ var ROUTE_NAMES = /* @__PURE__ */ new Set([
730
+ "page.tsx",
731
+ "page.jsx",
732
+ "layout.tsx",
733
+ "layout.jsx",
734
+ "loading.tsx",
735
+ "error.tsx",
736
+ "not-found.tsx"
737
+ ]);
738
+ var ROUTE_PATH_PATTERN = /[/\\](routes?|router)[/\\]/i;
739
+ var SERVICE_PATTERN = /\.(service|controller|middleware|handler)\.(ts|js)$/;
740
+ var COMPONENT_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
741
+ function classifyFile(filePath) {
742
+ const name = basename(filePath);
743
+ const ext = extname2(name);
744
+ if (TEST_PATTERN.test(name)) return "test";
745
+ if (CONFIG_PATTERN.test(name) || CONFIG_NAMES.has(name)) return "config";
746
+ if (HOOK_PATTERN.test(name) && (ext === ".ts" || ext === ".tsx")) return "custom-hook";
747
+ if (ROUTE_NAMES.has(name)) return "route-file";
748
+ if (ROUTE_PATH_PATTERN.test(filePath)) return "route-file";
749
+ if (SERVICE_PATTERN.test(name)) return "node-service";
750
+ if (COMPONENT_EXTENSIONS.has(ext)) return "react-component";
751
+ if ([".ts", ".js", ".mts", ".cts", ".mjs", ".cjs"].includes(ext)) return "ts-utility";
752
+ return "general";
753
+ }
754
+ function getThresholds(filePath) {
755
+ const fileType = classifyFile(filePath);
756
+ return { ...FILE_TYPE_THRESHOLDS[fileType], fileType };
757
+ }
758
+ var FILE_TYPE_LABELS = {
759
+ "react-component": "React component",
760
+ "custom-hook": "custom hook",
761
+ "node-service": "service",
762
+ "route-file": "route file",
763
+ "ts-utility": "utility",
764
+ config: "config",
765
+ test: "test",
766
+ general: "file"
767
+ };
768
+ function getFileTypeLabel(fileType) {
769
+ return FILE_TYPE_LABELS[fileType];
770
+ }
702
771
  var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mts", ".cts"]);
703
772
  var SOURCE_DIRS = ["src", "app", "lib"];
704
773
  var ComplexityRunner = class extends BaseRunner {
@@ -713,23 +782,34 @@ var ComplexityRunner = class extends BaseRunner {
713
782
  const files = SOURCE_DIRS.flatMap(
714
783
  (dir) => existsSync3(join7(projectPath, dir)) ? scanDirectory(join7(projectPath, dir), projectPath) : []
715
784
  );
716
- const oversized = files.filter((f) => f.lines >= WARN_LINES);
717
- const issues = oversized.map((f) => ({
718
- severity: f.lines >= CRITICAL_LINES ? "warning" : "info",
719
- message: `${f.path}: ${f.lines} lines \u2014 consider splitting into smaller modules`,
720
- fix: { description: "Extract concerns into smaller, focused files" },
721
- reportedBy: ["complexity"]
722
- }));
785
+ const issues = [];
786
+ let oversizedCount = 0;
787
+ for (const f of files) {
788
+ const { warn, critical, fileType } = getThresholds(f.path);
789
+ if (f.lines >= warn) {
790
+ oversizedCount++;
791
+ const label = getFileTypeLabel(fileType);
792
+ issues.push({
793
+ severity: f.lines >= critical ? "warning" : "info",
794
+ message: `${f.path} (${label}): ${f.lines} lines \u2014 consider splitting (threshold: ${warn})`,
795
+ fix: { description: "Extract concerns into smaller, focused files" },
796
+ reportedBy: ["complexity"]
797
+ });
798
+ }
799
+ }
723
800
  const totalLines = files.reduce((sum, f) => sum + f.lines, 0);
724
801
  const avgLines = files.length > 0 ? Math.round(totalLines / files.length) : 0;
725
- const score = Math.max(0, 100 - oversized.length * 10);
726
- const topFiles = [...files].sort((a, b) => b.lines - a.lines).slice(0, 10);
802
+ const score = Math.max(0, 100 - oversizedCount * 10);
803
+ const topFiles = [...files].sort((a, b) => b.lines - a.lines).slice(0, 10).map((f) => {
804
+ const { warn, critical, fileType } = getThresholds(f.path);
805
+ return { ...f, fileType, warn, critical };
806
+ });
727
807
  return {
728
808
  id: "complexity",
729
809
  category: this.category,
730
810
  name: "File Complexity",
731
811
  score,
732
- status: oversized.some((f) => f.lines >= CRITICAL_LINES) ? "warning" : oversized.length > 0 ? "warning" : "pass",
812
+ status: issues.some((i) => i.severity === "warning") ? "warning" : oversizedCount > 0 ? "warning" : "pass",
733
813
  issues,
734
814
  toolsUsed: ["complexity"],
735
815
  duration: elapsed(),
@@ -737,7 +817,7 @@ var ComplexityRunner = class extends BaseRunner {
737
817
  totalFiles: files.length,
738
818
  totalLines,
739
819
  avgLines,
740
- oversizedCount: oversized.length,
820
+ oversizedCount,
741
821
  topFiles
742
822
  }
743
823
  };
@@ -771,7 +851,7 @@ function scanDirectory(dir, projectRoot) {
771
851
  const stat = statSync5(fullPath);
772
852
  if (stat.isDirectory()) {
773
853
  files.push(...scanDirectory(fullPath, projectRoot));
774
- } else if (SOURCE_EXTENSIONS.has(extname2(entry)) && !isTestFile(entry)) {
854
+ } else if (SOURCE_EXTENSIONS.has(extname3(entry)) && !isTestFile(entry)) {
775
855
  try {
776
856
  const lines = readFileSync6(fullPath, "utf-8").split("\n").filter((l) => l.trim()).length;
777
857
  files.push({ path: fullPath.replace(projectRoot + "/", ""), lines });
@@ -2439,7 +2519,7 @@ function collectSourceFiles(dir) {
2439
2519
  const stat = statSync10(full);
2440
2520
  if (stat.isDirectory()) {
2441
2521
  files.push(...collectSourceFiles(full));
2442
- } else if (SOURCE_EXTENSIONS2.has(extname3(entry))) {
2522
+ } else if (SOURCE_EXTENSIONS2.has(extname4(entry))) {
2443
2523
  files.push(full);
2444
2524
  }
2445
2525
  } catch {
@@ -2884,7 +2964,7 @@ function getUpdateType(current, latest) {
2884
2964
  if (curMin < latMin) return "minor";
2885
2965
  return "patch";
2886
2966
  }
2887
- var COMPONENT_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
2967
+ var COMPONENT_EXTENSIONS2 = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
2888
2968
  var ReactPerfRunner = class extends BaseRunner {
2889
2969
  name = "react-perf";
2890
2970
  category = "performance";
@@ -2966,7 +3046,7 @@ function scanDirectory2(dir, projectRoot) {
2966
3046
  const stat = statSync11(fullPath);
2967
3047
  if (stat.isDirectory()) {
2968
3048
  files.push(...scanDirectory2(fullPath, projectRoot));
2969
- } else if (COMPONENT_EXTENSIONS.has(extname4(entry))) {
3049
+ } else if (COMPONENT_EXTENSIONS2.has(extname5(entry))) {
2970
3050
  try {
2971
3051
  const content = readFileSync19(fullPath, "utf-8");
2972
3052
  const lineCount = content.split("\n").length;
@@ -2988,11 +3068,12 @@ function analyzeFile(relPath, fullPath, lineCount) {
2988
3068
  try {
2989
3069
  const content = readFileSync19(fullPath, "utf-8");
2990
3070
  const lines = content.split("\n");
2991
- if (lineCount > WARN_LINES) {
3071
+ const { warn } = getThresholds(relPath);
3072
+ if (lineCount > warn) {
2992
3073
  findings.push({
2993
3074
  file: relPath,
2994
3075
  line: 0,
2995
- pattern: `Large component file (${lineCount} lines) \u2014 consider splitting`,
3076
+ pattern: `Large component file (${lineCount} lines, threshold: ${warn}) \u2014 consider splitting`,
2996
3077
  severity: "info"
2997
3078
  });
2998
3079
  }
@@ -3182,7 +3263,7 @@ function scanDirectory3(dir, projectRoot) {
3182
3263
  const stat = statSync12(fullPath);
3183
3264
  if (stat.isDirectory()) {
3184
3265
  findings.push(...scanDirectory3(fullPath, projectRoot));
3185
- } else if (SCAN_EXTENSIONS.has(extname5(entry)) && !SKIP_FILES.has(basename(entry)) && !isTestFile2(entry)) {
3266
+ } else if (SCAN_EXTENSIONS.has(extname6(entry)) && !SKIP_FILES.has(basename2(entry)) && !isTestFile2(entry)) {
3186
3267
  findings.push(...scanFile(fullPath, projectRoot));
3187
3268
  }
3188
3269
  }
@@ -3465,7 +3546,7 @@ function scanDirectory4(dir, projectRoot) {
3465
3546
  const stat = statSync14(fullPath);
3466
3547
  if (stat.isDirectory()) {
3467
3548
  todos.push(...scanDirectory4(fullPath, projectRoot));
3468
- } else if (SOURCE_EXTENSIONS3.has(extname6(entry))) {
3549
+ } else if (SOURCE_EXTENSIONS3.has(extname7(entry))) {
3469
3550
  todos.push(...scanFile2(fullPath, projectRoot));
3470
3551
  }
3471
3552
  }
@@ -11,7 +11,7 @@ var ASCII_ART = `
11
11
  A vitals health check for your app
12
12
  `.trim();
13
13
  function Header({ projectName }) {
14
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.4.1")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "white" }, projectName)));
14
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.4.2")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "white" }, projectName)));
15
15
  }
16
16
 
17
17
  export {
@@ -15,7 +15,7 @@ import {
15
15
  getScoreEmoji,
16
16
  runSickbay,
17
17
  runSickbayMonorepo
18
- } from "./chunk-WNCDYCPO.js";
18
+ } from "./chunk-T552XMJO.js";
19
19
  export {
20
20
  CRITICAL_LINES,
21
21
  SCORE_EXCELLENT,
package/dist/index.js CHANGED
@@ -8,12 +8,12 @@ import {
8
8
  } from "./chunk-TYG7ZQBP.js";
9
9
  import {
10
10
  Header
11
- } from "./chunk-C6CDVDZ2.js";
11
+ } from "./chunk-YBVU46HP.js";
12
12
  import {
13
13
  getScoreEmoji,
14
14
  runSickbay,
15
15
  runSickbayMonorepo
16
- } from "./chunk-WNCDYCPO.js";
16
+ } from "./chunk-T552XMJO.js";
17
17
 
18
18
  // src/index.ts
19
19
  import { existsSync } from "fs";
@@ -176,7 +176,7 @@ function App({
176
176
  setMonorepoReport(r);
177
177
  setProjectName(`monorepo (${r.packages.length} packages)`);
178
178
  try {
179
- const { getDependencyTree } = await import("./dist-YIK3YE5B.js");
179
+ const { getDependencyTree } = await import("./dist-ESNXUFHV.js");
180
180
  const { saveDepTree } = await import("./history-XLNVZEDI.js");
181
181
  const packages = {};
182
182
  for (const pkg of r.packages) {
@@ -245,7 +245,7 @@ function App({
245
245
  } catch {
246
246
  }
247
247
  try {
248
- const { getDependencyTree } = await import("./dist-YIK3YE5B.js");
248
+ const { getDependencyTree } = await import("./dist-ESNXUFHV.js");
249
249
  const { saveDepTree } = await import("./history-XLNVZEDI.js");
250
250
  const tree = await getDependencyTree(projectPath, r.projectInfo.packageManager);
251
251
  saveDepTree(projectPath, tree);
@@ -303,7 +303,7 @@ if (existsSync(globalConfigPath)) {
303
303
  }
304
304
  config({ debug: false, quiet: true });
305
305
  var program = new Command();
306
- program.name("sickbay").description("React project health check CLI").version("1.4.1", "-v, --version").enablePositionalOptions().passThroughOptions().option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single named package (monorepo only)").option("--json", "output raw JSON report").option("--web", "open web dashboard after scan").option("--no-ai", "disable AI features").option("--no-quotes", "suppress personality quotes in output").option("--verbose", "show verbose output").action(async (options) => {
306
+ program.name("sickbay").description("React project health check CLI").version("1.4.2", "-v, --version").enablePositionalOptions().passThroughOptions().option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single named package (monorepo only)").option("--json", "output raw JSON report").option("--web", "open web dashboard after scan").option("--no-ai", "disable AI features").option("--no-quotes", "suppress personality quotes in output").option("--verbose", "show verbose output").action(async (options) => {
307
307
  if (options.path && options.path !== process.cwd()) {
308
308
  const projectEnvPath = join(options.path, ".env");
309
309
  if (existsSync(projectEnvPath)) {
@@ -313,13 +313,13 @@ program.name("sickbay").description("React project health check CLI").version("1
313
313
  const updatePromise = (async () => {
314
314
  try {
315
315
  const { checkForUpdate } = await import("./update-check-M7IFOMLJ.js");
316
- return await checkForUpdate("1.4.1");
316
+ return await checkForUpdate("1.4.2");
317
317
  } catch {
318
318
  return null;
319
319
  }
320
320
  })();
321
321
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
322
- const { detectMonorepo, runSickbay: runSickbay2, runSickbayMonorepo: runSickbayMonorepo2 } = await import("./dist-YIK3YE5B.js");
322
+ const { detectMonorepo, runSickbay: runSickbay2, runSickbayMonorepo: runSickbayMonorepo2 } = await import("./dist-ESNXUFHV.js");
323
323
  const monorepoInfo = await detectMonorepo(options.path);
324
324
  if (options.package && monorepoInfo.isMonorepo) {
325
325
  const { readFileSync } = await import("fs");
@@ -383,7 +383,7 @@ program.name("sickbay").description("React project health check CLI").version("1
383
383
  } catch {
384
384
  }
385
385
  try {
386
- const { getDependencyTree } = await import("./dist-YIK3YE5B.js");
386
+ const { getDependencyTree } = await import("./dist-ESNXUFHV.js");
387
387
  const { saveDepTree } = await import("./history-XLNVZEDI.js");
388
388
  const tree = await getDependencyTree(options.path, report.projectInfo.packageManager);
389
389
  saveDepTree(options.path, tree);
@@ -406,7 +406,7 @@ program.name("sickbay").description("React project health check CLI").version("1
406
406
  );
407
407
  });
408
408
  program.command("init").description("Initialize .sickbay/ folder and run an initial baseline scan").option("-p, --path <path>", "project path to initialize", process.cwd()).action(async (options) => {
409
- const { initSickbay } = await import("./init-VMFU77S5.js");
409
+ const { initSickbay } = await import("./init-FLDYCXHA.js");
410
410
  await initSickbay(options.path);
411
411
  });
412
412
  program.command("fix").description("Interactively fix issues found by sickbay scan").option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single package (monorepo only)").option("--all", "apply all available fixes without prompting").option("--dry-run", "show what would be fixed without executing").option("--verbose", "show verbose output").action(async (options) => {
@@ -416,9 +416,9 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
416
416
  config({ path: projectEnvPath, override: true });
417
417
  }
418
418
  }
419
- const { resolveProject } = await import("./resolve-package-57YPNPWD.js");
419
+ const { resolveProject } = await import("./resolve-package-3FI7DU3Q.js");
420
420
  const resolution = await resolveProject(options.path, options.package);
421
- const { FixApp } = await import("./FixApp-2IRNVALD.js");
421
+ const { FixApp } = await import("./FixApp-UAHFPOJS.js");
422
422
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
423
423
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
424
424
  render(
@@ -441,10 +441,10 @@ program.command("trend").description("Show score history and trends over time").
441
441
  config({ path: projectEnvPath, override: true });
442
442
  }
443
443
  }
444
- const { resolveProject } = await import("./resolve-package-57YPNPWD.js");
444
+ const { resolveProject } = await import("./resolve-package-3FI7DU3Q.js");
445
445
  const resolution = await resolveProject(options.path, options.package);
446
446
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
447
- const { TrendApp } = await import("./TrendApp-7SR7UCVQ.js");
447
+ const { TrendApp } = await import("./TrendApp-N5AYGTQF.js");
448
448
  render(
449
449
  React6.createElement(TrendApp, {
450
450
  projectPath,
@@ -463,10 +463,10 @@ program.command("stats").description("Show a quick codebase overview and project
463
463
  config({ path: projectEnvPath, override: true });
464
464
  }
465
465
  }
466
- const { resolveProject } = await import("./resolve-package-57YPNPWD.js");
466
+ const { resolveProject } = await import("./resolve-package-3FI7DU3Q.js");
467
467
  const resolution = await resolveProject(options.path, options.package);
468
468
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
469
- const { StatsApp } = await import("./StatsApp-QDKFND5Q.js");
469
+ const { StatsApp } = await import("./StatsApp-3MLDHZ5C.js");
470
470
  render(
471
471
  React6.createElement(StatsApp, {
472
472
  projectPath,
@@ -478,7 +478,7 @@ program.command("stats").description("Show a quick codebase overview and project
478
478
  );
479
479
  });
480
480
  program.command("tui").description("Launch the persistent developer dashboard").option("-p, --path <path>", "project path to monitor", process.cwd()).option("--no-watch", "disable file-watching auto-refresh").option("--no-quotes", "suppress personality quotes in output").option("--refresh <seconds>", "auto-refresh interval in seconds", "300").option("-c, --checks <checks>", "comma-separated list of checks to run").action(async (options) => {
481
- const { TuiApp } = await import("./TuiApp-CWMLC5QI.js");
481
+ const { TuiApp } = await import("./TuiApp-XWUQZX42.js");
482
482
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
483
483
  render(
484
484
  React6.createElement(TuiApp, {
@@ -498,10 +498,10 @@ program.command("doctor").description("Diagnose project setup and configuration
498
498
  config({ path: projectEnvPath, override: true });
499
499
  }
500
500
  }
501
- const { resolveProject } = await import("./resolve-package-57YPNPWD.js");
501
+ const { resolveProject } = await import("./resolve-package-3FI7DU3Q.js");
502
502
  const resolution = await resolveProject(options.path, options.package);
503
503
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
504
- const { DoctorApp } = await import("./DoctorApp-C4UWQ2Y3.js");
504
+ const { DoctorApp } = await import("./DoctorApp-ZRMEYFRT.js");
505
505
  render(
506
506
  React6.createElement(DoctorApp, {
507
507
  projectPath,
@@ -514,13 +514,13 @@ program.command("doctor").description("Diagnose project setup and configuration
514
514
  );
515
515
  });
516
516
  program.command("badge").description("Generate a health score badge for your README").option("-p, --path <path>", "project path", process.cwd()).option("--package <name>", "scope to a single package (monorepo only)").option("--html", "output HTML <img> tag instead of markdown").option("--url", "output bare badge URL only").option("--label <text>", "custom badge label", "sickbay").option("--scan", "run a fresh scan instead of using last report").action(async (options) => {
517
- const { resolveProject } = await import("./resolve-package-57YPNPWD.js");
517
+ const { resolveProject } = await import("./resolve-package-3FI7DU3Q.js");
518
518
  const resolution = await resolveProject(options.path, options.package);
519
519
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
520
520
  const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } = await import("./badge-KQ73KEIN.js");
521
521
  let score = options.scan ? null : loadScoreFromLastReport(projectPath);
522
522
  if (score === null) {
523
- const { runSickbay: runSickbay2 } = await import("./dist-YIK3YE5B.js");
523
+ const { runSickbay: runSickbay2 } = await import("./dist-ESNXUFHV.js");
524
524
  const report = await runSickbay2({ projectPath, quotes: false });
525
525
  try {
526
526
  const { saveEntry, saveLastReport } = await import("./history-XLNVZEDI.js");
@@ -549,7 +549,7 @@ program.command("diff <branch>").description("Compare health score against anoth
549
549
  }
550
550
  }
551
551
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
552
- const { DiffApp } = await import("./DiffApp-URU5RDS3.js");
552
+ const { DiffApp } = await import("./DiffApp-VVB6Q2F3.js");
553
553
  render(
554
554
  React6.createElement(DiffApp, {
555
555
  projectPath: options.path,
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-3OR2GFVE.js";
4
4
  import {
5
5
  runSickbay
6
- } from "./chunk-WNCDYCPO.js";
6
+ } from "./chunk-T552XMJO.js";
7
7
 
8
8
  // src/commands/init.ts
9
9
  import { mkdirSync, writeFileSync, existsSync, readFileSync, appendFileSync } from "fs";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  resolveProject,
3
3
  shortName
4
- } from "./chunk-7CHSSJZH.js";
5
- import "./chunk-WNCDYCPO.js";
4
+ } from "./chunk-PMGLCTYQ.js";
5
+ import "./chunk-T552XMJO.js";
6
6
  export {
7
7
  resolveProject,
8
8
  shortName