@lumenflow/mcp 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/bin.d.ts +16 -0
  2. package/dist/bin.d.ts.map +1 -0
  3. package/dist/bin.js.map +1 -0
  4. package/dist/cli-runner.d.ts +58 -0
  5. package/dist/cli-runner.d.ts.map +1 -0
  6. package/dist/cli-runner.js +164 -0
  7. package/dist/cli-runner.js.map +1 -0
  8. package/dist/index.d.ts +37 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/mcp-constants.d.ts +177 -0
  12. package/dist/mcp-constants.d.ts.map +1 -0
  13. package/dist/mcp-constants.js +197 -0
  14. package/dist/mcp-constants.js.map +1 -0
  15. package/dist/resources.d.ts +53 -0
  16. package/dist/resources.d.ts.map +1 -0
  17. package/dist/resources.js +131 -0
  18. package/dist/resources.js.map +1 -0
  19. package/dist/runtime-cache.d.ts +7 -0
  20. package/dist/runtime-cache.d.ts.map +1 -0
  21. package/dist/runtime-cache.js +28 -0
  22. package/dist/runtime-cache.js.map +1 -0
  23. package/dist/runtime-tool-resolver.constants.d.ts +26 -0
  24. package/dist/runtime-tool-resolver.constants.d.ts.map +1 -0
  25. package/dist/runtime-tool-resolver.constants.js +36 -0
  26. package/dist/runtime-tool-resolver.constants.js.map +1 -0
  27. package/dist/runtime-tool-resolver.d.ts +5 -0
  28. package/dist/runtime-tool-resolver.d.ts.map +1 -0
  29. package/dist/runtime-tool-resolver.js +2030 -0
  30. package/dist/runtime-tool-resolver.js.map +1 -0
  31. package/dist/server.d.ts +58 -0
  32. package/dist/server.d.ts.map +1 -0
  33. package/dist/server.js +212 -0
  34. package/dist/server.js.map +1 -0
  35. package/dist/tools/agent-tools.d.ts +18 -0
  36. package/dist/tools/agent-tools.d.ts.map +1 -0
  37. package/dist/tools/agent-tools.js +235 -0
  38. package/dist/tools/agent-tools.js.map +1 -0
  39. package/dist/tools/context-tools.d.ts +13 -0
  40. package/dist/tools/context-tools.d.ts.map +1 -0
  41. package/dist/tools/context-tools.js +58 -0
  42. package/dist/tools/context-tools.js.map +1 -0
  43. package/dist/tools/flow-tools.d.ts +22 -0
  44. package/dist/tools/flow-tools.d.ts.map +1 -0
  45. package/dist/tools/flow-tools.js +130 -0
  46. package/dist/tools/flow-tools.js.map +1 -0
  47. package/dist/tools/initiative-tools.d.ts +34 -0
  48. package/dist/tools/initiative-tools.d.ts.map +1 -0
  49. package/dist/tools/initiative-tools.js +420 -0
  50. package/dist/tools/initiative-tools.js.map +1 -0
  51. package/dist/tools/memory-tools.d.ts +58 -0
  52. package/dist/tools/memory-tools.d.ts.map +1 -0
  53. package/dist/tools/memory-tools.js +523 -0
  54. package/dist/tools/memory-tools.js.map +1 -0
  55. package/dist/tools/orchestration-tools.d.ts +18 -0
  56. package/dist/tools/orchestration-tools.d.ts.map +1 -0
  57. package/dist/tools/orchestration-tools.js +202 -0
  58. package/dist/tools/orchestration-tools.js.map +1 -0
  59. package/dist/tools/parity-tools.d.ts +138 -0
  60. package/dist/tools/parity-tools.d.ts.map +1 -0
  61. package/dist/tools/parity-tools.js +1690 -0
  62. package/dist/tools/parity-tools.js.map +1 -0
  63. package/dist/tools/runtime-task-constants.d.ts +19 -0
  64. package/dist/tools/runtime-task-constants.d.ts.map +1 -0
  65. package/dist/tools/runtime-task-constants.js +21 -0
  66. package/dist/tools/runtime-task-constants.js.map +1 -0
  67. package/dist/tools/runtime-task-tools.d.ts +10 -0
  68. package/dist/tools/runtime-task-tools.d.ts.map +1 -0
  69. package/dist/tools/runtime-task-tools.js +116 -0
  70. package/dist/tools/runtime-task-tools.js.map +1 -0
  71. package/dist/tools/setup-tools.d.ts +34 -0
  72. package/dist/tools/setup-tools.d.ts.map +1 -0
  73. package/dist/tools/setup-tools.js +254 -0
  74. package/dist/tools/setup-tools.js.map +1 -0
  75. package/dist/tools/validation-tools.d.ts +26 -0
  76. package/dist/tools/validation-tools.d.ts.map +1 -0
  77. package/dist/tools/validation-tools.js +180 -0
  78. package/dist/tools/validation-tools.js.map +1 -0
  79. package/dist/tools/wu-tools.d.ts +101 -0
  80. package/dist/tools/wu-tools.d.ts.map +1 -0
  81. package/dist/tools/wu-tools.js +964 -0
  82. package/dist/tools/wu-tools.js.map +1 -0
  83. package/dist/tools-shared.d.ts +257 -0
  84. package/dist/tools-shared.d.ts.map +1 -0
  85. package/dist/tools-shared.js +410 -0
  86. package/dist/tools-shared.js.map +1 -0
  87. package/dist/tools.d.ts +99 -0
  88. package/dist/tools.d.ts.map +1 -0
  89. package/dist/tools.js +253 -0
  90. package/dist/tools.js.map +1 -0
  91. package/dist/worktree-enforcement.d.ts +32 -0
  92. package/dist/worktree-enforcement.d.ts.map +1 -0
  93. package/dist/worktree-enforcement.js +154 -0
  94. package/dist/worktree-enforcement.js.map +1 -0
  95. package/package.json +5 -5
