@wundr.io/cli 1.0.10 → 1.0.12

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 (269) hide show
  1. package/bin/wundr.js +8 -4
  2. package/package.json +23 -23
  3. package/src/ai/ai-service.ts +16 -17
  4. package/src/ai/claude-client.ts +16 -16
  5. package/src/ai/conversation-manager.ts +29 -29
  6. package/src/cli.ts +4 -4
  7. package/src/commands/ai.ts +246 -78
  8. package/src/commands/alignment.ts +74 -74
  9. package/src/commands/analyze-optimized.ts +111 -78
  10. package/src/commands/analyze.ts +14 -14
  11. package/src/commands/batch.ts +179 -42
  12. package/src/commands/chat.ts +37 -30
  13. package/src/commands/claude-init.ts +41 -45
  14. package/src/commands/claude-setup.ts +204 -119
  15. package/src/commands/computer-setup.ts +85 -43
  16. package/src/commands/create-command.ts +4 -4
  17. package/src/commands/create.ts +27 -27
  18. package/src/commands/dashboard.ts +24 -24
  19. package/src/commands/govern.ts +25 -25
  20. package/src/commands/governance.ts +34 -34
  21. package/src/commands/guardian.ts +56 -56
  22. package/src/commands/init.ts +25 -22
  23. package/src/commands/orchestrator.ts +68 -41
  24. package/src/commands/performance-optimizer.ts +34 -35
  25. package/src/commands/plugins.ts +27 -27
  26. package/src/commands/project-update.ts +175 -72
  27. package/src/commands/rag.ts +185 -78
  28. package/src/commands/session.ts +35 -35
  29. package/src/commands/setup.ts +40 -344
  30. package/src/commands/test-init.ts +3 -3
  31. package/src/commands/test.ts +4 -4
  32. package/src/commands/watch.ts +28 -29
  33. package/src/commands/worktree.ts +49 -49
  34. package/src/context/context-manager.ts +10 -10
  35. package/src/context/session-manager.ts +41 -41
  36. package/src/framework/command-interface.ts +520 -0
  37. package/src/framework/command-registry.ts +942 -0
  38. package/src/framework/completion-exporter.ts +383 -0
  39. package/src/framework/debug-logger.ts +519 -0
  40. package/src/framework/error-handler.ts +867 -0
  41. package/src/framework/help-generator.ts +540 -0
  42. package/src/framework/index.ts +169 -0
  43. package/src/framework/interactive-repl.ts +703 -0
  44. package/src/framework/output-formatter.ts +834 -0
  45. package/src/framework/progress-manager.ts +539 -0
  46. package/src/index.ts +4 -4
  47. package/src/interactive/interactive-mode.ts +16 -16
  48. package/src/lib/conflict-resolution.ts +799 -9
  49. package/src/lib/merge-strategy.ts +529 -7
  50. package/src/lib/safety-mechanisms.ts +422 -18
  51. package/src/lib/state-detection.ts +1015 -13
  52. package/src/nlp/command-mapper.ts +29 -29
  53. package/src/nlp/command-parser.ts +17 -17
  54. package/src/nlp/intent-classifier.ts +7 -7
  55. package/src/nlp/intent-parser.ts +54 -52
  56. package/src/plugins/plugin-manager.ts +61 -39
  57. package/src/tests/computer-setup-integration.test.ts +46 -15
  58. package/src/types/modules.d.ts +424 -1
  59. package/src/utils/backup-rollback-manager.ts +11 -8
  60. package/src/utils/config-manager.ts +3 -3
  61. package/src/utils/error-handler.ts +2 -2
  62. package/src/utils/logger.ts +22 -22
  63. package/templates/batch/ci-cd.yaml +7 -7
  64. package/test-suites/api/health.spec.ts +20 -23
  65. package/test-suites/helpers/test-config.ts +14 -13
  66. package/test-suites/ui/accessibility.spec.ts +27 -22
  67. package/test-suites/ui/smoke.spec.ts +26 -21
  68. package/LICENSE +0 -21
  69. package/dist/ai/ai-service.d.ts +0 -152
  70. package/dist/ai/ai-service.d.ts.map +0 -1
  71. package/dist/ai/ai-service.js +0 -430
  72. package/dist/ai/ai-service.js.map +0 -1
  73. package/dist/ai/claude-client.d.ts +0 -130
  74. package/dist/ai/claude-client.d.ts.map +0 -1
  75. package/dist/ai/claude-client.js +0 -340
  76. package/dist/ai/claude-client.js.map +0 -1
  77. package/dist/ai/conversation-manager.d.ts +0 -164
  78. package/dist/ai/conversation-manager.d.ts.map +0 -1
  79. package/dist/ai/conversation-manager.js +0 -614
  80. package/dist/ai/conversation-manager.js.map +0 -1
  81. package/dist/ai/index.d.ts +0 -5
  82. package/dist/ai/index.d.ts.map +0 -1
  83. package/dist/ai/index.js +0 -8
  84. package/dist/ai/index.js.map +0 -1
  85. package/dist/cli.d.ts +0 -36
  86. package/dist/cli.d.ts.map +0 -1
  87. package/dist/cli.js +0 -192
  88. package/dist/cli.js.map +0 -1
  89. package/dist/commands/ai.d.ts +0 -89
  90. package/dist/commands/ai.d.ts.map +0 -1
  91. package/dist/commands/ai.js +0 -799
  92. package/dist/commands/ai.js.map +0 -1
  93. package/dist/commands/alignment.d.ts +0 -78
  94. package/dist/commands/alignment.d.ts.map +0 -1
  95. package/dist/commands/alignment.js +0 -817
  96. package/dist/commands/alignment.js.map +0 -1
  97. package/dist/commands/analyze-optimized.d.ts +0 -14
  98. package/dist/commands/analyze-optimized.d.ts.map +0 -1
  99. package/dist/commands/analyze-optimized.js +0 -600
  100. package/dist/commands/analyze-optimized.js.map +0 -1
  101. package/dist/commands/analyze.d.ts +0 -65
  102. package/dist/commands/analyze.d.ts.map +0 -1
  103. package/dist/commands/analyze.js +0 -435
  104. package/dist/commands/analyze.js.map +0 -1
  105. package/dist/commands/batch.d.ts +0 -71
  106. package/dist/commands/batch.d.ts.map +0 -1
  107. package/dist/commands/batch.js +0 -738
  108. package/dist/commands/batch.js.map +0 -1
  109. package/dist/commands/chat.d.ts +0 -71
  110. package/dist/commands/chat.d.ts.map +0 -1
  111. package/dist/commands/chat.js +0 -674
  112. package/dist/commands/chat.js.map +0 -1
  113. package/dist/commands/claude-init.d.ts +0 -28
  114. package/dist/commands/claude-init.d.ts.map +0 -1
  115. package/dist/commands/claude-init.js +0 -591
  116. package/dist/commands/claude-init.js.map +0 -1
  117. package/dist/commands/claude-setup.d.ts +0 -119
  118. package/dist/commands/claude-setup.d.ts.map +0 -1
  119. package/dist/commands/claude-setup.js +0 -1073
  120. package/dist/commands/claude-setup.js.map +0 -1
  121. package/dist/commands/computer-setup-commands.d.ts +0 -53
  122. package/dist/commands/computer-setup-commands.d.ts.map +0 -1
  123. package/dist/commands/computer-setup-commands.js +0 -705
  124. package/dist/commands/computer-setup-commands.js.map +0 -1
  125. package/dist/commands/computer-setup.d.ts +0 -7
  126. package/dist/commands/computer-setup.d.ts.map +0 -1
  127. package/dist/commands/computer-setup.js +0 -849
  128. package/dist/commands/computer-setup.js.map +0 -1
  129. package/dist/commands/create-command.d.ts +0 -7
  130. package/dist/commands/create-command.d.ts.map +0 -1
  131. package/dist/commands/create-command.js +0 -158
  132. package/dist/commands/create-command.js.map +0 -1
  133. package/dist/commands/create.d.ts +0 -74
  134. package/dist/commands/create.d.ts.map +0 -1
  135. package/dist/commands/create.js +0 -556
  136. package/dist/commands/create.js.map +0 -1
  137. package/dist/commands/dashboard.d.ts +0 -91
  138. package/dist/commands/dashboard.d.ts.map +0 -1
  139. package/dist/commands/dashboard.js +0 -538
  140. package/dist/commands/dashboard.js.map +0 -1
  141. package/dist/commands/govern.d.ts +0 -70
  142. package/dist/commands/govern.d.ts.map +0 -1
  143. package/dist/commands/govern.js +0 -481
  144. package/dist/commands/govern.js.map +0 -1
  145. package/dist/commands/governance.d.ts +0 -17
  146. package/dist/commands/governance.d.ts.map +0 -1
  147. package/dist/commands/governance.js +0 -703
  148. package/dist/commands/governance.js.map +0 -1
  149. package/dist/commands/guardian.d.ts +0 -20
  150. package/dist/commands/guardian.d.ts.map +0 -1
  151. package/dist/commands/guardian.js +0 -597
  152. package/dist/commands/guardian.js.map +0 -1
  153. package/dist/commands/init.d.ts +0 -59
  154. package/dist/commands/init.d.ts.map +0 -1
  155. package/dist/commands/init.js +0 -650
  156. package/dist/commands/init.js.map +0 -1
  157. package/dist/commands/orchestrator.d.ts +0 -7
  158. package/dist/commands/orchestrator.d.ts.map +0 -1
  159. package/dist/commands/orchestrator.js +0 -571
  160. package/dist/commands/orchestrator.js.map +0 -1
  161. package/dist/commands/performance-optimizer.d.ts +0 -30
  162. package/dist/commands/performance-optimizer.d.ts.map +0 -1
  163. package/dist/commands/performance-optimizer.js +0 -650
  164. package/dist/commands/performance-optimizer.js.map +0 -1
  165. package/dist/commands/plugins.d.ts +0 -87
  166. package/dist/commands/plugins.d.ts.map +0 -1
  167. package/dist/commands/plugins.js +0 -685
  168. package/dist/commands/plugins.js.map +0 -1
  169. package/dist/commands/rag.d.ts +0 -7
  170. package/dist/commands/rag.d.ts.map +0 -1
  171. package/dist/commands/rag.js +0 -748
  172. package/dist/commands/rag.js.map +0 -1
  173. package/dist/commands/session.d.ts +0 -41
  174. package/dist/commands/session.d.ts.map +0 -1
  175. package/dist/commands/session.js +0 -441
  176. package/dist/commands/session.js.map +0 -1
  177. package/dist/commands/setup.d.ts +0 -29
  178. package/dist/commands/setup.d.ts.map +0 -1
  179. package/dist/commands/setup.js +0 -397
  180. package/dist/commands/setup.js.map +0 -1
  181. package/dist/commands/test-init.d.ts +0 -9
  182. package/dist/commands/test-init.d.ts.map +0 -1
  183. package/dist/commands/test-init.js +0 -222
  184. package/dist/commands/test-init.js.map +0 -1
  185. package/dist/commands/test.d.ts +0 -25
  186. package/dist/commands/test.d.ts.map +0 -1
  187. package/dist/commands/test.js +0 -217
  188. package/dist/commands/test.js.map +0 -1
  189. package/dist/commands/vp.d.ts +0 -7
  190. package/dist/commands/vp.d.ts.map +0 -1
  191. package/dist/commands/vp.js +0 -571
  192. package/dist/commands/vp.js.map +0 -1
  193. package/dist/commands/watch.d.ts +0 -76
  194. package/dist/commands/watch.d.ts.map +0 -1
  195. package/dist/commands/watch.js +0 -613
  196. package/dist/commands/watch.js.map +0 -1
  197. package/dist/commands/worktree.d.ts +0 -63
  198. package/dist/commands/worktree.d.ts.map +0 -1
  199. package/dist/commands/worktree.js +0 -774
  200. package/dist/commands/worktree.js.map +0 -1
  201. package/dist/context/context-manager.d.ts +0 -155
  202. package/dist/context/context-manager.d.ts.map +0 -1
  203. package/dist/context/context-manager.js +0 -383
  204. package/dist/context/context-manager.js.map +0 -1
  205. package/dist/context/index.d.ts +0 -3
  206. package/dist/context/index.d.ts.map +0 -1
  207. package/dist/context/index.js +0 -6
  208. package/dist/context/index.js.map +0 -1
  209. package/dist/context/session-manager.d.ts +0 -207
  210. package/dist/context/session-manager.d.ts.map +0 -1
  211. package/dist/context/session-manager.js +0 -686
  212. package/dist/context/session-manager.js.map +0 -1
  213. package/dist/index.d.ts +0 -8
  214. package/dist/index.d.ts.map +0 -1
  215. package/dist/index.js +0 -51
  216. package/dist/index.js.map +0 -1
  217. package/dist/interactive/interactive-mode.d.ts +0 -76
  218. package/dist/interactive/interactive-mode.d.ts.map +0 -1
  219. package/dist/interactive/interactive-mode.js +0 -732
  220. package/dist/interactive/interactive-mode.js.map +0 -1
  221. package/dist/nlp/command-mapper.d.ts +0 -174
  222. package/dist/nlp/command-mapper.d.ts.map +0 -1
  223. package/dist/nlp/command-mapper.js +0 -624
  224. package/dist/nlp/command-mapper.js.map +0 -1
  225. package/dist/nlp/command-parser.d.ts +0 -106
  226. package/dist/nlp/command-parser.d.ts.map +0 -1
  227. package/dist/nlp/command-parser.js +0 -417
  228. package/dist/nlp/command-parser.js.map +0 -1
  229. package/dist/nlp/index.d.ts +0 -5
  230. package/dist/nlp/index.d.ts.map +0 -1
  231. package/dist/nlp/index.js +0 -8
  232. package/dist/nlp/index.js.map +0 -1
  233. package/dist/nlp/intent-classifier.d.ts +0 -59
  234. package/dist/nlp/intent-classifier.d.ts.map +0 -1
  235. package/dist/nlp/intent-classifier.js +0 -384
  236. package/dist/nlp/intent-classifier.js.map +0 -1
  237. package/dist/nlp/intent-parser.d.ts +0 -152
  238. package/dist/nlp/intent-parser.d.ts.map +0 -1
  239. package/dist/nlp/intent-parser.js +0 -744
  240. package/dist/nlp/intent-parser.js.map +0 -1
  241. package/dist/plugins/plugin-manager.d.ts +0 -120
  242. package/dist/plugins/plugin-manager.d.ts.map +0 -1
  243. package/dist/plugins/plugin-manager.js +0 -595
  244. package/dist/plugins/plugin-manager.js.map +0 -1
  245. package/dist/types/index.d.ts +0 -224
  246. package/dist/types/index.d.ts.map +0 -1
  247. package/dist/types/index.js +0 -3
  248. package/dist/types/index.js.map +0 -1
  249. package/dist/utils/backup-rollback-manager.d.ts +0 -72
  250. package/dist/utils/backup-rollback-manager.d.ts.map +0 -1
  251. package/dist/utils/backup-rollback-manager.js +0 -289
  252. package/dist/utils/backup-rollback-manager.js.map +0 -1
  253. package/dist/utils/claude-config-installer.d.ts +0 -98
  254. package/dist/utils/claude-config-installer.d.ts.map +0 -1
  255. package/dist/utils/claude-config-installer.js +0 -678
  256. package/dist/utils/claude-config-installer.js.map +0 -1
  257. package/dist/utils/config-manager.d.ts +0 -73
  258. package/dist/utils/config-manager.d.ts.map +0 -1
  259. package/dist/utils/config-manager.js +0 -339
  260. package/dist/utils/config-manager.js.map +0 -1
  261. package/dist/utils/error-handler.d.ts +0 -46
  262. package/dist/utils/error-handler.d.ts.map +0 -1
  263. package/dist/utils/error-handler.js +0 -169
  264. package/dist/utils/error-handler.js.map +0 -1
  265. package/dist/utils/logger.d.ts +0 -25
  266. package/dist/utils/logger.d.ts.map +0 -1
  267. package/dist/utils/logger.js +0 -105
  268. package/dist/utils/logger.js.map +0 -1
  269. package/src/commands/computer-setup-commands.ts +0 -872
