vibecodingmachine-cli 2026.2.26-1739 → 2026.3.9-1621

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 (74) hide show
  1. package/bin/auth/auth-compliance.js +7 -1
  2. package/bin/commands/agent-commands.js +150 -228
  3. package/bin/commands/command-aliases.js +68 -0
  4. package/bin/vibecodingmachine.js +1 -2
  5. package/package.json +2 -2
  6. package/src/commands/agents/list.js +71 -115
  7. package/src/commands/agents-check.js +16 -4
  8. package/src/commands/analyze-file-sizes.js +1 -1
  9. package/src/commands/auto-direct/auto-provider-manager.js +290 -0
  10. package/src/commands/auto-direct/auto-status-display.js +331 -0
  11. package/src/commands/auto-direct/auto-utils.js +439 -0
  12. package/src/commands/auto-direct/file-operations.js +110 -0
  13. package/src/commands/auto-direct/provider-config.js +1 -1
  14. package/src/commands/auto-direct/provider-manager.js +1 -1
  15. package/src/commands/auto-direct/status-display.js +1 -1
  16. package/src/commands/auto-direct/utils.js +24 -18
  17. package/src/commands/auto-direct-refactored.js +413 -0
  18. package/src/commands/auto-direct.js +594 -188
  19. package/src/commands/requirements/commands.js +353 -0
  20. package/src/commands/requirements/default-handlers.js +272 -0
  21. package/src/commands/requirements/disable.js +97 -0
  22. package/src/commands/requirements/enable.js +97 -0
  23. package/src/commands/requirements/utils.js +194 -0
  24. package/src/commands/requirements-refactored.js +60 -0
  25. package/src/commands/requirements.js +38 -771
  26. package/src/commands/specs/disable.js +96 -0
  27. package/src/commands/specs/enable.js +96 -0
  28. package/src/trui/TruiInterface.js +5 -11
  29. package/src/trui/agents/AgentInterface.js +24 -396
  30. package/src/trui/agents/handlers/CommandHandler.js +93 -0
  31. package/src/trui/agents/handlers/ContextManager.js +117 -0
  32. package/src/trui/agents/handlers/DisplayHandler.js +243 -0
  33. package/src/trui/agents/handlers/HelpHandler.js +51 -0
  34. package/src/utils/auth.js +13 -111
  35. package/src/utils/config.js +5 -1
  36. package/src/utils/interactive/requirements-navigation.js +17 -15
  37. package/src/utils/interactive-broken.js +2 -2
  38. package/src/utils/provider-checker/agent-runner.js +15 -1
  39. package/src/utils/provider-checker/cli-installer.js +149 -7
  40. package/src/utils/provider-checker/opencode-checker.js +588 -0
  41. package/src/utils/provider-checker/provider-validator.js +88 -3
  42. package/src/utils/provider-checker/time-formatter.js +3 -2
  43. package/src/utils/provider-manager.js +28 -20
  44. package/src/utils/provider-registry.js +35 -3
  45. package/src/utils/requirements-navigator/index.js +94 -0
  46. package/src/utils/requirements-navigator/input-handler.js +217 -0
  47. package/src/utils/requirements-navigator/section-loader.js +188 -0
  48. package/src/utils/requirements-navigator/tree-builder.js +105 -0
  49. package/src/utils/requirements-navigator/tree-renderer.js +50 -0
  50. package/src/utils/requirements-navigator.js +2 -583
  51. package/src/utils/trui-clarifications.js +188 -0
  52. package/src/utils/trui-feedback.js +54 -1
  53. package/src/utils/trui-kiro-integration.js +398 -0
  54. package/src/utils/trui-main-handlers.js +194 -0
  55. package/src/utils/trui-main-menu.js +235 -0
  56. package/src/utils/trui-nav-agents.js +178 -25
  57. package/src/utils/trui-nav-requirements.js +203 -27
  58. package/src/utils/trui-nav-settings.js +114 -1
  59. package/src/utils/trui-nav-specifications.js +44 -3
  60. package/src/utils/trui-navigation-backup.js +603 -0
  61. package/src/utils/trui-navigation.js +70 -228
  62. package/src/utils/trui-provider-health.js +274 -0
  63. package/src/utils/trui-provider-manager.js +376 -0
  64. package/src/utils/trui-quick-menu.js +25 -1
  65. package/src/utils/trui-req-actions-backup.js +507 -0
  66. package/src/utils/trui-req-actions.js +148 -216
  67. package/src/utils/trui-req-editor.js +170 -0
  68. package/src/utils/trui-req-file-ops.js +278 -0
  69. package/src/utils/trui-req-tree-old.js +719 -0
  70. package/src/utils/trui-req-tree.js +348 -627
  71. package/src/utils/trui-specifications.js +25 -7
  72. package/src/utils/trui-windsurf.js +231 -10
  73. package/src/utils/welcome-screen-extracted.js +2 -2
  74. package/src/utils/welcome-screen.js +2 -2
