sickbay 1.14.0 → 1.14.2

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-AO3RLT4Q.js";
3
+ } from "./chunk-DC4FULTJ.js";
4
4
  import "./chunk-JSBRDJBE.js";
5
5
 
6
6
  // src/components/DiffApp.tsx
@@ -120,7 +120,7 @@ function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }) {
120
120
  useEffect(() => {
121
121
  (async () => {
122
122
  try {
123
- const { runSickbay } = await import("./dist-CC44WX2U.js");
123
+ const { runSickbay } = await import("./dist-ZWXOESKV.js");
124
124
  const currentReport = await runSickbay({
125
125
  projectPath,
126
126
  checks,
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  shortName
3
- } from "./chunk-MFINHA55.js";
3
+ } from "./chunk-RH2MTL2L.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-AO3RLT4Q.js";
6
+ } from "./chunk-DC4FULTJ.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  detectProject
10
- } from "./chunk-X3OVB6OA.js";
10
+ } from "./chunk-CYUCJO47.js";
11
11
  import "./chunk-JSBRDJBE.js";
12
12
 
13
13
  // src/components/DoctorApp.tsx
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  shortName
3
- } from "./chunk-MFINHA55.js";
3
+ } from "./chunk-RH2MTL2L.js";
4
4
  import {
5
5
  ProgressList
6
6
  } from "./chunk-MBVA75EM.js";
7
7
  import {
8
8
  Header
9
- } from "./chunk-AO3RLT4Q.js";
9
+ } from "./chunk-DC4FULTJ.js";
10
10
  import {
11
11
  runSickbay
12
- } from "./chunk-X3OVB6OA.js";
12
+ } from "./chunk-CYUCJO47.js";
13
13
  import "./chunk-JSBRDJBE.js";
14
14
 
15
15
  // src/components/FixApp.tsx
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  shortName
3
- } from "./chunk-MFINHA55.js";
3
+ } from "./chunk-RH2MTL2L.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-AO3RLT4Q.js";
6
+ } from "./chunk-DC4FULTJ.js";
7
7
  import {
8
8
  detectProject
9
- } from "./chunk-X3OVB6OA.js";
9
+ } from "./chunk-CYUCJO47.js";
10
10
  import "./chunk-JSBRDJBE.js";
11
11
 
12
12
  // src/components/StatsApp.tsx
@@ -4,11 +4,11 @@ import {
4
4
  } from "./chunk-SHO3ZXTH.js";
5
5
  import {
6
6
  shortName
7
- } from "./chunk-MFINHA55.js";
7
+ } from "./chunk-RH2MTL2L.js";
8
8
  import {
9
9
  Header
10
- } from "./chunk-AO3RLT4Q.js";
11
- import "./chunk-X3OVB6OA.js";
10
+ } from "./chunk-DC4FULTJ.js";
11
+ import "./chunk-CYUCJO47.js";
12
12
  import {
13
13
  detectRegressions,
14
14
  loadHistory
@@ -14,7 +14,7 @@ import {
14
14
  detectMonorepo,
15
15
  runSickbay,
16
16
  runSickbayMonorepo
17
- } from "./chunk-X3OVB6OA.js";
17
+ } from "./chunk-CYUCJO47.js";
18
18
  import {
19
19
  loadHistory
20
20
  } from "./chunk-3OR2GFVE.js";
@@ -690,7 +690,7 @@ function TuiApp({
690
690
  return () => timers.forEach(clearTimeout);
691
691
  }, []);