@@ -0,0 +1,520 @@
1
+ /**
2
+ * Command Interface - Core types and contracts for the Wundr CLI framework.
3
+ *
4
+ * Every CLI command implements CommandDefinition. This provides:
5
+ * - Consistent argument/option typing via generics
6
+ * - Built-in validation before execution
7
+ * - Structured output via CommandResult
8
+ * - Optional rollback on failure
9
+ * - Metadata for auto-generated help text and shell completions
10
+ *
11
+ * @module framework/command-interface
12
+ */
13
+
14
+ import type { Command as CommanderCommand } from 'commander';
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Command Categories
18
+ // ---------------------------------------------------------------------------
19
+
20
+ /**
21
+ * Grouping categories for commands. Used in help text and completion scripts.
22
+ */
23
+ export type CommandCategory =
24
+ | 'daemon'
25
+ | 'agent'
26
+ | 'memory'
27
+ | 'config'
28
+ | 'setup'
29
+ | 'batch'
30
+ | 'plugin'
31
+ | 'governance'
32
+ | 'analysis'
33
+ | 'development'
34
+ | 'monitoring';
35
+
36
+ /**
37
+ * Human-readable labels for each category.
38
+ */
39
+ export const CATEGORY_LABELS: Record<CommandCategory, string> = {
40
+ daemon: 'Daemon Management',
41
+ agent: 'Agent Management',
42
+ memory: 'Memory & RAG',
43
+ config: 'Configuration',
44
+ setup: 'Machine Setup',
45
+ batch: 'Batch Operations',
46
+ plugin: 'Plugin Management',
47
+ governance: 'Governance & Compliance',
48
+ analysis: 'Code Analysis',
49
+ development: 'Development Tools',
50
+ monitoring: 'Monitoring & Dashboard',
51
+ };
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // Argument & Option Definitions
55
+ // ---------------------------------------------------------------------------
56
+
57
+ /**
58
+ * Positional argument definition for a command.
59
+ */
60
+ export interface ArgumentDefinition {
61
+ /** Argument name (used in help text and as the key in parsed args) */
62
+ name: string;
63
+
64
+ /** Human-readable description */
65
+ description: string;
66
+
67
+ /** Whether this argument is required */
68
+ required?: boolean;
69
+
70
+ /** Default value if not provided */
71
+ defaultValue?: string;
72
+
73
+ /**
74
+ * Optional function that returns valid completions for this argument.
75
+ * Used by shell completion generation.
76
+ */
77
+ completions?: () => Promise<string[]>;
78
+
79
+ /** Variadic argument (collects remaining args into array) */
80
+ variadic?: boolean;
81
+ }
82
+
83
+ /**
84
+ * Option (flag) definition for a command.
85
+ */
86
+ export interface OptionDefinition {
87
+ /** Flag specification in Commander.js format, e.g. '-p, --port <number>' */
88
+ flags: string;
89
+
90
+ /** Human-readable description */
91
+ description: string;
92
+
93
+ /** Default value */
94
+ defaultValue?: unknown;
95
+
96
+ /**
97
+ * Whether this option is required.
98
+ * Commander marks it required; missing value causes an error before execute().
99
+ */
100
+ required?: boolean;
101
+
102
+ /**
103
+ * Allowed values. If set, Commander validates the value is in this set.
104
+ */
105
+ choices?: string[];
106
+
107
+ /**
108
+ * Environment variable that can provide this option's value.
109
+ * Checked if the option is not passed on the command line.
110
+ */
111
+ envVar?: string;
112
+
113
+ /**
114
+ * Optional function that returns valid completions for this option.
115
+ * Used by shell completion generation.
116
+ */
117
+ completions?: () => Promise<string[]>;
118
+
119
+ /**
120
+ * Whether this option conflicts with another option.
121
+ * Validated before execute().
122
+ */
123
+ conflicts?: string[];
124
+ }
125
+
126
+ /**
127
+ * Example usage shown in help text.
128
+ */
129
+ export interface CommandExample {
130
+ /** The command invocation */
131
+ command: string;
132
+
133
+ /** What this example demonstrates */
134
+ description: string;
135
+ }
136
+
137
+ // ---------------------------------------------------------------------------
138
+ // Validation
139
+ // ---------------------------------------------------------------------------
140
+
141
+ /**
142
+ * Result of command argument/option validation.
143
+ */
144
+ export interface ValidationResult {
145
+ /** Whether validation passed */
146
+ valid: boolean;
147
+
148
+ /** Validation error messages (empty when valid) */
149
+ errors: ValidationError[];
150
+ }
151
+
152
+ /**
153
+ * A single validation error with field context.
154
+ */
155
+ export interface ValidationError {
156
+ /** Which field (argument or option name) failed validation */
157
+ field: string;
158
+
159
+ /** Human-readable error message */
160
+ message: string;
161
+
162
+ /** Suggestion for how to fix the error */
163
+ suggestion?: string;
164
+ }
165
+
166
+ /**
167
+ * Helper to create a passing validation result.
168
+ */
169
+ export function validationOk(): ValidationResult {
170
+ return { valid: true, errors: [] };
171
+ }
172
+
173
+ /**
174
+ * Helper to create a failing validation result.
175
+ */
176
+ export function validationFail(...errors: ValidationError[]): ValidationResult {
177
+ return { valid: false, errors };
178
+ }
179
+
180
+ // ---------------------------------------------------------------------------
181
+ // Command Context
182
+ // ---------------------------------------------------------------------------
183
+
184
+ /**
185
+ * Runtime context passed to every command's execute() method.
186
+ *
187
+ * The context is constructed by the CLI runner and contains references
188
+ * to shared services. Commands should NOT import singletons directly;
189
+ * instead they receive everything through context for testability.
190
+ */
191
+ export interface CommandContext {
192
+ /** Parsed global options (--verbose, --quiet, --json, etc.) */
193
+ globalOptions: GlobalOptions;
194
+
195
+ /** Logger instance respecting current verbosity */
196
+ logger: ContextLogger;
197
+
198
+ /** Output formatter for consistent display */
199
+ formatter: OutputFormatterInterface;
200
+
201
+ /** Configuration manager */
202
+ config: ConfigManagerInterface;
203
+
204
+ /** Current working directory */
205
+ cwd: string;
206
+
207
+ /** Whether running in a CI environment */
208
+ ci: boolean;
209
+
210
+ /** Whether stdout is a TTY (affects interactive features) */
211
+ isTTY: boolean;
212
+
213
+ /** Abort signal for graceful cancellation */
214
+ signal?: AbortSignal;
215
+ }
216
+
217
+ /**
218
+ * Global CLI options inherited by all commands.
219
+ */
220
+ export interface GlobalOptions {
221
+ verbose: boolean;
222
+ quiet: boolean;
223
+ json: boolean;
224
+ noColor: boolean;
225
+ dryRun: boolean;
226
+ config?: string;
227
+ }
228
+
229
+ /**
230
+ * Minimal logger interface for command context.
231
+ */
232
+ export interface ContextLogger {
233
+ debug(message: string, ...args: unknown[]): void;
234
+ info(message: string, ...args: unknown[]): void;
235
+ warn(message: string, ...args: unknown[]): void;
236
+ error(message: string, ...args: unknown[]): void;
237
+ success(message: string, ...args: unknown[]): void;
238
+ }
239
+
240
+ /**
241
+ * Minimal output formatter interface for command context.
242
+ * Full implementation is in output-formatter.ts.
243
+ */
244
+ export interface OutputFormatterInterface {
245
+ table(data: Record<string, unknown>[], options?: unknown): string;
246
+ json(data: unknown, pretty?: boolean): string;
247
+ keyValue(data: Record<string, unknown>): string;
248
+ list(items: string[], ordered?: boolean): string;
249
+ status(state: string, label: string): string;
250
+ progressBar(current: number, total: number, width?: number): string;
251
+ }
252
+
253
+ /**
254
+ * Minimal config manager interface for command context.
255
+ */
256
+ export interface ConfigManagerInterface {
257
+ get<T = unknown>(key: string): T | undefined;
258
+ set(key: string, value: unknown): void;
259
+ loadConfig(path?: string): Promise<void>;
260
+ saveConfig(): Promise<void>;
261
+ }
262
+
263
+ // ---------------------------------------------------------------------------
264
+ // Command Result
265
+ // ---------------------------------------------------------------------------
266
+
267
+ /**
268
+ * Structured result returned by every command's execute() method.
269
+ *
270
+ * Commands return data, not formatted strings. The CLI runner uses
271
+ * the result + global options to determine final output format.
272
+ */
273
+ export interface CommandResult<T = unknown> {
274
+ /** Exit code. 0 = success, non-zero = failure. */
275
+ exitCode: number;
276
+
277
+ /**
278
+ * Structured data payload. When --json is passed, this is serialized
279
+ * directly. Otherwise the CLI runner uses the formatter.
280
+ */
281
+ data?: T;
282
+
283
+ /** Human-readable message for non-JSON output */
284
+ message?: string;
285
+
286
+ /**
287
+ * Warnings that should be displayed but don't constitute failure.
288
+ */
289
+ warnings?: string[];
290
+ }
291
+
292
+ /**
293
+ * Helper to create a success result.
294
+ */
295
+ export function commandSuccess<T>(
296
+ data?: T,
297
+ message?: string
298
+ ): CommandResult<T> {
299
+ return { exitCode: 0, data, message };
300
+ }
301
+
302
+ /**
303
+ * Helper to create a failure result.
304
+ */
305
+ export function commandFailure(
306
+ message: string,
307
+ exitCode: number = 1
308
+ ): CommandResult {
309
+ return { exitCode, message };
310
+ }
311
+
312
+ // ---------------------------------------------------------------------------
313
+ // Command Definition
314
+ // ---------------------------------------------------------------------------
315
+
316
+ /**
317
+ * The core interface that every CLI command must implement.
318
+ *
319
+ * @typeParam TArgs - Shape of parsed positional arguments
320
+ * @typeParam TOpts - Shape of parsed options
321
+ * @typeParam TResult - Shape of the data payload in CommandResult
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * const statusCommand: CommandDefinition<{}, { json?: boolean }, DaemonStatus> = {
326
+ * name: 'status',
327
+ * description: 'Show orchestrator daemon status',
328
+ * category: 'daemon',
329
+ * options: [
330
+ * { flags: '--json', description: 'Output as JSON' },
331
+ * ],
332
+ * examples: [
333
+ * { command: 'wundr status', description: 'Show daemon status' },
334
+ * { command: 'wundr status --json', description: 'Get status as JSON' },
335
+ * ],
336
+ * async execute(_args, options, context) {
337
+ * const status = await getDaemonStatus();
338
+ * return commandSuccess(status, status.running ? 'Daemon is running' : 'Daemon is stopped');
339
+ * },
340
+ * };
341
+ * ```
342
+ */
343
+ export interface CommandDefinition<
344
+ TArgs = Record<string, unknown>,
345
+ TOpts = Record<string, unknown>,
346
+ TResult = unknown,
347
+ > {
348
+ /** Unique command name. Use colon-separated for subcommands: 'agent:list' */
349
+ name: string;
350
+
351
+ /** Human-readable description shown in help text */
352
+ description: string;
353
+
354
+ /** Category for grouping in help output */
355
+ category?: CommandCategory;
356
+
357
+ /** Alternative names for this command */
358
+ aliases?: string[];
359
+
360
+ /**
361
+ * Whether this command is hidden from help text.
362
+ * Useful for deprecated or internal commands.
363
+ */
364
+ hidden?: boolean;
365
+
366
+ /** Positional argument definitions */
367
+ arguments?: ArgumentDefinition[];
368
+
369
+ /** Option/flag definitions */
370
+ options?: OptionDefinition[];
371
+
372
+ /** Example invocations shown in help text */
373
+ examples?: CommandExample[];
374
+
375
+ /**
376
+ * Subcommands nested under this command.
377
+ * For example, 'agent' has subcommands 'list', 'spawn', 'stop'.
378
+ */
379
+ subcommands?: CommandDefinition[];
380
+
381
+ /**
382
+ * Validate parsed arguments and options before execution.
383
+ *
384
+ * Return `validationOk()` to proceed, or `validationFail(...)` to abort
385
+ * with a helpful error message. If not provided, validation always passes.
386
+ *
387
+ * @param args - Parsed positional arguments
388
+ * @param options - Parsed options
389
+ * @param context - Command execution context
390
+ */
391
+ validate?(
392
+ args: TArgs,
393
+ options: TOpts,
394
+ context: CommandContext
395
+ ): ValidationResult | Promise<ValidationResult>;
396
+
397
+ /**
398
+ * Execute the command.
399
+ *
400
+ * @param args - Parsed positional arguments
401
+ * @param options - Parsed options
402
+ * @param context - Command execution context
403
+ * @returns Structured result with exit code and optional data
404
+ */
405
+ execute(
406
+ args: TArgs,
407
+ options: TOpts,
408
+ context: CommandContext
409
+ ): Promise<CommandResult<TResult>>;
410
+
411
+ /**
412
+ * Optional cleanup when execute() throws or returns a non-zero exit code.
413
+ * Use this to undo partial changes (e.g., remove a PID file on start failure).
414
+ *
415
+ * @param error - The error that caused the rollback
416
+ * @param context - Command execution context
417
+ */
418
+ rollback?(error: Error, context: CommandContext): Promise<void>;
419
+ }
420
+
421
+ // ---------------------------------------------------------------------------
422
+ // Command Lifecycle Hooks
423
+ // ---------------------------------------------------------------------------
424
+
425
+ /**
426
+ * Hook that runs before or after command execution.
427
+ */
428
+ export interface CommandHook {
429
+ /** When to run this hook */
430
+ phase: 'preValidate' | 'postValidate' | 'preExecute' | 'postExecute';
431
+
432
+ /**
433
+ * Optional filter: only run this hook for specific commands.
434
+ * If not provided, the hook runs for all commands.
435
+ */
436
+ commands?: string[];
437
+
438
+ /**
439
+ * The hook handler. Return false to abort the pipeline (preValidate/preExecute only).
440
+ */
441
+ handler(
442
+ command: CommandDefinition,
443
+ context: CommandContext,
444
+ result?: CommandResult
445
+ ): Promise<void | boolean>;
446
+ }
447
+
448
+ // ---------------------------------------------------------------------------
449
+ // Command Module
450
+ // ---------------------------------------------------------------------------
451
+
452
+ /**
453
+ * A command module is the unit of auto-discovery.
454
+ *
455
+ * Each file in the commands/ directory can export a `CommandModule` to be
456
+ * automatically registered by the `CommandRegistry`.
457
+ *
458
+ * @example
459
+ * ```typescript
460
+ * // commands/status.ts
461
+ * export const module: CommandModule = {
462
+ * command: statusCommand,
463
+ * hooks: [telemetryHook],
464
+ * };
465
+ * ```
466
+ */
467
+ export interface CommandModule {
468
+ /** The primary command definition */
469
+ command: CommandDefinition;
470
+
471
+ /** Optional lifecycle hooks specific to this command */
472
+ hooks?: CommandHook[];
473
+ }
474
+
475
+ // ---------------------------------------------------------------------------
476
+ // Legacy Adapter
477
+ // ---------------------------------------------------------------------------
478
+
479
+ /**
480
+ * Adapter for wrapping existing Commander.js command functions into the
481
+ * CommandDefinition interface. This enables incremental migration.
482
+ *
483
+ * @param name - Command name
484
+ * @param description - Command description
485
+ * @param factory - Existing factory function that returns a Commander.Command
486
+ * @param category - Optional category
487
+ *
488
+ * @example
489
+ * ```typescript
490
+ * const wrapped = wrapLegacyCommand(
491
+ * 'orchestrator',
492
+ * 'Manage the Orchestrator Daemon',
493
+ * createOrchestratorCommand,
494
+ * 'daemon'
495
+ * );
496
+ * registry.register(wrapped);
497
+ * ```
498
+ */
499
+ export function wrapLegacyCommand(
500
+ name: string,
501
+ description: string,
502
+ factory: () => CommanderCommand,
503
+ category?: CommandCategory
504
+ ): CommandDefinition {
505
+ return {
506
+ name,
507
+ description,
508
+ category,
509
+ hidden: false,
510
+ async execute(_args, _options, context) {
511
+ // Legacy commands handle their own output.
512
+ // The wrapper just ensures they integrate with the registry.
513
+ context.logger.debug(`Delegating to legacy command: ${name}`);
514
+ return { exitCode: 0, message: `Legacy command ${name} executed` };
515
+ },
516
+ // The actual Commander.Command is attached by the registry during buildProgram()
517
+ // via the _legacyFactory property.
518
+ _legacyFactory: factory,
519
+ } as CommandDefinition & { _legacyFactory: () => CommanderCommand };
520
+ }