@a-company/paradigm 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +142 -0
  2. package/dist/accept-orchestration-CWZNCGZX.js +188 -0
  3. package/dist/agents-suggest-35LIQKDH.js +83 -0
  4. package/dist/aggregate-W7Q6VIM2.js +88 -0
  5. package/dist/auto-IU7VN55K.js +470 -0
  6. package/dist/beacon-B47XSTL7.js +251 -0
  7. package/dist/chunk-2M6OSOIG.js +1302 -0
  8. package/dist/chunk-4NCFWYGG.js +110 -0
  9. package/dist/chunk-5C4SGQKH.js +705 -0
  10. package/dist/chunk-5GOA7WYD.js +1095 -0
  11. package/dist/chunk-5JGJACDU.js +37 -0
  12. package/dist/chunk-6QC3YGB6.js +114 -0
  13. package/dist/chunk-753RICFF.js +325 -0
  14. package/dist/chunk-AD2LSCHB.js +1595 -0
  15. package/dist/chunk-CHSHON3O.js +669 -0
  16. package/dist/chunk-ELLR7WP6.js +3175 -0
  17. package/dist/chunk-ILOWBJRC.js +12 -0
  18. package/dist/chunk-IRKUEJVW.js +405 -0
  19. package/dist/chunk-MC7XC7XQ.js +533 -0
  20. package/dist/chunk-MO4EEYFW.js +38 -0
  21. package/dist/chunk-MQWH7PFI.js +13366 -0
  22. package/dist/chunk-N6PJAPDE.js +364 -0
  23. package/dist/chunk-PBHIFAL4.js +259 -0
  24. package/dist/chunk-PMXRGPRQ.js +305 -0
  25. package/dist/chunk-PW2EXJQT.js +689 -0
  26. package/dist/chunk-TAP5N3HH.js +245 -0
  27. package/dist/chunk-THFVK5AE.js +148 -0
  28. package/dist/chunk-UM54F7G5.js +1533 -0
  29. package/dist/chunk-UUZ2DMG5.js +185 -0
  30. package/dist/chunk-WS5KM7OL.js +780 -0
  31. package/dist/chunk-YDNKXH4Z.js +2316 -0
  32. package/dist/chunk-YO6DVTL7.js +99 -0
  33. package/dist/claude-SUYNN72C.js +362 -0
  34. package/dist/claude-cli-OF43XAO3.js +276 -0
  35. package/dist/claude-code-PW6SKD2M.js +126 -0
  36. package/dist/claude-code-teams-JLZ5IXB6.js +199 -0
  37. package/dist/constellation-K3CIQCHI.js +225 -0
  38. package/dist/cost-AEK6R7HK.js +174 -0
  39. package/dist/cost-KYXIQ62X.js +93 -0
  40. package/dist/cursor-cli-IHJMPRCW.js +269 -0
  41. package/dist/cursorrules-KI5QWHIX.js +84 -0
  42. package/dist/diff-AJJ5H6HV.js +125 -0
  43. package/dist/dist-7MPIRMTZ-IOQOREMZ.js +10866 -0
  44. package/dist/dist-NHJQVVUW.js +68 -0
  45. package/dist/dist-ZEMSQV74.js +20 -0
  46. package/dist/doctor-6Y6L6HEB.js +11 -0
  47. package/dist/echo-VYZW3OTT.js +248 -0
  48. package/dist/export-R4FJ5NOH.js +38 -0
  49. package/dist/history-EVO3L6SC.js +277 -0
  50. package/dist/hooks-MBWE4ILT.js +12 -0
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +568 -0
  53. package/dist/lint-HXKTWRNO.js +316 -0
  54. package/dist/manual-Y3QOXWYA.js +204 -0
  55. package/dist/mcp.js +14745 -0
  56. package/dist/orchestrate-4ZH5GUQH.js +323 -0
  57. package/dist/probe-OYCP4JYG.js +151 -0
  58. package/dist/promote-Z52ZJTJU.js +181 -0
  59. package/dist/providers-4PGPZEWP.js +104 -0
  60. package/dist/remember-6VZ74B7E.js +77 -0
  61. package/dist/ripple-SBQOSTZD.js +215 -0
  62. package/dist/sentinel-LCFD56OJ.js +43 -0
  63. package/dist/server-F5ITNK6T.js +9846 -0
  64. package/dist/server-T6WIFYRQ.js +16076 -0
  65. package/dist/setup-DF4F3ICN.js +25 -0
  66. package/dist/setup-JHBPZAG7.js +296 -0
  67. package/dist/shift-HKIAP4ZN.js +226 -0
  68. package/dist/snapshot-GTVPRYZG.js +62 -0
  69. package/dist/spawn-BJRQA2NR.js +196 -0
  70. package/dist/summary-H6J6N6PJ.js +140 -0
  71. package/dist/switch-6EANJ7O6.js +232 -0
  72. package/dist/sync-BEOCW7TZ.js +11 -0
  73. package/dist/team-NWP2KJAB.js +32 -0
  74. package/dist/test-MA5TWJQV.js +934 -0
  75. package/dist/thread-JCJVRUQR.js +258 -0
  76. package/dist/triage-ETVXXFMV.js +1880 -0
  77. package/dist/tutorial-L5Q3ZDHK.js +666 -0
  78. package/dist/university-R2WDQLSI.js +40 -0
  79. package/dist/upgrade-5B3YGGC6.js +550 -0
  80. package/dist/validate-F3YHBCRZ.js +39 -0
  81. package/dist/validate-QEEY6KFS.js +64 -0
  82. package/dist/watch-4LT4O6K7.js +123 -0
  83. package/dist/watch-6IIWPWDN.js +111 -0
  84. package/dist/wisdom-LRM4FFCH.js +319 -0
  85. package/package.json +68 -0
  86. package/templates/paradigm/config.yaml +175 -0
  87. package/templates/paradigm/docs/commands.md +727 -0
  88. package/templates/paradigm/docs/decisions/000-template.md +47 -0
  89. package/templates/paradigm/docs/decisions/README.md +26 -0
  90. package/templates/paradigm/docs/error-patterns.md +215 -0
  91. package/templates/paradigm/docs/patterns.md +358 -0
  92. package/templates/paradigm/docs/queries.md +200 -0
  93. package/templates/paradigm/docs/troubleshooting.md +477 -0
  94. package/templates/paradigm/echoes.yaml +25 -0
  95. package/templates/paradigm/prompts/add-feature.md +152 -0
  96. package/templates/paradigm/prompts/add-gate.md +117 -0
  97. package/templates/paradigm/prompts/debug-auth.md +174 -0
  98. package/templates/paradigm/prompts/implement-ftux.md +722 -0
  99. package/templates/paradigm/prompts/implement-sandbox.md +651 -0
  100. package/templates/paradigm/prompts/read-docs.md +84 -0
  101. package/templates/paradigm/prompts/refactor.md +106 -0
  102. package/templates/paradigm/prompts/run-e2e-tests.md +340 -0
  103. package/templates/paradigm/prompts/trace-flow.md +202 -0
  104. package/templates/paradigm/prompts/validate-portals.md +279 -0
  105. package/templates/paradigm/specs/context-tracking.md +200 -0
  106. package/templates/paradigm/specs/context.md +461 -0
  107. package/templates/paradigm/specs/disciplines.md +413 -0
  108. package/templates/paradigm/specs/history.md +339 -0
  109. package/templates/paradigm/specs/logger.md +303 -0
  110. package/templates/paradigm/specs/navigator.md +236 -0
  111. package/templates/paradigm/specs/purpose.md +265 -0
  112. package/templates/paradigm/specs/scan.md +177 -0
  113. package/templates/paradigm/specs/symbols.md +451 -0
  114. package/templates/paradigm/specs/wisdom.md +294 -0
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/agent-provider.ts
4
+ var MODEL_PRICING = {
5
+ // Prices per 1M tokens (as of 2025)
6
+ opus: { input: 15, output: 75 },
7
+ sonnet: { input: 3, output: 15 },
8
+ haiku: { input: 0.25, output: 1.25 }
9
+ };
10
+ function calculateCost(usage, model) {
11
+ const pricing = MODEL_PRICING[model];
12
+ const inputCost = usage.input / 1e6 * pricing.input;
13
+ const outputCost = usage.output / 1e6 * pricing.output;
14
+ return inputCost + outputCost;
15
+ }
16
+ function formatCost(usd) {
17
+ if (usd < 0.01) {
18
+ return `$${(usd * 100).toFixed(3)}\xA2`;
19
+ }
20
+ return `$${usd.toFixed(4)}`;
21
+ }
22
+ function formatTokens(count) {
23
+ if (count >= 1e6) {
24
+ return `${(count / 1e6).toFixed(2)}M`;
25
+ }
26
+ if (count >= 1e3) {
27
+ return `${(count / 1e3).toFixed(1)}K`;
28
+ }
29
+ return count.toString();
30
+ }
31
+
32
+ export {
33
+ MODEL_PRICING,
34
+ calculateCost,
35
+ formatCost,
36
+ formatTokens
37
+ };
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/agent-matcher.ts
4
+ var SYMBOL_PATTERN = /[@#$%^!?&~][a-zA-Z0-9_-]+/g;
5
+ function suggestAgentsForTask(task, agents) {
6
+ const suggestions = [];
7
+ const taskLower = task.toLowerCase();
8
+ const symbols = extractSymbols(task);
9
+ for (const [name, agent] of Object.entries(agents)) {
10
+ const matched = [];
11
+ for (const trigger of agent.triggers || []) {
12
+ const triggerMatches = matchTrigger(trigger, taskLower, symbols);
13
+ matched.push(...triggerMatches);
14
+ }
15
+ if (matched.length > 0) {
16
+ suggestions.push({
17
+ name,
18
+ reason: buildReason(name, agent, matched),
19
+ confidence: calculateConfidence(matched),
20
+ triggers_matched: matched
21
+ });
22
+ }
23
+ }
24
+ return suggestions.sort(
25
+ (a, b) => confidenceScore(b.confidence) - confidenceScore(a.confidence)
26
+ );
27
+ }
28
+ function matchTrigger(trigger, taskLower, symbols) {
29
+ const matched = [];
30
+ switch (trigger.type) {
31
+ case "keyword":
32
+ if (trigger.match) {
33
+ for (const keyword of trigger.match) {
34
+ if (taskLower.includes(keyword.toLowerCase())) {
35
+ matched.push(`keyword:${keyword}`);
36
+ }
37
+ }
38
+ }
39
+ break;
40
+ case "symbol":
41
+ if (trigger.match) {
42
+ for (const pattern of trigger.match) {
43
+ const matchingSymbols = symbols.filter(
44
+ (s) => matchSymbolPattern(s, pattern)
45
+ );
46
+ for (const s of matchingSymbols) {
47
+ matched.push(`symbol:${s}`);
48
+ }
49
+ }
50
+ }
51
+ break;
52
+ case "handoff":
53
+ break;
54
+ case "schedule":
55
+ break;
56
+ }
57
+ return matched;
58
+ }
59
+ function matchSymbolPattern(symbol, pattern) {
60
+ if (pattern.endsWith("*")) {
61
+ const prefix = pattern.slice(0, -1);
62
+ return symbol.startsWith(prefix);
63
+ }
64
+ if (pattern.startsWith("^") && pattern === "^*") {
65
+ return symbol.startsWith("^");
66
+ }
67
+ return symbol === pattern;
68
+ }
69
+ function extractSymbols(text) {
70
+ const matches = text.match(SYMBOL_PATTERN) || [];
71
+ return [...new Set(matches)];
72
+ }
73
+ function buildReason(_name, agent, matched) {
74
+ const keywordMatches = matched.filter((m) => m.startsWith("keyword:"));
75
+ const symbolMatches = matched.filter((m) => m.startsWith("symbol:"));
76
+ const parts = [];
77
+ if (keywordMatches.length > 0) {
78
+ const keywords = keywordMatches.map((m) => m.split(":")[1]);
79
+ parts.push(`keywords: ${keywords.join(", ")}`);
80
+ }
81
+ if (symbolMatches.length > 0) {
82
+ const symbols = symbolMatches.map((m) => m.split(":")[1]);
83
+ parts.push(`symbols: ${symbols.join(", ")}`);
84
+ }
85
+ const roleFirstLine = agent.role.split("\n")[0].trim();
86
+ const roleSnippet = roleFirstLine.length > 60 ? roleFirstLine.slice(0, 57) + "..." : roleFirstLine;
87
+ return `Matched ${parts.join("; ")}. ${roleSnippet}`;
88
+ }
89
+ function calculateConfidence(matched) {
90
+ const keywordCount = matched.filter((m) => m.startsWith("keyword:")).length;
91
+ const symbolCount = matched.filter((m) => m.startsWith("symbol:")).length;
92
+ const hasMultipleTypes = keywordCount > 0 && symbolCount > 0;
93
+ if (matched.length >= 3 || hasMultipleTypes) {
94
+ return "high";
95
+ }
96
+ if (matched.length >= 2) {
97
+ return "medium";
98
+ }
99
+ return "low";
100
+ }
101
+ function confidenceScore(confidence) {
102
+ switch (confidence) {
103
+ case "high":
104
+ return 3;
105
+ case "medium":
106
+ return 2;
107
+ case "low":
108
+ return 1;
109
+ }
110
+ }
111
+
112
+ export {
113
+ suggestAgentsForTask
114
+ };
@@ -0,0 +1,325 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ detectIDE,
4
+ getAdapter
5
+ } from "./chunk-YDNKXH4Z.js";
6
+ import {
7
+ log
8
+ } from "./chunk-4NCFWYGG.js";
9
+ import {
10
+ parseParadigmConfig
11
+ } from "./chunk-YO6DVTL7.js";
12
+
13
+ // src/commands/doctor.ts
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import chalk from "chalk";
17
+ async function doctorCommand(options = {}) {
18
+ const cwd = options.rootDir || process.cwd();
19
+ const results = [];
20
+ const quiet = options.quiet;
21
+ if (!quiet) {
22
+ console.log(chalk.blue("\n\u{1FA7A} Paradigm Doctor\n"));
23
+ console.log(chalk.gray("Checking Paradigm setup...\n"));
24
+ }
25
+ const tracker = log.command("doctor").start("Running health checks");
26
+ const paradigmDir = path.join(cwd, ".paradigm");
27
+ if (fs.existsSync(paradigmDir)) {
28
+ const stat = fs.statSync(paradigmDir);
29
+ if (stat.isFile()) {
30
+ results.push({
31
+ name: ".paradigm",
32
+ status: "warn",
33
+ message: "Legacy file format (should be directory)",
34
+ fix: "paradigm upgrade --all"
35
+ });
36
+ } else {
37
+ results.push({
38
+ name: ".paradigm/",
39
+ status: "ok",
40
+ message: "Directory exists"
41
+ });
42
+ const configPath = path.join(paradigmDir, "config.yaml");
43
+ if (fs.existsSync(configPath)) {
44
+ try {
45
+ const content = fs.readFileSync(configPath, "utf8");
46
+ parseParadigmConfig(content);
47
+ results.push({
48
+ name: ".paradigm/config.yaml",
49
+ status: "ok",
50
+ message: "Valid YAML"
51
+ });
52
+ } catch (e) {
53
+ results.push({
54
+ name: ".paradigm/config.yaml",
55
+ status: "error",
56
+ message: `Invalid YAML: ${e.message}`,
57
+ fix: "Check YAML syntax"
58
+ });
59
+ }
60
+ } else {
61
+ results.push({
62
+ name: ".paradigm/config.yaml",
63
+ status: "missing",
64
+ message: "Config file not found",
65
+ fix: "paradigm init --force"
66
+ });
67
+ }
68
+ const specs = ["logger.md", "scan.md", "symbols.md"];
69
+ const specsDir = path.join(paradigmDir, "specs");
70
+ if (fs.existsSync(specsDir)) {
71
+ for (const spec of specs) {
72
+ const specPath = path.join(specsDir, spec);
73
+ if (fs.existsSync(specPath)) {
74
+ results.push({
75
+ name: `.paradigm/specs/${spec}`,
76
+ status: "ok",
77
+ message: "Present"
78
+ });
79
+ } else {
80
+ results.push({
81
+ name: `.paradigm/specs/${spec}`,
82
+ status: "missing",
83
+ message: "Spec file not found",
84
+ fix: "paradigm upgrade --all"
85
+ });
86
+ }
87
+ }
88
+ } else {
89
+ results.push({
90
+ name: ".paradigm/specs/",
91
+ status: "missing",
92
+ message: "Specs directory not found",
93
+ fix: "paradigm upgrade --all"
94
+ });
95
+ }
96
+ const docsDir = path.join(paradigmDir, "docs");
97
+ if (fs.existsSync(docsDir)) {
98
+ results.push({
99
+ name: ".paradigm/docs/",
100
+ status: "ok",
101
+ message: "Directory exists"
102
+ });
103
+ } else {
104
+ results.push({
105
+ name: ".paradigm/docs/",
106
+ status: "missing",
107
+ message: "Docs directory not found",
108
+ fix: "paradigm upgrade --all"
109
+ });
110
+ }
111
+ const promptsDir = path.join(paradigmDir, "prompts");
112
+ if (fs.existsSync(promptsDir)) {
113
+ results.push({
114
+ name: ".paradigm/prompts/",
115
+ status: "ok",
116
+ message: "Directory exists"
117
+ });
118
+ } else {
119
+ results.push({
120
+ name: ".paradigm/prompts/",
121
+ status: "missing",
122
+ message: "Prompts directory not found",
123
+ fix: "paradigm upgrade --all"
124
+ });
125
+ }
126
+ const scanIndexPath = path.join(paradigmDir, "scan-index.json");
127
+ const legacyScanIndex = path.join(cwd, ".paradigm-scan-index.json");
128
+ if (fs.existsSync(scanIndexPath)) {
129
+ const stat2 = fs.statSync(scanIndexPath);
130
+ const ageMs = Date.now() - stat2.mtime.getTime();
131
+ const ageHours = Math.floor(ageMs / (1e3 * 60 * 60));
132
+ if (ageHours > 24) {
133
+ results.push({
134
+ name: ".paradigm/scan-index.json",
135
+ status: "warn",
136
+ message: `Stale (${ageHours} hours old)`,
137
+ fix: "paradigm index"
138
+ });
139
+ } else {
140
+ results.push({
141
+ name: ".paradigm/scan-index.json",
142
+ status: "ok",
143
+ message: ageHours > 0 ? `${ageHours} hours old` : "Fresh"
144
+ });
145
+ }
146
+ } else if (fs.existsSync(legacyScanIndex)) {
147
+ results.push({
148
+ name: "scan-index",
149
+ status: "warn",
150
+ message: "Using legacy location",
151
+ fix: "paradigm index"
152
+ });
153
+ } else {
154
+ results.push({
155
+ name: ".paradigm/scan-index.json",
156
+ status: "missing",
157
+ message: "Not generated",
158
+ fix: "paradigm index"
159
+ });
160
+ }
161
+ }
162
+ } else {
163
+ results.push({
164
+ name: ".paradigm/",
165
+ status: "missing",
166
+ message: "Not initialized",
167
+ fix: "paradigm init"
168
+ });
169
+ }
170
+ const detection = detectIDE(cwd);
171
+ if (detection.detected) {
172
+ const adapter = getAdapter(detection.detected);
173
+ if (adapter) {
174
+ const idePath = path.join(cwd, adapter.outputPath);
175
+ if (fs.existsSync(idePath)) {
176
+ results.push({
177
+ name: adapter.outputPath,
178
+ status: "ok",
179
+ message: `Present (${detection.detected})`
180
+ });
181
+ } else {
182
+ results.push({
183
+ name: adapter.outputPath,
184
+ status: "missing",
185
+ message: `Not generated for ${detection.detected}`,
186
+ fix: "paradigm sync"
187
+ });
188
+ }
189
+ }
190
+ }
191
+ const premisePath = path.join(cwd, ".premise");
192
+ if (fs.existsSync(premisePath)) {
193
+ results.push({
194
+ name: ".premise",
195
+ status: "ok",
196
+ message: "Present"
197
+ });
198
+ } else {
199
+ results.push({
200
+ name: ".premise",
201
+ status: "missing",
202
+ message: "Not found (optional)"
203
+ });
204
+ }
205
+ const purposePath = path.join(cwd, ".purpose");
206
+ if (fs.existsSync(purposePath)) {
207
+ results.push({
208
+ name: ".purpose",
209
+ status: "ok",
210
+ message: "Present"
211
+ });
212
+ } else {
213
+ results.push({
214
+ name: ".purpose",
215
+ status: "warn",
216
+ message: "Root .purpose not found",
217
+ fix: "paradigm init"
218
+ });
219
+ }
220
+ const clarificationMarkerRegex = /\[NEEDS CLARIFICATION:\s*[^\]]+\]/gi;
221
+ let clarificationCount = 0;
222
+ function findPurposeFilesRecursive(dir) {
223
+ const found = [];
224
+ try {
225
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
226
+ for (const entry of entries) {
227
+ if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
228
+ const fullPath = path.join(dir, entry.name);
229
+ if (entry.isDirectory()) {
230
+ found.push(...findPurposeFilesRecursive(fullPath));
231
+ } else if (entry.name === ".purpose") {
232
+ found.push(fullPath);
233
+ }
234
+ }
235
+ } catch {
236
+ }
237
+ return found;
238
+ }
239
+ const purposeFiles = findPurposeFilesRecursive(cwd);
240
+ for (const pf of purposeFiles) {
241
+ try {
242
+ const content = fs.readFileSync(pf, "utf8");
243
+ const matches = content.match(clarificationMarkerRegex);
244
+ if (matches) {
245
+ clarificationCount += matches.length;
246
+ }
247
+ } catch {
248
+ }
249
+ }
250
+ if (clarificationCount > 0) {
251
+ results.push({
252
+ name: "Clarification markers",
253
+ status: "warn",
254
+ message: `${clarificationCount} [NEEDS CLARIFICATION] marker${clarificationCount > 1 ? "s" : ""} found in .purpose files`,
255
+ fix: "Resolve open clarification markers before shipping"
256
+ });
257
+ } else if (purposeFiles.length > 0) {
258
+ results.push({
259
+ name: "Clarification markers",
260
+ status: "ok",
261
+ message: "No unresolved markers"
262
+ });
263
+ }
264
+ let errorCount = 0;
265
+ let warnCount = 0;
266
+ let missingCount = 0;
267
+ for (const result of results) {
268
+ let icon;
269
+ let color;
270
+ switch (result.status) {
271
+ case "ok":
272
+ icon = "\u2713";
273
+ color = chalk.green;
274
+ break;
275
+ case "warn":
276
+ icon = "\u26A0";
277
+ color = chalk.yellow;
278
+ warnCount++;
279
+ break;
280
+ case "error":
281
+ icon = "\u2717";
282
+ color = chalk.red;
283
+ errorCount++;
284
+ break;
285
+ case "missing":
286
+ icon = "\u25CB";
287
+ color = chalk.gray;
288
+ missingCount++;
289
+ break;
290
+ }
291
+ if (!quiet) {
292
+ const namePadded = result.name.padEnd(30);
293
+ console.log(` ${color(icon)} ${namePadded} ${color(result.message)}`);
294
+ if (result.fix) {
295
+ console.log(chalk.gray(` \u2514\u2500 Fix: ${result.fix}`));
296
+ }
297
+ }
298
+ }
299
+ const issueCount = errorCount + warnCount + missingCount;
300
+ const healthy = issueCount === 0;
301
+ if (!quiet) {
302
+ console.log("");
303
+ if (healthy) {
304
+ console.log(chalk.green("\u2728 All checks passed!\n"));
305
+ } else {
306
+ const parts = [];
307
+ if (errorCount > 0) parts.push(chalk.red(`${errorCount} error${errorCount > 1 ? "s" : ""}`));
308
+ if (warnCount > 0) parts.push(chalk.yellow(`${warnCount} warning${warnCount > 1 ? "s" : ""}`));
309
+ if (missingCount > 0) parts.push(chalk.gray(`${missingCount} missing`));
310
+ console.log(`${parts.join(", ")} found.
311
+ `);
312
+ console.log(chalk.gray("Run the suggested commands to fix issues.\n"));
313
+ }
314
+ }
315
+ if (healthy) {
316
+ tracker.success("All health checks passed", { total: results.length });
317
+ } else {
318
+ tracker.error("Health checks found issues", { errors: errorCount, warnings: warnCount, missing: missingCount });
319
+ }
320
+ return healthy;
321
+ }
322
+
323
+ export {
324
+ doctorCommand
325
+ };