sickbay 1.16.4 → 1.16.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.
Files changed (24) hide show
  1. package/dist/{DiffApp-39aMGuNc.js → DiffApp-CLb_519R.js} +2 -2
  2. package/dist/{DiffApp-39aMGuNc.js.map → DiffApp-CLb_519R.js.map} +1 -1
  3. package/dist/{DoctorApp-CaiqnhHH.js → DoctorApp-DGRU6kEv.js} +3 -3
  4. package/dist/{DoctorApp-CaiqnhHH.js.map → DoctorApp-DGRU6kEv.js.map} +1 -1
  5. package/dist/{FixApp-CFotJ2y8.js → FixApp-XMR6MFXY.js} +3 -3
  6. package/dist/{FixApp-CFotJ2y8.js.map → FixApp-XMR6MFXY.js.map} +1 -1
  7. package/dist/{StatsApp-BC4P4hII.js → StatsApp-CXhNyWlK.js} +3 -3
  8. package/dist/{StatsApp-BC4P4hII.js.map → StatsApp-CXhNyWlK.js.map} +1 -1
  9. package/dist/{TrendApp-D_YTj9kI.js → TrendApp-Disixyy9.js} +2 -2
  10. package/dist/{TrendApp-D_YTj9kI.js.map → TrendApp-Disixyy9.js.map} +1 -1
  11. package/dist/{TuiApp-B3l1OC7M.js → TuiApp-INOoV9j8.js} +5 -5
  12. package/dist/{TuiApp-B3l1OC7M.js.map → TuiApp-INOoV9j8.js.map} +1 -1
  13. package/dist/config.js +1 -1
  14. package/dist/{dist-Bjhxbcak.js → dist-CHT6_2R4.js} +2 -2
  15. package/dist/dist-CHT6_2R4.js.map +1 -0
  16. package/dist/index.js +25 -25
  17. package/dist/{init-Czn8P7An.js → init-B-i_T2IR.js} +2 -2
  18. package/dist/{init-Czn8P7An.js.map → init-B-i_T2IR.js.map} +1 -1
  19. package/dist/{resolve-package-DS27JBhN.js → resolve-package-DOgU3aGV.js} +2 -2
  20. package/dist/{resolve-package-DS27JBhN.js.map → resolve-package-DOgU3aGV.js.map} +1 -1
  21. package/dist/{web-CFBLfBdc.js → web-DUk_L4uZ.js} +2 -2
  22. package/dist/{web-CFBLfBdc.js.map → web-DUk_L4uZ.js.map} +1 -1
  23. package/package.json +3 -3
  24. package/dist/dist-Bjhxbcak.js.map +0 -1