692
692
  useEffect7(() => {
693
- checkForUpdate("1.13.0").then((info) => {
693
+ checkForUpdate("1.14.1").then((info) => {
694
694
  if (info) setUpdateInfo(info);
695
695
  });
696
696
  }, []);
@@ -716,7 +716,7 @@ function TuiApp({
716
716
  } catch {
717
717
  }
718
718
  try {
719
- const { getDependencyTree } = await import("./dist-CC44WX2U.js");
719
+ const { getDependencyTree } = await import("./dist-ZWXOESKV.js");
720
720
  const { saveDepTree } = await import("./history-KXLC45VS.js");
721
721
  const tree = await getDependencyTree(projectPath, result.projectInfo.packageManager);
722
722
  saveDepTree(projectPath, tree);
@@ -820,7 +820,7 @@ function TuiApp({
820
820
  const webReport = monorepoReportRef.current ?? reportRef.current;
821
821
  if (!webReport) return;
822
822
  try {
823
- const { serveWeb } = await import("./web-7OLVXHBT.js");
823
+ const { serveWeb } = await import("./web-74HLV7N5.js");
824
824
  const { default: openBrowser } = await import("open");
825
825
  let aiService;
826
826
  if (withAI && process.env.ANTHROPIC_API_KEY && !monorepoReportRef.current) {
@@ -6932,6 +6932,35 @@ async function detectMonorepo(rootPath) {
6932
6932
  packagePaths
6933
6933
  };
6934
6934
  }
6935
+ var SEVERITY_WEIGHT = {
6936
+ critical: 10,
6937
+ warning: 3,
6938
+ info: 1
6939
+ };
6940
+ function issueWeight(issues) {
6941
+ return issues.reduce((sum, i) => sum + SEVERITY_WEIGHT[i.severity], 0);
6942
+ }
6943
+ function recalcScoreAfterSuppression(result, originalIssues) {
6944
+ if (result.issues.length === 0) {
6945
+ result.score = 100;
6946
+ result.status = "pass";
6947
+ return;
6948
+ }
6949
+ if (result.issues.length === originalIssues.length) return;
6950
+ const origWeight = issueWeight(originalIssues);
6951
+ if (origWeight === 0) return;
6952
+ const remainWeight = issueWeight(result.issues);
6953
+ const penalty = 100 - result.score;
6954
+ result.score = Math.round(100 - penalty * (remainWeight / origWeight));
6955
+ const hasCritical = result.issues.some((i) => i.severity === "critical");
6956
+ if (hasCritical) {
6957
+ result.status = "fail";
6958
+ } else if (result.issues.length > 0) {
6959
+ result.status = "warning";
6960
+ } else {
6961
+ result.status = "pass";
6962
+ }
6963
+ }
6935
6964
  function applySuppression(issues, rules) {
6936
6965
  if (rules.length === 0) return { issues, suppressedCount: 0 };
6937
6966
  const compiled = rules.map((rule) => ({
@@ -7036,9 +7065,11 @@ async function runSickbay(options = {}) {
7036
7065
  } : void 0
7037
7066
  });
7038
7067
  if (checkCfg?.suppress?.length) {
7068
+ const originalIssues = result.issues;
7039
7069
  const { issues, suppressedCount } = applySuppression(result.issues, checkCfg.suppress);
7040
7070
  result.issues = issues;
7041
7071
  if (suppressedCount > 0) {
7072
+ recalcScoreAfterSuppression(result, originalIssues);
7042
7073
  result.metadata = { ...result.metadata, suppressedCount };
7043
7074
  }
7044
7075
  }
@@ -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.13.0")), 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.14.1")), 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 {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  detectMonorepo
3
- } from "./chunk-X3OVB6OA.js";
3
+ } from "./chunk-CYUCJO47.js";
4
4
 
5
5
  // src/lib/resolve-package.ts
6
6
  import { readFileSync } from "fs";
package/dist/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineConfig
3
- } from "./chunk-X3OVB6OA.js";
3
+ } from "./chunk-CYUCJO47.js";
4
4
  import "./chunk-JSBRDJBE.js";
5
5
  export {
6
6
  defineConfig
@@ -29,7 +29,7 @@ import {
29
29
  runSickbay,
30
30
  runSickbayMonorepo,
31
31
  validateConfig
32
- } from "./chunk-X3OVB6OA.js";
32
+ } from "./chunk-CYUCJO47.js";
33
33
  import "./chunk-JSBRDJBE.js";
34
34
  export {
35
35
  BaseAdvisor,
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-AO3RLT4Q.js";
11
+ } from "./chunk-DC4FULTJ.js";
12
12
  import {
13
13
  getScoreEmoji,
14
14
  runSickbay,
15
15
  runSickbayMonorepo
16
- } from "./chunk-X3OVB6OA.js";
16
+ } from "./chunk-CYUCJO47.js";
17
17
  import "./chunk-JSBRDJBE.js";
18
18
 
19
19
  // src/index.ts
@@ -177,7 +177,7 @@ function App({
177
177
  setMonorepoReport(r);
178
178
  setProjectName(`monorepo (${r.packages.length} packages)`);
179
179
  try {
180
- const { getDependencyTree } = await import("./dist-CC44WX2U.js");
180
+ const { getDependencyTree } = await import("./dist-ZWXOESKV.js");
181
181
  const { saveDepTree } = await import("./history-KXLC45VS.js");
182
182
  const packages = {};
183
183
  for (const pkg of r.packages) {
@@ -189,7 +189,7 @@ function App({
189
189
  if (openWeb) {
190
190
  setPhase("opening-web");
191
191
  try {
192
- const { serveWeb } = await import("./web-7OLVXHBT.js");
192
+ const { serveWeb } = await import("./web-74HLV7N5.js");
193
193
  const { default: openBrowser } = await import("open");
194
194
  let aiService;
195
195
  if (enableAI && process.env.ANTHROPIC_API_KEY) {
@@ -246,7 +246,7 @@ function App({
246
246
  } catch {
247
247
  }
248
248
  try {
249
- const { getDependencyTree } = await import("./dist-CC44WX2U.js");
249
+ const { getDependencyTree } = await import("./dist-ZWXOESKV.js");
250
250
  const { saveDepTree } = await import("./history-KXLC45VS.js");
251
251
  const tree = await getDependencyTree(projectPath, r.projectInfo.packageManager);
252
252
  saveDepTree(projectPath, tree);
@@ -255,7 +255,7 @@ function App({
255
255
  if (openWeb) {
256
256
  setPhase("opening-web");
257
257
  try {
258
- const { serveWeb } = await import("./web-7OLVXHBT.js");
258
+ const { serveWeb } = await import("./web-74HLV7N5.js");
259
259
  const { default: openBrowser } = await import("open");
260
260
  let aiService;
261
261
  if (enableAI && process.env.ANTHROPIC_API_KEY) {
@@ -304,7 +304,7 @@ if (existsSync(globalConfigPath)) {
304
304
  }
305
305
  config({ debug: false, quiet: true });
306
306
  var program = new Command();
307
- program.name("sickbay").description("React project health check CLI").version("1.13.0", "-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
+ program.name("sickbay").description("React project health check CLI").version("1.14.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) => {
308
308
  if (options.path && options.path !== process.cwd()) {
309
309
  const projectEnvPath = join(options.path, ".env");
310
310
  if (existsSync(projectEnvPath)) {
@@ -314,13 +314,13 @@ program.name("sickbay").description("React project health check CLI").version("1
314
314
  const updatePromise = (async () => {
315
315
  try {
316
316
  const { checkForUpdate } = await import("./update-check-QLG6GA4Z.js");
317
- return await checkForUpdate("1.13.0");
317
+ return await checkForUpdate("1.14.1");
318
318
  } catch {
319
319
  return null;
320
320
  }
321
321
  })();
322
322
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
323
- const { detectMonorepo, runSickbay: runSickbay2, runSickbayMonorepo: runSickbayMonorepo2 } = await import("./dist-CC44WX2U.js");
323
+ const { detectMonorepo, runSickbay: runSickbay2, runSickbayMonorepo: runSickbayMonorepo2 } = await import("./dist-ZWXOESKV.js");
324
324
  const monorepoInfo = await detectMonorepo(options.path);
325
325
  if (options.package && monorepoInfo.isMonorepo) {
326
326
  const { readFileSync } = await import("fs");
@@ -384,7 +384,7 @@ program.name("sickbay").description("React project health check CLI").version("1
384
384
  } catch {
385
385
  }
386
386
  try {
387
- const { getDependencyTree } = await import("./dist-CC44WX2U.js");
387
+ const { getDependencyTree } = await import("./dist-ZWXOESKV.js");
388
388
  const { saveDepTree } = await import("./history-KXLC45VS.js");
389
389
  const tree = await getDependencyTree(options.path, report.projectInfo.packageManager);
390
390
  saveDepTree(options.path, tree);
@@ -411,16 +411,16 @@ program.command("init").description("Initialize .sickbay/ folder and run an init
411
411
  "add newly available checks to existing config without touching existing entries"
412
412
  ).option("--reset-config", "regenerate config from scratch (overwrites existing)").action(async (options) => {
413
413
  if (options.resetConfig) {
414
- const { generateConfigFile } = await import("./init-IDUYC5ZY.js");
414
+ const { generateConfigFile } = await import("./init-722XRGCW.js");
415
415
  await generateConfigFile(options.path, { force: true });
416
416
  return;
417
417
  }
418
418
  if (options.sync) {
419
- const { syncConfigFile } = await import("./init-IDUYC5ZY.js");
419
+ const { syncConfigFile } = await import("./init-722XRGCW.js");
420
420
  await syncConfigFile(options.path);
421
421
  return;
422
422
  }
423
- const { initSickbay } = await import("./init-IDUYC5ZY.js");
423
+ const { initSickbay } = await import("./init-722XRGCW.js");
424
424
  await initSickbay(options.path);
425
425
  });
426
426
  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) => {
@@ -430,9 +430,9 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
430
430
  config({ path: projectEnvPath, override: true });
431
431
  }
432
432
  }
433
- const { resolveProject } = await import("./resolve-package-W7BS3CDL.js");
433
+ const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
434
434
  const resolution = await resolveProject(options.path, options.package);
435
- const { FixApp } = await import("./FixApp-P3HE5VBZ.js");
435
+ const { FixApp } = await import("./FixApp-GUVSGB5F.js");
436
436
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
437
437
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
438
438
  render(
@@ -455,10 +455,10 @@ program.command("trend").description("Show score history and trends over time").
455
455
  config({ path: projectEnvPath, override: true });
456
456
  }
457
457
  }
458
- const { resolveProject } = await import("./resolve-package-W7BS3CDL.js");
458
+ const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
459
459
  const resolution = await resolveProject(options.path, options.package);
460
460
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
461
- const { TrendApp } = await import("./TrendApp-3UFL4P7I.js");
461
+ const { TrendApp } = await import("./TrendApp-3KY6FXKB.js");
462
462
  render(
463
463
  React6.createElement(TrendApp, {
464
464
  projectPath,
@@ -477,10 +477,10 @@ program.command("stats").description("Show a quick codebase overview and project
477
477
  config({ path: projectEnvPath, override: true });
478
478
  }
479
479
  }
480
- const { resolveProject } = await import("./resolve-package-W7BS3CDL.js");
480
+ const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
481
481
  const resolution = await resolveProject(options.path, options.package);
482
482
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
483
- const { StatsApp } = await import("./StatsApp-OQ3UHHCX.js");
483
+ const { StatsApp } = await import("./StatsApp-CEI7BSPT.js");
484
484
  render(
485
485
  React6.createElement(StatsApp, {
486
486
  projectPath,
@@ -492,7 +492,7 @@ program.command("stats").description("Show a quick codebase overview and project
492
492
  );
493
493
  });
494
494
  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) => {
495
- const { TuiApp } = await import("./TuiApp-XJALAKP6.js");
495
+ const { TuiApp } = await import("./TuiApp-SRIZ5KDI.js");
496
496
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
497
497
  render(
498
498
  React6.createElement(TuiApp, {
@@ -512,10 +512,10 @@ program.command("doctor").description("Diagnose project setup and configuration
512
512
  config({ path: projectEnvPath, override: true });
513
513
  }
514
514
  }
515
- const { resolveProject } = await import("./resolve-package-W7BS3CDL.js");
515
+ const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
516
516
  const resolution = await resolveProject(options.path, options.package);
517
517
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
518
- const { DoctorApp } = await import("./DoctorApp-YVQXYJKB.js");
518
+ const { DoctorApp } = await import("./DoctorApp-EPJ6LBBL.js");
519
519
  render(
520
520
  React6.createElement(DoctorApp, {
521
521
  projectPath,
@@ -528,13 +528,13 @@ program.command("doctor").description("Diagnose project setup and configuration
528
528
  );
529
529
  });
530
530
  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) => {
531
- const { resolveProject } = await import("./resolve-package-W7BS3CDL.js");
531
+ const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
532
532
  const resolution = await resolveProject(options.path, options.package);
533
533
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
534
534
  const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } = await import("./badge-AO2FZVHJ.js");
535
535
  let score = options.scan ? null : loadScoreFromLastReport(projectPath);
536
536
  if (score === null) {
537
- const { runSickbay: runSickbay2 } = await import("./dist-CC44WX2U.js");
537
+ const { runSickbay: runSickbay2 } = await import("./dist-ZWXOESKV.js");
538
538
  const report = await runSickbay2({ projectPath, quotes: false });
539
539
  try {
540
540
  const { saveEntry, saveLastReport } = await import("./history-KXLC45VS.js");
@@ -563,7 +563,7 @@ program.command("diff <branch>").description("Compare health score against anoth
563
563
  }
564
564
  }
565
565
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
566
- const { DiffApp } = await import("./DiffApp-TDXQ3AGJ.js");
566
+ const { DiffApp } = await import("./DiffApp-P7GVBMLM.js");
567
567
  render(
568
568
  React6.createElement(DiffApp, {
569
569
  projectPath: options.path,
@@ -4,7 +4,7 @@ import {
4
4
  getAvailableChecks,
5
5
  runSickbay,
6
6
  runSickbayMonorepo
7
- } from "./chunk-X3OVB6OA.js";
7
+ } from "./chunk-CYUCJO47.js";
8
8
  import {
9
9
  saveEntry
10
10
  } from "./chunk-3OR2GFVE.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  resolveProject,
3
3
  shortName
4
- } from "./chunk-MFINHA55.js";
5
- import "./chunk-X3OVB6OA.js";
4
+ } from "./chunk-RH2MTL2L.js";
5
+ import "./chunk-CYUCJO47.js";
6
6
  import "./chunk-JSBRDJBE.js";
7
7
  export {
8
8
  resolveProject,
@@ -108,7 +108,7 @@ async function serveWeb(report, preferredPort = 3030, aiService) {
108
108
  if (url === "/sickbay-config.json") {
109
109
  const basePath = "isMonorepo" in report ? report.rootPath : report.projectPath;
110
110
  try {
111
- const { loadConfig } = await import("./dist-CC44WX2U.js");
111
+ const { loadConfig } = await import("./dist-ZWXOESKV.js");
112
112
  const config = await loadConfig(basePath);
113
113
  if (config) {
114
114
  res.writeHead(200, { "Content-Type": "application/json" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sickbay",
3
- "version": "1.14.0",
3
+ "version": "1.14.2",
4
4
  "description": "Zero-config health check CLI for JavaScript and TypeScript projects",
5
5
  "license": "MIT",
6
6
  "repository": {