@@ -0,0 +1,1690 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * @file parity-tools.ts
5
+ * @description Wave-1 and Wave-2 public parity tool implementations
6
+ *
7
+ * WU-1642: Extracted from tools.ts during modular decomposition.
8
+ * WU-1482: Wave-1 public parity tools
9
+ * WU-1483: Wave-2 public parity tools (file, git, plan, signal, wu:proto)
10
+ */
11
+ import path from 'node:path';
12
+ import { z } from 'zod';
13
+ import { gatesSchema, lumenflowInitSchema, initiativePlanSchema } from '@lumenflow/core';
14
+ import { ErrorCodes, ErrorMessages, CliArgs, SharedErrorMessages, SuccessMessages, success, error, buildGatesArgs, executeViaPack, } from '../tools-shared.js';
15
+ import { CliCommands, MetadataKeys } from '../mcp-constants.js';
16
+ import { checkWorktreeEnforcement } from '../worktree-enforcement.js';
17
+ // WU-1482: Schemas for wave-1 parity commands not yet modeled in @lumenflow/core
18
+ const backlogPruneSchema = z.object({
19
+ execute: z.boolean().optional(),
20
+ dry_run: z.boolean().optional(),
21
+ stale_days_in_progress: z.number().optional(),
22
+ stale_days_ready: z.number().optional(),
23
+ archive_days: z.number().optional(),
24
+ });
25
+ const docsSyncMcpSchema = z.object({
26
+ vendor: z.enum(['claude', 'cursor', 'aider', 'all', 'none']).optional(),
27
+ force: z.boolean().optional(),
28
+ });
29
+ const laneHealthSchema = z.object({
30
+ json: z.boolean().optional(),
31
+ verbose: z.boolean().optional(),
32
+ no_coverage: z.boolean().optional(),
33
+ });
34
+ const laneSuggestSchema = z.object({
35
+ dry_run: z.boolean().optional(),
36
+ interactive: z.boolean().optional(),
37
+ output: z.string().optional(),
38
+ json: z.boolean().optional(),
39
+ no_llm: z.boolean().optional(),
40
+ include_git: z.boolean().optional(),
41
+ });
42
+ /**
43
+ * WU-1802: Fallback messages for lane tools migrated to executeViaPack.
44
+ */
45
+ const LaneMessages = {
46
+ HEALTH_PASSED: 'Lane health check complete',
47
+ HEALTH_FAILED: 'lane:health failed',
48
+ SUGGEST_GENERATED: 'Lane suggestions generated',
49
+ SUGGEST_FAILED: 'lane:suggest failed',
50
+ };
51
+ const LaneFlags = {
52
+ NO_COVERAGE: '--no-coverage',
53
+ DRY_RUN: '--dry-run',
54
+ INTERACTIVE: '--interactive',
55
+ OUTPUT: '--output',
56
+ NO_LLM: '--no-llm',
57
+ INCLUDE_GIT: '--include-git',
58
+ };
59
+ const GatesRuntimeMessages = {
60
+ GATES_FAILED: 'gates failed',
61
+ GATES_DOCS_PASSED: 'Docs-only gates passed',
62
+ GATES_DOCS_FAILED: 'gates:docs failed',
63
+ LUMENFLOW_GATES_FAILED: 'lumenflow-gates failed',
64
+ };
65
+ const GatesRuntimeConstants = {
66
+ FALLBACK_TIMEOUT_MS: 600000,
67
+ };
68
+ const stateBootstrapSchema = z.object({
69
+ execute: z.boolean().optional(),
70
+ dry_run: z.boolean().optional(),
71
+ force: z.boolean().optional(),
72
+ wu_dir: z.string().optional(),
73
+ state_dir: z.string().optional(),
74
+ });
75
+ const stateCleanupSchema = z.object({
76
+ dry_run: z.boolean().optional(),
77
+ signals_only: z.boolean().optional(),
78
+ memory_only: z.boolean().optional(),
79
+ events_only: z.boolean().optional(),
80
+ json: z.boolean().optional(),
81
+ quiet: z.boolean().optional(),
82
+ base_dir: z.string().optional(),
83
+ });
84
+ const stateDoctorSchema = z.object({
85
+ fix: z.boolean().optional(),
86
+ dry_run: z.boolean().optional(),
87
+ json: z.boolean().optional(),
88
+ quiet: z.boolean().optional(),
89
+ base_dir: z.string().optional(),
90
+ });
91
+ const syncTemplatesMcpSchema = z.object({
92
+ dry_run: z.boolean().optional(),
93
+ verbose: z.boolean().optional(),
94
+ check_drift: z.boolean().optional(),
95
+ });
96
+ // WU-1483: Schemas for wave-2 parity commands not yet modeled in @lumenflow/core
97
+ const fileReadSchema = z.object({
98
+ path: z.string().optional(),
99
+ encoding: z.string().optional(),
100
+ start_line: z.number().optional(),
101
+ end_line: z.number().optional(),
102
+ max_size: z.number().optional(),
103
+ });
104
+ const fileWriteSchema = z.object({
105
+ path: z.string().optional(),
106
+ content: z.string().optional(),
107
+ encoding: z.string().optional(),
108
+ no_create_dirs: z.boolean().optional(),
109
+ });
110
+ const fileEditSchema = z.object({
111
+ path: z.string().optional(),
112
+ old_string: z.string().optional(),
113
+ new_string: z.string().optional(),
114
+ encoding: z.string().optional(),
115
+ replace_all: z.boolean().optional(),
116
+ });
117
+ const fileDeleteSchema = z.object({
118
+ path: z.string().optional(),
119
+ recursive: z.boolean().optional(),
120
+ force: z.boolean().optional(),
121
+ });
122
+ const gitStatusSchema = z.object({
123
+ base_dir: z.string().optional(),
124
+ path: z.string().optional(),
125
+ porcelain: z.boolean().optional(),
126
+ short: z.boolean().optional(),
127
+ });
128
+ const gitDiffSchema = z.object({
129
+ base_dir: z.string().optional(),
130
+ ref: z.string().optional(),
131
+ staged: z.boolean().optional(),
132
+ name_only: z.boolean().optional(),
133
+ stat: z.boolean().optional(),
134
+ path: z.string().optional(),
135
+ });
136
+ const gitLogSchema = z.object({
137
+ base_dir: z.string().optional(),
138
+ ref: z.string().optional(),
139
+ oneline: z.boolean().optional(),
140
+ max_count: z.number().optional(),
141
+ format: z.string().optional(),
142
+ since: z.string().optional(),
143
+ author: z.string().optional(),
144
+ });
145
+ const gitBranchSchema = z.object({
146
+ base_dir: z.string().optional(),
147
+ list: z.boolean().optional(),
148
+ all: z.boolean().optional(),
149
+ remotes: z.boolean().optional(),
150
+ show_current: z.boolean().optional(),
151
+ contains: z.string().optional(),
152
+ });
153
+ const planCreateSchema = z.object({
154
+ id: z.string().optional(),
155
+ title: z.string().optional(),
156
+ });
157
+ const planEditSchema = z.object({
158
+ id: z.string().optional(),
159
+ section: z.string().optional(),
160
+ content: z.string().optional(),
161
+ append: z.string().optional(),
162
+ });
163
+ const planLinkSchema = z.object({
164
+ id: z.string().optional(),
165
+ plan: z.string().optional(),
166
+ });
167
+ const planPromoteSchema = z.object({
168
+ id: z.string().optional(),
169
+ force: z.boolean().optional(),
170
+ });
171
+ const signalCleanupSchema = z.object({
172
+ dry_run: z.boolean().optional(),
173
+ ttl: z.string().optional(),
174
+ unread_ttl: z.string().optional(),
175
+ max_entries: z.number().optional(),
176
+ json: z.boolean().optional(),
177
+ quiet: z.boolean().optional(),
178
+ base_dir: z.string().optional(),
179
+ });
180
+ // WU-1902: Schemas for config:set and config:get commands
181
+ const configSetSchema = z.object({
182
+ key: z.string().optional(),
183
+ value: z.string().optional(),
184
+ });
185
+ const configGetSchema = z.object({
186
+ key: z.string().optional(),
187
+ });
188
+ const cloudConnectSchema = z.object({
189
+ endpoint: z.string().optional(),
190
+ org_id: z.string().optional(),
191
+ project_id: z.string().optional(),
192
+ token_env: z.string().optional(),
193
+ policy_mode: z.enum(['authoritative', 'tighten-only', 'dev-override']).optional(),
194
+ sync_interval: z.number().int().positive().optional(),
195
+ output: z.string().optional(),
196
+ force: z.boolean().optional(),
197
+ });
198
+ const onboardSchema = z.object({
199
+ yes: z.boolean().optional(),
200
+ domain: z.enum(['software-delivery', 'infra', 'custom']).optional(),
201
+ project_name: z.string().optional(),
202
+ output: z.string().optional(),
203
+ force: z.boolean().optional(),
204
+ skip_pack_install: z.boolean().optional(),
205
+ skip_dashboard: z.boolean().optional(),
206
+ });
207
+ const workspaceInitSchema = z.object({
208
+ yes: z.boolean().optional(),
209
+ output: z.string().optional(),
210
+ force: z.boolean().optional(),
211
+ });
212
+ const wuProtoSchema = z.object({
213
+ lane: z.string().optional(),
214
+ title: z.string().optional(),
215
+ description: z.string().optional(),
216
+ code_paths: z.array(z.string()).optional(),
217
+ labels: z.array(z.string()).optional(),
218
+ assigned_to: z.string().optional(),
219
+ });
220
+ const BootstrapFlags = {
221
+ ENDPOINT: '--endpoint',
222
+ ORG_ID: '--org-id',
223
+ PROJECT_ID: '--project-id',
224
+ TOKEN_ENV: '--token-env',
225
+ POLICY_MODE: '--policy-mode',
226
+ SYNC_INTERVAL: '--sync-interval',
227
+ OUTPUT: '--output',
228
+ YES: '--yes',
229
+ DOMAIN: '--domain',
230
+ PROJECT_NAME: '--project-name',
231
+ SKIP_PACK_INSTALL: '--skip-pack-install',
232
+ SKIP_DASHBOARD: '--skip-dashboard',
233
+ };
234
+ const GIT_RUNTIME_TOOL_NAME = CliCommands.GIT_STATUS;
235
+ const GIT_BINARY = 'git';
236
+ const RUNTIME_PROJECT_ROOT_KEY = MetadataKeys.PROJECT_ROOT;
237
+ const GIT_COMMAND_RESULT_STDOUT_KEY = 'stdout';
238
+ const GIT_COMMAND_RESULTS_KEY = 'command_results';
239
+ const GIT_OUTPUT_KEY = 'output';
240
+ function unwrapExecuteViaPackData(data) {
241
+ if (!data || typeof data !== 'object') {
242
+ return data;
243
+ }
244
+ if (!('success' in data)) {
245
+ return data;
246
+ }
247
+ const output = data;
248
+ if (!output.success) {
249
+ return data;
250
+ }
251
+ return output.data ?? {};
252
+ }
253
+ function resolveRuntimeProjectRoot(baseDir, projectRoot) {
254
+ if (typeof baseDir !== 'string' || baseDir.trim().length === 0) {
255
+ return projectRoot ?? process.cwd();
256
+ }
257
+ return path.resolve(projectRoot ?? process.cwd(), baseDir);
258
+ }
259
+ function extractGitOutput(data) {
260
+ if (!data || typeof data !== 'object') {
261
+ return '';
262
+ }
263
+ const runtimeData = data;
264
+ if (typeof runtimeData[GIT_OUTPUT_KEY] === 'string') {
265
+ return runtimeData[GIT_OUTPUT_KEY];
266
+ }
267
+ const commandResults = runtimeData[GIT_COMMAND_RESULTS_KEY];
268
+ if (!Array.isArray(commandResults) || commandResults.length === 0) {
269
+ return '';
270
+ }
271
+ const lastCommandResult = commandResults[commandResults.length - 1];
272
+ return typeof lastCommandResult[GIT_COMMAND_RESULT_STDOUT_KEY] === 'string'
273
+ ? lastCommandResult[GIT_COMMAND_RESULT_STDOUT_KEY]
274
+ : '';
275
+ }
276
+ // ============================================================================
277
+ // Wave-1 Public Parity Operations (WU-1482)
278
+ // ============================================================================
279
+ /**
280
+ * backlog_prune - Clean stale backlog entries
281
+ */
282
+ export const backlogPruneTool = {
283
+ name: 'backlog_prune',
284
+ description: 'Clean stale backlog entries and archive old completed WUs',
285
+ inputSchema: backlogPruneSchema,
286
+ async execute(input, options) {
287
+ const args = [];
288
+ if (input.execute)
289
+ args.push(CliArgs.EXECUTE);
290
+ if (input.dry_run)
291
+ args.push('--dry-run');
292
+ if (input.stale_days_in_progress !== undefined) {
293
+ args.push('--stale-days-in-progress', String(input.stale_days_in_progress));
294
+ }
295
+ if (input.stale_days_ready !== undefined) {
296
+ args.push('--stale-days-ready', String(input.stale_days_ready));
297
+ }
298
+ if (input.archive_days !== undefined) {
299
+ args.push('--archive-days', String(input.archive_days));
300
+ }
301
+ const execution = await executeViaPack(CliCommands.BACKLOG_PRUNE, {
302
+ execute: input.execute,
303
+ dry_run: input.dry_run,
304
+ stale_days_in_progress: input.stale_days_in_progress,
305
+ stale_days_ready: input.stale_days_ready,
306
+ archive_days: input.archive_days,
307
+ }, {
308
+ projectRoot: options?.projectRoot,
309
+ contextInput: {
310
+ metadata: {
311
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
312
+ },
313
+ },
314
+ fallback: {
315
+ command: CliCommands.BACKLOG_PRUNE,
316
+ args,
317
+ errorCode: ErrorCodes.BACKLOG_PRUNE_ERROR,
318
+ },
319
+ });
320
+ if (!execution.success) {
321
+ return execution;
322
+ }
323
+ return success(unwrapExecuteViaPackData(execution.data));
324
+ },
325
+ };
326
+ /**
327
+ * docs_sync - Sync agent docs to existing project
328
+ */
329
+ export const docsSyncTool = {
330
+ name: 'docs_sync',
331
+ description: 'Sync agent onboarding docs and skills to existing projects',
332
+ inputSchema: docsSyncMcpSchema,
333
+ async execute(input, options) {
334
+ const args = [];
335
+ if (input.vendor)
336
+ args.push('--vendor', input.vendor);
337
+ if (input.force)
338
+ args.push(CliArgs.FORCE);
339
+ const execution = await executeViaPack(CliCommands.DOCS_SYNC, {
340
+ vendor: input.vendor,
341
+ force: input.force,
342
+ }, {
343
+ projectRoot: options?.projectRoot,
344
+ contextInput: {
345
+ metadata: {
346
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
347
+ },
348
+ },
349
+ fallback: {
350
+ command: CliCommands.DOCS_SYNC,
351
+ args,
352
+ errorCode: ErrorCodes.DOCS_SYNC_ERROR,
353
+ },
354
+ });
355
+ if (!execution.success) {
356
+ return execution;
357
+ }
358
+ return success(unwrapExecuteViaPackData(execution.data));
359
+ },
360
+ };
361
+ /**
362
+ * gates - Public gates command
363
+ */
364
+ export const gatesTool = {
365
+ name: 'gates',
366
+ description: 'Run LumenFlow quality gates',
367
+ inputSchema: gatesSchema,
368
+ async execute(input, options) {
369
+ const args = buildGatesArgs(input);
370
+ const result = await executeViaPack(CliCommands.GATES, input, {
371
+ projectRoot: options?.projectRoot,
372
+ contextInput: {
373
+ metadata: {
374
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
375
+ },
376
+ },
377
+ fallback: {
378
+ command: CliCommands.GATES,
379
+ args,
380
+ errorCode: ErrorCodes.GATES_ALIAS_ERROR,
381
+ },
382
+ fallbackCliOptions: {
383
+ timeout: GatesRuntimeConstants.FALLBACK_TIMEOUT_MS,
384
+ },
385
+ });
386
+ return result.success
387
+ ? success(result.data ?? { message: SuccessMessages.ALL_GATES_PASSED })
388
+ : error(result.error?.message ?? GatesRuntimeMessages.GATES_FAILED, ErrorCodes.GATES_ALIAS_ERROR);
389
+ },
390
+ };
391
+ /**
392
+ * gates_docs - Public docs-only gates alias
393
+ */
394
+ export const gatesDocsTool = {
395
+ name: 'gates_docs',
396
+ description: 'Run docs-only quality gates',
397
+ inputSchema: gatesSchema,
398
+ async execute(input, options) {
399
+ const args = buildGatesArgs(input, { forceDocsOnly: true });
400
+ const result = await executeViaPack(CliCommands.GATES, input, {
401
+ projectRoot: options?.projectRoot,
402
+ contextInput: {
403
+ metadata: {
404
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
405
+ },
406
+ },
407
+ fallback: {
408
+ command: CliCommands.GATES,
409
+ args,
410
+ errorCode: ErrorCodes.GATES_ALIAS_ERROR,
411
+ },
412
+ fallbackCliOptions: {
413
+ timeout: GatesRuntimeConstants.FALLBACK_TIMEOUT_MS,
414
+ },
415
+ });
416
+ return result.success
417
+ ? success(result.data ?? { message: GatesRuntimeMessages.GATES_DOCS_PASSED })
418
+ : error(result.error?.message ?? GatesRuntimeMessages.GATES_DOCS_FAILED, ErrorCodes.GATES_ALIAS_ERROR);
419
+ },
420
+ };
421
+ /**
422
+ * lane_health - Diagnose lane configuration issues
423
+ * WU-1802: Migrated from CLI shell-out to executeViaPack (runtime-first)
424
+ */
425
+ export const laneHealthTool = {
426
+ name: 'lane_health',
427
+ description: 'Check lane configuration health (overlaps and coverage gaps)',
428
+ inputSchema: laneHealthSchema,
429
+ async execute(input, options) {
430
+ const args = [];
431
+ if (input.json)
432
+ args.push(CliArgs.JSON);
433
+ if (input.verbose)
434
+ args.push(CliArgs.VERBOSE);
435
+ if (input.no_coverage)
436
+ args.push(LaneFlags.NO_COVERAGE);
437
+ const result = await executeViaPack(CliCommands.LANE_HEALTH, input, {
438
+ projectRoot: options?.projectRoot,
439
+ fallback: {
440
+ command: CliCommands.LANE_HEALTH,
441
+ args,
442
+ errorCode: ErrorCodes.LANE_HEALTH_ERROR,
443
+ },
444
+ });
445
+ return result.success
446
+ ? success(result.data ?? { message: LaneMessages.HEALTH_PASSED })
447
+ : error(result.error?.message ?? LaneMessages.HEALTH_FAILED, ErrorCodes.LANE_HEALTH_ERROR);
448
+ },
449
+ };
450
+ /**
451
+ * lane_suggest - Suggest lane definitions from project context
452
+ * WU-1802: Migrated from CLI shell-out to executeViaPack (runtime-first)
453
+ */
454
+ export const laneSuggestTool = {
455
+ name: 'lane_suggest',
456
+ description: 'Generate lane suggestions from codebase context',
457
+ inputSchema: laneSuggestSchema,
458
+ async execute(input, options) {
459
+ const args = [];
460
+ if (input.dry_run)
461
+ args.push(LaneFlags.DRY_RUN);
462
+ if (input.interactive)
463
+ args.push(LaneFlags.INTERACTIVE);
464
+ if (input.output)
465
+ args.push(LaneFlags.OUTPUT, input.output);
466
+ if (input.json)
467
+ args.push(CliArgs.JSON);
468
+ if (input.no_llm)
469
+ args.push(LaneFlags.NO_LLM);
470
+ if (input.include_git)
471
+ args.push(LaneFlags.INCLUDE_GIT);
472
+ const result = await executeViaPack(CliCommands.LANE_SUGGEST, input, {
473
+ projectRoot: options?.projectRoot,
474
+ fallback: {
475
+ command: CliCommands.LANE_SUGGEST,
476
+ args,
477
+ errorCode: ErrorCodes.LANE_SUGGEST_ERROR,
478
+ },
479
+ });
480
+ return result.success
481
+ ? success(result.data ?? { message: LaneMessages.SUGGEST_GENERATED })
482
+ : error(result.error?.message ?? LaneMessages.SUGGEST_FAILED, ErrorCodes.LANE_SUGGEST_ERROR);
483
+ },
484
+ };
485
+ /**
486
+ * lumenflow - Public initializer command
487
+ */
488
+ export const lumenflowTool = {
489
+ name: 'lumenflow',
490
+ description: 'Initialize LumenFlow in a project',
491
+ inputSchema: lumenflowInitSchema,
492
+ async execute(input, options) {
493
+ const args = [];
494
+ if (input.client)
495
+ args.push('--client', input.client);
496
+ if (input.merge)
497
+ args.push('--merge');
498
+ if (input.full)
499
+ args.push('--full');
500
+ if (input.minimal)
501
+ args.push('--minimal');
502
+ if (input.framework)
503
+ args.push('--framework', input.framework);
504
+ const execution = await executeViaPack(CliCommands.LUMENFLOW, {
505
+ client: input.client,
506
+ merge: input.merge,
507
+ full: input.full,
508
+ minimal: input.minimal,
509
+ framework: input.framework,
510
+ }, {
511
+ projectRoot: options?.projectRoot,
512
+ contextInput: {
513
+ metadata: {
514
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
515
+ },
516
+ },
517
+ fallback: {
518
+ command: CliCommands.LUMENFLOW,
519
+ args,
520
+ errorCode: ErrorCodes.LUMENFLOW_ALIAS_ERROR,
521
+ },
522
+ });
523
+ if (!execution.success) {
524
+ return execution;
525
+ }
526
+ return success(unwrapExecuteViaPackData(execution.data));
527
+ },
528
+ };
529
+ /**
530
+ * lumenflow_gates - Public gates alias
531
+ */
532
+ export const lumenflowGatesTool = {
533
+ name: 'lumenflow_gates',
534
+ description: 'Run quality gates (lumenflow-gates alias)',
535
+ inputSchema: gatesSchema,
536
+ async execute(input, options) {
537
+ const args = buildGatesArgs(input);
538
+ const result = await executeViaPack(CliCommands.GATES, input, {
539
+ projectRoot: options?.projectRoot,
540
+ contextInput: {
541
+ metadata: {
542
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
543
+ },
544
+ },
545
+ fallback: {
546
+ command: CliCommands.GATES,
547
+ args,
548
+ errorCode: ErrorCodes.LUMENFLOW_GATES_ERROR,
549
+ },
550
+ fallbackCliOptions: {
551
+ timeout: GatesRuntimeConstants.FALLBACK_TIMEOUT_MS,
552
+ },
553
+ });
554
+ return result.success
555
+ ? success(result.data ?? { message: SuccessMessages.ALL_GATES_PASSED })
556
+ : error(result.error?.message ?? GatesRuntimeMessages.LUMENFLOW_GATES_FAILED, ErrorCodes.LUMENFLOW_GATES_ERROR);
557
+ },
558
+ };
559
+ /**
560
+ * state_bootstrap - Bootstrap event store from WU YAMLs
561
+ */
562
+ export const stateBootstrapTool = {
563
+ name: 'state_bootstrap',
564
+ description: 'Bootstrap state store from existing WU YAML files',
565
+ inputSchema: stateBootstrapSchema,
566
+ async execute(input, options) {
567
+ const args = [];
568
+ if (input.execute)
569
+ args.push(CliArgs.EXECUTE);
570
+ if (input.dry_run)
571
+ args.push('--dry-run');
572
+ if (input.force)
573
+ args.push(CliArgs.FORCE);
574
+ if (input.wu_dir)
575
+ args.push('--wu-dir', input.wu_dir);
576
+ if (input.state_dir)
577
+ args.push('--state-dir', input.state_dir);
578
+ const execution = await executeViaPack(CliCommands.STATE_BOOTSTRAP, {
579
+ execute: input.execute,
580
+ dry_run: input.dry_run,
581
+ force: input.force,
582
+ wu_dir: input.wu_dir,
583
+ state_dir: input.state_dir,
584
+ }, {
585
+ projectRoot: options?.projectRoot,
586
+ contextInput: {
587
+ metadata: {
588
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
589
+ },
590
+ },
591
+ fallback: {
592
+ command: CliCommands.STATE_BOOTSTRAP,
593
+ args,
594
+ errorCode: ErrorCodes.STATE_BOOTSTRAP_ERROR,
595
+ },
596
+ });
597
+ if (!execution.success) {
598
+ return execution;
599
+ }
600
+ return success(unwrapExecuteViaPackData(execution.data));
601
+ },
602
+ };
603
+ /**
604
+ * state_cleanup - Run unified state cleanup
605
+ */
606
+ export const stateCleanupTool = {
607
+ name: 'state_cleanup',
608
+ description: 'Clean stale state, memory, and signal data',
609
+ inputSchema: stateCleanupSchema,
610
+ async execute(input, options) {
611
+ const args = [];
612
+ if (input.dry_run)
613
+ args.push('--dry-run');
614
+ if (input.signals_only)
615
+ args.push('--signals-only');
616
+ if (input.memory_only)
617
+ args.push('--memory-only');
618
+ if (input.events_only)
619
+ args.push('--events-only');
620
+ if (input.json)
621
+ args.push(CliArgs.JSON);
622
+ if (input.quiet)
623
+ args.push(CliArgs.QUIET);
624
+ if (input.base_dir)
625
+ args.push(CliArgs.BASE_DIR, input.base_dir);
626
+ const execution = await executeViaPack(CliCommands.STATE_CLEANUP, {
627
+ dry_run: input.dry_run,
628
+ signals_only: input.signals_only,
629
+ memory_only: input.memory_only,
630
+ events_only: input.events_only,
631
+ json: input.json,
632
+ quiet: input.quiet,
633
+ base_dir: input.base_dir,
634
+ }, {
635
+ projectRoot: options?.projectRoot,
636
+ contextInput: {
637
+ metadata: {
638
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
639
+ },
640
+ },
641
+ fallback: {
642
+ command: CliCommands.STATE_CLEANUP,
643
+ args,
644
+ errorCode: ErrorCodes.STATE_CLEANUP_ERROR,
645
+ },
646
+ });
647
+ if (!execution.success) {
648
+ return execution;
649
+ }
650
+ return success(unwrapExecuteViaPackData(execution.data));
651
+ },
652
+ };
653
+ /**
654
+ * state_doctor - Diagnose and repair state issues
655
+ */
656
+ export const stateDoctorTool = {
657
+ name: 'state_doctor',
658
+ description: 'Diagnose state store integrity issues',
659
+ inputSchema: stateDoctorSchema,
660
+ async execute(input, options) {
661
+ const args = [];
662
+ if (input.fix)
663
+ args.push('--fix');
664
+ if (input.dry_run)
665
+ args.push('--dry-run');
666
+ if (input.json)
667
+ args.push(CliArgs.JSON);
668
+ if (input.quiet)
669
+ args.push(CliArgs.QUIET);
670
+ if (input.base_dir)
671
+ args.push(CliArgs.BASE_DIR, input.base_dir);
672
+ const execution = await executeViaPack(CliCommands.STATE_DOCTOR, {
673
+ fix: input.fix,
674
+ dry_run: input.dry_run,
675
+ json: input.json,
676
+ quiet: input.quiet,
677
+ base_dir: input.base_dir,
678
+ }, {
679
+ projectRoot: options?.projectRoot,
680
+ contextInput: {
681
+ metadata: {
682
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
683
+ },
684
+ },
685
+ fallback: {
686
+ command: CliCommands.STATE_DOCTOR,
687
+ args,
688
+ errorCode: ErrorCodes.STATE_DOCTOR_ERROR,
689
+ },
690
+ });
691
+ if (!execution.success) {
692
+ return execution;
693
+ }
694
+ return success(unwrapExecuteViaPackData(execution.data));
695
+ },
696
+ };
697
+ /**
698
+ * sync_templates - Sync templates from source docs
699
+ */
700
+ export const syncTemplatesTool = {
701
+ name: 'sync_templates',
702
+ description: 'Sync internal docs to CLI templates',
703
+ inputSchema: syncTemplatesMcpSchema,
704
+ async execute(input, options) {
705
+ const args = [];
706
+ if (input.dry_run)
707
+ args.push('--dry-run');
708
+ if (input.verbose)
709
+ args.push(CliArgs.VERBOSE);
710
+ if (input.check_drift)
711
+ args.push('--check-drift');
712
+ const execution = await executeViaPack(CliCommands.SYNC_TEMPLATES, {
713
+ dry_run: input.dry_run,
714
+ verbose: input.verbose,
715
+ check_drift: input.check_drift,
716
+ }, {
717
+ projectRoot: options?.projectRoot,
718
+ contextInput: {
719
+ metadata: {
720
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
721
+ },
722
+ },
723
+ fallback: {
724
+ command: CliCommands.SYNC_TEMPLATES,
725
+ args,
726
+ errorCode: ErrorCodes.SYNC_TEMPLATES_ALIAS_ERROR,
727
+ },
728
+ });
729
+ if (!execution.success) {
730
+ return execution;
731
+ }
732
+ return success(unwrapExecuteViaPackData(execution.data));
733
+ },
734
+ };
735
+ // ============================================================================
736
+ // Wave-2 Public Parity Operations (WU-1483)
737
+ // ============================================================================
738
+ /**
739
+ * file_read - Read file content with audit trail
740
+ */
741
+ export const fileReadTool = {
742
+ name: 'file_read',
743
+ description: 'Read a file with optional line ranges and encoding',
744
+ inputSchema: fileReadSchema,
745
+ async execute(input, options) {
746
+ if (!input.path) {
747
+ return error(ErrorMessages.PATH_REQUIRED, ErrorCodes.MISSING_PARAMETER);
748
+ }
749
+ const args = [CliArgs.PATH, input.path];
750
+ if (input.encoding)
751
+ args.push(CliArgs.ENCODING, input.encoding);
752
+ if (input.start_line !== undefined)
753
+ args.push('--start-line', String(input.start_line));
754
+ if (input.end_line !== undefined)
755
+ args.push('--end-line', String(input.end_line));
756
+ if (input.max_size !== undefined)
757
+ args.push('--max-size', String(input.max_size));
758
+ const execution = await executeViaPack(CliCommands.FILE_READ, {
759
+ path: input.path,
760
+ encoding: input.encoding,
761
+ start_line: input.start_line,
762
+ end_line: input.end_line,
763
+ max_size: input.max_size,
764
+ }, {
765
+ projectRoot: options?.projectRoot,
766
+ contextInput: {
767
+ metadata: {
768
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
769
+ },
770
+ },
771
+ fallback: {
772
+ command: CliCommands.FILE_READ,
773
+ args,
774
+ errorCode: ErrorCodes.FILE_READ_ERROR,
775
+ },
776
+ });
777
+ if (!execution.success) {
778
+ return execution;
779
+ }
780
+ return success(unwrapExecuteViaPackData(execution.data));
781
+ },
782
+ };
783
+ /**
784
+ * file_write - Write file content with audit trail
785
+ */
786
+ export const fileWriteTool = {
787
+ name: 'file_write',
788
+ description: 'Write content to a file with audit trail',
789
+ inputSchema: fileWriteSchema,
790
+ async execute(input, options) {
791
+ if (!input.path) {
792
+ return error(ErrorMessages.PATH_REQUIRED, ErrorCodes.MISSING_PARAMETER);
793
+ }
794
+ if (input.content === undefined) {
795
+ return error(ErrorMessages.CONTENT_REQUIRED, ErrorCodes.MISSING_PARAMETER);
796
+ }
797
+ // WU-1853: Check worktree enforcement before writing
798
+ const enforcement = checkWorktreeEnforcement({
799
+ filePath: input.path,
800
+ projectRoot: options?.projectRoot,
801
+ });
802
+ if (!enforcement.allowed) {
803
+ return error(enforcement.reason ?? 'Write blocked by worktree enforcement', enforcement.errorCode ?? ErrorCodes.WORKTREE_ENFORCEMENT_BLOCKED);
804
+ }
805
+ const args = [
806
+ CliArgs.PATH,
807
+ input.path,
808
+ '--content',
809
+ input.content,
810
+ ];
811
+ if (input.encoding)
812
+ args.push(CliArgs.ENCODING, input.encoding);
813
+ if (input.no_create_dirs)
814
+ args.push('--no-create-dirs');
815
+ const execution = await executeViaPack(CliCommands.FILE_WRITE, {
816
+ path: input.path,
817
+ content: input.content,
818
+ encoding: input.encoding,
819
+ no_create_dirs: input.no_create_dirs,
820
+ }, {
821
+ projectRoot: options?.projectRoot,
822
+ contextInput: {
823
+ metadata: {
824
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
825
+ },
826
+ },
827
+ fallback: {
828
+ command: CliCommands.FILE_WRITE,
829
+ args,
830
+ errorCode: ErrorCodes.FILE_WRITE_ERROR,
831
+ },
832
+ });
833
+ if (!execution.success) {
834
+ return execution;
835
+ }
836
+ return success(unwrapExecuteViaPackData(execution.data));
837
+ },
838
+ };
839
+ /**
840
+ * file_edit - Replace exact string matches in a file
841
+ */
842
+ export const fileEditTool = {
843
+ name: 'file_edit',
844
+ description: 'Edit a file via exact string replacement',
845
+ inputSchema: fileEditSchema,
846
+ async execute(input, options) {
847
+ if (!input.path) {
848
+ return error(ErrorMessages.PATH_REQUIRED, ErrorCodes.MISSING_PARAMETER);
849
+ }
850
+ if (!input.old_string) {
851
+ return error(ErrorMessages.OLD_STRING_REQUIRED, ErrorCodes.MISSING_PARAMETER);
852
+ }
853
+ if (input.new_string === undefined) {
854
+ return error(ErrorMessages.NEW_STRING_REQUIRED, ErrorCodes.MISSING_PARAMETER);
855
+ }
856
+ // WU-1853: Check worktree enforcement before editing
857
+ const enforcement = checkWorktreeEnforcement({
858
+ filePath: input.path,
859
+ projectRoot: options?.projectRoot,
860
+ });
861
+ if (!enforcement.allowed) {
862
+ return error(enforcement.reason ?? 'Edit blocked by worktree enforcement', enforcement.errorCode ?? ErrorCodes.WORKTREE_ENFORCEMENT_BLOCKED);
863
+ }
864
+ const args = [
865
+ CliArgs.PATH,
866
+ input.path,
867
+ '--old-string',
868
+ input.old_string,
869
+ '--new-string',
870
+ input.new_string,
871
+ ];
872
+ if (input.encoding)
873
+ args.push(CliArgs.ENCODING, input.encoding);
874
+ if (input.replace_all)
875
+ args.push('--replace-all');
876
+ const execution = await executeViaPack(CliCommands.FILE_EDIT, {
877
+ path: input.path,
878
+ old_string: input.old_string,
879
+ new_string: input.new_string,
880
+ encoding: input.encoding,
881
+ replace_all: input.replace_all,
882
+ }, {
883
+ projectRoot: options?.projectRoot,
884
+ contextInput: {
885
+ metadata: {
886
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
887
+ },
888
+ },
889
+ fallback: {
890
+ command: CliCommands.FILE_EDIT,
891
+ args,
892
+ errorCode: ErrorCodes.FILE_EDIT_ERROR,
893
+ },
894
+ });
895
+ if (!execution.success) {
896
+ return execution;
897
+ }
898
+ return success(unwrapExecuteViaPackData(execution.data));
899
+ },
900
+ };
901
+ /**
902
+ * file_delete - Delete file or directory with audit trail
903
+ */
904
+ export const fileDeleteTool = {
905
+ name: 'file_delete',
906
+ description: 'Delete files or directories with safety flags',
907
+ inputSchema: fileDeleteSchema,
908
+ async execute(input, options) {
909
+ if (!input.path) {
910
+ return error(ErrorMessages.PATH_REQUIRED, ErrorCodes.MISSING_PARAMETER);
911
+ }
912
+ const args = [CliArgs.PATH, input.path];
913
+ if (input.recursive)
914
+ args.push('--recursive');
915
+ if (input.force)
916
+ args.push(CliArgs.FORCE);
917
+ const execution = await executeViaPack(CliCommands.FILE_DELETE, {
918
+ path: input.path,
919
+ recursive: input.recursive,
920
+ force: input.force,
921
+ }, {
922
+ projectRoot: options?.projectRoot,
923
+ contextInput: {
924
+ metadata: {
925
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
926
+ },
927
+ },
928
+ fallback: {
929
+ command: CliCommands.FILE_DELETE,
930
+ args,
931
+ errorCode: ErrorCodes.FILE_DELETE_ERROR,
932
+ },
933
+ });
934
+ if (!execution.success) {
935
+ return execution;
936
+ }
937
+ return success(unwrapExecuteViaPackData(execution.data));
938
+ },
939
+ };
940
+ /**
941
+ * git_status - Show git status
942
+ */
943
+ export const gitStatusTool = {
944
+ name: 'git_status',
945
+ description: 'Show git status with optional porcelain/short modes',
946
+ inputSchema: gitStatusSchema,
947
+ async execute(input, options) {
948
+ const runtimeProjectRoot = resolveRuntimeProjectRoot(input.base_dir, options?.projectRoot);
949
+ const args = [];
950
+ if (input.base_dir)
951
+ args.push(CliArgs.BASE_DIR, input.base_dir);
952
+ if (input.porcelain)
953
+ args.push('--porcelain');
954
+ if (input.short)
955
+ args.push('--short');
956
+ if (input.path)
957
+ args.push(input.path);
958
+ const gitCommandArgs = ['status'];
959
+ if (input.porcelain)
960
+ gitCommandArgs.push('--porcelain');
961
+ if (input.short)
962
+ gitCommandArgs.push('--short');
963
+ if (input.path)
964
+ gitCommandArgs.push(input.path);
965
+ const execution = await executeViaPack(GIT_RUNTIME_TOOL_NAME, {
966
+ commands: [[GIT_BINARY, ...gitCommandArgs]],
967
+ }, {
968
+ projectRoot: runtimeProjectRoot,
969
+ contextInput: {
970
+ metadata: {
971
+ [RUNTIME_PROJECT_ROOT_KEY]: runtimeProjectRoot,
972
+ },
973
+ },
974
+ fallback: {
975
+ command: CliCommands.GIT_STATUS,
976
+ args,
977
+ errorCode: ErrorCodes.GIT_STATUS_ERROR,
978
+ },
979
+ });
980
+ if (!execution.success) {
981
+ return execution;
982
+ }
983
+ const runtimeData = unwrapExecuteViaPackData(execution.data);
984
+ return success({ output: extractGitOutput(runtimeData) });
985
+ },
986
+ };
987
+ /**
988
+ * git_diff - Show git diff
989
+ */
990
+ export const gitDiffTool = {
991
+ name: 'git_diff',
992
+ description: 'Show git diff with staged/name-only/stat modes',
993
+ inputSchema: gitDiffSchema,
994
+ async execute(input, options) {
995
+ const runtimeProjectRoot = resolveRuntimeProjectRoot(input.base_dir, options?.projectRoot);
996
+ const args = [];
997
+ if (input.base_dir)
998
+ args.push(CliArgs.BASE_DIR, input.base_dir);
999
+ if (input.staged)
1000
+ args.push('--staged');
1001
+ if (input.name_only)
1002
+ args.push('--name-only');
1003
+ if (input.stat)
1004
+ args.push('--stat');
1005
+ if (input.ref)
1006
+ args.push(input.ref);
1007
+ if (input.path)
1008
+ args.push('--', input.path);
1009
+ const gitCommandArgs = ['diff'];
1010
+ if (input.staged)
1011
+ gitCommandArgs.push('--staged');
1012
+ if (input.name_only)
1013
+ gitCommandArgs.push('--name-only');
1014
+ if (input.stat)
1015
+ gitCommandArgs.push('--stat');
1016
+ if (input.ref)
1017
+ gitCommandArgs.push(input.ref);
1018
+ if (input.path)
1019
+ gitCommandArgs.push('--', input.path);
1020
+ const execution = await executeViaPack(GIT_RUNTIME_TOOL_NAME, {
1021
+ commands: [[GIT_BINARY, ...gitCommandArgs]],
1022
+ }, {
1023
+ projectRoot: runtimeProjectRoot,
1024
+ contextInput: {
1025
+ metadata: {
1026
+ [RUNTIME_PROJECT_ROOT_KEY]: runtimeProjectRoot,
1027
+ },
1028
+ },
1029
+ fallback: {
1030
+ command: CliCommands.GIT_DIFF,
1031
+ args,
1032
+ errorCode: ErrorCodes.GIT_DIFF_ERROR,
1033
+ },
1034
+ });
1035
+ if (!execution.success) {
1036
+ return execution;
1037
+ }
1038
+ const runtimeData = unwrapExecuteViaPackData(execution.data);
1039
+ return success({ output: extractGitOutput(runtimeData) });
1040
+ },
1041
+ };
1042
+ /**
1043
+ * git_log - Show commit history
1044
+ */
1045
+ export const gitLogTool = {
1046
+ name: 'git_log',
1047
+ description: 'Show git commit log with filters',
1048
+ inputSchema: gitLogSchema,
1049
+ async execute(input, options) {
1050
+ const runtimeProjectRoot = resolveRuntimeProjectRoot(input.base_dir, options?.projectRoot);
1051
+ const args = [];
1052
+ if (input.base_dir)
1053
+ args.push(CliArgs.BASE_DIR, input.base_dir);
1054
+ if (input.oneline)
1055
+ args.push('--oneline');
1056
+ if (input.max_count !== undefined)
1057
+ args.push('-n', String(input.max_count));
1058
+ if (input.format)
1059
+ args.push(CliArgs.FORMAT, input.format);
1060
+ if (input.since)
1061
+ args.push(CliArgs.SINCE, input.since);
1062
+ if (input.author)
1063
+ args.push('--author', input.author);
1064
+ if (input.ref)
1065
+ args.push(input.ref);
1066
+ const gitCommandArgs = ['log'];
1067
+ if (input.oneline)
1068
+ gitCommandArgs.push('--oneline');
1069
+ if (input.max_count !== undefined)
1070
+ gitCommandArgs.push('-n', String(input.max_count));
1071
+ if (input.format)
1072
+ gitCommandArgs.push(CliArgs.FORMAT, input.format);
1073
+ if (input.since)
1074
+ gitCommandArgs.push(CliArgs.SINCE, input.since);
1075
+ if (input.author)
1076
+ gitCommandArgs.push('--author', input.author);
1077
+ if (input.ref)
1078
+ gitCommandArgs.push(input.ref);
1079
+ const execution = await executeViaPack(GIT_RUNTIME_TOOL_NAME, {
1080
+ commands: [[GIT_BINARY, ...gitCommandArgs]],
1081
+ }, {
1082
+ projectRoot: runtimeProjectRoot,
1083
+ contextInput: {
1084
+ metadata: {
1085
+ [RUNTIME_PROJECT_ROOT_KEY]: runtimeProjectRoot,
1086
+ },
1087
+ },
1088
+ fallback: {
1089
+ command: CliCommands.GIT_LOG,
1090
+ args,
1091
+ errorCode: ErrorCodes.GIT_LOG_ERROR,
1092
+ },
1093
+ });
1094
+ if (!execution.success) {
1095
+ return execution;
1096
+ }
1097
+ const runtimeData = unwrapExecuteViaPackData(execution.data);
1098
+ return success({ output: extractGitOutput(runtimeData) });
1099
+ },
1100
+ };
1101
+ /**
1102
+ * git_branch - Show branch information
1103
+ */
1104
+ export const gitBranchTool = {
1105
+ name: 'git_branch',
1106
+ description: 'Show git branch listing and current branch',
1107
+ inputSchema: gitBranchSchema,
1108
+ async execute(input, options) {
1109
+ const runtimeProjectRoot = resolveRuntimeProjectRoot(input.base_dir, options?.projectRoot);
1110
+ const args = [];
1111
+ if (input.base_dir)
1112
+ args.push(CliArgs.BASE_DIR, input.base_dir);
1113
+ if (input.list)
1114
+ args.push('--list');
1115
+ if (input.all)
1116
+ args.push('--all');
1117
+ if (input.remotes)
1118
+ args.push('--remotes');
1119
+ if (input.show_current)
1120
+ args.push('--show-current');
1121
+ if (input.contains)
1122
+ args.push('--contains', input.contains);
1123
+ const gitCommandArgs = ['branch'];
1124
+ if (input.list)
1125
+ gitCommandArgs.push('--list');
1126
+ if (input.all)
1127
+ gitCommandArgs.push('--all');
1128
+ if (input.remotes)
1129
+ gitCommandArgs.push('--remotes');
1130
+ if (input.show_current)
1131
+ gitCommandArgs.push('--show-current');
1132
+ if (input.contains)
1133
+ gitCommandArgs.push('--contains', input.contains);
1134
+ const execution = await executeViaPack(GIT_RUNTIME_TOOL_NAME, {
1135
+ commands: [[GIT_BINARY, ...gitCommandArgs]],
1136
+ }, {
1137
+ projectRoot: runtimeProjectRoot,
1138
+ contextInput: {
1139
+ metadata: {
1140
+ [RUNTIME_PROJECT_ROOT_KEY]: runtimeProjectRoot,
1141
+ },
1142
+ },
1143
+ fallback: {
1144
+ command: CliCommands.GIT_BRANCH,
1145
+ args,
1146
+ errorCode: ErrorCodes.GIT_BRANCH_ERROR,
1147
+ },
1148
+ });
1149
+ if (!execution.success) {
1150
+ return execution;
1151
+ }
1152
+ const runtimeData = unwrapExecuteViaPackData(execution.data);
1153
+ return success({ output: extractGitOutput(runtimeData) });
1154
+ },
1155
+ };
1156
+ /**
1157
+ * init_plan - Link plan to initiative (alias)
1158
+ */
1159
+ export const initPlanTool = {
1160
+ name: 'init_plan',
1161
+ description: 'Link or create a plan for an initiative',
1162
+ inputSchema: initiativePlanSchema,
1163
+ async execute(input, options) {
1164
+ if (!input.initiative) {
1165
+ return error(SharedErrorMessages.INITIATIVE_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1166
+ }
1167
+ if (!input.plan && !input.create) {
1168
+ return error(ErrorMessages.PLAN_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1169
+ }
1170
+ const args = ['--initiative', input.initiative];
1171
+ if (input.plan)
1172
+ args.push('--plan', input.plan);
1173
+ if (input.create)
1174
+ args.push('--create');
1175
+ const execution = await executeViaPack(CliCommands.INIT_PLAN, input, {
1176
+ projectRoot: options?.projectRoot,
1177
+ contextInput: {
1178
+ metadata: {
1179
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1180
+ },
1181
+ },
1182
+ fallback: {
1183
+ command: CliCommands.INIT_PLAN,
1184
+ args,
1185
+ errorCode: ErrorCodes.INIT_PLAN_ERROR,
1186
+ },
1187
+ });
1188
+ return execution.success
1189
+ ? success(unwrapExecuteViaPackData(execution.data))
1190
+ : error(execution.error?.message ?? 'init:plan failed', ErrorCodes.INIT_PLAN_ERROR);
1191
+ },
1192
+ };
1193
+ /**
1194
+ * plan_create - Create a plan file
1195
+ */
1196
+ export const planCreateTool = {
1197
+ name: 'plan_create',
1198
+ description: 'Create a new plan for a WU or initiative',
1199
+ inputSchema: planCreateSchema,
1200
+ async execute(input, options) {
1201
+ if (!input.id) {
1202
+ return error(ErrorMessages.ID_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1203
+ }
1204
+ if (!input.title) {
1205
+ return error(ErrorMessages.TITLE_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1206
+ }
1207
+ const args = [CliArgs.ID, input.id, '--title', input.title];
1208
+ const execution = await executeViaPack(CliCommands.PLAN_CREATE, {
1209
+ id: input.id,
1210
+ title: input.title,
1211
+ }, {
1212
+ projectRoot: options?.projectRoot,
1213
+ contextInput: {
1214
+ metadata: {
1215
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1216
+ },
1217
+ },
1218
+ fallback: {
1219
+ command: CliCommands.PLAN_CREATE,
1220
+ args,
1221
+ errorCode: ErrorCodes.PLAN_CREATE_ERROR,
1222
+ },
1223
+ });
1224
+ if (!execution.success) {
1225
+ return execution;
1226
+ }
1227
+ return success(unwrapExecuteViaPackData(execution.data));
1228
+ },
1229
+ };
1230
+ /**
1231
+ * plan_edit - Edit an existing plan section
1232
+ */
1233
+ export const planEditTool = {
1234
+ name: 'plan_edit',
1235
+ description: 'Edit or append content to a plan section',
1236
+ inputSchema: planEditSchema,
1237
+ async execute(input, options) {
1238
+ if (!input.id) {
1239
+ return error(ErrorMessages.ID_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1240
+ }
1241
+ if (!input.section) {
1242
+ return error(ErrorMessages.SECTION_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1243
+ }
1244
+ if (!input.content && !input.append) {
1245
+ return error(ErrorMessages.CONTENT_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1246
+ }
1247
+ const args = [CliArgs.ID, input.id, '--section', input.section];
1248
+ if (input.content)
1249
+ args.push('--content', input.content);
1250
+ if (input.append)
1251
+ args.push('--append', input.append);
1252
+ const execution = await executeViaPack(CliCommands.PLAN_EDIT, {
1253
+ id: input.id,
1254
+ section: input.section,
1255
+ content: input.content,
1256
+ append: input.append,
1257
+ }, {
1258
+ projectRoot: options?.projectRoot,
1259
+ contextInput: {
1260
+ metadata: {
1261
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1262
+ },
1263
+ },
1264
+ fallback: {
1265
+ command: CliCommands.PLAN_EDIT,
1266
+ args,
1267
+ errorCode: ErrorCodes.PLAN_EDIT_ERROR,
1268
+ },
1269
+ });
1270
+ if (!execution.success) {
1271
+ return execution;
1272
+ }
1273
+ return success(unwrapExecuteViaPackData(execution.data));
1274
+ },
1275
+ };
1276
+ /**
1277
+ * plan_link - Link plan URI to WU/initiative
1278
+ */
1279
+ export const planLinkTool = {
1280
+ name: 'plan_link',
1281
+ description: 'Link an existing plan URI to a WU or initiative',
1282
+ inputSchema: planLinkSchema,
1283
+ async execute(input, options) {
1284
+ if (!input.id) {
1285
+ return error(ErrorMessages.ID_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1286
+ }
1287
+ if (!input.plan) {
1288
+ return error(ErrorMessages.PLAN_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1289
+ }
1290
+ const args = [CliArgs.ID, input.id, '--plan', input.plan];
1291
+ const execution = await executeViaPack(CliCommands.PLAN_LINK, {
1292
+ id: input.id,
1293
+ plan: input.plan,
1294
+ }, {
1295
+ projectRoot: options?.projectRoot,
1296
+ contextInput: {
1297
+ metadata: {
1298
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1299
+ },
1300
+ },
1301
+ fallback: {
1302
+ command: CliCommands.PLAN_LINK,
1303
+ args,
1304
+ errorCode: ErrorCodes.PLAN_LINK_ERROR,
1305
+ },
1306
+ });
1307
+ if (!execution.success) {
1308
+ return execution;
1309
+ }
1310
+ return success(unwrapExecuteViaPackData(execution.data));
1311
+ },
1312
+ };
1313
+ /**
1314
+ * plan_promote - Promote plan to approved status
1315
+ */
1316
+ export const planPromoteTool = {
1317
+ name: 'plan_promote',
1318
+ description: 'Promote plan from draft to approved status',
1319
+ inputSchema: planPromoteSchema,
1320
+ async execute(input, options) {
1321
+ if (!input.id) {
1322
+ return error(ErrorMessages.ID_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1323
+ }
1324
+ const args = [CliArgs.ID, input.id];
1325
+ if (input.force)
1326
+ args.push(CliArgs.FORCE);
1327
+ const execution = await executeViaPack(CliCommands.PLAN_PROMOTE, {
1328
+ id: input.id,
1329
+ force: input.force,
1330
+ }, {
1331
+ projectRoot: options?.projectRoot,
1332
+ contextInput: {
1333
+ metadata: {
1334
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1335
+ },
1336
+ },
1337
+ fallback: {
1338
+ command: CliCommands.PLAN_PROMOTE,
1339
+ args,
1340
+ errorCode: ErrorCodes.PLAN_PROMOTE_ERROR,
1341
+ },
1342
+ });
1343
+ if (!execution.success) {
1344
+ return execution;
1345
+ }
1346
+ return success(unwrapExecuteViaPackData(execution.data));
1347
+ },
1348
+ };
1349
+ /**
1350
+ * signal_cleanup - Clean stale signals
1351
+ */
1352
+ export const signalCleanupTool = {
1353
+ name: 'signal_cleanup',
1354
+ description: 'Cleanup stale signals using TTL policy',
1355
+ inputSchema: signalCleanupSchema,
1356
+ async execute(input, options) {
1357
+ const args = [];
1358
+ if (input.dry_run)
1359
+ args.push('--dry-run');
1360
+ if (input.ttl)
1361
+ args.push('--ttl', input.ttl);
1362
+ if (input.unread_ttl)
1363
+ args.push('--unread-ttl', input.unread_ttl);
1364
+ if (input.max_entries !== undefined)
1365
+ args.push('--max-entries', String(input.max_entries));
1366
+ if (input.json)
1367
+ args.push(CliArgs.JSON);
1368
+ if (input.quiet)
1369
+ args.push(CliArgs.QUIET);
1370
+ if (input.base_dir)
1371
+ args.push(CliArgs.BASE_DIR, input.base_dir);
1372
+ const execution = await executeViaPack(CliCommands.SIGNAL_CLEANUP, {
1373
+ dry_run: input.dry_run,
1374
+ ttl: input.ttl,
1375
+ unread_ttl: input.unread_ttl,
1376
+ max_entries: input.max_entries,
1377
+ json: input.json,
1378
+ quiet: input.quiet,
1379
+ base_dir: input.base_dir,
1380
+ }, {
1381
+ projectRoot: options?.projectRoot,
1382
+ contextInput: {
1383
+ metadata: {
1384
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1385
+ },
1386
+ },
1387
+ fallback: {
1388
+ command: CliCommands.SIGNAL_CLEANUP,
1389
+ args,
1390
+ errorCode: ErrorCodes.SIGNAL_CLEANUP_ERROR,
1391
+ },
1392
+ });
1393
+ if (!execution.success) {
1394
+ return execution;
1395
+ }
1396
+ return success(unwrapExecuteViaPackData(execution.data));
1397
+ },
1398
+ };
1399
+ /**
1400
+ * config_set - Safely update workspace.yaml via micro-worktree
1401
+ * WU-1902: config:set MCP parity tool
1402
+ */
1403
+ export const configSetTool = {
1404
+ name: 'config_set',
1405
+ description: 'Safely update workspace.yaml via micro-worktree',
1406
+ inputSchema: configSetSchema,
1407
+ async execute(input, options) {
1408
+ if (!input.key) {
1409
+ return error(ErrorMessages.KEY_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1410
+ }
1411
+ if (input.value === undefined) {
1412
+ return error(ErrorMessages.VALUE_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1413
+ }
1414
+ const args = ['--key', input.key, '--value', input.value];
1415
+ const execution = await executeViaPack(CliCommands.CONFIG_SET, {
1416
+ key: input.key,
1417
+ value: input.value,
1418
+ }, {
1419
+ projectRoot: options?.projectRoot,
1420
+ contextInput: {
1421
+ metadata: {
1422
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1423
+ },
1424
+ },
1425
+ fallback: {
1426
+ command: CliCommands.CONFIG_SET,
1427
+ args,
1428
+ errorCode: ErrorCodes.CONFIG_SET_ERROR,
1429
+ },
1430
+ });
1431
+ if (!execution.success) {
1432
+ return execution;
1433
+ }
1434
+ return success(unwrapExecuteViaPackData(execution.data));
1435
+ },
1436
+ };
1437
+ /**
1438
+ * config_get - Read and display a value from workspace.yaml
1439
+ * WU-1902: config:get MCP parity tool
1440
+ */
1441
+ export const configGetTool = {
1442
+ name: 'config_get',
1443
+ description: 'Read and display a value from workspace.yaml',
1444
+ inputSchema: configGetSchema,
1445
+ async execute(input, options) {
1446
+ if (!input.key) {
1447
+ return error(ErrorMessages.KEY_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1448
+ }
1449
+ const args = ['--key', input.key];
1450
+ const execution = await executeViaPack(CliCommands.CONFIG_GET, {
1451
+ key: input.key,
1452
+ }, {
1453
+ projectRoot: options?.projectRoot,
1454
+ contextInput: {
1455
+ metadata: {
1456
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1457
+ },
1458
+ },
1459
+ fallback: {
1460
+ command: CliCommands.CONFIG_GET,
1461
+ args,
1462
+ errorCode: ErrorCodes.CONFIG_GET_ERROR,
1463
+ },
1464
+ });
1465
+ if (!execution.success) {
1466
+ return execution;
1467
+ }
1468
+ return success(unwrapExecuteViaPackData(execution.data));
1469
+ },
1470
+ };
1471
+ /**
1472
+ * cloud_connect - Connect workspace.yaml to cloud control plane
1473
+ */
1474
+ export const cloudConnectTool = {
1475
+ name: 'cloud_connect',
1476
+ description: 'Connect workspace.yaml to cloud control plane',
1477
+ inputSchema: cloudConnectSchema,
1478
+ async execute(input, options) {
1479
+ if (!input.endpoint) {
1480
+ return error(ErrorMessages.ENDPOINT_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1481
+ }
1482
+ if (!input.org_id) {
1483
+ return error(ErrorMessages.ORG_ID_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1484
+ }
1485
+ if (!input.project_id) {
1486
+ return error(ErrorMessages.PROJECT_ID_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1487
+ }
1488
+ const args = [
1489
+ BootstrapFlags.ENDPOINT,
1490
+ input.endpoint,
1491
+ BootstrapFlags.ORG_ID,
1492
+ input.org_id,
1493
+ BootstrapFlags.PROJECT_ID,
1494
+ input.project_id,
1495
+ ];
1496
+ if (input.token_env)
1497
+ args.push(BootstrapFlags.TOKEN_ENV, input.token_env);
1498
+ if (input.policy_mode)
1499
+ args.push(BootstrapFlags.POLICY_MODE, input.policy_mode);
1500
+ if (input.sync_interval !== undefined) {
1501
+ args.push(BootstrapFlags.SYNC_INTERVAL, String(input.sync_interval));
1502
+ }
1503
+ if (input.output)
1504
+ args.push(BootstrapFlags.OUTPUT, input.output);
1505
+ if (input.force)
1506
+ args.push(CliArgs.FORCE);
1507
+ const execution = await executeViaPack(CliCommands.CLOUD_CONNECT, {
1508
+ endpoint: input.endpoint,
1509
+ org_id: input.org_id,
1510
+ project_id: input.project_id,
1511
+ token_env: input.token_env,
1512
+ policy_mode: input.policy_mode,
1513
+ sync_interval: input.sync_interval,
1514
+ output: input.output,
1515
+ force: input.force,
1516
+ }, {
1517
+ projectRoot: options?.projectRoot,
1518
+ contextInput: {
1519
+ metadata: {
1520
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1521
+ },
1522
+ },
1523
+ fallback: {
1524
+ command: CliCommands.CLOUD_CONNECT,
1525
+ args,
1526
+ errorCode: ErrorCodes.CLOUD_CONNECT_ERROR,
1527
+ },
1528
+ });
1529
+ if (!execution.success) {
1530
+ return execution;
1531
+ }
1532
+ return success(unwrapExecuteViaPackData(execution.data));
1533
+ },
1534
+ };
1535
+ function buildOnboardArgs(input) {
1536
+ const args = [];
1537
+ if (input.yes)
1538
+ args.push(BootstrapFlags.YES);
1539
+ if (input.domain)
1540
+ args.push(BootstrapFlags.DOMAIN, input.domain);
1541
+ if (input.project_name)
1542
+ args.push(BootstrapFlags.PROJECT_NAME, input.project_name);
1543
+ if (input.output)
1544
+ args.push(BootstrapFlags.OUTPUT, input.output);
1545
+ if (input.force)
1546
+ args.push(CliArgs.FORCE);
1547
+ if (input.skip_pack_install)
1548
+ args.push(BootstrapFlags.SKIP_PACK_INSTALL);
1549
+ if (input.skip_dashboard)
1550
+ args.push(BootstrapFlags.SKIP_DASHBOARD);
1551
+ return args;
1552
+ }
1553
+ async function executeOnboardAlias(command, errorCode, input, options) {
1554
+ return executeViaPack(command, {
1555
+ yes: input.yes,
1556
+ domain: input.domain,
1557
+ project_name: input.project_name,
1558
+ output: input.output,
1559
+ force: input.force,
1560
+ skip_pack_install: input.skip_pack_install,
1561
+ skip_dashboard: input.skip_dashboard,
1562
+ }, {
1563
+ projectRoot: options?.projectRoot,
1564
+ contextInput: {
1565
+ metadata: {
1566
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1567
+ },
1568
+ },
1569
+ fallback: {
1570
+ command,
1571
+ args: buildOnboardArgs(input),
1572
+ errorCode,
1573
+ },
1574
+ });
1575
+ }
1576
+ /**
1577
+ * onboard - Interactive setup wizard for LumenFlow workspace
1578
+ */
1579
+ export const onboardTool = {
1580
+ name: 'onboard',
1581
+ description: 'Interactive setup wizard for LumenFlow workspace',
1582
+ inputSchema: onboardSchema,
1583
+ async execute(input, options) {
1584
+ const execution = await executeOnboardAlias(CliCommands.ONBOARD, ErrorCodes.ONBOARD_ERROR, input, options);
1585
+ if (!execution.success) {
1586
+ return execution;
1587
+ }
1588
+ return success(unwrapExecuteViaPackData(execution.data));
1589
+ },
1590
+ };
1591
+ /**
1592
+ * lumenflow_onboard - Alias for onboard command
1593
+ */
1594
+ export const lumenflowOnboardTool = {
1595
+ name: 'lumenflow_onboard',
1596
+ description: 'Interactive setup wizard for LumenFlow workspace (alias)',
1597
+ inputSchema: onboardSchema,
1598
+ async execute(input, options) {
1599
+ const execution = await executeOnboardAlias(CliCommands.LUMENFLOW_ONBOARD, ErrorCodes.LUMENFLOW_ONBOARD_ERROR, input, options);
1600
+ if (!execution.success) {
1601
+ return execution;
1602
+ }
1603
+ return success(unwrapExecuteViaPackData(execution.data));
1604
+ },
1605
+ };
1606
+ /**
1607
+ * workspace_init - Initialize workspace.yaml via interactive prompts
1608
+ */
1609
+ export const workspaceInitTool = {
1610
+ name: 'workspace_init',
1611
+ description: 'Initialize workspace.yaml from interactive prompts',
1612
+ inputSchema: workspaceInitSchema,
1613
+ async execute(input, options) {
1614
+ const args = [];
1615
+ if (input.yes)
1616
+ args.push(BootstrapFlags.YES);
1617
+ if (input.output)
1618
+ args.push(BootstrapFlags.OUTPUT, input.output);
1619
+ if (input.force)
1620
+ args.push(CliArgs.FORCE);
1621
+ const execution = await executeViaPack(CliCommands.WORKSPACE_INIT, {
1622
+ yes: input.yes,
1623
+ output: input.output,
1624
+ force: input.force,
1625
+ }, {
1626
+ projectRoot: options?.projectRoot,
1627
+ contextInput: {
1628
+ metadata: {
1629
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1630
+ },
1631
+ },
1632
+ fallback: {
1633
+ command: CliCommands.WORKSPACE_INIT,
1634
+ args,
1635
+ errorCode: ErrorCodes.WORKSPACE_INIT_ERROR,
1636
+ },
1637
+ });
1638
+ if (!execution.success) {
1639
+ return execution;
1640
+ }
1641
+ return success(unwrapExecuteViaPackData(execution.data));
1642
+ },
1643
+ };
1644
+ /**
1645
+ * wu_proto - Create and claim a prototype WU
1646
+ */
1647
+ export const wuProtoTool = {
1648
+ name: 'wu_proto',
1649
+ description: 'Create and claim a prototype WU with relaxed validation',
1650
+ inputSchema: wuProtoSchema,
1651
+ async execute(input, options) {
1652
+ if (!input.lane) {
1653
+ return error(ErrorMessages.LANE_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1654
+ }
1655
+ if (!input.title) {
1656
+ return error(ErrorMessages.TITLE_REQUIRED, ErrorCodes.MISSING_PARAMETER);
1657
+ }
1658
+ const args = [CliArgs.LANE, input.lane, '--title', input.title];
1659
+ if (input.description)
1660
+ args.push(CliArgs.DESCRIPTION, input.description);
1661
+ if (Array.isArray(input.code_paths)) {
1662
+ for (const codePath of input.code_paths) {
1663
+ args.push(CliArgs.CODE_PATHS, String(codePath));
1664
+ }
1665
+ }
1666
+ if (Array.isArray(input.labels) && input.labels.length > 0) {
1667
+ args.push('--labels', input.labels.join(','));
1668
+ }
1669
+ if (input.assigned_to)
1670
+ args.push('--assigned-to', input.assigned_to);
1671
+ const execution = await executeViaPack(CliCommands.WU_PROTO, input, {
1672
+ projectRoot: options?.projectRoot,
1673
+ contextInput: {
1674
+ metadata: {
1675
+ [MetadataKeys.PROJECT_ROOT]: options?.projectRoot,
1676
+ },
1677
+ },
1678
+ fallback: {
1679
+ command: CliCommands.WU_PROTO,
1680
+ args,
1681
+ errorCode: ErrorCodes.WU_PROTO_ERROR,
1682
+ },
1683
+ });
1684
+ if (!execution.success) {
1685
+ return error(execution.error?.message ?? 'wu:proto failed', ErrorCodes.WU_PROTO_ERROR);
1686
+ }
1687
+ return success(execution.data ?? { message: 'Prototype WU created' });
1688
+ },
1689
+ };
1690
+ //# sourceMappingURL=parity-tools.js.map