@@ -126,7 +126,7 @@ function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }) {
126
126
  useEffect(() => {
127
127
  (async () => {
128
128
  try {
129
- const { runSickbay } = await import("./dist-Bjhxbcak.js").then((n) => n.s);
129
+ const { runSickbay } = await import("./dist-CHT6_2R4.js").then((n) => n.s);
130
130
  const currentReport = await runSickbay({
131
131
  projectPath,
132
132
  checks,
@@ -178,4 +178,4 @@ function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }) {
178
178
  //#endregion
179
179
  export { DiffApp };
180
180
 
181
- //# sourceMappingURL=DiffApp-39aMGuNc.js.map
181
+ //# sourceMappingURL=DiffApp-CLb_519R.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DiffApp-39aMGuNc.js","names":[],"sources":["../src/commands/diff.ts","../src/components/DiffApp.tsx"],"sourcesContent":["import { execFileSync } from 'child_process';\n\nimport type { SickbayReport } from 'sickbay-core';\n\nexport interface CheckDiff {\n id: string;\n name: string;\n category: string;\n currentScore: number;\n baseScore: number;\n delta: number;\n status: 'improved' | 'regressed' | 'unchanged' | 'new' | 'removed';\n}\n\nexport interface DiffResult {\n branch: string;\n currentScore: number;\n baseScore: number;\n scoreDelta: number;\n checks: CheckDiff[];\n summary: {\n improved: number;\n regressed: number;\n unchanged: number;\n newChecks: number;\n removedChecks: number;\n };\n}\n\nexport function loadBaseReport(projectPath: string, branch: string): SickbayReport | null {\n try {\n const output = execFileSync('git', ['show', `${branch}:.sickbay/last-report.json`], {\n cwd: projectPath,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return JSON.parse(output) as SickbayReport;\n } catch {\n return null;\n }\n}\n\nconst STATUS_ORDER: Record<CheckDiff['status'], number> = {\n regressed: 0,\n improved: 1,\n new: 2,\n removed: 3,\n unchanged: 4,\n};\n\nexport function compareReports(\n current: SickbayReport,\n base: SickbayReport,\n branch: string,\n): DiffResult {\n const baseMap = new Map(base.checks.map((c) => [c.id, c]));\n const currentMap = new Map(current.checks.map((c) => [c.id, c]));\n\n const checks: CheckDiff[] = [];\n\n // Checks in current\n for (const check of current.checks) {\n const baseCheck = baseMap.get(check.id);\n if (!baseCheck) {\n checks.push({\n id: check.id,\n name: check.name,\n category: check.category,\n currentScore: check.score,\n baseScore: 0,\n delta: check.score,\n status: 'new',\n });\n } else {\n const delta = check.score - baseCheck.score;\n checks.push({\n id: check.id,\n name: check.name,\n category: check.category,\n currentScore: check.score,\n baseScore: baseCheck.score,\n delta,\n status: delta > 0 ? 'improved' : delta < 0 ? 'regressed' : 'unchanged',\n });\n }\n }\n\n // Checks only in base (removed)\n for (const check of base.checks) {\n if (!currentMap.has(check.id)) {\n checks.push({\n id: check.id,\n name: check.name,\n category: check.category,\n currentScore: 0,\n baseScore: check.score,\n delta: -check.score,\n status: 'removed',\n });\n }\n }\n\n // Sort: regressions first, then improvements, then new, removed, unchanged\n checks.sort((a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status]);\n\n const summary = {\n improved: checks.filter((c) => c.status === 'improved').length,\n regressed: checks.filter((c) => c.status === 'regressed').length,\n unchanged: checks.filter((c) => c.status === 'unchanged').length,\n newChecks: checks.filter((c) => c.status === 'new').length,\n removedChecks: checks.filter((c) => c.status === 'removed').length,\n };\n\n return {\n branch,\n currentScore: current.overallScore,\n baseScore: base.overallScore,\n scoreDelta: current.overallScore - base.overallScore,\n checks,\n summary,\n };\n}\n","import React, { useState, useEffect } from 'react';\n\nimport { Box, Text, useApp } from 'ink';\nimport Spinner from 'ink-spinner';\n\nimport {\n loadBaseReport,\n compareReports,\n type DiffResult,\n type CheckDiff,\n} from '../commands/diff.js';\nimport { Header } from './Header.js';\n\ninterface DiffAppProps {\n projectPath: string;\n branch: string;\n jsonOutput: boolean;\n checks?: string[];\n verbose?: boolean;\n}\n\nconst STATUS_ICONS: Record<CheckDiff['status'], string> = {\n improved: '↑',\n regressed: '↓',\n unchanged: '=',\n new: '+',\n removed: '−',\n};\n\nconst STATUS_COLORS: Record<CheckDiff['status'], string> = {\n improved: 'green',\n regressed: 'red',\n unchanged: 'gray',\n new: 'cyan',\n removed: 'yellow',\n};\n\nfunction formatDelta(delta: number): string {\n if (delta > 0) return `+${delta}`;\n if (delta < 0) return `${delta}`;\n return '0';\n}\n\nfunction DiffTable({ diff }: { diff: DiffResult }) {\n return (\n <Box flexDirection=\"column\">\n <Box marginTop={1}>\n <Text bold>Overall: </Text>\n <Text bold>{diff.baseScore}</Text>\n <Text dimColor> → </Text>\n <Text bold>{diff.currentScore}</Text>\n <Text> </Text>\n <Text color={diff.scoreDelta > 0 ? 'green' : diff.scoreDelta < 0 ? 'red' : 'gray'} bold>\n ({formatDelta(diff.scoreDelta)})\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Box>\n <Text bold>{' Check'.padEnd(30)}</Text>\n <Text bold>{'Current'.padEnd(10)}</Text>\n <Text bold>{'Base'.padEnd(10)}</Text>\n <Text bold>Delta</Text>\n </Box>\n <Text dimColor>{'━'.repeat(56)}</Text>\n {diff.checks.map((check) => (\n <Box key={check.id}>\n <Text color={STATUS_COLORS[check.status]}>{STATUS_ICONS[check.status]} </Text>\n <Text>{check.name.padEnd(28)}</Text>\n <Text>{String(check.currentScore || '—').padEnd(10)}</Text>\n <Text>{String(check.baseScore || '—').padEnd(10)}</Text>\n <Text color={STATUS_COLORS[check.status]} bold>\n {check.status === 'new'\n ? 'new'\n : check.status === 'removed'\n ? 'removed'\n : formatDelta(check.delta)}\n </Text>\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>\n {diff.summary.improved > 0 && <Text color=\"green\">{diff.summary.improved} improved</Text>}\n {diff.summary.improved > 0 && diff.summary.regressed > 0 && <Text>, </Text>}\n {diff.summary.regressed > 0 && (\n <Text color=\"red\">{diff.summary.regressed} regressed</Text>\n )}\n {(diff.summary.improved > 0 || diff.summary.regressed > 0) &&\n diff.summary.unchanged > 0 && <Text>, </Text>}\n {diff.summary.unchanged > 0 && <Text>{diff.summary.unchanged} unchanged</Text>}\n {diff.summary.newChecks > 0 && <Text color=\"cyan\">, {diff.summary.newChecks} new</Text>}\n {diff.summary.removedChecks > 0 && (\n <Text color=\"yellow\">, {diff.summary.removedChecks} removed</Text>\n )}\n </Text>\n </Box>\n </Box>\n );\n}\n\nexport function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }: DiffAppProps) {\n const { exit } = useApp();\n const [phase, setPhase] = useState<'scanning' | 'loading-base' | 'results' | 'error'>('scanning');\n const [diff, setDiff] = useState<DiffResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n (async () => {\n try {\n // Run fresh scan on current branch\n const { runSickbay } = await import('sickbay-core');\n const currentReport = await runSickbay({\n projectPath,\n checks,\n verbose,\n });\n\n // Save current report\n try {\n const { saveEntry, saveLastReport } = await import('../lib/history.js');\n saveEntry(currentReport);\n saveLastReport(currentReport);\n } catch {\n // Non-critical\n }\n\n setPhase('loading-base');\n\n // Load base report from target branch\n const baseReport = loadBaseReport(projectPath, branch);\n if (!baseReport) {\n setError(\n `No saved report found on \"${branch}\". Run \\`sickbay\\` on that branch and commit .sickbay/last-report.json so it can be read via git.`,\n );\n setPhase('error');\n setTimeout(() => exit(), 100);\n return;\n }\n\n const result = compareReports(currentReport, baseReport, branch);\n setDiff(result);\n setPhase('results');\n\n if (jsonOutput) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n }\n\n setTimeout(() => exit(), 100);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setPhase('error');\n setTimeout(() => exit(), 100);\n }\n })();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (phase === 'scanning') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n Scanning current branch...\n </Text>\n </Box>\n );\n }\n\n if (phase === 'loading-base') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n Loading {branch} baseline...\n </Text>\n </Box>\n );\n }\n\n if (phase === 'error') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text color=\"red\">✗ {error}</Text>\n </Box>\n );\n }\n\n if (jsonOutput || !diff) return null;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text bold>Branch Diff: current vs {branch}</Text>\n <DiffTable diff={diff} />\n </Box>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DiffApp-CLb_519R.js","names":[],"sources":["../src/commands/diff.ts","../src/components/DiffApp.tsx"],"sourcesContent":["import { execFileSync } from 'child_process';\n\nimport type { SickbayReport } from 'sickbay-core';\n\nexport interface CheckDiff {\n id: string;\n name: string;\n category: string;\n currentScore: number;\n baseScore: number;\n delta: number;\n status: 'improved' | 'regressed' | 'unchanged' | 'new' | 'removed';\n}\n\nexport interface DiffResult {\n branch: string;\n currentScore: number;\n baseScore: number;\n scoreDelta: number;\n checks: CheckDiff[];\n summary: {\n improved: number;\n regressed: number;\n unchanged: number;\n newChecks: number;\n removedChecks: number;\n };\n}\n\nexport function loadBaseReport(projectPath: string, branch: string): SickbayReport | null {\n try {\n const output = execFileSync('git', ['show', `${branch}:.sickbay/last-report.json`], {\n cwd: projectPath,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return JSON.parse(output) as SickbayReport;\n } catch {\n return null;\n }\n}\n\nconst STATUS_ORDER: Record<CheckDiff['status'], number> = {\n regressed: 0,\n improved: 1,\n new: 2,\n removed: 3,\n unchanged: 4,\n};\n\nexport function compareReports(\n current: SickbayReport,\n base: SickbayReport,\n branch: string,\n): DiffResult {\n const baseMap = new Map(base.checks.map((c) => [c.id, c]));\n const currentMap = new Map(current.checks.map((c) => [c.id, c]));\n\n const checks: CheckDiff[] = [];\n\n // Checks in current\n for (const check of current.checks) {\n const baseCheck = baseMap.get(check.id);\n if (!baseCheck) {\n checks.push({\n id: check.id,\n name: check.name,\n category: check.category,\n currentScore: check.score,\n baseScore: 0,\n delta: check.score,\n status: 'new',\n });\n } else {\n const delta = check.score - baseCheck.score;\n checks.push({\n id: check.id,\n name: check.name,\n category: check.category,\n currentScore: check.score,\n baseScore: baseCheck.score,\n delta,\n status: delta > 0 ? 'improved' : delta < 0 ? 'regressed' : 'unchanged',\n });\n }\n }\n\n // Checks only in base (removed)\n for (const check of base.checks) {\n if (!currentMap.has(check.id)) {\n checks.push({\n id: check.id,\n name: check.name,\n category: check.category,\n currentScore: 0,\n baseScore: check.score,\n delta: -check.score,\n status: 'removed',\n });\n }\n }\n\n // Sort: regressions first, then improvements, then new, removed, unchanged\n checks.sort((a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status]);\n\n const summary = {\n improved: checks.filter((c) => c.status === 'improved').length,\n regressed: checks.filter((c) => c.status === 'regressed').length,\n unchanged: checks.filter((c) => c.status === 'unchanged').length,\n newChecks: checks.filter((c) => c.status === 'new').length,\n removedChecks: checks.filter((c) => c.status === 'removed').length,\n };\n\n return {\n branch,\n currentScore: current.overallScore,\n baseScore: base.overallScore,\n scoreDelta: current.overallScore - base.overallScore,\n checks,\n summary,\n };\n}\n","import React, { useState, useEffect } from 'react';\n\nimport { Box, Text, useApp } from 'ink';\nimport Spinner from 'ink-spinner';\n\nimport {\n loadBaseReport,\n compareReports,\n type DiffResult,\n type CheckDiff,\n} from '../commands/diff.js';\nimport { Header } from './Header.js';\n\ninterface DiffAppProps {\n projectPath: string;\n branch: string;\n jsonOutput: boolean;\n checks?: string[];\n verbose?: boolean;\n}\n\nconst STATUS_ICONS: Record<CheckDiff['status'], string> = {\n improved: '↑',\n regressed: '↓',\n unchanged: '=',\n new: '+',\n removed: '−',\n};\n\nconst STATUS_COLORS: Record<CheckDiff['status'], string> = {\n improved: 'green',\n regressed: 'red',\n unchanged: 'gray',\n new: 'cyan',\n removed: 'yellow',\n};\n\nfunction formatDelta(delta: number): string {\n if (delta > 0) return `+${delta}`;\n if (delta < 0) return `${delta}`;\n return '0';\n}\n\nfunction DiffTable({ diff }: { diff: DiffResult }) {\n return (\n <Box flexDirection=\"column\">\n <Box marginTop={1}>\n <Text bold>Overall: </Text>\n <Text bold>{diff.baseScore}</Text>\n <Text dimColor> → </Text>\n <Text bold>{diff.currentScore}</Text>\n <Text> </Text>\n <Text color={diff.scoreDelta > 0 ? 'green' : diff.scoreDelta < 0 ? 'red' : 'gray'} bold>\n ({formatDelta(diff.scoreDelta)})\n </Text>\n </Box>\n\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Box>\n <Text bold>{' Check'.padEnd(30)}</Text>\n <Text bold>{'Current'.padEnd(10)}</Text>\n <Text bold>{'Base'.padEnd(10)}</Text>\n <Text bold>Delta</Text>\n </Box>\n <Text dimColor>{'━'.repeat(56)}</Text>\n {diff.checks.map((check) => (\n <Box key={check.id}>\n <Text color={STATUS_COLORS[check.status]}>{STATUS_ICONS[check.status]} </Text>\n <Text>{check.name.padEnd(28)}</Text>\n <Text>{String(check.currentScore || '—').padEnd(10)}</Text>\n <Text>{String(check.baseScore || '—').padEnd(10)}</Text>\n <Text color={STATUS_COLORS[check.status]} bold>\n {check.status === 'new'\n ? 'new'\n : check.status === 'removed'\n ? 'removed'\n : formatDelta(check.delta)}\n </Text>\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>\n {diff.summary.improved > 0 && <Text color=\"green\">{diff.summary.improved} improved</Text>}\n {diff.summary.improved > 0 && diff.summary.regressed > 0 && <Text>, </Text>}\n {diff.summary.regressed > 0 && (\n <Text color=\"red\">{diff.summary.regressed} regressed</Text>\n )}\n {(diff.summary.improved > 0 || diff.summary.regressed > 0) &&\n diff.summary.unchanged > 0 && <Text>, </Text>}\n {diff.summary.unchanged > 0 && <Text>{diff.summary.unchanged} unchanged</Text>}\n {diff.summary.newChecks > 0 && <Text color=\"cyan\">, {diff.summary.newChecks} new</Text>}\n {diff.summary.removedChecks > 0 && (\n <Text color=\"yellow\">, {diff.summary.removedChecks} removed</Text>\n )}\n </Text>\n </Box>\n </Box>\n );\n}\n\nexport function DiffApp({ projectPath, branch, jsonOutput, checks, verbose }: DiffAppProps) {\n const { exit } = useApp();\n const [phase, setPhase] = useState<'scanning' | 'loading-base' | 'results' | 'error'>('scanning');\n const [diff, setDiff] = useState<DiffResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n (async () => {\n try {\n // Run fresh scan on current branch\n const { runSickbay } = await import('sickbay-core');\n const currentReport = await runSickbay({\n projectPath,\n checks,\n verbose,\n });\n\n // Save current report\n try {\n const { saveEntry, saveLastReport } = await import('../lib/history.js');\n saveEntry(currentReport);\n saveLastReport(currentReport);\n } catch {\n // Non-critical\n }\n\n setPhase('loading-base');\n\n // Load base report from target branch\n const baseReport = loadBaseReport(projectPath, branch);\n if (!baseReport) {\n setError(\n `No saved report found on \"${branch}\". Run \\`sickbay\\` on that branch and commit .sickbay/last-report.json so it can be read via git.`,\n );\n setPhase('error');\n setTimeout(() => exit(), 100);\n return;\n }\n\n const result = compareReports(currentReport, baseReport, branch);\n setDiff(result);\n setPhase('results');\n\n if (jsonOutput) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n }\n\n setTimeout(() => exit(), 100);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setPhase('error');\n setTimeout(() => exit(), 100);\n }\n })();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (phase === 'scanning') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n Scanning current branch...\n </Text>\n </Box>\n );\n }\n\n if (phase === 'loading-base') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n Loading {branch} baseline...\n </Text>\n </Box>\n );\n }\n\n if (phase === 'error') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text color=\"red\">✗ {error}</Text>\n </Box>\n );\n }\n\n if (jsonOutput || !diff) return null;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text bold>Branch Diff: current vs {branch}</Text>\n <DiffTable diff={diff} />\n </Box>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { a as detectPackageManager, o as detectProject } from "./dist-Bjhxbcak.js";
1
+ import { a as detectPackageManager, o as detectProject } from "./dist-CHT6_2R4.js";
2
2
  import { r as Header } from "./index.js";
3
- import { shortName } from "./resolve-package-DS27JBhN.js";
3
+ import { shortName } from "./resolve-package-DOgU3aGV.js";
4
4
  import { existsSync, readFileSync } from "fs";
5
5
  import { join } from "path";
6
6
  import React, { useEffect, useState } from "react";
@@ -412,4 +412,4 @@ function DoctorApp({ projectPath, jsonOutput, isMonorepo, packagePaths, packageN
412
412
  //#endregion
413
413
  export { DoctorApp };
414
414
 
415
- //# sourceMappingURL=DoctorApp-CaiqnhHH.js.map
415
+ //# sourceMappingURL=DoctorApp-DGRU6kEv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DoctorApp-CaiqnhHH.js","names":[],"sources":["../src/commands/doctor.ts","../src/components/DoctorApp.tsx"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nimport { detectProject, detectPackageManager } from 'sickbay-core';\n\n/**\n * This module defines a set of diagnostic checks that can be run against a JavaScript/TypeScript project to identify common issues and best practice violations. Each check returns a DiagnosticResult indicating whether the check passed, failed, or has warnings, along with messages and potential fixes. The runDiagnostics function executes all checks and aggregates their results for reporting.\n */\n\nexport interface DiagnosticResult {\n id: string;\n label: string;\n status: 'pass' | 'fail' | 'warn';\n message: string;\n fixCommand?: string;\n fixDescription?: string;\n}\n\ntype DiagnosticCheck = (projectPath: string) => Promise<DiagnosticResult>;\n\nasync function checkGitignore(projectPath: string): Promise<DiagnosticResult> {\n const gitignorePath = join(projectPath, '.gitignore');\n if (!existsSync(gitignorePath)) {\n return {\n id: 'gitignore',\n label: '.gitignore exists',\n status: 'fail',\n message: 'No .gitignore found',\n fixDescription: 'Create .gitignore with standard entries',\n };\n }\n const content = readFileSync(gitignorePath, 'utf-8');\n const lines = content.split('\\n').map((l) => l.trim());\n const required = ['node_modules', '.env', 'dist', '.DS_Store'];\n const missing = required.filter((entry) => !lines.includes(entry));\n if (missing.length > 0) {\n return {\n id: 'gitignore',\n label: '.gitignore entries',\n status: 'warn',\n message: `Missing entries: ${missing.join(', ')}`,\n fixDescription: `Add ${missing.join(', ')} to .gitignore`,\n };\n }\n return {\n id: 'gitignore',\n label: '.gitignore entries',\n status: 'pass',\n message: 'All standard entries present',\n };\n}\n\nasync function checkEnginesField(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n if (!pkg.engines) {\n return {\n id: 'engines',\n label: 'package.json engines field',\n status: 'warn',\n message: 'No engines field — Node.js version not specified',\n fixDescription: 'Add \"engines\": { \"node\": \">=18.0.0\" } to package.json',\n };\n }\n return {\n id: 'engines',\n label: 'package.json engines field',\n status: 'pass',\n message: `node ${pkg.engines.node ?? 'unspecified'}`,\n };\n}\n\nasync function checkBrowserslist(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n const hasFile =\n existsSync(join(projectPath, '.browserslistrc')) ||\n existsSync(join(projectPath, 'browserslist'));\n const hasField = !!pkg.browserslist;\n if (!hasFile && !hasField) {\n return {\n id: 'browserslist',\n label: 'Browserslist config',\n status: 'warn',\n message: 'No browserslist config — browser targets not defined',\n fixDescription: 'Create .browserslistrc with default targets',\n };\n }\n return {\n id: 'browserslist',\n label: 'Browserslist config',\n status: 'pass',\n message: 'Browserslist configured',\n };\n}\n\nasync function checkNodeVersion(projectPath: string): Promise<DiagnosticResult> {\n const hasNvmrc = existsSync(join(projectPath, '.nvmrc'));\n const hasNodeVersion = existsSync(join(projectPath, '.node-version'));\n const hasToolVersions = existsSync(join(projectPath, '.tool-versions'));\n if (!hasNvmrc && !hasNodeVersion && !hasToolVersions) {\n return {\n id: 'node-version',\n label: 'Node version pinning',\n status: 'warn',\n message: 'No .nvmrc or .node-version — Node version not pinned',\n fixDescription: 'Create .nvmrc with current Node version',\n };\n }\n return {\n id: 'node-version',\n label: 'Node version pinning',\n status: 'pass',\n message: hasNvmrc\n ? '.nvmrc found'\n : hasNodeVersion\n ? '.node-version found'\n : '.tool-versions found',\n };\n}\n\nasync function checkNpmScripts(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n const scripts = pkg.scripts ?? {};\n const expected = ['lint', 'test', 'build'];\n const missing = expected.filter((s) => !scripts[s]);\n if (missing.length > 0) {\n return {\n id: 'npm-scripts',\n label: 'Essential npm scripts',\n status: missing.includes('build') || missing.includes('test') ? 'fail' : 'warn',\n message: `Missing scripts: ${missing.join(', ')}`,\n fixDescription: `Add ${missing.join(', ')} scripts to package.json`,\n };\n }\n return {\n id: 'npm-scripts',\n label: 'Essential npm scripts',\n status: 'pass',\n message: 'lint, test, build all defined',\n };\n}\n\nasync function checkLockfile(projectPath: string): Promise<DiagnosticResult> {\n const hasNpmLock = existsSync(join(projectPath, 'package-lock.json'));\n const hasPnpmLock = existsSync(join(projectPath, 'pnpm-lock.yaml'));\n const hasYarnLock = existsSync(join(projectPath, 'yarn.lock'));\n const hasBunLock =\n existsSync(join(projectPath, 'bun.lockb')) || existsSync(join(projectPath, 'bun.lock'));\n if (!hasNpmLock && !hasPnpmLock && !hasYarnLock && !hasBunLock) {\n return {\n id: 'lockfile',\n label: 'Lockfile present',\n status: 'fail',\n message: 'No lockfile found — dependencies not pinned',\n fixCommand: 'npm install',\n fixDescription: 'Generate lockfile with npm install',\n };\n }\n const lockfileNames: Record<string, string> = {\n pnpm: 'pnpm-lock.yaml',\n yarn: 'yarn.lock',\n bun: 'bun.lockb',\n npm: 'package-lock.json',\n };\n return {\n id: 'lockfile',\n label: 'Lockfile present',\n status: 'pass',\n message: lockfileNames[detectPackageManager(projectPath)],\n };\n}\n\nasync function checkEditorconfig(projectPath: string): Promise<DiagnosticResult> {\n if (!existsSync(join(projectPath, '.editorconfig'))) {\n return {\n id: 'editorconfig',\n label: '.editorconfig',\n status: 'warn',\n message: 'No .editorconfig — editor settings not standardized',\n fixDescription: 'Create .editorconfig with standard settings',\n };\n }\n return {\n id: 'editorconfig',\n label: '.editorconfig',\n status: 'pass',\n message: '.editorconfig found',\n };\n}\n\nasync function checkPrettier(projectPath: string): Promise<DiagnosticResult> {\n const info = await detectProject(projectPath);\n if (!info.hasPrettier) {\n return {\n id: 'prettier',\n label: 'Prettier config',\n status: 'warn',\n message: 'No Prettier configured — code formatting not standardized',\n fixCommand: 'npm install -D prettier',\n fixDescription: 'Install prettier and create .prettierrc',\n };\n }\n return {\n id: 'prettier',\n label: 'Prettier config',\n status: 'pass',\n message: 'Prettier configured',\n };\n}\n\nasync function checkESLintConfig(projectPath: string): Promise<DiagnosticResult> {\n const info = await detectProject(projectPath);\n if (!info.hasESLint) {\n return {\n id: 'eslint-config',\n label: 'ESLint config',\n status: 'fail',\n message: 'No ESLint configured — no lint rules enforced',\n fixCommand: 'npm init @eslint/config',\n fixDescription: 'Initialize ESLint configuration',\n };\n }\n return {\n id: 'eslint-config',\n label: 'ESLint config',\n status: 'pass',\n message: 'ESLint configured',\n };\n}\n\nasync function checkTsconfig(projectPath: string): Promise<DiagnosticResult> {\n const info = await detectProject(projectPath);\n const hasTsconfig = existsSync(join(projectPath, 'tsconfig.json'));\n if (info.hasTypeScript && !hasTsconfig) {\n return {\n id: 'tsconfig',\n label: 'TypeScript config',\n status: 'fail',\n message: 'TypeScript deps found but no tsconfig.json',\n fixCommand: 'npx tsc --init',\n fixDescription: 'Generate tsconfig.json',\n };\n }\n if (!info.hasTypeScript) {\n return {\n id: 'tsconfig',\n label: 'TypeScript',\n status: 'warn',\n message: 'TypeScript not in use (consider adopting)',\n };\n }\n return {\n id: 'tsconfig',\n label: 'TypeScript config',\n status: 'pass',\n message: 'tsconfig.json found',\n };\n}\n\nasync function checkEnvExample(projectPath: string): Promise<DiagnosticResult> {\n const hasEnv = existsSync(join(projectPath, '.env'));\n const hasExample =\n existsSync(join(projectPath, '.env.example')) ||\n existsSync(join(projectPath, '.env.template')) ||\n existsSync(join(projectPath, '.env.sample'));\n if (hasEnv && !hasExample) {\n return {\n id: 'env-example',\n label: '.env.example',\n status: 'warn',\n message: \".env exists but no .env.example — team members won't know required vars\",\n fixDescription: 'Create .env.example with variable names (no values)',\n };\n }\n if (!hasEnv) {\n return {\n id: 'env-example',\n label: '.env.example',\n status: 'pass',\n message: 'No .env file (not applicable)',\n };\n }\n return {\n id: 'env-example',\n label: '.env.example',\n status: 'pass',\n message: '.env.example exists',\n };\n}\n\nasync function checkReactVersions(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n const react = deps['react'];\n const reactDom = deps['react-dom'];\n\n if (!react) {\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'pass',\n message: 'Not a React project',\n };\n }\n if (!reactDom) {\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'warn',\n message: 'react installed but react-dom missing',\n fixCommand: `npm install react-dom@${react}`,\n fixDescription: 'Install react-dom matching react version',\n };\n }\n if (react !== reactDom) {\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'fail',\n message: `react@${react} and react-dom@${reactDom} version mismatch`,\n fixCommand: `npm install react-dom@${react}`,\n fixDescription: 'Align react-dom version with react',\n };\n }\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'pass',\n message: `react and react-dom both at ${react}`,\n };\n}\n\nconst ALL_DIAGNOSTICS: DiagnosticCheck[] = [\n checkGitignore,\n checkEnginesField,\n checkBrowserslist,\n checkNodeVersion,\n checkNpmScripts,\n checkLockfile,\n checkEditorconfig,\n checkPrettier,\n checkESLintConfig,\n checkTsconfig,\n checkEnvExample,\n checkReactVersions,\n];\n\nexport async function runDiagnostics(projectPath: string): Promise<DiagnosticResult[]> {\n const results: DiagnosticResult[] = [];\n for (const check of ALL_DIAGNOSTICS) {\n try {\n results.push(await check(projectPath));\n } catch (err) {\n results.push({\n id: 'unknown',\n label: 'Unknown check',\n status: 'fail',\n message: `Check failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n return results;\n}\n","import React, { useState, useEffect } from 'react';\n\nimport { Box, Text, useApp } from 'ink';\nimport Spinner from 'ink-spinner';\n\nimport { runDiagnostics, type DiagnosticResult } from '../commands/doctor.js';\nimport { shortName } from '../lib/resolve-package.js';\nimport { Header } from './Header.js';\n\ninterface DoctorAppProps {\n projectPath: string;\n autoFix: boolean;\n jsonOutput: boolean;\n isMonorepo?: boolean;\n packagePaths?: string[];\n packageNames?: Map<string, string>;\n}\n\ninterface PackageDiagnostics {\n name: string;\n path: string;\n results: DiagnosticResult[];\n}\n\nconst STATUS_CONFIG = {\n pass: { icon: '✓', color: 'green' as const },\n fail: { icon: '✗', color: 'red' as const },\n warn: { icon: '⚠', color: 'yellow' as const },\n};\n\nfunction DiagnosticsList({ results }: { results: DiagnosticResult[] }) {\n return (\n <Box flexDirection=\"column\" marginLeft={2}>\n {results.map((r) => {\n const { icon, color } = STATUS_CONFIG[r.status];\n return (\n <Box key={r.id} flexDirection=\"column\">\n <Box>\n <Text color={color}>{icon} </Text>\n <Text bold={r.status !== 'pass'}>{r.label}</Text>\n <Text dimColor> — {r.message}</Text>\n </Box>\n {r.status !== 'pass' && r.fixCommand && (\n <Box marginLeft={4}>\n <Text dimColor>fix: </Text>\n <Text color=\"cyan\">{r.fixCommand}</Text>\n </Box>\n )}\n {r.status !== 'pass' && !r.fixCommand && r.fixDescription && (\n <Box marginLeft={4}>\n <Text dimColor>→ {r.fixDescription}</Text>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n}\n\nfunction DiagnosticsSummary({ results }: { results: DiagnosticResult[] }) {\n const passed = results.filter((r) => r.status === 'pass').length;\n const warned = results.filter((r) => r.status === 'warn').length;\n const failed = results.filter((r) => r.status === 'fail').length;\n\n return (\n <Box>\n <Text color=\"green\"> ✓ {passed} passed</Text>\n <Text color=\"yellow\"> ⚠ {warned} warnings</Text>\n <Text color=\"red\"> ✗ {failed} failed</Text>\n <Text dimColor> ({results.length} checks)</Text>\n </Box>\n );\n}\n\nexport function DoctorApp({\n projectPath,\n jsonOutput,\n isMonorepo,\n packagePaths,\n packageNames,\n}: DoctorAppProps) {\n const { exit } = useApp();\n const [results, setResults] = useState<DiagnosticResult[]>([]);\n const [packageResults, setPackageResults] = useState<PackageDiagnostics[]>([]);\n const [running, setRunning] = useState(true);\n\n useEffect(() => {\n if (isMonorepo && packagePaths && packageNames) {\n Promise.all(\n packagePaths.map(async (pkgPath) => {\n const name = packageNames.get(pkgPath) ?? pkgPath;\n const r = await runDiagnostics(pkgPath);\n return { name, path: pkgPath, results: r };\n }),\n )\n .then((all) => {\n setPackageResults(all);\n setRunning(false);\n\n if (jsonOutput) {\n const output = all.map((p) => ({\n package: p.name,\n path: p.path,\n results: p.results,\n }));\n process.stdout.write(JSON.stringify(output, null, 2) + '\\n');\n }\n\n setTimeout(() => exit(), 100);\n })\n .catch((err) => {\n setPackageResults([\n {\n name: 'error',\n path: projectPath,\n results: [\n {\n id: 'error',\n label: 'Doctor',\n status: 'fail',\n message: `Failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n },\n ]);\n setRunning(false);\n setTimeout(() => exit(), 100);\n });\n } else {\n runDiagnostics(projectPath)\n .then((r) => {\n setResults(r);\n setRunning(false);\n\n if (jsonOutput) {\n process.stdout.write(JSON.stringify(r, null, 2) + '\\n');\n }\n\n setTimeout(() => exit(), 100);\n })\n .catch((err) => {\n setResults([\n {\n id: 'error',\n label: 'Doctor',\n status: 'fail',\n message: `Failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ]);\n setRunning(false);\n setTimeout(() => exit(), 100);\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (running) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n Running project diagnostics\n {isMonorepo ? ` across ${packagePaths?.length} packages` : ''}...\n </Text>\n </Box>\n );\n }\n\n if (jsonOutput) return null;\n\n // Monorepo: show per-package results\n if (isMonorepo && packageResults.length > 0) {\n const allResults = packageResults.flatMap((p) => p.results);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text bold>Monorepo Setup Diagnosis</Text>\n\n {packageResults.map((pkg) => (\n <Box key={pkg.path} flexDirection=\"column\" marginTop={1}>\n <Text bold color=\"cyan\">\n {shortName(pkg.name)}\n </Text>\n <DiagnosticsList results={pkg.results} />\n </Box>\n ))}\n\n <Box marginTop={1}>\n <Text dimColor>{'━'.repeat(52)}</Text>\n </Box>\n <DiagnosticsSummary results={allResults} />\n </Box>\n );\n }\n\n // Single project\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text bold>Project Setup Diagnosis</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <DiagnosticsList results={results} />\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>{'━'.repeat(52)}</Text>\n </Box>\n <Box marginTop={1}>\n <DiagnosticsSummary results={results} />\n </Box>\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;AAoBA,eAAe,eAAe,aAAgD;CAC5E,MAAM,gBAAgB,KAAK,aAAa,aAAa;AACrD,KAAI,CAAC,WAAW,cAAc,CAC5B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,gBAAgB;EACjB;CAGH,MAAM,QADU,aAAa,eAAe,QAAQ,CAC9B,MAAM,KAAK,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC;CAEtD,MAAM,UADW;EAAC;EAAgB;EAAQ;EAAQ;EAAY,CACrC,QAAQ,UAAU,CAAC,MAAM,SAAS,MAAM,CAAC;AAClE,KAAI,QAAQ,SAAS,EACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,oBAAoB,QAAQ,KAAK,KAAK;EAC/C,gBAAgB,OAAO,QAAQ,KAAK,KAAK,CAAC;EAC3C;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,kBAAkB,aAAgD;CAC/E,MAAM,MAAM,KAAK,MAAM,aAAa,KAAK,aAAa,eAAe,EAAE,QAAQ,CAAC;AAChF,KAAI,CAAC,IAAI,QACP,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,QAAQ,IAAI,QAAQ,QAAQ;EACtC;;AAGH,eAAe,kBAAkB,aAAgD;CAC/E,MAAM,MAAM,KAAK,MAAM,aAAa,KAAK,aAAa,eAAe,EAAE,QAAQ,CAAC;CAChF,MAAM,UACJ,WAAW,KAAK,aAAa,kBAAkB,CAAC,IAChD,WAAW,KAAK,aAAa,eAAe,CAAC;CAC/C,MAAM,WAAW,CAAC,CAAC,IAAI;AACvB,KAAI,CAAC,WAAW,CAAC,SACf,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,iBAAiB,aAAgD;CAC9E,MAAM,WAAW,WAAW,KAAK,aAAa,SAAS,CAAC;CACxD,MAAM,iBAAiB,WAAW,KAAK,aAAa,gBAAgB,CAAC;CACrE,MAAM,kBAAkB,WAAW,KAAK,aAAa,iBAAiB,CAAC;AACvE,KAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,gBACnC,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,WACL,iBACA,iBACE,wBACA;EACP;;AAGH,eAAe,gBAAgB,aAAgD;CAE7E,MAAM,UADM,KAAK,MAAM,aAAa,KAAK,aAAa,eAAe,EAAE,QAAQ,CAAC,CAC5D,WAAW,EAAE;CAEjC,MAAM,UADW;EAAC;EAAQ;EAAQ;EAAQ,CACjB,QAAQ,MAAM,CAAC,QAAQ,GAAG;AACnD,KAAI,QAAQ,SAAS,EACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ,QAAQ,SAAS,QAAQ,IAAI,QAAQ,SAAS,OAAO,GAAG,SAAS;EACzE,SAAS,oBAAoB,QAAQ,KAAK,KAAK;EAC/C,gBAAgB,OAAO,QAAQ,KAAK,KAAK,CAAC;EAC3C;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,cAAc,aAAgD;CAC3E,MAAM,aAAa,WAAW,KAAK,aAAa,oBAAoB,CAAC;CACrE,MAAM,cAAc,WAAW,KAAK,aAAa,iBAAiB,CAAC;CACnE,MAAM,cAAc,WAAW,KAAK,aAAa,YAAY,CAAC;CAC9D,MAAM,aACJ,WAAW,KAAK,aAAa,YAAY,CAAC,IAAI,WAAW,KAAK,aAAa,WAAW,CAAC;AACzF,KAAI,CAAC,cAAc,CAAC,eAAe,CAAC,eAAe,CAAC,WAClD,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,YAAY;EACZ,gBAAgB;EACjB;AAQH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAV4C;GAC5C,MAAM;GACN,MAAM;GACN,KAAK;GACL,KAAK;GACN,CAKwB,qBAAqB,YAAY;EACzD;;AAGH,eAAe,kBAAkB,aAAgD;AAC/E,KAAI,CAAC,WAAW,KAAK,aAAa,gBAAgB,CAAC,CACjD,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,cAAc,aAAgD;AAE3E,KAAI,EADS,MAAM,cAAc,YAAY,EACnC,YACR,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,YAAY;EACZ,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,kBAAkB,aAAgD;AAE/E,KAAI,EADS,MAAM,cAAc,YAAY,EACnC,UACR,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,YAAY;EACZ,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,cAAc,aAAgD;CAC3E,MAAM,OAAO,MAAM,cAAc,YAAY;CAC7C,MAAM,cAAc,WAAW,KAAK,aAAa,gBAAgB,CAAC;AAClE,KAAI,KAAK,iBAAiB,CAAC,YACzB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,YAAY;EACZ,gBAAgB;EACjB;AAEH,KAAI,CAAC,KAAK,cACR,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,gBAAgB,aAAgD;CAC7E,MAAM,SAAS,WAAW,KAAK,aAAa,OAAO,CAAC;CACpD,MAAM,aACJ,WAAW,KAAK,aAAa,eAAe,CAAC,IAC7C,WAAW,KAAK,aAAa,gBAAgB,CAAC,IAC9C,WAAW,KAAK,aAAa,cAAc,CAAC;AAC9C,KAAI,UAAU,CAAC,WACb,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,gBAAgB;EACjB;AAEH,KAAI,CAAC,OACH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;;AAGH,eAAe,mBAAmB,aAAgD;CAChF,MAAM,MAAM,KAAK,MAAM,aAAa,KAAK,aAAa,eAAe,EAAE,QAAQ,CAAC;CAChF,MAAM,OAAO;EAAE,GAAI,IAAI,gBAAgB,EAAE;EAAG,GAAI,IAAI,mBAAmB,EAAE;EAAG;CAC5E,MAAM,QAAQ,KAAK;CACnB,MAAM,WAAW,KAAK;AAEtB,KAAI,CAAC,MACH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACV;AAEH,KAAI,CAAC,SACH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,YAAY,yBAAyB;EACrC,gBAAgB;EACjB;AAEH,KAAI,UAAU,SACZ,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,SAAS,MAAM,iBAAiB,SAAS;EAClD,YAAY,yBAAyB;EACrC,gBAAgB;EACjB;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,+BAA+B;EACzC;;AAGH,MAAM,kBAAqC;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,eAAsB,eAAe,aAAkD;CACrF,MAAM,UAA8B,EAAE;AACtC,MAAK,MAAM,SAAS,gBAClB,KAAI;AACF,UAAQ,KAAK,MAAM,MAAM,YAAY,CAAC;UAC/B,KAAK;AACZ,UAAQ,KAAK;GACX,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GAC3E,CAAC;;AAGN,QAAO;;;;AChVT,MAAM,gBAAgB;CACpB,MAAM;EAAE,MAAM;EAAK,OAAO;EAAkB;CAC5C,MAAM;EAAE,MAAM;EAAK,OAAO;EAAgB;CAC1C,MAAM;EAAE,MAAM;EAAK,OAAO;EAAmB;CAC9C;AAED,SAAS,gBAAgB,EAAE,WAA4C;AACrE,QACE,sBAAA,cAAC,KAAD;EAAK,eAAc;EAAS,YAAY;EAwBlC,EAvBH,QAAQ,KAAK,MAAM;EAClB,MAAM,EAAE,MAAM,UAAU,cAAc,EAAE;AACxC,SACE,sBAAA,cAAC,KAAD;GAAK,KAAK,EAAE;GAAI,eAAc;GAiBxB,EAhBJ,sBAAA,cAAC,KAAA,MACC,sBAAA,cAAC,MAAD,EAAa,OAAqB,EAAb,MAAK,IAAQ,EAClC,sBAAA,cAAC,MAAD,EAAM,MAAM,EAAE,WAAW,QAAwB,EAAf,EAAE,MAAa,EACjD,sBAAA,cAAC,MAAD,EAAM,UAAA,MAA8B,EAArB,OAAI,EAAE,QAAe,CAChC,EACL,EAAE,WAAW,UAAU,EAAE,cACxB,sBAAA,cAAC,KAAD,EAAK,YAAY,GAGX,EAFJ,sBAAA,cAAC,MAAD,EAAM,UAAA,MAAqB,EAAZ,QAAY,EAC3B,sBAAA,cAAC,MAAD,EAAM,OAAM,QAA4B,EAApB,EAAE,WAAkB,CACpC,EAEP,EAAE,WAAW,UAAU,CAAC,EAAE,cAAc,EAAE,kBACzC,sBAAA,cAAC,KAAD,EAAK,YAAY,GAEX,EADJ,sBAAA,cAAC,MAAD,EAAM,UAAA,MAAoC,EAA3B,MAAG,EAAE,eAAsB,CACtC,CAEJ;GAER,CACE;;AAIV,SAAS,mBAAmB,EAAE,WAA4C;CACxE,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC;CAC1D,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC;CAC1D,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC;AAE1D,QACE,sBAAA,cAAC,KAAA,MACC,sBAAA,cAAC,MAAD,EAAM,OAAM,SAAiC,EAAzB,OAAI,QAAO,UAAc,EAC7C,sBAAA,cAAC,MAAD,EAAM,OAAM,UAAoC,EAA3B,OAAI,QAAO,YAAgB,EAChD,sBAAA,cAAC,MAAD,EAAM,OAAM,OAA+B,EAAzB,OAAI,QAAO,UAAc,EAC3C,sBAAA,cAAC,MAAD,EAAM,UAAA,MAA0C,EAAjC,MAAG,QAAQ,QAAO,WAAe,CAC5C;;AAIV,SAAgB,UAAU,EACxB,aACA,YACA,YACA,cACA,gBACiB;CACjB,MAAM,EAAE,SAAS,QAAQ;CACzB,MAAM,CAAC,SAAS,cAAc,SAA6B,EAAE,CAAC;CAC9D,MAAM,CAAC,gBAAgB,qBAAqB,SAA+B,EAAE,CAAC;CAC9E,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;AAE5C,iBAAgB;AACd,MAAI,cAAc,gBAAgB,aAChC,SAAQ,IACN,aAAa,IAAI,OAAO,YAAY;AAGlC,UAAO;IAAE,MAFI,aAAa,IAAI,QAAQ,IAAI;IAE3B,MAAM;IAAS,SADpB,MAAM,eAAe,QAAQ;IACG;IAC1C,CACH,CACE,MAAM,QAAQ;AACb,qBAAkB,IAAI;AACtB,cAAW,MAAM;AAEjB,OAAI,YAAY;IACd,MAAM,SAAS,IAAI,KAAK,OAAO;KAC7B,SAAS,EAAE;KACX,MAAM,EAAE;KACR,SAAS,EAAE;KACZ,EAAE;AACH,YAAQ,OAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG,KAAK;;AAG9D,oBAAiB,MAAM,EAAE,IAAI;IAC7B,CACD,OAAO,QAAQ;AACd,qBAAkB,CAChB;IACE,MAAM;IACN,MAAM;IACN,SAAS,CACP;KACE,IAAI;KACJ,OAAO;KACP,QAAQ;KACR,SAAS,WAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;KACrE,CACF;IACF,CACF,CAAC;AACF,cAAW,MAAM;AACjB,oBAAiB,MAAM,EAAE,IAAI;IAC7B;MAEJ,gBAAe,YAAY,CACxB,MAAM,MAAM;AACX,cAAW,EAAE;AACb,cAAW,MAAM;AAEjB,OAAI,WACF,SAAQ,OAAO,MAAM,KAAK,UAAU,GAAG,MAAM,EAAE,GAAG,KAAK;AAGzD,oBAAiB,MAAM,EAAE,IAAI;IAC7B,CACD,OAAO,QAAQ;AACd,cAAW,CACT;IACE,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,WAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACrE,CACF,CAAC;AACF,cAAW,MAAM;AACjB,oBAAiB,MAAM,EAAE,IAAI;IAC7B;IAGL,EAAE,CAAC;AAEN,KAAI,QACF,QACE,sBAAA,cAAC,KAAD;EAAK,eAAc;EAAS,SAAS;EAS/B,EARJ,sBAAA,cAAC,QAAA,KAAS,EACV,sBAAA,cAAC,MAAA,MACC,sBAAA,cAAC,MAAD,EAAM,OAAM,SAEL,EADL,sBAAA,cAAC,SAAD,EAAS,MAAK,QAAS,CAAA,CAClB,EAAC,KAAI,+BAEX,aAAa,WAAW,cAAc,OAAO,aAAa,IAAG,MACzD,CACH;AAIV,KAAI,WAAY,QAAO;AAGvB,KAAI,cAAc,eAAe,SAAS,GAAG;EAC3C,MAAM,aAAa,eAAe,SAAS,MAAM,EAAE,QAAQ;AAE3D,SACE,sBAAA,cAAC,KAAD;GAAK,eAAc;GAAS,SAAS;GAiB/B,EAhBJ,sBAAA,cAAC,QAAA,KAAS,EACV,sBAAA,cAAC,MAAD,EAAM,MAAA,MAAoC,EAA/B,2BAA+B,EAEzC,eAAe,KAAK,QACnB,sBAAA,cAAC,KAAD;GAAK,KAAK,IAAI;GAAM,eAAc;GAAS,WAAW;GAKhD,EAJJ,sBAAA,cAAC,MAAD;GAAM,MAAA;GAAK,OAAM;GAEV,EADJ,UAAU,IAAI,KAAK,CACf,EACP,sBAAA,cAAC,iBAAD,EAAiB,SAAS,IAAI,SAAW,CAAA,CACrC,CACN,EAEF,sBAAA,cAAC,KAAD,EAAK,WAAW,GAEV,EADJ,sBAAA,cAAC,MAAD,EAAM,UAAA,MAAgC,EAAtB,IAAI,OAAO,GAAG,CAAQ,CAClC,EACN,sBAAA,cAAC,oBAAD,EAAoB,SAAS,YAAc,CAAA,CACvC;;AAKV,QACE,sBAAA,cAAC,KAAD;EAAK,eAAc;EAAS,SAAS;EAa/B,EAZJ,sBAAA,cAAC,QAAA,KAAS,EACV,sBAAA,cAAC,MAAD,EAAM,MAAA,MAAmC,EAA9B,0BAA8B,EACzC,sBAAA,cAAC,KAAD;EAAK,eAAc;EAAS,WAAW;EAEjC,EADJ,sBAAA,cAAC,iBAAD,EAA0B,SAAW,CAAA,CACjC,EAEN,sBAAA,cAAC,KAAD,EAAK,WAAW,GAEV,EADJ,sBAAA,cAAC,MAAD,EAAM,UAAA,MAAgC,EAAtB,IAAI,OAAO,GAAG,CAAQ,CAClC,EACN,sBAAA,cAAC,KAAD,EAAK,WAAW,GAEV,EADJ,sBAAA,cAAC,oBAAD,EAA6B,SAAW,CAAA,CACpC,CACF"}
1
+ {"version":3,"file":"DoctorApp-DGRU6kEv.js","names":[],"sources":["../src/commands/doctor.ts","../src/components/DoctorApp.tsx"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nimport { detectProject, detectPackageManager } from 'sickbay-core';\n\n/**\n * This module defines a set of diagnostic checks that can be run against a JavaScript/TypeScript project to identify common issues and best practice violations. Each check returns a DiagnosticResult indicating whether the check passed, failed, or has warnings, along with messages and potential fixes. The runDiagnostics function executes all checks and aggregates their results for reporting.\n */\n\nexport interface DiagnosticResult {\n id: string;\n label: string;\n status: 'pass' | 'fail' | 'warn';\n message: string;\n fixCommand?: string;\n fixDescription?: string;\n}\n\ntype DiagnosticCheck = (projectPath: string) => Promise<DiagnosticResult>;\n\nasync function checkGitignore(projectPath: string): Promise<DiagnosticResult> {\n const gitignorePath = join(projectPath, '.gitignore');\n if (!existsSync(gitignorePath)) {\n return {\n id: 'gitignore',\n label: '.gitignore exists',\n status: 'fail',\n message: 'No .gitignore found',\n fixDescription: 'Create .gitignore with standard entries',\n };\n }\n const content = readFileSync(gitignorePath, 'utf-8');\n const lines = content.split('\\n').map((l) => l.trim());\n const required = ['node_modules', '.env', 'dist', '.DS_Store'];\n const missing = required.filter((entry) => !lines.includes(entry));\n if (missing.length > 0) {\n return {\n id: 'gitignore',\n label: '.gitignore entries',\n status: 'warn',\n message: `Missing entries: ${missing.join(', ')}`,\n fixDescription: `Add ${missing.join(', ')} to .gitignore`,\n };\n }\n return {\n id: 'gitignore',\n label: '.gitignore entries',\n status: 'pass',\n message: 'All standard entries present',\n };\n}\n\nasync function checkEnginesField(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n if (!pkg.engines) {\n return {\n id: 'engines',\n label: 'package.json engines field',\n status: 'warn',\n message: 'No engines field — Node.js version not specified',\n fixDescription: 'Add \"engines\": { \"node\": \">=18.0.0\" } to package.json',\n };\n }\n return {\n id: 'engines',\n label: 'package.json engines field',\n status: 'pass',\n message: `node ${pkg.engines.node ?? 'unspecified'}`,\n };\n}\n\nasync function checkBrowserslist(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n const hasFile =\n existsSync(join(projectPath, '.browserslistrc')) ||\n existsSync(join(projectPath, 'browserslist'));\n const hasField = !!pkg.browserslist;\n if (!hasFile && !hasField) {\n return {\n id: 'browserslist',\n label: 'Browserslist config',\n status: 'warn',\n message: 'No browserslist config — browser targets not defined',\n fixDescription: 'Create .browserslistrc with default targets',\n };\n }\n return {\n id: 'browserslist',\n label: 'Browserslist config',\n status: 'pass',\n message: 'Browserslist configured',\n };\n}\n\nasync function checkNodeVersion(projectPath: string): Promise<DiagnosticResult> {\n const hasNvmrc = existsSync(join(projectPath, '.nvmrc'));\n const hasNodeVersion = existsSync(join(projectPath, '.node-version'));\n const hasToolVersions = existsSync(join(projectPath, '.tool-versions'));\n if (!hasNvmrc && !hasNodeVersion && !hasToolVersions) {\n return {\n id: 'node-version',\n label: 'Node version pinning',\n status: 'warn',\n message: 'No .nvmrc or .node-version — Node version not pinned',\n fixDescription: 'Create .nvmrc with current Node version',\n };\n }\n return {\n id: 'node-version',\n label: 'Node version pinning',\n status: 'pass',\n message: hasNvmrc\n ? '.nvmrc found'\n : hasNodeVersion\n ? '.node-version found'\n : '.tool-versions found',\n };\n}\n\nasync function checkNpmScripts(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n const scripts = pkg.scripts ?? {};\n const expected = ['lint', 'test', 'build'];\n const missing = expected.filter((s) => !scripts[s]);\n if (missing.length > 0) {\n return {\n id: 'npm-scripts',\n label: 'Essential npm scripts',\n status: missing.includes('build') || missing.includes('test') ? 'fail' : 'warn',\n message: `Missing scripts: ${missing.join(', ')}`,\n fixDescription: `Add ${missing.join(', ')} scripts to package.json`,\n };\n }\n return {\n id: 'npm-scripts',\n label: 'Essential npm scripts',\n status: 'pass',\n message: 'lint, test, build all defined',\n };\n}\n\nasync function checkLockfile(projectPath: string): Promise<DiagnosticResult> {\n const hasNpmLock = existsSync(join(projectPath, 'package-lock.json'));\n const hasPnpmLock = existsSync(join(projectPath, 'pnpm-lock.yaml'));\n const hasYarnLock = existsSync(join(projectPath, 'yarn.lock'));\n const hasBunLock =\n existsSync(join(projectPath, 'bun.lockb')) || existsSync(join(projectPath, 'bun.lock'));\n if (!hasNpmLock && !hasPnpmLock && !hasYarnLock && !hasBunLock) {\n return {\n id: 'lockfile',\n label: 'Lockfile present',\n status: 'fail',\n message: 'No lockfile found — dependencies not pinned',\n fixCommand: 'npm install',\n fixDescription: 'Generate lockfile with npm install',\n };\n }\n const lockfileNames: Record<string, string> = {\n pnpm: 'pnpm-lock.yaml',\n yarn: 'yarn.lock',\n bun: 'bun.lockb',\n npm: 'package-lock.json',\n };\n return {\n id: 'lockfile',\n label: 'Lockfile present',\n status: 'pass',\n message: lockfileNames[detectPackageManager(projectPath)],\n };\n}\n\nasync function checkEditorconfig(projectPath: string): Promise<DiagnosticResult> {\n if (!existsSync(join(projectPath, '.editorconfig'))) {\n return {\n id: 'editorconfig',\n label: '.editorconfig',\n status: 'warn',\n message: 'No .editorconfig — editor settings not standardized',\n fixDescription: 'Create .editorconfig with standard settings',\n };\n }\n return {\n id: 'editorconfig',\n label: '.editorconfig',\n status: 'pass',\n message: '.editorconfig found',\n };\n}\n\nasync function checkPrettier(projectPath: string): Promise<DiagnosticResult> {\n const info = await detectProject(projectPath);\n if (!info.hasPrettier) {\n return {\n id: 'prettier',\n label: 'Prettier config',\n status: 'warn',\n message: 'No Prettier configured — code formatting not standardized',\n fixCommand: 'npm install -D prettier',\n fixDescription: 'Install prettier and create .prettierrc',\n };\n }\n return {\n id: 'prettier',\n label: 'Prettier config',\n status: 'pass',\n message: 'Prettier configured',\n };\n}\n\nasync function checkESLintConfig(projectPath: string): Promise<DiagnosticResult> {\n const info = await detectProject(projectPath);\n if (!info.hasESLint) {\n return {\n id: 'eslint-config',\n label: 'ESLint config',\n status: 'fail',\n message: 'No ESLint configured — no lint rules enforced',\n fixCommand: 'npm init @eslint/config',\n fixDescription: 'Initialize ESLint configuration',\n };\n }\n return {\n id: 'eslint-config',\n label: 'ESLint config',\n status: 'pass',\n message: 'ESLint configured',\n };\n}\n\nasync function checkTsconfig(projectPath: string): Promise<DiagnosticResult> {\n const info = await detectProject(projectPath);\n const hasTsconfig = existsSync(join(projectPath, 'tsconfig.json'));\n if (info.hasTypeScript && !hasTsconfig) {\n return {\n id: 'tsconfig',\n label: 'TypeScript config',\n status: 'fail',\n message: 'TypeScript deps found but no tsconfig.json',\n fixCommand: 'npx tsc --init',\n fixDescription: 'Generate tsconfig.json',\n };\n }\n if (!info.hasTypeScript) {\n return {\n id: 'tsconfig',\n label: 'TypeScript',\n status: 'warn',\n message: 'TypeScript not in use (consider adopting)',\n };\n }\n return {\n id: 'tsconfig',\n label: 'TypeScript config',\n status: 'pass',\n message: 'tsconfig.json found',\n };\n}\n\nasync function checkEnvExample(projectPath: string): Promise<DiagnosticResult> {\n const hasEnv = existsSync(join(projectPath, '.env'));\n const hasExample =\n existsSync(join(projectPath, '.env.example')) ||\n existsSync(join(projectPath, '.env.template')) ||\n existsSync(join(projectPath, '.env.sample'));\n if (hasEnv && !hasExample) {\n return {\n id: 'env-example',\n label: '.env.example',\n status: 'warn',\n message: \".env exists but no .env.example — team members won't know required vars\",\n fixDescription: 'Create .env.example with variable names (no values)',\n };\n }\n if (!hasEnv) {\n return {\n id: 'env-example',\n label: '.env.example',\n status: 'pass',\n message: 'No .env file (not applicable)',\n };\n }\n return {\n id: 'env-example',\n label: '.env.example',\n status: 'pass',\n message: '.env.example exists',\n };\n}\n\nasync function checkReactVersions(projectPath: string): Promise<DiagnosticResult> {\n const pkg = JSON.parse(readFileSync(join(projectPath, 'package.json'), 'utf-8'));\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n const react = deps['react'];\n const reactDom = deps['react-dom'];\n\n if (!react) {\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'pass',\n message: 'Not a React project',\n };\n }\n if (!reactDom) {\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'warn',\n message: 'react installed but react-dom missing',\n fixCommand: `npm install react-dom@${react}`,\n fixDescription: 'Install react-dom matching react version',\n };\n }\n if (react !== reactDom) {\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'fail',\n message: `react@${react} and react-dom@${reactDom} version mismatch`,\n fixCommand: `npm install react-dom@${react}`,\n fixDescription: 'Align react-dom version with react',\n };\n }\n return {\n id: 'react-versions',\n label: 'React version consistency',\n status: 'pass',\n message: `react and react-dom both at ${react}`,\n };\n}\n\nconst ALL_DIAGNOSTICS: DiagnosticCheck[] = [\n checkGitignore,\n checkEnginesField,\n checkBrowserslist,\n checkNodeVersion,\n checkNpmScripts,\n checkLockfile,\n checkEditorconfig,\n checkPrettier,\n checkESLintConfig,\n checkTsconfig,\n checkEnvExample,\n checkReactVersions,\n];\n\nexport async function runDiagnostics(projectPath: string): Promise<DiagnosticResult[]> {\n const results: DiagnosticResult[] = [];\n for (const check of ALL_DIAGNOSTICS) {\n try {\n results.push(await check(projectPath));\n } catch (err) {\n results.push({\n id: 'unknown',\n label: 'Unknown check',\n status: 'fail',\n message: `Check failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n return results;\n}\n","import React, { useState, useEffect } from 'react';\n\nimport { Box, Text, useApp } from 'ink';\nimport Spinner from 'ink-spinner';\n\nimport { runDiagnostics, type DiagnosticResult } from '../commands/doctor.js';\nimport { shortName } from '../lib/resolve-package.js';\nimport { Header } from './Header.js';\n\ninterface DoctorAppProps {\n projectPath: string;\n autoFix: boolean;\n jsonOutput: boolean;\n isMonorepo?: boolean;\n packagePaths?: string[];\n packageNames?: Map<string, string>;\n}\n\ninterface PackageDiagnostics {\n name: string;\n path: string;\n results: DiagnosticResult[];\n}\n\nconst STATUS_CONFIG = {\n pass: { icon: '✓', color: 'green' as const },\n fail: { icon: '✗', color: 'red' as const },\n warn: { icon: '⚠', color: 'yellow' as const },\n};\n\nfunction DiagnosticsList({ results }: { results: DiagnosticResult[] }) {\n return (\n <Box flexDirection=\"column\" marginLeft={2}>\n {results.map((r) => {\n const { icon, color } = STATUS_CONFIG[r.status];\n return (\n <Box key={r.id} flexDirection=\"column\">\n <Box>\n <Text color={color}>{icon} </Text>\n <Text bold={r.status !== 'pass'}>{r.label}</Text>\n <Text dimColor> — {r.message}</Text>\n </Box>\n {r.status !== 'pass' && r.fixCommand && (\n <Box marginLeft={4}>\n <Text dimColor>fix: </Text>\n <Text color=\"cyan\">{r.fixCommand}</Text>\n </Box>\n )}\n {r.status !== 'pass' && !r.fixCommand && r.fixDescription && (\n <Box marginLeft={4}>\n <Text dimColor>→ {r.fixDescription}</Text>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n}\n\nfunction DiagnosticsSummary({ results }: { results: DiagnosticResult[] }) {\n const passed = results.filter((r) => r.status === 'pass').length;\n const warned = results.filter((r) => r.status === 'warn').length;\n const failed = results.filter((r) => r.status === 'fail').length;\n\n return (\n <Box>\n <Text color=\"green\"> ✓ {passed} passed</Text>\n <Text color=\"yellow\"> ⚠ {warned} warnings</Text>\n <Text color=\"red\"> ✗ {failed} failed</Text>\n <Text dimColor> ({results.length} checks)</Text>\n </Box>\n );\n}\n\nexport function DoctorApp({\n projectPath,\n jsonOutput,\n isMonorepo,\n packagePaths,\n packageNames,\n}: DoctorAppProps) {\n const { exit } = useApp();\n const [results, setResults] = useState<DiagnosticResult[]>([]);\n const [packageResults, setPackageResults] = useState<PackageDiagnostics[]>([]);\n const [running, setRunning] = useState(true);\n\n useEffect(() => {\n if (isMonorepo && packagePaths && packageNames) {\n Promise.all(\n packagePaths.map(async (pkgPath) => {\n const name = packageNames.get(pkgPath) ?? pkgPath;\n const r = await runDiagnostics(pkgPath);\n return { name, path: pkgPath, results: r };\n }),\n )\n .then((all) => {\n setPackageResults(all);\n setRunning(false);\n\n if (jsonOutput) {\n const output = all.map((p) => ({\n package: p.name,\n path: p.path,\n results: p.results,\n }));\n process.stdout.write(JSON.stringify(output, null, 2) + '\\n');\n }\n\n setTimeout(() => exit(), 100);\n })\n .catch((err) => {\n setPackageResults([\n {\n name: 'error',\n path: projectPath,\n results: [\n {\n id: 'error',\n label: 'Doctor',\n status: 'fail',\n message: `Failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n },\n ]);\n setRunning(false);\n setTimeout(() => exit(), 100);\n });\n } else {\n runDiagnostics(projectPath)\n .then((r) => {\n setResults(r);\n setRunning(false);\n\n if (jsonOutput) {\n process.stdout.write(JSON.stringify(r, null, 2) + '\\n');\n }\n\n setTimeout(() => exit(), 100);\n })\n .catch((err) => {\n setResults([\n {\n id: 'error',\n label: 'Doctor',\n status: 'fail',\n message: `Failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ]);\n setRunning(false);\n setTimeout(() => exit(), 100);\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n if (running) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n Running project diagnostics\n {isMonorepo ? ` across ${packagePaths?.length} packages` : ''}...\n </Text>\n </Box>\n );\n }\n\n if (jsonOutput) return null;\n\n // Monorepo: show per-package results\n if (isMonorepo && packageResults.length > 0) {\n const allResults = packageResults.flatMap((p) => p.results);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text bold>Monorepo Setup Diagnosis</Text>\n\n {packageResults.map((pkg) => (\n <Box key={pkg.path} flexDirection=\"column\" marginTop={1}>\n <Text bold color=\"cyan\">\n {shortName(pkg.name)}\n </Text>\n <DiagnosticsList results={pkg.results} />\n </Box>\n ))}\n\n <Box marginTop={1}>\n <Text dimColor>{'━'.repeat(52)}</Text>\n </Box>\n <DiagnosticsSummary results={allResults} />\n </Box>\n );\n }\n\n // Single project\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text bold>Project Setup Diagnosis</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n <DiagnosticsList results={results} />\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>{'━'.repeat(52)}</Text>\n </Box>\n <Box marginTop={1}>\n <DiagnosticsSummary results={results} />\n </Box>\n </Box>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { u as runSickbay } from "./dist-Bjhxbcak.js";
1
+ import { u as runSickbay } from "./dist-CHT6_2R4.js";
2
2
  import { n as ProgressList, r as Header } from "./index.js";
3
- import { shortName } from "./resolve-package-DS27JBhN.js";
3
+ import { shortName } from "./resolve-package-DOgU3aGV.js";
4
4
  import React, { useCallback, useEffect, useState } from "react";
5
5
  import { Box, Text, useApp, useInput } from "ink";
6
6
  import Spinner from "ink-spinner";
@@ -395,4 +395,4 @@ function FixApp({ projectPath, checks, applyAll, dryRun, skipGitCheck, verbose,
395
395
  //#endregion
396
396
  export { FixApp };
397
397
 
398
- //# sourceMappingURL=FixApp-CFotJ2y8.js.map
398
+ //# sourceMappingURL=FixApp-XMR6MFXY.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FixApp-CFotJ2y8.js","names":[],"sources":["../src/commands/fix.ts","../src/components/FixApp.tsx"],"sourcesContent":["import { execFile } from 'child_process';\nimport { promisify } from 'util';\n\nimport type { Issue, SickbayReport } from 'sickbay-core';\n\n/**\n * This module provides functions to collect fixable issues from a Sickbay report and execute the associated fix commands.\n * The collectFixableIssues function scans through the checks and their issues to find those that have a fix command,\n * while ensuring that duplicate commands are not included. The executeFix function runs the specified command in the context of the project directory,\n * capturing the output and any errors that may occur during execution. This allows for an automated way to address issues found in the health checks.\n */\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Check whether the project's git working tree is clean before applying\n * source-modifying fixes. A dirty tree mixed with Sickbay's own edits means\n * `git checkout` or `git stash` can no longer cleanly revert the bot's work\n * if a fix goes wrong.\n *\n * Returns `clean: true` when there's genuinely nothing to report AND when\n * git is unavailable (no repo, git not installed, permission denied) — the\n * check is advisory, not a hard gate on non-git projects.\n */\nexport async function checkGitCleanliness(\n projectPath: string,\n): Promise<{ clean: boolean; changedFiles: number }> {\n try {\n const { stdout } = await execFileAsync('git', ['status', '--porcelain'], {\n cwd: projectPath,\n timeout: 10_000,\n });\n const lines = stdout.split('\\n').filter((l) => l.trim().length > 0);\n return { clean: lines.length === 0, changedFiles: lines.length };\n } catch {\n // Not a git repo, git not installed, or command failed. Treat as clean\n // so we never block a user who chose not to version-control their project.\n return { clean: true, changedFiles: 0 };\n }\n}\n\nexport function hasSourceModifyingFixes(issues: FixableIssue[]): boolean {\n return issues.some((f) => f.issue.fix?.modifiesSource === true);\n}\n\nexport interface FixableIssue {\n issue: Issue;\n checkId: string;\n checkName: string;\n command?: string;\n}\n\nexport interface FixResult {\n fixable: FixableIssue;\n success: boolean;\n stdout: string;\n stderr: string;\n duration: number;\n}\n\nexport function collectFixableIssues(report: SickbayReport): FixableIssue[] {\n const seen = new Set<string>();\n const fixable: FixableIssue[] = [];\n\n for (const check of report.checks) {\n for (const issue of check.issues) {\n if (issue.fix) {\n const dedupeKey = issue.fix.command ?? issue.fix.description;\n if (!seen.has(dedupeKey)) {\n seen.add(dedupeKey);\n fixable.push({\n issue,\n checkId: check.id,\n checkName: check.name,\n command: issue.fix.command,\n });\n }\n }\n }\n }\n\n const order = { critical: 0, warning: 1, info: 2 };\n fixable.sort((a, b) => order[a.issue.severity] - order[b.issue.severity]);\n\n return fixable;\n}\n\nexport async function executeFix(fix: FixableIssue, projectPath: string): Promise<FixResult> {\n const start = Date.now();\n if (!fix.command) {\n return {\n fixable: fix,\n success: false,\n stdout: '',\n stderr: 'No command to execute (guidance-only fix)',\n duration: 0,\n };\n }\n try {\n const parts = fix.command.split(/\\s+/);\n const cmd = parts[0];\n const args = parts.slice(1);\n // SECURITY: shell is intentionally NOT enabled. Running with `shell: true`\n // would pass cmd+args through `/bin/sh -c`, making any shell metacharacter\n // in `fix.command` (e.g. `;`, `|`, `$()`, backticks) injectable. Today these\n // commands come from internal runner constants, but this is the trust\n // boundary that protects future runners from accidental command injection.\n const { stdout, stderr } = await execFileAsync(cmd, args, {\n cwd: projectPath,\n timeout: 60_000,\n });\n return {\n fixable: fix,\n success: true,\n stdout: stdout ?? '',\n stderr: stderr ?? '',\n duration: Date.now() - start,\n };\n } catch (err) {\n return {\n fixable: fix,\n success: false,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n duration: Date.now() - start,\n };\n }\n}\n","import React, { useState, useEffect, useCallback } from 'react';\n\nimport { Box, Text, useApp, useInput } from 'ink';\nimport Spinner from 'ink-spinner';\nimport { runSickbay } from 'sickbay-core';\n\nimport {\n checkGitCleanliness,\n collectFixableIssues,\n executeFix,\n type FixableIssue,\n type FixResult,\n} from '../commands/fix.js';\nimport { shortName } from '../lib/resolve-package.js';\nimport { Header } from './Header.js';\nimport { ProgressList } from './ProgressList.js';\n\ninterface FixAppProps {\n projectPath: string;\n checks?: string[];\n applyAll: boolean;\n dryRun: boolean;\n skipGitCheck: boolean;\n verbose: boolean;\n isMonorepo?: boolean;\n packagePaths?: string[];\n packageNames?: Map<string, string>;\n}\n\ntype Phase = 'scanning' | 'git-warning' | 'selecting' | 'confirming' | 'fixing' | 'done' | 'error';\n\ninterface ProgressItem {\n name: string;\n status: 'pending' | 'running' | 'done';\n}\n\ninterface MonorepoFixableIssue extends FixableIssue {\n packageName: string;\n packagePath: string;\n}\n\nconst SEVERITY_COLOR = {\n critical: 'red' as const,\n warning: 'yellow' as const,\n info: 'gray' as const,\n};\n\nexport function FixApp({\n projectPath,\n checks,\n applyAll,\n dryRun,\n skipGitCheck,\n verbose,\n isMonorepo,\n packagePaths,\n packageNames,\n}: FixAppProps) {\n const { exit } = useApp();\n const [phase, setPhase] = useState<Phase>('scanning');\n const [fixableIssues, setFixableIssues] = useState<MonorepoFixableIssue[]>([]);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n const [cursor, setCursor] = useState(0);\n const [results, setResults] = useState<FixResult[]>([]);\n const [currentFixIndex, setCurrentFixIndex] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [progress, setProgress] = useState<ProgressItem[]>([]);\n const [projectName, setProjectName] = useState<string | undefined>();\n\n // Git-cleanliness preflight state — populated before confirming tier-2 fixes\n const [gitChangedFiles, setGitChangedFiles] = useState(0);\n\n // Confirmation state\n const [confirmQueue, setConfirmQueue] = useState<MonorepoFixableIssue[]>([]);\n const [confirmIndex, setConfirmIndex] = useState(0);\n const [confirmedFixes, setConfirmedFixes] = useState<MonorepoFixableIssue[]>([]);\n\n // Route decision after scan. Extracted so the git-warning phase can\n // resume the flow when the user accepts the warning.\n const proceedAfterScan = useCallback(\n (tagged: MonorepoFixableIssue[]) => {\n const hasActionable = tagged.some((f) => f.command);\n if (!hasActionable) {\n setPhase('done');\n return;\n }\n if (applyAll) {\n setSelected(new Set(tagged.map((_, i) => i)));\n startConfirmation(tagged, new Set(tagged.map((_, i) => i)), true);\n } else {\n setPhase('selecting');\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [applyAll],\n );\n\n // Post-scan routing. If any fix will modify source files and the tree\n // is dirty, pause for an explicit go-ahead so the user isn't mixing\n // their own uncommitted work with Sickbay's edits — that state is not\n // cleanly revertable with `git checkout` or `git stash`.\n const onScanComplete = useCallback(\n async (tagged: MonorepoFixableIssue[]) => {\n const hasTier2 = tagged.some((f) => f.issue.fix?.modifiesSource === true);\n if (hasTier2 && !skipGitCheck) {\n const status = await checkGitCleanliness(projectPath);\n if (!status.clean) {\n setGitChangedFiles(status.changedFiles);\n setPhase('git-warning');\n return;\n }\n }\n proceedAfterScan(tagged);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [projectPath, skipGitCheck, proceedAfterScan],\n );\n\n // Phase 1: Run scan\n useEffect(() => {\n if (isMonorepo && packagePaths && packageNames) {\n // Monorepo: scan each package\n const pkgItems = packagePaths.map((p) => ({\n name: shortName(packageNames.get(p) ?? p),\n status: 'pending' as const,\n }));\n setProgress(pkgItems);\n\n (async () => {\n try {\n const allFixable: MonorepoFixableIssue[] = [];\n\n for (const pkgPath of packagePaths) {\n const pkgName = packageNames.get(pkgPath) ?? pkgPath;\n const display = shortName(pkgName);\n\n setProgress((prev) =>\n prev.map((p) => (p.name === display ? { ...p, status: 'running' } : p)),\n );\n\n const report = await runSickbay({\n projectPath: pkgPath,\n checks,\n verbose,\n });\n\n const fixable = collectFixableIssues(report);\n for (const fix of fixable) {\n allFixable.push({\n ...fix,\n packageName: pkgName,\n packagePath: pkgPath,\n });\n }\n\n setProgress((prev) =>\n prev.map((p) => (p.name === display ? { ...p, status: 'done' } : p)),\n );\n }\n\n setFixableIssues(allFixable);\n await onScanComplete(allFixable);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setPhase('error');\n setTimeout(() => exit(), 100);\n }\n })();\n } else {\n // Single project scan\n const initial: ProgressItem[] = (\n checks ?? [\n 'knip',\n 'depcheck',\n 'npm-check-updates',\n 'npm-audit',\n 'madge',\n 'source-map-explorer',\n 'coverage',\n 'license-checker',\n 'jscpd',\n 'git',\n 'eslint',\n 'typescript',\n 'todo-scanner',\n 'complexity',\n 'secrets',\n 'heavy-deps',\n 'react-perf',\n 'asset-size',\n ]\n ).map((name) => ({ name, status: 'pending' as const }));\n setProgress(initial);\n\n runSickbay({\n projectPath,\n checks,\n verbose,\n onCheckStart: (name) => {\n setProgress((prev) =>\n prev.map((p) => (p.name === name ? { ...p, status: 'running' } : p)),\n );\n },\n onCheckComplete: (result) => {\n setProgress((prev) =>\n prev.map((p) => (p.name === result.id ? { ...p, status: 'done' } : p)),\n );\n },\n })\n .then((r) => {\n setProjectName(r.projectInfo.name);\n const fixable = collectFixableIssues(r);\n const tagged = fixable.map((f) => ({\n ...f,\n packageName: r.projectInfo.name,\n packagePath: projectPath,\n }));\n setFixableIssues(tagged);\n return onScanComplete(tagged);\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : String(err));\n setPhase('error');\n setTimeout(() => exit(), 100);\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Start confirmation flow for selected actionable fixes\n function startConfirmation(\n issues: MonorepoFixableIssue[],\n selectedSet: Set<number>,\n isApplyAll: boolean,\n ) {\n // Only actionable fixes (with command) need confirmation\n const actionable = issues.filter((f, i) => selectedSet.has(i) && f.command);\n\n if (isApplyAll) {\n // --apply-all: skip tier-1, but still confirm tier-2 (modifiesSource)\n const tier2 = actionable.filter((f) => f.issue.fix?.modifiesSource);\n const autoApproved = actionable.filter((f) => !f.issue.fix?.modifiesSource);\n if (tier2.length === 0) {\n // No tier-2 confirms needed, go straight to fixing\n setConfirmedFixes(autoApproved);\n setPhase('fixing');\n return;\n }\n setConfirmedFixes(autoApproved);\n setConfirmQueue(tier2);\n } else {\n setConfirmedFixes([]);\n setConfirmQueue(actionable);\n }\n setConfirmIndex(0);\n\n if (actionable.length === 0) {\n // All selected are guidance-only\n setPhase('done');\n setTimeout(() => exit(), 100);\n return;\n }\n\n setPhase('confirming');\n }\n\n // Phase 3: Execute fixes\n useEffect(() => {\n if (phase !== 'fixing') return;\n\n const toFix = confirmedFixes;\n if (toFix.length === 0) {\n setPhase('done');\n setTimeout(() => exit(), 100);\n return;\n }\n\n (async () => {\n const fixResults: FixResult[] = [];\n for (let i = 0; i < toFix.length; i++) {\n setCurrentFixIndex(i);\n if (dryRun) {\n fixResults.push({\n fixable: toFix[i],\n success: true,\n stdout: '(dry run)',\n stderr: '',\n duration: 0,\n });\n } else {\n const result = await executeFix(toFix[i], toFix[i].packagePath);\n fixResults.push(result);\n }\n setResults([...fixResults]);\n }\n setPhase('done');\n setTimeout(() => exit(), 100);\n })();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [phase]);\n\n // Handle keyboard input during selection and confirmation phases\n const handleInput = useCallback(\n (input: string, key: { upArrow: boolean; downArrow: boolean; return: boolean }) => {\n if (phase === 'git-warning') {\n const lower = input.toLowerCase();\n if (lower === 'y' || key.return) {\n // User acknowledges dirty tree — continue with selection/confirmation flow\n proceedAfterScan(fixableIssues);\n } else if (lower === 'n') {\n setPhase('done');\n setTimeout(() => exit(), 100);\n }\n return;\n }\n if (phase === 'selecting') {\n const actionable = fixableIssues.filter((f) => f.command);\n\n if (key.upArrow) {\n setCursor((c) => Math.max(0, c - 1));\n } else if (key.downArrow) {\n setCursor((c) => Math.min(actionable.length - 1, c + 1));\n } else if (input === ' ') {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(cursor)) {\n next.delete(cursor);\n } else {\n next.add(cursor);\n }\n return next;\n });\n } else if (input === 'a') {\n setSelected(new Set(actionable.map((_, i) => i)));\n } else if (input === 'n') {\n setSelected(new Set());\n } else if (key.return) {\n if (selected.size > 0) {\n // Map selected indices back to the actionable items\n const selectedIssues = actionable.filter((_, i) => selected.has(i));\n startConfirmation(selectedIssues, new Set(selectedIssues.map((_, i) => i)), false);\n }\n }\n } else if (phase === 'confirming') {\n const lower = input.toLowerCase();\n if (lower === 'y' || key.return) {\n // Confirm current fix\n setConfirmedFixes((prev) => [...prev, confirmQueue[confirmIndex]]);\n if (confirmIndex + 1 < confirmQueue.length) {\n setConfirmIndex((i) => i + 1);\n } else {\n setPhase('fixing');\n }\n } else if (lower === 'n') {\n // Skip current fix\n if (confirmIndex + 1 < confirmQueue.length) {\n setConfirmIndex((i) => i + 1);\n } else {\n setPhase('fixing');\n }\n }\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [phase, cursor, selected, confirmIndex, confirmQueue, fixableIssues, proceedAfterScan],\n );\n\n useInput(handleInput);\n\n const currentConfirmFix = confirmQueue[confirmIndex];\n const isTier2 = currentConfirmFix?.issue.fix?.modifiesSource;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header projectName={projectName} />\n\n {/* Scanning phase */}\n {phase === 'scanning' && (\n <Box flexDirection=\"column\">\n <Text dimColor>\n Scanning for fixable issues\n {isMonorepo ? ` across ${packagePaths?.length} packages` : ''}...\n </Text>\n <Box marginTop={1} marginLeft={2}>\n <ProgressList items={progress} />\n </Box>\n </Box>\n )}\n\n {/* Error phase */}\n {phase === 'error' && (\n <Box>\n <Text color=\"red\">✗ Error: {error}</Text>\n </Box>\n )}\n\n {/* Git-cleanliness warning phase */}\n {phase === 'git-warning' && (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text color=\"yellow\" bold>\n ⚠ Uncommitted changes detected\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text>\n Your working tree has {gitChangedFiles} changed file\n {gitChangedFiles === 1 ? '' : 's'}. Some fixes will modify source code.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>\n If a fix goes wrong, mixing Sickbay's edits with your own uncommitted work makes it\n hard to revert cleanly with <Text color=\"cyan\">git checkout</Text> or{' '}\n <Text color=\"cyan\">git stash</Text>.\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text>Commit or stash first, then re-run. Proceed anyway? (y/N)</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n (Pass <Text color=\"cyan\">--skip-git-check</Text> to suppress this prompt, e.g. in\n CI.)\n </Text>\n </Box>\n </Box>\n </Box>\n )}\n\n {/* Selection phase */}\n {phase === 'selecting' &&\n (() => {\n const actionable = fixableIssues.filter((f) => f.command);\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text color=\"yellow\">⚠ </Text>\n <Text dimColor>\n Sickbay can make mistakes. Review each fix before applying — false positives exist\n and some commands modify your project.\n </Text>\n </Box>\n <Text bold>Select fixes to apply ({actionable.length} available)</Text>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {actionable.map((fix, i) => (\n <Box key={`${fix.packageName}-${fix.checkId}-${fix.command}`}>\n <Text color={i === cursor ? 'cyan' : undefined}>\n {i === cursor ? '❯ ' : ' '}\n </Text>\n <Text color={i === cursor ? 'cyan' : undefined}>\n {selected.has(i) ? '[✓] ' : '[ ] '}\n </Text>\n {isMonorepo && (\n <Text color=\"magenta\" dimColor>\n [{shortName(fix.packageName)}]{' '}\n </Text>\n )}\n <Text color={SEVERITY_COLOR[fix.issue.severity]}>\n {fix.issue.fix!.description}\n </Text>\n <Text dimColor> ({fix.command})</Text>\n </Box>\n ))}\n </Box>\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>\n ↑↓ navigate · space toggle · a all · n none · enter confirm\n {selected.size > 0 && ` (${selected.size} selected)`}\n </Text>\n </Box>\n {dryRun && (\n <Box marginLeft={2}>\n <Text color=\"yellow\">⚠ Dry run mode — no changes will be made</Text>\n </Box>\n )}\n </Box>\n );\n })()}\n\n {/* Confirmation phase */}\n {phase === 'confirming' && currentConfirmFix && (\n <Box flexDirection=\"column\">\n <Text bold>\n Confirming fixes ({confirmIndex + 1}/{confirmQueue.length})\n </Text>\n <Box marginTop={1} marginLeft={2} flexDirection=\"column\">\n <Text>\n {currentConfirmFix.issue.fix!.description} ({currentConfirmFix.command})\n </Text>\n {isTier2 ? (\n <Text color=\"yellow\">⚠ This will modify source files. Proceed? (Y/n)</Text>\n ) : (\n <Text dimColor>→ Proceed? (Y/n)</Text>\n )}\n </Box>\n </Box>\n )}\n\n {/* Fixing phase */}\n {phase === 'fixing' && !dryRun && (\n <Box marginBottom={1}>\n <Text color=\"yellow\">⚠ </Text>\n <Text dimColor>\n Sickbay can make mistakes — verify results afterwards and revert anything that looks\n wrong.\n </Text>\n </Box>\n )}\n {phase === 'fixing' && (\n <Box flexDirection=\"column\">\n <Text bold>\n {dryRun ? 'Dry run' : 'Applying fixes'}... ({results.length}/{confirmedFixes.length})\n </Text>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {results.map((r) => (\n <Box\n key={`${r.fixable.checkId}-${r.fixable.command ?? r.fixable.issue.fix?.description}`}\n flexDirection=\"column\"\n >\n <Box>\n <Text color={r.success ? 'green' : 'red'}>{r.success ? '✓' : '✗'} </Text>\n {isMonorepo && (\n <Text color=\"magenta\" dimColor>\n [{shortName((r.fixable as MonorepoFixableIssue).packageName)}]{' '}\n </Text>\n )}\n <Text>{r.fixable.issue.fix!.description}</Text>\n </Box>\n {r.success && r.fixable.issue.fix?.nextSteps && (\n <Box marginLeft={2}>\n <Text dimColor> → Next: {r.fixable.issue.fix.nextSteps}</Text>\n </Box>\n )}\n </Box>\n ))}\n {results.length < confirmedFixes.length && (\n <Box>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>\n <Text> {confirmedFixes[currentFixIndex]?.issue.fix!.description}</Text>\n </Box>\n )}\n </Box>\n </Box>\n )}\n\n {/* Done phase */}\n {phase === 'done' && (\n <Box flexDirection=\"column\">\n {results.length === 0 ? (\n <Box flexDirection=\"column\">\n <Box>\n <Text color=\"green\">✓ </Text>\n <Text>\n No auto-fixable issues found\n {isMonorepo ? ' across any package' : ''}\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n Run <Text color=\"cyan\">sickbay</Text> to see the full report — there may be issues\n that require manual attention.\n </Text>\n </Box>\n </Box>\n ) : (\n <>\n <Text bold>{dryRun ? 'Dry Run Results' : 'Fix Results'}</Text>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {results.map((r) => (\n <Box\n key={`${r.fixable.checkId}-${r.fixable.command ?? r.fixable.issue.fix?.description}`}\n flexDirection=\"column\"\n >\n <Box>\n <Text color={r.success ? 'green' : 'red'}>{r.success ? '✓' : '✗'} </Text>\n {isMonorepo && (\n <Text color=\"magenta\" dimColor>\n [{shortName((r.fixable as MonorepoFixableIssue).packageName)}]{' '}\n </Text>\n )}\n <Text>{r.fixable.issue.fix!.description}</Text>\n {r.duration > 0 && <Text dimColor> ({r.duration}ms)</Text>}\n </Box>\n {r.success && r.fixable.issue.fix?.nextSteps && (\n <Box marginLeft={2}>\n <Text dimColor> → Next: {r.fixable.issue.fix.nextSteps}</Text>\n </Box>\n )}\n </Box>\n ))}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>{'━'.repeat(52)}</Text>\n </Box>\n <Box marginTop={1}>\n <Text bold>\n {results.filter((r) => r.success).length}/{results.length} fixes{' '}\n {dryRun ? 'would be applied' : 'applied successfully'}\n </Text>\n </Box>\n {!dryRun && results.some((r) => r.success) && (\n <Box marginTop={1}>\n <Text dimColor>Run </Text>\n <Text color=\"cyan\">sickbay</Text>\n <Text dimColor> to see your updated score</Text>\n </Box>\n )}\n </>\n )}\n </Box>\n )}\n </Box>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FixApp-XMR6MFXY.js","names":[],"sources":["../src/commands/fix.ts","../src/components/FixApp.tsx"],"sourcesContent":["import { execFile } from 'child_process';\nimport { promisify } from 'util';\n\nimport type { Issue, SickbayReport } from 'sickbay-core';\n\n/**\n * This module provides functions to collect fixable issues from a Sickbay report and execute the associated fix commands.\n * The collectFixableIssues function scans through the checks and their issues to find those that have a fix command,\n * while ensuring that duplicate commands are not included. The executeFix function runs the specified command in the context of the project directory,\n * capturing the output and any errors that may occur during execution. This allows for an automated way to address issues found in the health checks.\n */\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Check whether the project's git working tree is clean before applying\n * source-modifying fixes. A dirty tree mixed with Sickbay's own edits means\n * `git checkout` or `git stash` can no longer cleanly revert the bot's work\n * if a fix goes wrong.\n *\n * Returns `clean: true` when there's genuinely nothing to report AND when\n * git is unavailable (no repo, git not installed, permission denied) — the\n * check is advisory, not a hard gate on non-git projects.\n */\nexport async function checkGitCleanliness(\n projectPath: string,\n): Promise<{ clean: boolean; changedFiles: number }> {\n try {\n const { stdout } = await execFileAsync('git', ['status', '--porcelain'], {\n cwd: projectPath,\n timeout: 10_000,\n });\n const lines = stdout.split('\\n').filter((l) => l.trim().length > 0);\n return { clean: lines.length === 0, changedFiles: lines.length };\n } catch {\n // Not a git repo, git not installed, or command failed. Treat as clean\n // so we never block a user who chose not to version-control their project.\n return { clean: true, changedFiles: 0 };\n }\n}\n\nexport function hasSourceModifyingFixes(issues: FixableIssue[]): boolean {\n return issues.some((f) => f.issue.fix?.modifiesSource === true);\n}\n\nexport interface FixableIssue {\n issue: Issue;\n checkId: string;\n checkName: string;\n command?: string;\n}\n\nexport interface FixResult {\n fixable: FixableIssue;\n success: boolean;\n stdout: string;\n stderr: string;\n duration: number;\n}\n\nexport function collectFixableIssues(report: SickbayReport): FixableIssue[] {\n const seen = new Set<string>();\n const fixable: FixableIssue[] = [];\n\n for (const check of report.checks) {\n for (const issue of check.issues) {\n if (issue.fix) {\n const dedupeKey = issue.fix.command ?? issue.fix.description;\n if (!seen.has(dedupeKey)) {\n seen.add(dedupeKey);\n fixable.push({\n issue,\n checkId: check.id,\n checkName: check.name,\n command: issue.fix.command,\n });\n }\n }\n }\n }\n\n const order = { critical: 0, warning: 1, info: 2 };\n fixable.sort((a, b) => order[a.issue.severity] - order[b.issue.severity]);\n\n return fixable;\n}\n\nexport async function executeFix(fix: FixableIssue, projectPath: string): Promise<FixResult> {\n const start = Date.now();\n if (!fix.command) {\n return {\n fixable: fix,\n success: false,\n stdout: '',\n stderr: 'No command to execute (guidance-only fix)',\n duration: 0,\n };\n }\n try {\n const parts = fix.command.split(/\\s+/);\n const cmd = parts[0];\n const args = parts.slice(1);\n // SECURITY: shell is intentionally NOT enabled. Running with `shell: true`\n // would pass cmd+args through `/bin/sh -c`, making any shell metacharacter\n // in `fix.command` (e.g. `;`, `|`, `$()`, backticks) injectable. Today these\n // commands come from internal runner constants, but this is the trust\n // boundary that protects future runners from accidental command injection.\n const { stdout, stderr } = await execFileAsync(cmd, args, {\n cwd: projectPath,\n timeout: 60_000,\n });\n return {\n fixable: fix,\n success: true,\n stdout: stdout ?? '',\n stderr: stderr ?? '',\n duration: Date.now() - start,\n };\n } catch (err) {\n return {\n fixable: fix,\n success: false,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n duration: Date.now() - start,\n };\n }\n}\n","import React, { useState, useEffect, useCallback } from 'react';\n\nimport { Box, Text, useApp, useInput } from 'ink';\nimport Spinner from 'ink-spinner';\nimport { runSickbay } from 'sickbay-core';\n\nimport {\n checkGitCleanliness,\n collectFixableIssues,\n executeFix,\n type FixableIssue,\n type FixResult,\n} from '../commands/fix.js';\nimport { shortName } from '../lib/resolve-package.js';\nimport { Header } from './Header.js';\nimport { ProgressList } from './ProgressList.js';\n\ninterface FixAppProps {\n projectPath: string;\n checks?: string[];\n applyAll: boolean;\n dryRun: boolean;\n skipGitCheck: boolean;\n verbose: boolean;\n isMonorepo?: boolean;\n packagePaths?: string[];\n packageNames?: Map<string, string>;\n}\n\ntype Phase = 'scanning' | 'git-warning' | 'selecting' | 'confirming' | 'fixing' | 'done' | 'error';\n\ninterface ProgressItem {\n name: string;\n status: 'pending' | 'running' | 'done';\n}\n\ninterface MonorepoFixableIssue extends FixableIssue {\n packageName: string;\n packagePath: string;\n}\n\nconst SEVERITY_COLOR = {\n critical: 'red' as const,\n warning: 'yellow' as const,\n info: 'gray' as const,\n};\n\nexport function FixApp({\n projectPath,\n checks,\n applyAll,\n dryRun,\n skipGitCheck,\n verbose,\n isMonorepo,\n packagePaths,\n packageNames,\n}: FixAppProps) {\n const { exit } = useApp();\n const [phase, setPhase] = useState<Phase>('scanning');\n const [fixableIssues, setFixableIssues] = useState<MonorepoFixableIssue[]>([]);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n const [cursor, setCursor] = useState(0);\n const [results, setResults] = useState<FixResult[]>([]);\n const [currentFixIndex, setCurrentFixIndex] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [progress, setProgress] = useState<ProgressItem[]>([]);\n const [projectName, setProjectName] = useState<string | undefined>();\n\n // Git-cleanliness preflight state — populated before confirming tier-2 fixes\n const [gitChangedFiles, setGitChangedFiles] = useState(0);\n\n // Confirmation state\n const [confirmQueue, setConfirmQueue] = useState<MonorepoFixableIssue[]>([]);\n const [confirmIndex, setConfirmIndex] = useState(0);\n const [confirmedFixes, setConfirmedFixes] = useState<MonorepoFixableIssue[]>([]);\n\n // Route decision after scan. Extracted so the git-warning phase can\n // resume the flow when the user accepts the warning.\n const proceedAfterScan = useCallback(\n (tagged: MonorepoFixableIssue[]) => {\n const hasActionable = tagged.some((f) => f.command);\n if (!hasActionable) {\n setPhase('done');\n return;\n }\n if (applyAll) {\n setSelected(new Set(tagged.map((_, i) => i)));\n startConfirmation(tagged, new Set(tagged.map((_, i) => i)), true);\n } else {\n setPhase('selecting');\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [applyAll],\n );\n\n // Post-scan routing. If any fix will modify source files and the tree\n // is dirty, pause for an explicit go-ahead so the user isn't mixing\n // their own uncommitted work with Sickbay's edits — that state is not\n // cleanly revertable with `git checkout` or `git stash`.\n const onScanComplete = useCallback(\n async (tagged: MonorepoFixableIssue[]) => {\n const hasTier2 = tagged.some((f) => f.issue.fix?.modifiesSource === true);\n if (hasTier2 && !skipGitCheck) {\n const status = await checkGitCleanliness(projectPath);\n if (!status.clean) {\n setGitChangedFiles(status.changedFiles);\n setPhase('git-warning');\n return;\n }\n }\n proceedAfterScan(tagged);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [projectPath, skipGitCheck, proceedAfterScan],\n );\n\n // Phase 1: Run scan\n useEffect(() => {\n if (isMonorepo && packagePaths && packageNames) {\n // Monorepo: scan each package\n const pkgItems = packagePaths.map((p) => ({\n name: shortName(packageNames.get(p) ?? p),\n status: 'pending' as const,\n }));\n setProgress(pkgItems);\n\n (async () => {\n try {\n const allFixable: MonorepoFixableIssue[] = [];\n\n for (const pkgPath of packagePaths) {\n const pkgName = packageNames.get(pkgPath) ?? pkgPath;\n const display = shortName(pkgName);\n\n setProgress((prev) =>\n prev.map((p) => (p.name === display ? { ...p, status: 'running' } : p)),\n );\n\n const report = await runSickbay({\n projectPath: pkgPath,\n checks,\n verbose,\n });\n\n const fixable = collectFixableIssues(report);\n for (const fix of fixable) {\n allFixable.push({\n ...fix,\n packageName: pkgName,\n packagePath: pkgPath,\n });\n }\n\n setProgress((prev) =>\n prev.map((p) => (p.name === display ? { ...p, status: 'done' } : p)),\n );\n }\n\n setFixableIssues(allFixable);\n await onScanComplete(allFixable);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setPhase('error');\n setTimeout(() => exit(), 100);\n }\n })();\n } else {\n // Single project scan\n const initial: ProgressItem[] = (\n checks ?? [\n 'knip',\n 'depcheck',\n 'npm-check-updates',\n 'npm-audit',\n 'madge',\n 'source-map-explorer',\n 'coverage',\n 'license-checker',\n 'jscpd',\n 'git',\n 'eslint',\n 'typescript',\n 'todo-scanner',\n 'complexity',\n 'secrets',\n 'heavy-deps',\n 'react-perf',\n 'asset-size',\n ]\n ).map((name) => ({ name, status: 'pending' as const }));\n setProgress(initial);\n\n runSickbay({\n projectPath,\n checks,\n verbose,\n onCheckStart: (name) => {\n setProgress((prev) =>\n prev.map((p) => (p.name === name ? { ...p, status: 'running' } : p)),\n );\n },\n onCheckComplete: (result) => {\n setProgress((prev) =>\n prev.map((p) => (p.name === result.id ? { ...p, status: 'done' } : p)),\n );\n },\n })\n .then((r) => {\n setProjectName(r.projectInfo.name);\n const fixable = collectFixableIssues(r);\n const tagged = fixable.map((f) => ({\n ...f,\n packageName: r.projectInfo.name,\n packagePath: projectPath,\n }));\n setFixableIssues(tagged);\n return onScanComplete(tagged);\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : String(err));\n setPhase('error');\n setTimeout(() => exit(), 100);\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Start confirmation flow for selected actionable fixes\n function startConfirmation(\n issues: MonorepoFixableIssue[],\n selectedSet: Set<number>,\n isApplyAll: boolean,\n ) {\n // Only actionable fixes (with command) need confirmation\n const actionable = issues.filter((f, i) => selectedSet.has(i) && f.command);\n\n if (isApplyAll) {\n // --apply-all: skip tier-1, but still confirm tier-2 (modifiesSource)\n const tier2 = actionable.filter((f) => f.issue.fix?.modifiesSource);\n const autoApproved = actionable.filter((f) => !f.issue.fix?.modifiesSource);\n if (tier2.length === 0) {\n // No tier-2 confirms needed, go straight to fixing\n setConfirmedFixes(autoApproved);\n setPhase('fixing');\n return;\n }\n setConfirmedFixes(autoApproved);\n setConfirmQueue(tier2);\n } else {\n setConfirmedFixes([]);\n setConfirmQueue(actionable);\n }\n setConfirmIndex(0);\n\n if (actionable.length === 0) {\n // All selected are guidance-only\n setPhase('done');\n setTimeout(() => exit(), 100);\n return;\n }\n\n setPhase('confirming');\n }\n\n // Phase 3: Execute fixes\n useEffect(() => {\n if (phase !== 'fixing') return;\n\n const toFix = confirmedFixes;\n if (toFix.length === 0) {\n setPhase('done');\n setTimeout(() => exit(), 100);\n return;\n }\n\n (async () => {\n const fixResults: FixResult[] = [];\n for (let i = 0; i < toFix.length; i++) {\n setCurrentFixIndex(i);\n if (dryRun) {\n fixResults.push({\n fixable: toFix[i],\n success: true,\n stdout: '(dry run)',\n stderr: '',\n duration: 0,\n });\n } else {\n const result = await executeFix(toFix[i], toFix[i].packagePath);\n fixResults.push(result);\n }\n setResults([...fixResults]);\n }\n setPhase('done');\n setTimeout(() => exit(), 100);\n })();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [phase]);\n\n // Handle keyboard input during selection and confirmation phases\n const handleInput = useCallback(\n (input: string, key: { upArrow: boolean; downArrow: boolean; return: boolean }) => {\n if (phase === 'git-warning') {\n const lower = input.toLowerCase();\n if (lower === 'y' || key.return) {\n // User acknowledges dirty tree — continue with selection/confirmation flow\n proceedAfterScan(fixableIssues);\n } else if (lower === 'n') {\n setPhase('done');\n setTimeout(() => exit(), 100);\n }\n return;\n }\n if (phase === 'selecting') {\n const actionable = fixableIssues.filter((f) => f.command);\n\n if (key.upArrow) {\n setCursor((c) => Math.max(0, c - 1));\n } else if (key.downArrow) {\n setCursor((c) => Math.min(actionable.length - 1, c + 1));\n } else if (input === ' ') {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(cursor)) {\n next.delete(cursor);\n } else {\n next.add(cursor);\n }\n return next;\n });\n } else if (input === 'a') {\n setSelected(new Set(actionable.map((_, i) => i)));\n } else if (input === 'n') {\n setSelected(new Set());\n } else if (key.return) {\n if (selected.size > 0) {\n // Map selected indices back to the actionable items\n const selectedIssues = actionable.filter((_, i) => selected.has(i));\n startConfirmation(selectedIssues, new Set(selectedIssues.map((_, i) => i)), false);\n }\n }\n } else if (phase === 'confirming') {\n const lower = input.toLowerCase();\n if (lower === 'y' || key.return) {\n // Confirm current fix\n setConfirmedFixes((prev) => [...prev, confirmQueue[confirmIndex]]);\n if (confirmIndex + 1 < confirmQueue.length) {\n setConfirmIndex((i) => i + 1);\n } else {\n setPhase('fixing');\n }\n } else if (lower === 'n') {\n // Skip current fix\n if (confirmIndex + 1 < confirmQueue.length) {\n setConfirmIndex((i) => i + 1);\n } else {\n setPhase('fixing');\n }\n }\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [phase, cursor, selected, confirmIndex, confirmQueue, fixableIssues, proceedAfterScan],\n );\n\n useInput(handleInput);\n\n const currentConfirmFix = confirmQueue[confirmIndex];\n const isTier2 = currentConfirmFix?.issue.fix?.modifiesSource;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header projectName={projectName} />\n\n {/* Scanning phase */}\n {phase === 'scanning' && (\n <Box flexDirection=\"column\">\n <Text dimColor>\n Scanning for fixable issues\n {isMonorepo ? ` across ${packagePaths?.length} packages` : ''}...\n </Text>\n <Box marginTop={1} marginLeft={2}>\n <ProgressList items={progress} />\n </Box>\n </Box>\n )}\n\n {/* Error phase */}\n {phase === 'error' && (\n <Box>\n <Text color=\"red\">✗ Error: {error}</Text>\n </Box>\n )}\n\n {/* Git-cleanliness warning phase */}\n {phase === 'git-warning' && (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text color=\"yellow\" bold>\n ⚠ Uncommitted changes detected\n </Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text>\n Your working tree has {gitChangedFiles} changed file\n {gitChangedFiles === 1 ? '' : 's'}. Some fixes will modify source code.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>\n If a fix goes wrong, mixing Sickbay's edits with your own uncommitted work makes it\n hard to revert cleanly with <Text color=\"cyan\">git checkout</Text> or{' '}\n <Text color=\"cyan\">git stash</Text>.\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text>Commit or stash first, then re-run. Proceed anyway? (y/N)</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n (Pass <Text color=\"cyan\">--skip-git-check</Text> to suppress this prompt, e.g. in\n CI.)\n </Text>\n </Box>\n </Box>\n </Box>\n )}\n\n {/* Selection phase */}\n {phase === 'selecting' &&\n (() => {\n const actionable = fixableIssues.filter((f) => f.command);\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text color=\"yellow\">⚠ </Text>\n <Text dimColor>\n Sickbay can make mistakes. Review each fix before applying — false positives exist\n and some commands modify your project.\n </Text>\n </Box>\n <Text bold>Select fixes to apply ({actionable.length} available)</Text>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {actionable.map((fix, i) => (\n <Box key={`${fix.packageName}-${fix.checkId}-${fix.command}`}>\n <Text color={i === cursor ? 'cyan' : undefined}>\n {i === cursor ? '❯ ' : ' '}\n </Text>\n <Text color={i === cursor ? 'cyan' : undefined}>\n {selected.has(i) ? '[✓] ' : '[ ] '}\n </Text>\n {isMonorepo && (\n <Text color=\"magenta\" dimColor>\n [{shortName(fix.packageName)}]{' '}\n </Text>\n )}\n <Text color={SEVERITY_COLOR[fix.issue.severity]}>\n {fix.issue.fix!.description}\n </Text>\n <Text dimColor> ({fix.command})</Text>\n </Box>\n ))}\n </Box>\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>\n ↑↓ navigate · space toggle · a all · n none · enter confirm\n {selected.size > 0 && ` (${selected.size} selected)`}\n </Text>\n </Box>\n {dryRun && (\n <Box marginLeft={2}>\n <Text color=\"yellow\">⚠ Dry run mode — no changes will be made</Text>\n </Box>\n )}\n </Box>\n );\n })()}\n\n {/* Confirmation phase */}\n {phase === 'confirming' && currentConfirmFix && (\n <Box flexDirection=\"column\">\n <Text bold>\n Confirming fixes ({confirmIndex + 1}/{confirmQueue.length})\n </Text>\n <Box marginTop={1} marginLeft={2} flexDirection=\"column\">\n <Text>\n {currentConfirmFix.issue.fix!.description} ({currentConfirmFix.command})\n </Text>\n {isTier2 ? (\n <Text color=\"yellow\">⚠ This will modify source files. Proceed? (Y/n)</Text>\n ) : (\n <Text dimColor>→ Proceed? (Y/n)</Text>\n )}\n </Box>\n </Box>\n )}\n\n {/* Fixing phase */}\n {phase === 'fixing' && !dryRun && (\n <Box marginBottom={1}>\n <Text color=\"yellow\">⚠ </Text>\n <Text dimColor>\n Sickbay can make mistakes — verify results afterwards and revert anything that looks\n wrong.\n </Text>\n </Box>\n )}\n {phase === 'fixing' && (\n <Box flexDirection=\"column\">\n <Text bold>\n {dryRun ? 'Dry run' : 'Applying fixes'}... ({results.length}/{confirmedFixes.length})\n </Text>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {results.map((r) => (\n <Box\n key={`${r.fixable.checkId}-${r.fixable.command ?? r.fixable.issue.fix?.description}`}\n flexDirection=\"column\"\n >\n <Box>\n <Text color={r.success ? 'green' : 'red'}>{r.success ? '✓' : '✗'} </Text>\n {isMonorepo && (\n <Text color=\"magenta\" dimColor>\n [{shortName((r.fixable as MonorepoFixableIssue).packageName)}]{' '}\n </Text>\n )}\n <Text>{r.fixable.issue.fix!.description}</Text>\n </Box>\n {r.success && r.fixable.issue.fix?.nextSteps && (\n <Box marginLeft={2}>\n <Text dimColor> → Next: {r.fixable.issue.fix.nextSteps}</Text>\n </Box>\n )}\n </Box>\n ))}\n {results.length < confirmedFixes.length && (\n <Box>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>\n <Text> {confirmedFixes[currentFixIndex]?.issue.fix!.description}</Text>\n </Box>\n )}\n </Box>\n </Box>\n )}\n\n {/* Done phase */}\n {phase === 'done' && (\n <Box flexDirection=\"column\">\n {results.length === 0 ? (\n <Box flexDirection=\"column\">\n <Box>\n <Text color=\"green\">✓ </Text>\n <Text>\n No auto-fixable issues found\n {isMonorepo ? ' across any package' : ''}\n </Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n Run <Text color=\"cyan\">sickbay</Text> to see the full report — there may be issues\n that require manual attention.\n </Text>\n </Box>\n </Box>\n ) : (\n <>\n <Text bold>{dryRun ? 'Dry Run Results' : 'Fix Results'}</Text>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {results.map((r) => (\n <Box\n key={`${r.fixable.checkId}-${r.fixable.command ?? r.fixable.issue.fix?.description}`}\n flexDirection=\"column\"\n >\n <Box>\n <Text color={r.success ? 'green' : 'red'}>{r.success ? '✓' : '✗'} </Text>\n {isMonorepo && (\n <Text color=\"magenta\" dimColor>\n [{shortName((r.fixable as MonorepoFixableIssue).packageName)}]{' '}\n </Text>\n )}\n <Text>{r.fixable.issue.fix!.description}</Text>\n {r.duration > 0 && <Text dimColor> ({r.duration}ms)</Text>}\n </Box>\n {r.success && r.fixable.issue.fix?.nextSteps && (\n <Box marginLeft={2}>\n <Text dimColor> → Next: {r.fixable.issue.fix.nextSteps}</Text>\n </Box>\n )}\n </Box>\n ))}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>{'━'.repeat(52)}</Text>\n </Box>\n <Box marginTop={1}>\n <Text bold>\n {results.filter((r) => r.success).length}/{results.length} fixes{' '}\n {dryRun ? 'would be applied' : 'applied successfully'}\n </Text>\n </Box>\n {!dryRun && results.some((r) => r.success) && (\n <Box marginTop={1}>\n <Text dimColor>Run </Text>\n <Text color=\"cyan\">sickbay</Text>\n <Text dimColor> to see your updated score</Text>\n </Box>\n )}\n </>\n )}\n </Box>\n )}\n </Box>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { o as detectProject } from "./dist-Bjhxbcak.js";
1
+ import { o as detectProject } from "./dist-CHT6_2R4.js";
2
2
  import { r as Header } from "./index.js";
3
- import { shortName } from "./resolve-package-DS27JBhN.js";
3
+ import { shortName } from "./resolve-package-DOgU3aGV.js";
4
4
  import { existsSync, readFileSync, readdirSync, statSync } from "fs";
5
5
  import { extname, join } from "path";
6
6
  import React, { useEffect, useState } from "react";
@@ -369,4 +369,4 @@ function StatsApp({ projectPath, jsonOutput, isMonorepo, packagePaths, packageNa
369
369
  //#endregion
370
370
  export { StatsApp };
371
371
 
372
- //# sourceMappingURL=StatsApp-BC4P4hII.js.map
372
+ //# sourceMappingURL=StatsApp-CXhNyWlK.js.map