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
@@ -1,586 +1,5 @@
1
- const chalk = require('chalk');
2
- const inquirer = require('inquirer');
3
- const fs = require('fs-extra');
4
- const path = require('path');
5
- const readline = require('readline');
6
- const { t, getRequirementsPath, getVibeCodingMachineDir, checkVibeCodingMachineExists } = require('vibecodingmachine-core');
7
- const { parseRequirementsFromContent } = require('./requirements-parser');
8
- const { countRequirements } = require('./status-helpers');
9
-
10
- // Import helper functions that will be extracted separately
11
- // These will need to be imported from requirement-actions.js once created
12
- const {
13
- confirmAndExit,
14
- showRequirementActions,
15
- showClarificationActions,
16
- handleAddRequirement,
17
- deleteRequirement,
18
- deleteClarification,
19
- permanentlyDeleteRequirement,
20
- moveRequirementDown,
21
- moveRequirementUp,
22
- promoteRequirement,
23
- demoteRequirement,
24
- moveClarificationToTodo,
25
- handleFeedbackSubmission
26
- } = require('./requirement-actions');
27
-
28
- /**
29
- * Tree-style requirements navigator
30
- */
31
- async function showRequirementsTree() {
32
- console.log(chalk.bold.cyan('\n📋 ' + t('requirements.navigator.title') + '\n'));
33
- console.log(chalk.gray(t('requirements.navigator.basic.instructions') + '\n'));
34
- console.log(chalk.gray('💡 Press F for feedback - Share your thoughts anytime\n'));
35
-
36
- const tree = {
37
- expanded: { root: true },
38
- selected: 0,
39
- items: []
40
- };
41
-
42
- // Build tree structure
43
- const buildTree = async () => {
44
- tree.items = [];
45
-
46
- // Root: Requirements
47
- tree.items.push({ level: 0, type: 'root', label: `📋 ${t('requirements.menu.label')}`, key: 'root' });
48
-
49
- if (tree.expanded.root) {
50
- tree.items.push({ level: 1, type: 'add', label: '➕ ' + t('requirements.add.new'), key: 'add-one' });
51
- tree.items.push({ level: 1, type: 'add', label: '➕ ' + t('requirements.add.multiple'), key: 'add-many' });
52
-
53
- // Use pre-calculated stats and labels from shared logic
54
- const stats = await countRequirements();
55
- const { todoCount, toVerifyCount, verifiedCount, total, todoLabel, toVerifyLabel, verifiedLabel } = stats || {
56
- todoCount: 0, toVerifyCount: 0, verifiedCount: 0, total: 0,
57
- todoLabel: '⏳ TODO (0 - 0%)', toVerifyLabel: '✅ TO VERIFY (0 - 0%)', verifiedLabel: '🎉 VERIFIED (0 - 0%)'
58
- };
59
-
60
- // Create localized labels
61
- const localizedTodoLabel = todoCount > 0 ?
62
- `⏳ ${t('requirements.section.todo')} (${todoCount} - ${Math.round((todoCount / total) * 100)}%)` :
63
- `⏳ ${t('requirements.section.todo')} (0 - 0%)`;
64
-
65
- const localizedToVerifyLabel = toVerifyCount > 0 ?
66
- `✅ ${t('requirements.section.to.verify')} (${toVerifyCount} - ${Math.round((toVerifyCount / total) * 100)}%)` :
67
- `✅ ${t('requirements.section.to.verify')} (0 - 0%)`;
68
-
69
- const localizedVerifiedLabel = verifiedCount > 0 ?
70
- `🎉 ${t('requirements.section.verified')} (${verifiedCount} - ${Math.round((verifiedCount / total) * 100)}%)` :
71
- `🎉 ${t('requirements.section.verified')} (0 - 0%)`;
72
-
73
- const verifiedReqs = tree.verifiedReqs || [];
74
- const verifyReqs = tree.verifyReqs || [];
75
- const clarificationReqs = tree.clarificationReqs || [];
76
- const todoReqs = tree.todoReqs || [];
77
- const recycledReqs = tree.recycledReqs || [];
78
-
79
- // Calculate percentages for clarification and recycled sections
80
- const clarificationPercent = total > 0 ? Math.round((clarificationReqs.length / total) * 100) : 0;
81
- const recycledPercent = total > 0 ? Math.round((recycledReqs.length / total) * 100) : 0;
82
-
83
- // VERIFIED section (first) - only show if has requirements
84
- if (verifiedReqs.length > 0 || verifiedCount > 0) {
85
- tree.items.push({ level: 1, type: 'section', label: localizedVerifiedLabel, key: 'verified' });
86
-
87
- if (tree.expanded.verified) {
88
- verifiedReqs.forEach((req, idx) => {
89
- tree.items.push({ level: 2, type: 'verified', label: req, key: `verified-${idx}` });
90
- });
91
- }
92
- }
93
-
94
- // TO VERIFY section (second) - only show if has requirements
95
- if (verifyReqs.length > 0 || toVerifyCount > 0) {
96
- tree.items.push({ level: 1, type: 'section', label: localizedToVerifyLabel, key: 'verify', section: '✅ Verified by AI screenshot' });
97
-
98
- if (tree.expanded.verify) {
99
- verifyReqs.forEach((req, idx) => {
100
- tree.items.push({ level: 2, type: 'requirement', label: req.title, key: `verify-${idx}`, req, sectionKey: 'verify' });
101
- });
102
- }
103
- }
104
-
105
- // NEEDING CLARIFICATION section (third) - only show if has requirements
106
- if (clarificationReqs.length > 0) {
107
- tree.items.push({ level: 1, type: 'section', label: `❓ NEEDING CLARIFICATION (${clarificationReqs.length} - ${clarificationPercent}%)`, key: 'clarification', section: '❓ Requirements needing manual feedback' });
108
-
109
- if (tree.expanded.clarification) {
110
- clarificationReqs.forEach((req, idx) => {
111
- tree.items.push({ level: 2, type: 'clarification', label: req.title, key: `clarification-${idx}`, req, sectionKey: 'clarification' });
112
- });
113
- }
114
- }
115
-
116
- // TODO section (fourth) - only show if has requirements
117
- if (todoReqs.length > 0 || todoCount > 0) {
118
- tree.items.push({ level: 1, type: 'section', label: localizedTodoLabel, key: 'todo', section: '⏳ Requirements not yet completed' });
119
-
120
- if (tree.expanded.todo) {
121
- todoReqs.forEach((req, idx) => {
122
- tree.items.push({ level: 2, type: 'requirement', label: req.title, key: `todo-${idx}`, req, sectionKey: 'todo' });
123
- });
124
- }
125
- }
126
-
127
- // RECYCLED section (last) - only show if has requirements
128
- if (recycledReqs.length > 0) {
129
- tree.items.push({ level: 1, type: 'section', label: `♻️ RECYCLED (${recycledReqs.length} - ${recycledPercent}%)`, key: 'recycled', section: '♻️ Recycled' });
130
-
131
- if (tree.expanded.recycled) {
132
- recycledReqs.forEach((req, idx) => {
133
- tree.items.push({ level: 2, type: 'recycled', label: req.title, key: `recycled-${idx}`, req, sectionKey: 'recycled' });
134
- });
135
- }
136
- }
137
- }
138
- };
139
-
140
- // Load requirements for a section
141
- const loadSection = async (sectionKey, sectionTitle) => {
142
- const reqPath = await getRequirementsPath();
143
-
144
- if (!reqPath || !await fs.pathExists(reqPath)) {
145
- return [];
146
- }
147
-
148
- const content = await fs.readFile(reqPath, 'utf8');
149
-
150
- // Delegate to reusable parser
151
- const allReqs = parseRequirementsFromContent(content, sectionKey, sectionTitle);
152
-
153
- // For TODO section, only show primary heading requirements (those marked from '###' titles)
154
- if (sectionKey === 'todo') return allReqs.filter(r => r.source === 'heading');
155
-
156
- return allReqs;
157
- };
158
-
159
- // Load VERIFIED requirements from CHANGELOG
160
- const loadVerified = async () => {
161
- const allnightStatus = await checkVibeCodingMachineExists();
162
- let changelogPath;
163
-
164
- if (allnightStatus.insideExists) {
165
- const allnightDir = await getVibeCodingMachineDir();
166
- changelogPath = path.join(path.dirname(allnightDir), 'CHANGELOG.md');
167
- } else if (allnightStatus.siblingExists) {
168
- changelogPath = path.join(process.cwd(), 'CHANGELOG.md');
169
- }
170
-
171
- if (!changelogPath || !await fs.pathExists(changelogPath)) {
172
- return [];
173
- }
174
-
175
- const content = await fs.readFile(changelogPath, 'utf8');
176
- const lines = content.split('\n');
177
- const requirements = [];
178
- let inVerifiedSection = false;
179
-
180
- for (const line of lines) {
181
- const trimmed = line.trim();
182
-
183
- // Check for Verified Requirements section
184
- if (trimmed.includes('## Verified Requirements')) {
185
- inVerifiedSection = true;
186
- continue;
187
- }
188
-
189
- // Exit section if we hit another ## header
190
- if (inVerifiedSection && trimmed.startsWith('##') && !trimmed.includes('Verified Requirements')) {
191
- break;
192
- }
193
-
194
- // Only collect items from within the Verified Requirements section
195
- if (inVerifiedSection && trimmed.startsWith('- ') && trimmed.length > 10) {
196
- requirements.push(trimmed.substring(2));
197
- }
198
- }
199
-
200
- return requirements;
201
- };
202
-
203
- // Load clarification requirements with questions
204
- const loadClarification = async () => {
205
- const reqPath = await getRequirementsPath();
206
-
207
- if (!reqPath || !await fs.pathExists(reqPath)) {
208
- return [];
209
- }
210
-
211
- const content = await fs.readFile(reqPath, 'utf8');
212
- const lines = content.split('\n');
213
-
214
- let inSection = false;
215
- const requirements = [];
216
-
217
- for (let i = 0; i < lines.length; i++) {
218
- const line = lines[i];
219
- const trimmed = line.trim();
220
-
221
- // Check if we're entering the clarification section
222
- if (trimmed.includes('❓ Requirements needing manual feedback')) {
223
- inSection = true;
224
- continue;
225
- }
226
-
227
- // Check if we're leaving the section (hit another ## section)
228
- if (inSection && trimmed.startsWith('##') && !trimmed.startsWith('###')) {
229
- break;
230
- }
231
-
232
- // Read requirements in new format (### header)
233
- if (inSection && trimmed.startsWith('###')) {
234
- const title = trimmed.replace(/^###\s*/, '').trim();
235
-
236
- // Skip empty titles
237
- if (!title || title.length === 0) {
238
- continue;
239
- }
240
-
241
- const details = [];
242
- const questions = [];
243
- let pkg = null;
244
- let findings = null;
245
- let currentQuestion = null;
246
-
247
- // Read package, description, and clarifying questions
248
- for (let j = i + 1; j < lines.length; j++) {
249
- const nextLine = lines[j].trim();
250
-
251
- // Stop if we hit another requirement or section
252
- if (nextLine.startsWith('###') || (nextLine.startsWith('##') && !nextLine.startsWith('###'))) {
253
- break;
254
- }
255
-
256
- // Check for PACKAGE line
257
- if (nextLine.startsWith('PACKAGE:')) {
258
- pkg = nextLine.replace(/^PACKAGE:\s*/, '').trim();
259
- }
260
- // Check for AI findings
261
- else if (nextLine.startsWith('**AI found in codebase:**')) {
262
- // Next line will be the findings
263
- continue;
264
- }
265
- else if (nextLine.startsWith('**What went wrong')) {
266
- // Description line
267
- details.push(nextLine);
268
- }
269
- else if (nextLine.startsWith('**Clarifying questions:**')) {
270
- // Start of questions section
271
- continue;
272
- }
273
- else if (nextLine.match(/^\d+\./)) {
274
- // Save previous question if exists
275
- if (currentQuestion) {
276
- questions.push(currentQuestion);
277
- }
278
- // This is a new question
279
- currentQuestion = { question: nextLine, response: null };
280
- }
281
- else if (currentQuestion && nextLine && !nextLine.startsWith('PACKAGE:') && !nextLine.startsWith('**')) {
282
- // This might be a response to the current question or description/findings
283
- if (!findings && !currentQuestion.response && questions.length === 0 && !nextLine.match(/^\d+\./)) {
284
- // This is findings content
285
- findings = nextLine;
286
- } else if (currentQuestion && !currentQuestion.response) {
287
- // This is a response to the current question
288
- currentQuestion.response = nextLine;
289
- } else {
290
- // Description line
291
- details.push(nextLine);
292
- }
293
- }
294
- else if (nextLine && !nextLine.startsWith('PACKAGE:') && !nextLine.startsWith('**')) {
295
- // Description line
296
- details.push(nextLine);
297
- }
298
- }
299
-
300
- // Save last question if exists
301
- if (currentQuestion) {
302
- questions.push(currentQuestion);
303
- }
304
-
305
- requirements.push({ title, details, pkg, questions, findings, lineIndex: i });
306
- }
307
- }
308
-
309
- return requirements;
310
- };
311
-
312
- // Load all sections upfront to show counts immediately
313
- tree.todoReqs = await loadSection('todo', '⏳ Requirements not yet completed');
314
- tree.verifyReqs = await loadSection('verify', '✅ Verified by AI screenshot');
315
- tree.clarificationReqs = await loadClarification();
316
- tree.verifiedReqs = await loadVerified();
317
- tree.recycledReqs = await loadSection('recycled', '♻️ Recycled');
318
-
319
- let inTree = true;
320
- await buildTree();
321
-
322
- while (inTree) {
323
- console.clear();
324
- console.log(chalk.bold.cyan('\n📋 ' + t('requirements.navigator.title') + '\n'));
325
- console.log(chalk.gray(t('requirements.navigator.instructions') + '\n'));
326
-
327
- // Safety check: ensure tree.selected is within bounds
328
- if (tree.items.length === 0) {
329
- console.log(chalk.yellow('No items to display.'));
330
- const inquirer = require('inquirer');
331
- await inquirer.prompt([{
332
- type: 'input',
333
- name: 'continue',
334
- message: `${t('interactive.press.any.key.return')}`
335
- }]);
336
- inTree = false;
337
- continue;
338
- }
339
-
340
- if (tree.selected >= tree.items.length) {
341
- tree.selected = tree.items.length - 1;
342
- }
343
-
344
- if (tree.selected < 0) {
345
- tree.selected = 0;
346
- }
347
-
348
- // Calculate window for scrolling (show max 20 items at a time)
349
- const maxVisible = 20;
350
- let startIdx = 0;
351
- let endIdx = tree.items.length;
352
-
353
- if (tree.items.length > maxVisible) {
354
- // Center the selected item in the window
355
- startIdx = Math.max(0, tree.selected - Math.floor(maxVisible / 2));
356
- endIdx = Math.min(tree.items.length, startIdx + maxVisible);
357
-
358
- // Adjust if we're near the end
359
- if (endIdx - startIdx < maxVisible) {
360
- startIdx = Math.max(0, endIdx - maxVisible);
361
- }
362
- }
363
-
364
- // Show indicator if there are items above
365
- if (startIdx > 0) {
366
- console.log(chalk.gray(` ↑ ${startIdx} more above...`));
367
- }
368
-
369
- // Display visible tree items
370
- for (let idx = startIdx; idx < endIdx; idx++) {
371
- const item = tree.items[idx];
372
- const indent = ' '.repeat(item.level);
373
- const arrow = tree.expanded[item.key] ? '▼' : (item.type === 'section' ? '▶' : ' ');
374
- const prefix = item.type === 'section' || item.type === 'root' ? arrow + ' ' : ' ';
375
- const selected = idx === tree.selected ? chalk.cyan('❯ ') : ' ';
376
-
377
- // Truncate long labels to fit terminal width (max 120 chars)
378
- const maxLabelWidth = 120;
379
- let label = item.label;
380
- if (label.length > maxLabelWidth) {
381
- label = label.substring(0, maxLabelWidth - 3) + '...';
382
- }
383
-
384
- console.log(selected + indent + prefix + (idx === tree.selected ? chalk.cyan(label) : chalk.gray(label)));
385
- }
386
-
387
- // Show indicator if there are items below
388
- if (endIdx < tree.items.length) {
389
- console.log(chalk.gray(` ↓ ${tree.items.length - endIdx} more below...`));
390
- }
391
-
392
- console.log();
393
-
394
- // Handle input
395
- const key = await new Promise((resolve) => {
396
- readline.emitKeypressEvents(process.stdin);
397
- if (process.stdin.isTTY) {
398
- process.stdin.setRawMode(true);
399
- }
400
-
401
- const handler = (str, key) => {
402
- process.stdin.removeListener('keypress', handler);
403
- if (process.stdin.isTTY) {
404
- process.stdin.setRawMode(false);
405
- }
406
- resolve(key);
407
- };
408
-
409
- process.stdin.on('keypress', handler);
410
- process.stdin.resume();
411
- });
412
-
413
- if (!key) continue;
414
-
415
- // Handle key presses
416
- if (key.ctrl && key.name === 'c') {
417
- // Ctrl+C always exits immediately
418
- process.exit(0);
419
- } else if (key.name === 'x' || key.name === 'escape') {
420
- // X or ESC key - exit CLI with confirmation
421
- await confirmAndExit();
422
- } else if (key.name === 'left') {
423
- const current = tree.items[tree.selected];
424
- if (!current) continue; // Safety check
425
-
426
- if (tree.expanded[current.key]) {
427
- // Collapse expanded section
428
- tree.expanded[current.key] = false;
429
- await buildTree();
430
- } else if (current.level > 0) {
431
- // Go to parent
432
- for (let i = tree.selected - 1; i >= 0; i--) {
433
- if (tree.items[i].level < current.level) {
434
- tree.selected = i;
435
- break;
436
- }
437
- }
438
- } else {
439
- // At root level, go back to main menu
440
- inTree = false;
441
- }
442
- } else if (key.name === 'k' || key.name === 'up') {
443
- tree.selected = Math.max(0, tree.selected - 1);
444
- await buildTree();
445
- } else if (key.name === 'j' || key.name === 'down') {
446
- tree.selected = Math.min(tree.items.length - 1, tree.selected + 1);
447
- await buildTree();
448
- } else if (key.name === 'right' || key.name === 'return' || key.name === 'space') {
449
- const current = tree.items[tree.selected];
450
- if (!current) continue; // Safety check
451
- if (current.type === 'section') {
452
- if (!tree.expanded[current.key]) {
453
- tree.expanded[current.key] = true;
454
- // Load requirements for this section
455
- if (current.key === 'todo') {
456
- tree.todoReqs = await loadSection(current.key, current.section);
457
- } else if (current.key === 'verify') {
458
- tree.verifyReqs = await loadSection(current.key, current.section);
459
- } else if (current.key === 'verified') {
460
- tree.verifiedReqs = await loadVerified();
461
- } else if (current.key === 'recycled') {
462
- tree.recycledReqs = await loadSection(current.key, current.section);
463
- }
464
- await buildTree();
465
- } else {
466
- tree.expanded[current.key] = false;
467
- await buildTree();
468
- }
469
- } else if (current.type === 'requirement') {
470
- // Show requirement actions
471
- await showRequirementActions(current.req, current.sectionKey, tree);
472
- await buildTree();
473
- } else if (current.type === 'clarification') {
474
- // Show clarification requirement with questions
475
- await showClarificationActions(current.req, tree, loadClarification);
476
- await buildTree();
477
- } else if (current.type === 'verified') {
478
- // Show verified item details (read-only)
479
- console.clear();
480
- console.log(chalk.bold.green(`\n${current.label}\n`));
481
- console.log(chalk.gray('(From CHANGELOG.md - read only)'));
482
- console.log(chalk.gray(`\n${t('interactive.press.any.key.back')}`));
483
- await new Promise((resolve) => {
484
- readline.emitKeypressEvents(process.stdin);
485
- if (process.stdin.isTTY) {
486
- process.stdin.setRawMode(true);
487
- }
488
- const handler = (str, key) => {
489
- process.stdin.removeListener('keypress', handler);
490
- if (process.stdin.isTTY) {
491
- process.stdin.setRawMode(false);
492
- }
493
- resolve();
494
- };
495
- process.stdin.on('keypress', handler);
496
- process.stdin.resume();
497
- });
498
- } else if (current.type === 'add') {
499
- // Handle add requirement
500
- await handleAddRequirement(current.key);
501
- // Reload TODO section
502
- tree.todoReqs = await loadSection('todo', '⏳ Requirements not yet completed');
503
- await buildTree();
504
- }
505
- } else if (key.name === 'f') {
506
- // Feedback button ( megaphone 📣 )
507
- await handleFeedbackSubmission();
508
- await buildTree();
509
- } else if (key.name === 'r') {
510
- const current = tree.items[tree.selected];
511
- if (!current) continue; // Safety check
512
-
513
- if (current.type === 'requirement') {
514
- await deleteRequirement(current.req, current.sectionKey, tree);
515
- // Reload the section that the requirement was deleted from
516
- if (current.sectionKey === 'todo') {
517
- tree.todoReqs = await loadSection('todo', '⏳ Requirements not yet completed');
518
- } else if (current.sectionKey === 'verify') {
519
- tree.verifyReqs = await loadSection('verify', '✅ Verified by AI screenshot');
520
- }
521
- await buildTree();
522
- } else if (current.type === 'clarification') {
523
- await deleteClarification(current.req, tree);
524
- tree.clarificationReqs = await loadClarification();
525
- await buildTree();
526
- } else if (current.type === 'recycled') {
527
- await permanentlyDeleteRequirement(current.req, current.sectionKey, tree);
528
- tree.recycledReqs = await loadSection('recycled', '♻️ Recycled');
529
- await buildTree();
530
- }
531
- } else if (key.name === 'j') {
532
- const current = tree.items[tree.selected];
533
- if (!current) continue; // Safety check
534
-
535
- if (current.type === 'requirement') {
536
- await moveRequirementDown(current.req, current.sectionKey, tree);
537
- await buildTree();
538
- // Move selection down to follow the item
539
- if (tree.selected < tree.items.length - 1) {
540
- tree.selected++;
541
- }
542
- }
543
- } else if (key.name === 'k') {
544
- const current = tree.items[tree.selected];
545
- if (!current) continue; // Safety check
546
-
547
- if (current.type === 'requirement') {
548
- await moveRequirementUp(current.req, current.sectionKey, tree);
549
- await buildTree();
550
- // Move selection up to follow the item
551
- if (tree.selected > 0) {
552
- tree.selected--;
553
- }
554
- }
555
- } else if (key.name === 'u') {
556
- const current = tree.items[tree.selected];
557
- if (!current) continue; // Safety check
558
-
559
- if (current.type === 'requirement') {
560
- await promoteRequirement(current.req, current.sectionKey, tree, loadSection, loadVerified);
561
- await buildTree();
562
- }
563
- } else if (key.name === 'd') {
564
- const current = tree.items[tree.selected];
565
- if (!current) continue; // Safety check
566
-
567
- if (current.type === 'clarification') {
568
- // D on clarification item = Move to TODO
569
- await moveClarificationToTodo(current.req, tree);
570
- tree.clarificationReqs = await loadClarification();
571
- tree.todoReqs = await loadSection('todo', '⏳ Requirements not yet completed');
572
- await buildTree();
573
- } else if (current.type === 'requirement' || current.type === 'verified') {
574
- const sectionKey = current.type === 'verified' ? 'verified' : current.sectionKey;
575
- const reqTitle = current.type === 'verified' ? current.label : current.req.title;
576
- await demoteRequirement(reqTitle, sectionKey, tree, loadSection, loadVerified);
577
- await buildTree();
578
- }
579
- }
580
- }
581
-
582
- process.stdin.pause();
583
- }
1
+ // Re-export from modular implementation
2
+ const { showRequirementsTree } = require('./requirements-navigator/index');
584
3
 
585
4
  module.exports = {
586
5
  showRequirementsTree