@@ -0,0 +1,507 @@
1
+ /**
2
+ * TRUI Requirement Actions
3
+ *
4
+ * Provides an action menu for a selected requirement and the addRequirementFlow.
5
+ * Uses inquirer for prompted input (rename, add) and showQuickMenu for action selection.
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const inquirer = require('inquirer');
10
+ const fs = require('fs-extra');
11
+ const readline = require('readline');
12
+ const { hasClarificationResponse, editClarificationResponse } = require('./trui-clarifications');
13
+
14
+ /**
15
+ * Single-keypress confirm: Y/Enter/- = yes, N/Esc = no. No Enter required.
16
+ * Shows: `message (Y/n/-)` and echoes the choice.
17
+ */
18
+ async function _confirmKeypress(message) {
19
+ return new Promise(resolve => {
20
+ process.stdout.write(message + ' (Y/n/-)\n\n');
21
+ readline.emitKeypressEvents(process.stdin);
22
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
23
+ process.stdin.setRawMode(true);
24
+ }
25
+ process.stdin.resume();
26
+
27
+ const cleanup = () => {
28
+ process.stdin.removeListener('keypress', onKey);
29
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
30
+ process.stdin.setRawMode(false);
31
+ }
32
+ process.stdin.pause();
33
+ };
34
+
35
+ const onKey = (str, key) => {
36
+ if (!key) return;
37
+ if (key.ctrl && key.name === 'c') { cleanup(); process.exit(0); }
38
+ const ch = (str || '').toLowerCase();
39
+ if (ch === 'y' || key.name === 'return' || ch === '-') {
40
+ cleanup();
41
+ process.stdout.write(chalk.green('y') + '\n');
42
+ resolve(true);
43
+ } else if (ch === 'n' || key.name === 'escape') {
44
+ cleanup();
45
+ process.stdout.write(chalk.gray('n') + '\n');
46
+ resolve(false);
47
+ }
48
+ };
49
+
50
+ process.stdin.on('keypress', onKey);
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Show action menu for a requirement item.
56
+ * @param {{title: string, status: string}} req
57
+ * @param {string} sectionKey - 'todo' | 'verify' | 'verified' | 'recycled'
58
+ * @param {Function} onChanged - called with true when data changes (tree should reload)
59
+ * @returns {Promise<boolean>} true if data changed
60
+ */
61
+ async function showRequirementActions(req, sectionKey, onChanged) {
62
+ const { showQuickMenu } = require('./trui-quick-menu');
63
+
64
+ const {
65
+ promoteToVerified,
66
+ demoteFromVerifiedToTodo,
67
+ promoteTodoToVerify,
68
+ demoteVerifyToTodo,
69
+ getOrCreateRequirementsFilePath,
70
+ getRequirementsPath,
71
+ } = require('vibecodingmachine-core');
72
+ const { getRepoPath, getEffectiveRepoPath } = require('./config');
73
+
74
+ // Build action items based on current section
75
+ const actions = [];
76
+
77
+ if (sectionKey === 'todo') {
78
+ actions.push({ type: 'action', name: 'Promote to TO VERIFY', value: 'promote' });
79
+ }
80
+ if (sectionKey === 'verify') {
81
+ actions.push({ type: 'action', name: 'Promote to VERIFIED', value: 'verify-promote' });
82
+ actions.push({ type: 'action', name: 'Demote to TODO', value: 'demote' });
83
+ }
84
+ if (sectionKey === 'verified') {
85
+ actions.push({ type: 'action', name: 'Demote to TODO', value: 'demote-verified' });
86
+ }
87
+
88
+ // Add clarification editing if requirement has clarification response
89
+ if (hasClarificationResponse(req)) {
90
+ actions.push({ type: 'action', name: 'šŸ’¬ Edit Clarification Response', value: 'edit-clarification' });
91
+ }
92
+
93
+ // Add bulk operations
94
+ actions.push({ type: 'separator', name: chalk.gray(' ── Bulk Operations ──'), value: 'separator' });
95
+ actions.push({ type: 'action', name: '[šŸ“‹ Select Multiple Items]', value: 'bulk-select' });
96
+ actions.push({ type: 'action', name: '[šŸš€ Move Multiple Items]', value: 'bulk-move' });
97
+
98
+ actions.push({ type: 'action', name: 'Move Item Up in section', value: 'move-up' });
99
+ actions.push({ type: 'action', name: 'Move Item Down in section', value: 'move-down' });
100
+ actions.push({ type: 'action', name: 'Rename', value: 'rename' });
101
+ actions.push({ type: 'action', name: chalk.red('Delete'), value: 'delete' });
102
+
103
+ console.log(chalk.bold.cyan(`\nšŸ“Œ ${req.title} [${sectionKey}]\n`));
104
+
105
+ const result = await showQuickMenu(actions, 0);
106
+ if (result.value === '__cancel__' || result.value === 'exit') return false;
107
+
108
+ let reqPath;
109
+ try {
110
+ const repoPath = await getRepoPath();
111
+ const p = await getRequirementsPath(repoPath);
112
+ // Use effectiveRepoPath (git root) for creation so .vibecodingmachine is never
113
+ // created inside a sub-package directory when repoPath is null.
114
+ reqPath = (p && await fs.pathExists(p)) ? p : await getOrCreateRequirementsFilePath(await getEffectiveRepoPath());
115
+ } catch (err) {
116
+ console.log(chalk.red('Cannot find requirements file: ' + err.message));
117
+ await _pause();
118
+ return false;
119
+ }
120
+
121
+ try {
122
+ if (result.value === 'promote') {
123
+ console.log(chalk.gray('\nEquivalent: vcm req:promote "' + req.title + '"'));
124
+ await promoteTodoToVerify(reqPath, req.title);
125
+ console.log(chalk.green('āœ“ Moved to TO VERIFY'));
126
+ await _pause();
127
+ return true;
128
+ }
129
+
130
+ if (result.value === 'verify-promote') {
131
+ console.log(chalk.gray('\nEquivalent: vcm req:verify "' + req.title + '"'));
132
+ await promoteToVerified(reqPath, req.title);
133
+ console.log(chalk.green('āœ“ Moved to VERIFIED'));
134
+ await _pause();
135
+ return true;
136
+ }
137
+
138
+ if (result.value === 'demote') {
139
+ console.log(chalk.gray('\nEquivalent: vcm req:demote "' + req.title + '"'));
140
+ await demoteVerifyToTodo(reqPath, req.title);
141
+ console.log(chalk.green('āœ“ Moved back to TODO'));
142
+ await _pause();
143
+ return true;
144
+ }
145
+
146
+ if (result.value === 'demote-verified') {
147
+ console.log(chalk.gray('\nEquivalent: vcm req:demote "' + req.title + '"'));
148
+ await demoteFromVerifiedToTodo(reqPath, req.title);
149
+ console.log(chalk.green('āœ“ Moved back to TODO'));
150
+ await _pause();
151
+ return true;
152
+ }
153
+
154
+ if (result.value === 'edit-clarification') {
155
+ console.log(chalk.gray('\nOpening clarification response editor...'));
156
+
157
+ // Create save callback for the requirement
158
+ const saveCallback = async (updatedReq) => {
159
+ // Update the requirement in the file
160
+ const content = await fs.readFile(reqPath, 'utf8');
161
+ const lines = content.split('\n');
162
+
163
+ // Find and replace the requirement section
164
+ let inRequirement = false;
165
+ let reqStart = -1;
166
+ let reqEnd = -1;
167
+
168
+ for (let i = 0; i < lines.length; i++) {
169
+ const line = lines[i];
170
+ if (line.includes(`## ${req.title}`) || line.includes(`### ${req.title}`)) {
171
+ inRequirement = true;
172
+ reqStart = i;
173
+ } else if (inRequirement && (line.startsWith('## ') || line.startsWith('### ')) && !line.includes(req.title)) {
174
+ reqEnd = i;
175
+ break;
176
+ }
177
+ }
178
+
179
+ if (reqEnd === -1) reqEnd = lines.length;
180
+
181
+ // Replace the requirement content
182
+ const newContent = [
183
+ ...lines.slice(0, reqStart),
184
+ ...updatedReq.content.split('\n'),
185
+ ...lines.slice(reqEnd)
186
+ ].join('\n');
187
+
188
+ await fs.writeFile(reqPath, newContent, 'utf8');
189
+ };
190
+
191
+ await editClarificationResponse(req, saveCallback);
192
+ return true;
193
+ }
194
+
195
+ if (result.value === 'bulk-select') {
196
+ await showBulkSelection(sectionKey, navigation);
197
+ return true;
198
+ }
199
+
200
+ if (result.value === 'bulk-move') {
201
+ await showBulkMove(sectionKey, navigation);
202
+ return true;
203
+ }
204
+
205
+ if (result.value === 'move-up' || result.value === 'move-down') {
206
+ const direction = result.value === 'move-up' ? 'up' : 'down';
207
+ const moved = await _moveRequirement(reqPath, req.title, sectionKey, direction);
208
+ if (moved) {
209
+ console.log(chalk.green(`āœ“ Moved ${direction}`));
210
+ console.log(chalk.gray(`Equivalent: vcm req:move-${direction} "${req.title}"`));
211
+ } else {
212
+ console.log(chalk.yellow('Already at the ' + (direction === 'up' ? 'top' : 'bottom')));
213
+ }
214
+ await _pause();
215
+ return moved;
216
+ }
217
+
218
+ if (result.value === 'rename') {
219
+ return await _renameRequirement(reqPath, req.title, sectionKey);
220
+ }
221
+
222
+ if (result.value === 'delete') {
223
+ return await _deleteRequirement(reqPath, req.title);
224
+ }
225
+ } catch (err) {
226
+ console.log(chalk.red('Error: ' + err.message));
227
+ await _pause();
228
+ }
229
+
230
+ return false;
231
+ }
232
+
233
+ /**
234
+ * Move a requirement up or down within its section
235
+ */
236
+ async function _moveRequirement(reqPath, title, sectionKey, direction) {
237
+ const content = await fs.readFile(reqPath, 'utf8');
238
+ const lines = content.split('\n');
239
+
240
+ // Find section boundaries
241
+ const sectionHeadings = {
242
+ todo: /requirements not yet completed/i,
243
+ verify: /to verify|verified by ai/i,
244
+ verified: /verified\b/i,
245
+ recycled: /recycled/i,
246
+ };
247
+ const pattern = sectionHeadings[sectionKey];
248
+
249
+ let sectionStart = -1;
250
+ let sectionEnd = lines.length;
251
+
252
+ for (let i = 0; i < lines.length; i++) {
253
+ const line = lines[i].trim();
254
+ if (sectionStart === -1 && line.startsWith('##') && pattern && pattern.test(line)) {
255
+ sectionStart = i;
256
+ } else if (sectionStart !== -1 && line.startsWith('## ') && i > sectionStart) {
257
+ sectionEnd = i;
258
+ break;
259
+ }
260
+ }
261
+
262
+ if (sectionStart === -1) return false;
263
+
264
+ // Find all requirement blocks (### headers) within the section
265
+ const reqBlocks = [];
266
+ let currentBlock = null;
267
+ for (let i = sectionStart + 1; i < sectionEnd; i++) {
268
+ const line = lines[i];
269
+ if (line.trim().startsWith('### ')) {
270
+ if (currentBlock) { currentBlock.end = i; reqBlocks.push(currentBlock); }
271
+ currentBlock = { title: line.trim().replace(/^###\s*/, ''), start: i, end: sectionEnd };
272
+ }
273
+ }
274
+ if (currentBlock) { currentBlock.end = sectionEnd; reqBlocks.push(currentBlock); }
275
+
276
+ const idx = reqBlocks.findIndex(b => b.title === title);
277
+ if (idx === -1) return false;
278
+ if (direction === 'up' && idx === 0) return false;
279
+ if (direction === 'down' && idx === reqBlocks.length - 1) return false;
280
+
281
+ const swapIdx = direction === 'up' ? idx - 1 : idx + 1;
282
+ const blockA = reqBlocks[idx];
283
+ const blockB = reqBlocks[swapIdx];
284
+
285
+ // Extract block content
286
+ const [first, second] = blockA.start < blockB.start ? [blockA, blockB] : [blockB, blockA];
287
+ const firstContent = lines.slice(first.start, first.end);
288
+ const secondContent = lines.slice(second.start, second.end);
289
+
290
+ // Swap
291
+ const newLines = [
292
+ ...lines.slice(0, first.start),
293
+ ...secondContent,
294
+ ...firstContent,
295
+ ...lines.slice(second.end),
296
+ ];
297
+
298
+ await fs.writeFile(reqPath, newLines.join('\n'), 'utf8');
299
+ return true;
300
+ }
301
+
302
+ /**
303
+ * Rename a requirement
304
+ */
305
+ async function _renameRequirement(reqPath, oldTitle, sectionKey) {
306
+ const { newTitle } = await inquirer.prompt([{
307
+ type: 'input',
308
+ name: 'newTitle',
309
+ message: chalk.cyan('New title:'),
310
+ default: oldTitle,
311
+ validate: v => v.trim().length > 0 || 'Title required',
312
+ }]);
313
+
314
+ if (newTitle.trim() === oldTitle) return false;
315
+
316
+ const content = await fs.readFile(reqPath, 'utf8');
317
+ const escaped = oldTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
318
+ const updated = content.replace(new RegExp(`^(###\\s*)${escaped}\\s*$`, 'm'), `$1${newTitle.trim()}`);
319
+
320
+ if (updated === content) {
321
+ console.log(chalk.yellow('Could not find requirement to rename'));
322
+ await _pause();
323
+ return false;
324
+ }
325
+
326
+ await fs.writeFile(reqPath, updated, 'utf8');
327
+ console.log(chalk.green(`āœ“ Renamed to "${newTitle.trim()}"`));
328
+ console.log(chalk.gray(`Equivalent: vcm req:rename "${oldTitle}" "${newTitle.trim()}"`));
329
+ await _pause();
330
+ return true;
331
+ }
332
+
333
+ /**
334
+ * Delete a requirement after confirmation
335
+ */
336
+ async function _deleteRequirement(reqPath, title) {
337
+ const confirmed = await _confirmKeypress(chalk.red(`Delete "${title}"?`));
338
+ if (!confirmed) return false;
339
+
340
+ const content = await fs.readFile(reqPath, 'utf8');
341
+ const lines = content.split('\n');
342
+ const escaped = title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
343
+ const startRe = new RegExp(`^###\\s*${escaped}\\s*$`);
344
+
345
+ let startIdx = -1;
346
+ for (let i = 0; i < lines.length; i++) {
347
+ if (startRe.test(lines[i].trim())) { startIdx = i; break; }
348
+ }
349
+ if (startIdx === -1) {
350
+ console.log(chalk.yellow('Could not find requirement to delete'));
351
+ return false;
352
+ }
353
+
354
+ // Find end of this requirement block
355
+ let endIdx = startIdx + 1;
356
+ while (endIdx < lines.length) {
357
+ const line = lines[endIdx].trim();
358
+ if (line.startsWith('### ') || (line.startsWith('## ') && !line.startsWith('### '))) break;
359
+ endIdx++;
360
+ }
361
+
362
+ lines.splice(startIdx, endIdx - startIdx);
363
+ await fs.writeFile(reqPath, lines.join('\n'), 'utf8');
364
+ console.log(chalk.green(`āœ“ Deleted "${title}"`));
365
+ return true;
366
+ }
367
+
368
+ /**
369
+ * Prompt for a new requirement and append to the TODO section
370
+ */
371
+ async function addRequirementFlow() {
372
+ console.log(chalk.bold.cyan('\nšŸ“‹ Add New Requirement\n'));
373
+ console.log(chalk.gray('Equivalent: vcm req:add "<title>"\n'));
374
+
375
+ const { createNewRequirement } = require('./trui-req-editor');
376
+
377
+ try {
378
+ const requirement = await createNewRequirement();
379
+
380
+ const { getOrCreateRequirementsFilePath, getRequirementsPath } = require('vibecodingmachine-core');
381
+ const { getRepoPath: _getRepoPath, getEffectiveRepoPath: _getEffectiveRepoPath } = require('./config');
382
+ const _repoPath = await _getRepoPath();
383
+ const _p = await getRequirementsPath(_repoPath);
384
+ // Use effectiveRepoPath (git root) for creation to avoid nested .vibecodingmachine dirs.
385
+ const reqPath = (_p && await fs.pathExists(_p)) ? _p : await getOrCreateRequirementsFilePath(await _getEffectiveRepoPath());
386
+ const content = await fs.readFile(reqPath, 'utf8');
387
+ const lines = content.split('\n');
388
+
389
+ let insertIndex = -1;
390
+ for (let i = 0; i < lines.length; i++) {
391
+ if (lines[i].trim().match(/^##\s+.*(?:Requirements not yet completed|TODO)/i)) {
392
+ insertIndex = i + 1;
393
+ for (let j = i + 1; j < lines.length; j++) {
394
+ const inner = lines[j].trim();
395
+ if (inner.startsWith('## ') && !inner.startsWith('### ')) { insertIndex = j; break; }
396
+ if (inner.startsWith('### ') || inner.startsWith('- ')) { insertIndex = j; break; }
397
+ }
398
+ break;
399
+ }
400
+ }
401
+
402
+ const block = requirement.description
403
+ ? `### ${requirement.title.trim()}\n\n${requirement.description.trim()}\n`
404
+ : `### ${requirement.title.trim()}\n`;
405
+
406
+ if (insertIndex >= 0) {
407
+ lines.splice(insertIndex, 0, block);
408
+ } else {
409
+ lines.push('', '## Requirements not yet completed', '', block);
410
+ }
411
+
412
+ await fs.writeFile(reqPath, lines.join('\n'), 'utf8');
413
+ console.log(chalk.green(`\nāœ“ Added "${title.trim()}"`));
414
+ } catch (err) {
415
+ console.log(chalk.red('Error: ' + err.message));
416
+ }
417
+
418
+ await _pause();
419
+ }
420
+
421
+ async function _pause() {
422
+ await inquirer.prompt([{ type: 'input', name: 'c', message: chalk.gray('Press Enter to continue...') }]);
423
+ }
424
+
425
+ /**
426
+ * Handle requirement selection from the tree navigator
427
+ * @param {number} index - Index of the requirement in the section
428
+ * @param {Array} requirements - Array of requirements in the section
429
+ * @param {Object} navigation - Navigation object
430
+ */
431
+ async function handleRequirementSelection(index, requirements, navigation) {
432
+ if (index < 0 || index >= requirements.length) {
433
+ console.log(chalk.red('Invalid requirement index'));
434
+ return;
435
+ }
436
+
437
+ const req = requirements[index];
438
+ const sectionKey = navigation.currentSection || 'todo';
439
+
440
+ const changed = await showRequirementActions(req, sectionKey, () => {
441
+ // Refresh callback - the tree will reload
442
+ });
443
+
444
+ return changed;
445
+ }
446
+
447
+ module.exports = {
448
+ showRequirementActions,
449
+ addRequirementFlow,
450
+ _moveRequirement,
451
+ _deleteRequirement,
452
+ handleRequirementSelection,
453
+ showBulkSelection,
454
+ showBulkMove
455
+ };
456
+
457
+ /**
458
+ * Show bulk selection interface
459
+ */
460
+ async function showBulkSelection(sectionKey, navigation) {
461
+ console.clear();
462
+ console.log(chalk.bold.cyan('šŸ“‹ Bulk Selection\n'));
463
+ console.log(chalk.gray('Select multiple requirements for bulk operations\n'));
464
+
465
+ // Load requirements for the section
466
+ const data = await navigation.resolver.resolve('list requirements');
467
+ const result = await data.command.execute();
468
+ const requirements = result.data.sections[sectionKey] || [];
469
+
470
+ if (requirements.length === 0) {
471
+ console.log(chalk.yellow('No requirements in this section'));
472
+ await _pause();
473
+ return;
474
+ }
475
+
476
+ const { selectedItems } = await inquirer.prompt([
477
+ {
478
+ type: 'checkbox',
479
+ name: 'selectedItems',
480
+ message: 'Select requirements:',
481
+ choices: requirements.map((req, index) => ({
482
+ name: req.title || req.name || 'Untitled',
483
+ value: index
484
+ }))
485
+ }
486
+ ]);
487
+
488
+ if (selectedItems.length === 0) {
489
+ console.log(chalk.yellow('No items selected'));
490
+ await _pause();
491
+ return;
492
+ }
493
+
494
+ console.log(chalk.green(`\nSelected ${selectedItems.length} item(s)`));
495
+ await _pause();
496
+ }
497
+
498
+ /**
499
+ * Show bulk move interface
500
+ */
501
+ async function showBulkMove(sectionKey, navigation) {
502
+ console.clear();
503
+ console.log(chalk.bold.cyan('šŸš€ Bulk Move\n'));
504
+ console.log(chalk.gray('Move multiple requirements to another section\n'));
505
+
506
+ await _pause();
507
+ }