vibecodingmachine-cli 2026.3.14-1537 → 2026.6.17-1835

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 (162) hide show
  1. package/bin/auth/auth-compliance.js +7 -7
  2. package/bin/commands/agent-commands.js +15 -15
  3. package/bin/commands/auto-commands.js +3 -3
  4. package/bin/commands/command-aliases.js +13 -4
  5. package/bin/config/cli-config.js +15 -5
  6. package/bin/update/update-checker.js +5 -5
  7. package/bin/vibecodingmachine.js +2 -2
  8. package/package.json +2 -2
  9. package/src/commands/agents/add.js +5 -5
  10. package/src/commands/agents/check.js +19 -19
  11. package/src/commands/agents/list.js +24 -24
  12. package/src/commands/agents/remove.js +4 -4
  13. package/src/commands/agents-check.js +1 -1
  14. package/src/commands/analyze-file-sizes.js +43 -43
  15. package/src/commands/auto-direct/auto-provider-manager.js +19 -19
  16. package/src/commands/auto-direct/auto-start-phases.js +493 -0
  17. package/src/commands/auto-direct/auto-status-display.js +35 -35
  18. package/src/commands/auto-direct/auto-utils.js +50 -50
  19. package/src/commands/auto-direct/cline-installer.js +56 -0
  20. package/src/commands/auto-direct/code-processor.js +27 -27
  21. package/src/commands/auto-direct/file-scanner.js +19 -19
  22. package/src/commands/auto-direct/ide-completion-waiter.js +485 -0
  23. package/src/commands/auto-direct/ide-fallback-runner.js +226 -0
  24. package/src/commands/auto-direct/ide-provider-runner.js +103 -0
  25. package/src/commands/auto-direct/iteration-handlers.js +189 -0
  26. package/src/commands/auto-direct/iteration-runner.js +485 -0
  27. package/src/commands/auto-direct/provider-config.js +38 -7
  28. package/src/commands/auto-direct/provider-manager.js +132 -6
  29. package/src/commands/auto-direct/requirement-manager.js +169 -104
  30. package/src/commands/auto-direct/requirement-mover.js +350 -0
  31. package/src/commands/auto-direct/spec-handlers.js +155 -0
  32. package/src/commands/auto-direct/spec-ide-runner.js +318 -0
  33. package/src/commands/auto-direct/spec-processing.js +203 -0
  34. package/src/commands/auto-direct/status-display.js +9 -9
  35. package/src/commands/auto-direct/utils.js +83 -1
  36. package/src/commands/auto-direct-refactored.js +1 -413
  37. package/src/commands/auto-direct.js +127 -4119
  38. package/src/commands/auto-execution.js +21 -21
  39. package/src/commands/auto-status-helpers.js +0 -2
  40. package/src/commands/auto.js +22 -22
  41. package/src/commands/check-compliance.js +65 -65
  42. package/src/commands/computers.js +39 -39
  43. package/src/commands/continuous-scan.js +19 -19
  44. package/src/commands/ide.js +4 -4
  45. package/src/commands/locale.js +7 -7
  46. package/src/commands/refactor-file.js +59 -59
  47. package/src/commands/requirements/commands.js +17 -17
  48. package/src/commands/requirements/default-handlers.js +30 -30
  49. package/src/commands/requirements/disable.js +3 -3
  50. package/src/commands/requirements/enable.js +3 -3
  51. package/src/commands/requirements/utils.js +6 -6
  52. package/src/commands/requirements-refactored.js +3 -3
  53. package/src/commands/requirements-remote.js +38 -38
  54. package/src/commands/requirements.js +3 -3
  55. package/src/commands/settings.js +111 -0
  56. package/src/commands/specs/count.js +60 -0
  57. package/src/commands/specs/disable.js +3 -3
  58. package/src/commands/specs/enable.js +3 -3
  59. package/src/commands/status.js +10 -10
  60. package/src/commands/sync.js +25 -25
  61. package/src/commands/timeout.js +35 -35
  62. package/src/trui/TruiInterface.js +2 -2
  63. package/src/trui/agents/AgentInterface.js +4 -4
  64. package/src/trui/agents/handlers/CommandHandler.js +4 -4
  65. package/src/trui/agents/handlers/ContextManager.js +1 -1
  66. package/src/trui/agents/handlers/DisplayHandler.js +11 -11
  67. package/src/trui/agents/handlers/HelpHandler.js +1 -1
  68. package/src/utils/agent-selector.js +6 -6
  69. package/src/utils/antigravity-installer.js +4 -4
  70. package/src/utils/asset-cleanup.js +1 -1
  71. package/src/utils/auth.js +9 -12
  72. package/src/utils/clarification-actions.js +4 -4
  73. package/src/utils/cline-js-handler.js +5 -5
  74. package/src/utils/compliance-check.js +6 -6
  75. package/src/utils/config.js +12 -12
  76. package/src/utils/display-formatters-complete.js +2 -2
  77. package/src/utils/display-formatters-extracted.js +2 -2
  78. package/src/utils/display-formatters.js +2 -2
  79. package/src/utils/feedback-handler.js +2 -2
  80. package/src/utils/first-run.js +7 -7
  81. package/src/utils/ide-detection.js +1 -1
  82. package/src/utils/ide-handlers.js +6 -6
  83. package/src/utils/interactive/clarification-actions.js +3 -3
  84. package/src/utils/interactive/core-ui.js +7 -7
  85. package/src/utils/interactive/file-backup.js +6 -6
  86. package/src/utils/interactive/file-import-export.js +49 -49
  87. package/src/utils/interactive/file-operations.js +3 -3
  88. package/src/utils/interactive/file-validation.js +41 -41
  89. package/src/utils/interactive/interactive-prompts.js +41 -41
  90. package/src/utils/interactive/requirement-actions.js +5 -5
  91. package/src/utils/interactive/requirement-crud.js +4 -4
  92. package/src/utils/interactive/requirements-navigation.js +10 -10
  93. package/src/utils/interactive-broken.js +6 -6
  94. package/src/utils/interactive.js +37 -37
  95. package/src/utils/keyboard-handler.js +4 -4
  96. package/src/utils/prompt-helper.js +6 -6
  97. package/src/utils/provider-checker/agent-checker.js +1 -1
  98. package/src/utils/provider-checker/agent-runner.js +203 -314
  99. package/src/utils/provider-checker/agents-file-lock.js +134 -0
  100. package/src/utils/provider-checker/agents-manager.js +224 -36
  101. package/src/utils/provider-checker/cli-installer.js +28 -28
  102. package/src/utils/provider-checker/cli-utils.js +2 -2
  103. package/src/utils/provider-checker/cursor-approval-clicker.js +108 -0
  104. package/src/utils/provider-checker/format-utils.js +4 -4
  105. package/src/utils/provider-checker/ide-installer-helper.js +96 -0
  106. package/src/utils/provider-checker/ide-manager.js +19 -8
  107. package/src/utils/provider-checker/ide-quota-checker.js +120 -0
  108. package/src/utils/provider-checker/ide-utils.js +2 -2
  109. package/src/utils/provider-checker/node-detector.js +4 -4
  110. package/src/utils/provider-checker/node-utils.js +5 -5
  111. package/src/utils/provider-checker/opencode-checker.js +107 -73
  112. package/src/utils/provider-checker/process-utils.js +1 -1
  113. package/src/utils/provider-checker/provider-validator.js +11 -11
  114. package/src/utils/provider-checker/quota-checker.js +5 -5
  115. package/src/utils/provider-checker/quota-detector.js +5 -5
  116. package/src/utils/provider-checker/requirements-manager.js +6 -6
  117. package/src/utils/provider-checker/test-requirements.js +1 -1
  118. package/src/utils/provider-checker/vscode-approval-clicker.js +328 -0
  119. package/src/utils/provider-checker-new.js +6 -6
  120. package/src/utils/provider-checker.js +6 -6
  121. package/src/utils/provider-checkers/ide-manager.js +13 -13
  122. package/src/utils/provider-checkers/node-executable-finder.js +4 -4
  123. package/src/utils/provider-checkers/provider-checker-core.js +5 -5
  124. package/src/utils/provider-checkers/provider-checker-main.js +17 -17
  125. package/src/utils/provider-registry.js +5 -6
  126. package/src/utils/provider-utils.js +12 -12
  127. package/src/utils/quota-detectors.js +32 -32
  128. package/src/utils/requirement-action-handlers.js +12 -12
  129. package/src/utils/requirement-actions/requirement-operations.js +3 -3
  130. package/src/utils/requirement-actions.js +1 -1
  131. package/src/utils/requirement-file-operations.js +5 -5
  132. package/src/utils/requirement-helpers.js +1 -1
  133. package/src/utils/requirement-management.js +5 -5
  134. package/src/utils/requirement-navigation.js +2 -2
  135. package/src/utils/requirement-organization.js +3 -3
  136. package/src/utils/rui-trui-adapter.js +14 -14
  137. package/src/utils/simple-trui.js +3 -3
  138. package/src/utils/status-helpers-extracted.js +3 -3
  139. package/src/utils/trui-clarifications.js +11 -11
  140. package/src/utils/trui-debug.js +3 -2
  141. package/src/utils/trui-devin.js +217 -0
  142. package/src/utils/trui-feedback.js +7 -7
  143. package/src/utils/trui-kiro-integration.js +34 -34
  144. package/src/utils/trui-main-handlers.js +20 -21
  145. package/src/utils/trui-main-menu.js +19 -19
  146. package/src/utils/trui-nav-agents.js +59 -8
  147. package/src/utils/trui-nav-requirements.js +3 -3
  148. package/src/utils/trui-nav-settings.js +10 -10
  149. package/src/utils/trui-nav-specifications.js +1 -1
  150. package/src/utils/trui-navigation-backup.js +11 -11
  151. package/src/utils/trui-navigation.js +9 -9
  152. package/src/utils/trui-provider-health.js +25 -25
  153. package/src/utils/trui-provider-manager.js +28 -28
  154. package/src/utils/trui-quick-menu.js +2 -2
  155. package/src/utils/trui-req-actions-backup.js +21 -21
  156. package/src/utils/trui-req-actions.js +20 -20
  157. package/src/utils/trui-req-editor.js +10 -10
  158. package/src/utils/trui-req-file-ops.js +3 -3
  159. package/src/utils/trui-req-tree.js +7 -7
  160. package/src/utils/trui-windsurf.js +103 -103
  161. package/src/utils/user-tracking.js +15 -15
  162. package/src/utils/trui-req-tree-old.js +0 -719
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Auto Mode Status Display
3
- *
3
+ *
4
4
  * Handles status display and UI components for auto mode
5
5
  */
6
6
 
7
7
  const chalk = require('chalk');
8
- const { getStages, DEFAULT_STAGES } = require('../../../utils/config');
8
+ const { getStages, DEFAULT_STAGES } = require('../../utils/config');
9
9
  const { stripAnsi, padToVisualWidth } = require('./auto-utils');
10
10
 
11
11
  // Global status mode tracking
@@ -16,36 +16,36 @@ let currentStatusMode = 'active';
16
16
  */
17
17
  function printStatusCard(currentTitle, currentStatus, mode = 'active') {
18
18
  currentStatusMode = mode; // Update global mode tracking
19
-
19
+
20
20
  const stages = configuredStages || DEFAULT_STAGES;
21
21
  const currentStageIndex = stages.indexOf(currentStatus);
22
-
22
+
23
23
  // Build status card
24
24
  const width = 60;
25
25
  const border = '─'.repeat(width);
26
-
26
+
27
27
  console.log(chalk.cyan(`┌─ ${border} ─┐`));
28
28
  console.log(chalk.cyan('│') + padToVisualWidth(` 🤖 Auto Mode Status`, width - 4) + chalk.cyan('│'));
29
29
  console.log(chalk.cyan(`├─ ${border} ─┤`));
30
-
30
+
31
31
  // Current requirement
32
32
  if (currentTitle) {
33
33
  const titleLine = ` 📋 ${currentTitle}`;
34
34
  console.log(chalk.cyan('│') + padToVisualWidth(titleLine, width - 4) + chalk.cyan('│'));
35
35
  }
36
-
36
+
37
37
  // Current stage
38
38
  const statusIcon = getStatusIcon(currentStatus, mode);
39
39
  const statusLine = ` ${statusIcon} ${currentStatus}`;
40
40
  console.log(chalk.cyan('│') + padToVisualWidth(statusLine, width - 4) + chalk.cyan('│'));
41
-
41
+
42
42
  // Progress bar
43
43
  if (currentStageIndex >= 0) {
44
44
  const progress = ((currentStageIndex + 1) / stages.length) * 100;
45
45
  const progressBar = createProgressBar(progress, width - 8);
46
46
  console.log(chalk.cyan('│') + padToVisualWidth(` ${progressBar}`, width - 4) + chalk.cyan('│'));
47
47
  }
48
-
48
+
49
49
  console.log(chalk.cyan(`└─ ${border} ─┘`));
50
50
  }
51
51
 
@@ -61,15 +61,15 @@ function getStatusIcon(status, mode) {
61
61
  'VERIFY': '✅',
62
62
  'DONE': '🎉'
63
63
  };
64
-
64
+
65
65
  const baseIcon = statusIcons[status] || '❓';
66
-
66
+
67
67
  if (mode === 'waiting') {
68
68
  return '⏳';
69
69
  } else if (mode === 'stopped') {
70
70
  return '⏹️';
71
71
  }
72
-
72
+
73
73
  return baseIcon;
74
74
  }
75
75
 
@@ -79,10 +79,10 @@ function getStatusIcon(status, mode) {
79
79
  function createProgressBar(percentage, width) {
80
80
  const filled = Math.round((percentage / 100) * width);
81
81
  const empty = width - filled;
82
-
82
+
83
83
  const filledBar = '█'.repeat(filled);
84
84
  const emptyBar = '░'.repeat(empty);
85
-
85
+
86
86
  return chalk.green(filledBar) + chalk.gray(emptyBar) + ` ${Math.round(percentage)}%`;
87
87
  }
88
88
 
@@ -92,17 +92,17 @@ function createProgressBar(percentage, width) {
92
92
  function printWorkflowStages(currentStatus) {
93
93
  const stages = configuredStages || DEFAULT_STAGES;
94
94
  const currentIndex = stages.indexOf(currentStatus);
95
-
95
+
96
96
  console.log(chalk.blue('\n🔄 Workflow Stages:'));
97
-
97
+
98
98
  stages.forEach((stage, index) => {
99
99
  const isCurrent = index === currentIndex;
100
100
  const isCompleted = index < currentIndex;
101
101
  const isPending = index > currentIndex;
102
-
102
+
103
103
  let icon = '⭕';
104
104
  let color = chalk.gray;
105
-
105
+
106
106
  if (isCurrent) {
107
107
  icon = '🔵';
108
108
  color = chalk.blue;
@@ -113,11 +113,11 @@ function printWorkflowStages(currentStatus) {
113
113
  icon = '⭕';
114
114
  color = chalk.gray;
115
115
  }
116
-
116
+
117
117
  const stageText = `${icon} ${stage}`;
118
118
  console.log(color(` ${stageText}`));
119
119
  });
120
-
120
+
121
121
  console.log();
122
122
  }
123
123
 
@@ -127,19 +127,19 @@ function printWorkflowStages(currentStatus) {
127
127
  function printProviderInfo(providerName, providerConfig) {
128
128
  console.log(chalk.blue('\n🔌 Provider Information:'));
129
129
  console.log(chalk.cyan(` Provider: ${providerName}`));
130
-
130
+
131
131
  if (providerConfig.model) {
132
132
  console.log(chalk.cyan(` Model: ${providerConfig.model}`));
133
133
  }
134
-
134
+
135
135
  if (providerConfig.baseUrl) {
136
136
  console.log(chalk.cyan(` Base URL: ${providerConfig.baseUrl}`));
137
137
  }
138
-
138
+
139
139
  if (providerConfig.region) {
140
140
  console.log(chalk.cyan(` Region: ${providerConfig.region}`));
141
141
  }
142
-
142
+
143
143
  console.log();
144
144
  }
145
145
 
@@ -159,11 +159,11 @@ function printRateLimitWarning(providerName, waitTime) {
159
159
  function printError(error, context = '') {
160
160
  console.log(chalk.red(`\n❌ Error${context ? ` (${context})` : ''}:`));
161
161
  console.log(chalk.red(` ${error.message}`));
162
-
162
+
163
163
  if (error.stack && process.env.DEBUG) {
164
164
  console.log(chalk.gray(` Stack trace:\n${error.stack}`));
165
165
  }
166
-
166
+
167
167
  console.log();
168
168
  }
169
169
 
@@ -206,7 +206,7 @@ function printDebug(message) {
206
206
  function createSpinner(text) {
207
207
  const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
208
208
  let index = 0;
209
-
209
+
210
210
  return {
211
211
  start: () => {
212
212
  process.stdout.write(`\r${frames[index]} ${text}`);
@@ -225,19 +225,19 @@ function printFileChangeSummary(changes) {
225
225
  if (!changes || changes.length === 0) {
226
226
  return;
227
227
  }
228
-
228
+
229
229
  console.log(chalk.blue('\n📁 File Changes:'));
230
-
230
+
231
231
  changes.forEach(change => {
232
232
  const icon = getFileChangeIcon(change.type);
233
233
  const color = getFileChangeColor(change.type);
234
234
  console.log(color(` ${icon} ${change.path}`));
235
-
235
+
236
236
  if (change.type === 'modify' && change.linesAdded) {
237
237
  console.log(chalk.gray(` +${change.linesAdded} -${change.linesRemoved || 0} lines`));
238
238
  }
239
239
  });
240
-
240
+
241
241
  console.log();
242
242
  }
243
243
 
@@ -252,7 +252,7 @@ function getFileChangeIcon(type) {
252
252
  'move': '📂',
253
253
  'copy': '📋'
254
254
  };
255
-
255
+
256
256
  return icons[type] || '📄';
257
257
  }
258
258
 
@@ -267,7 +267,7 @@ function getFileChangeColor(type) {
267
267
  'move': chalk.blue,
268
268
  'copy': chalk.cyan
269
269
  };
270
-
270
+
271
271
  return colors[type] || chalk.gray;
272
272
  }
273
273
 
@@ -277,7 +277,7 @@ function getFileChangeColor(type) {
277
277
  function printIterationSummary(iteration, total, title, status) {
278
278
  const percentage = Math.round((iteration / total) * 100);
279
279
  const icon = status === 'completed' ? '✅' : '🔄';
280
-
280
+
281
281
  console.log(chalk.blue(`${icon} Iteration ${iteration}/${total} (${percentage}%) - ${title}`));
282
282
  }
283
283
 
@@ -289,7 +289,7 @@ function printTiming(startTime, endTime) {
289
289
  const seconds = Math.round(duration / 1000);
290
290
  const minutes = Math.floor(seconds / 60);
291
291
  const remainingSeconds = seconds % 60;
292
-
292
+
293
293
  if (minutes > 0) {
294
294
  console.log(chalk.gray(`⏱️ Duration: ${minutes}m ${remainingSeconds}s`));
295
295
  } else {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto Mode Utilities
3
- *
3
+ *
4
4
  * Shared utility functions for auto mode operations
5
5
  */
6
6
 
@@ -33,7 +33,7 @@ function getLogTimestamp(date = new Date()) {
33
33
  minute: '2-digit',
34
34
  timeZoneName: 'short'
35
35
  });
36
-
36
+
37
37
  return `${datePart} ${timePart}`;
38
38
  }
39
39
 
@@ -49,7 +49,7 @@ function translateStage(stage) {
49
49
  'VERIFY': 'workflow.stage.verify',
50
50
  'DONE': 'workflow.stage.done'
51
51
  };
52
-
52
+
53
53
  return stageMap[stage] || stage;
54
54
  }
55
55
 
@@ -134,11 +134,11 @@ async function updateRequirementsStatus(repoPath, status) {
134
134
  }
135
135
 
136
136
  let content = await fs.readFile(reqPath, 'utf8');
137
-
137
+
138
138
  // Find and update status line
139
139
  const statusLineRegex = /^## Current Status:.*$/m;
140
140
  const newStatusLine = `## Current Status: ${status}`;
141
-
141
+
142
142
  if (statusLineRegex.test(content)) {
143
143
  content = content.replace(statusLineRegex, newStatusLine);
144
144
  } else {
@@ -147,7 +147,7 @@ async function updateRequirementsStatus(repoPath, status) {
147
147
  lines.splice(1, 0, newStatusLine);
148
148
  content = lines.join('\n');
149
149
  }
150
-
150
+
151
151
  await fs.writeFile(reqPath, content, 'utf8');
152
152
  } catch (error) {
153
153
  console.error('Error updating requirements status:', error.message);
@@ -166,29 +166,29 @@ async function getCurrentRequirement(repoPath) {
166
166
 
167
167
  const content = await fs.readFile(reqPath, 'utf8');
168
168
  const lines = content.split('\n');
169
-
169
+
170
170
  // Look for current status section
171
171
  let currentSection = null;
172
172
  let currentRequirement = null;
173
-
173
+
174
174
  for (let i = 0; i < lines.length; i++) {
175
175
  const line = lines[i].trim();
176
-
176
+
177
177
  if (line.startsWith('## Current Status:')) {
178
178
  currentSection = 'current';
179
179
  continue;
180
180
  }
181
-
181
+
182
182
  if (line.startsWith('##') && currentSection === 'current') {
183
183
  break;
184
184
  }
185
-
185
+
186
186
  if (currentSection === 'current' && line.startsWith('###')) {
187
187
  currentRequirement = line.replace(/^###\s*/, '').trim();
188
188
  break;
189
189
  }
190
190
  }
191
-
191
+
192
192
  return currentRequirement;
193
193
  } catch (error) {
194
194
  console.error('Error getting current requirement:', error.message);
@@ -208,27 +208,27 @@ async function countTodoRequirements(repoPath) {
208
208
 
209
209
  const content = await fs.readFile(reqPath, 'utf8');
210
210
  const lines = content.split('\n');
211
-
211
+
212
212
  let inTodoSection = false;
213
213
  let count = 0;
214
-
214
+
215
215
  for (const line of lines) {
216
216
  const trimmed = line.trim();
217
-
217
+
218
218
  if (trimmed === '## TODO') {
219
219
  inTodoSection = true;
220
220
  continue;
221
221
  }
222
-
222
+
223
223
  if (trimmed.startsWith('##') && inTodoSection) {
224
224
  break;
225
225
  }
226
-
226
+
227
227
  if (inTodoSection && trimmed.startsWith('###')) {
228
228
  count++;
229
229
  }
230
230
  }
231
-
231
+
232
232
  return count;
233
233
  } catch (error) {
234
234
  console.error('Error counting TODO requirements:', error.message);
@@ -248,31 +248,31 @@ async function moveRequirementToVerify(repoPath, requirementText) {
248
248
 
249
249
  const content = await fs.readFile(reqPath, 'utf8');
250
250
  const lines = content.split('\n');
251
-
251
+
252
252
  // Find the requirement by its title
253
253
  const normalizedRequirement = requirementText.trim();
254
254
  const snippet = normalizedRequirement.substring(0, 80);
255
255
  let requirementStartIndex = -1;
256
256
  let requirementEndIndex = -1;
257
257
  let inTodoSection = false;
258
-
258
+
259
259
  for (let i = 0; i < lines.length; i++) {
260
260
  const line = lines[i];
261
-
261
+
262
262
  if (line.trim() === '## TODO') {
263
263
  inTodoSection = true;
264
264
  continue;
265
265
  }
266
-
266
+
267
267
  if (line.trim().startsWith('##') && inTodoSection) {
268
268
  break;
269
269
  }
270
-
270
+
271
271
  if (inTodoSection && line.trim().startsWith('###')) {
272
272
  const title = line.replace(/^###\s*/, '').trim();
273
273
  if (title.includes(snippet) || title === normalizedRequirement) {
274
274
  requirementStartIndex = i;
275
-
275
+
276
276
  // Find end of requirement
277
277
  for (let j = i + 1; j < lines.length; j++) {
278
278
  if (lines[j].trim().startsWith('###') || lines[j].trim().startsWith('##')) {
@@ -280,27 +280,27 @@ async function moveRequirementToVerify(repoPath, requirementText) {
280
280
  break;
281
281
  }
282
282
  }
283
-
283
+
284
284
  if (requirementEndIndex === -1) {
285
285
  requirementEndIndex = lines.length;
286
286
  }
287
-
287
+
288
288
  break;
289
289
  }
290
290
  }
291
291
  }
292
-
292
+
293
293
  if (requirementStartIndex === -1) {
294
294
  console.warn('Requirement not found in TODO section:', requirementText);
295
295
  return;
296
296
  }
297
-
297
+
298
298
  // Extract the requirement block
299
299
  const requirementBlock = lines.slice(requirementStartIndex, requirementEndIndex);
300
-
300
+
301
301
  // Remove from TODO
302
302
  lines.splice(requirementStartIndex, requirementEndIndex - requirementStartIndex);
303
-
303
+
304
304
  // Find TO VERIFY BY HUMAN section and add requirement
305
305
  let verifyIndex = -1;
306
306
  for (let i = 0; i < lines.length; i++) {
@@ -309,19 +309,19 @@ async function moveRequirementToVerify(repoPath, requirementText) {
309
309
  break;
310
310
  }
311
311
  }
312
-
312
+
313
313
  if (verifyIndex === -1) {
314
314
  // Create section if it doesn't exist
315
315
  lines.push('## TO VERIFY BY HUMAN');
316
316
  verifyIndex = lines.length;
317
317
  }
318
-
318
+
319
319
  // Insert requirement
320
320
  lines.splice(verifyIndex, 0, ...requirementBlock);
321
-
321
+
322
322
  // Write back to file
323
323
  await fs.writeFile(reqPath, lines.join('\n'), 'utf8');
324
-
324
+
325
325
  console.log(chalk.green(`Moved requirement to verify: ${requirementText}`));
326
326
  } catch (error) {
327
327
  console.error('Error moving requirement to verify:', error.message);
@@ -340,31 +340,31 @@ async function moveRequirementToRecycle(repoPath, requirementText) {
340
340
 
341
341
  const content = await fs.readFile(reqPath, 'utf8');
342
342
  const lines = content.split('\n');
343
-
343
+
344
344
  // Find and remove requirement from current section
345
345
  const normalizedRequirement = requirementText.trim();
346
346
  const snippet = normalizedRequirement.substring(0, 80);
347
347
  let requirementStartIndex = -1;
348
348
  let requirementEndIndex = -1;
349
349
  let inCurrentSection = false;
350
-
350
+
351
351
  for (let i = 0; i < lines.length; i++) {
352
352
  const line = lines[i];
353
-
353
+
354
354
  if (line.trim().startsWith('## Current Status:')) {
355
355
  inCurrentSection = true;
356
356
  continue;
357
357
  }
358
-
358
+
359
359
  if (line.trim().startsWith('##') && inCurrentSection) {
360
360
  break;
361
361
  }
362
-
362
+
363
363
  if (inCurrentSection && line.trim().startsWith('###')) {
364
364
  const title = line.replace(/^###\s*/, '').trim();
365
365
  if (title.includes(snippet) || title === normalizedRequirement) {
366
366
  requirementStartIndex = i;
367
-
367
+
368
368
  // Find end of requirement
369
369
  for (let j = i + 1; j < lines.length; j++) {
370
370
  if (lines[j].trim().startsWith('###') || lines[j].trim().startsWith('##')) {
@@ -372,27 +372,27 @@ async function moveRequirementToRecycle(repoPath, requirementText) {
372
372
  break;
373
373
  }
374
374
  }
375
-
375
+
376
376
  if (requirementEndIndex === -1) {
377
377
  requirementEndIndex = lines.length;
378
378
  }
379
-
379
+
380
380
  break;
381
381
  }
382
382
  }
383
383
  }
384
-
384
+
385
385
  if (requirementStartIndex === -1) {
386
386
  console.warn('Requirement not found in current section:', requirementText);
387
387
  return;
388
388
  }
389
-
389
+
390
390
  // Extract the requirement block
391
391
  const requirementBlock = lines.slice(requirementStartIndex, requirementEndIndex);
392
-
392
+
393
393
  // Remove from current section
394
394
  lines.splice(requirementStartIndex, requirementEndIndex - requirementStartIndex);
395
-
395
+
396
396
  // Find RECYCLED section and add requirement
397
397
  let recycleIndex = -1;
398
398
  for (let i = 0; i < lines.length; i++) {
@@ -401,20 +401,20 @@ async function moveRequirementToRecycle(repoPath, requirementText) {
401
401
  break;
402
402
  }
403
403
  }
404
-
404
+
405
405
  if (recycleIndex === -1) {
406
406
  // Create section if it doesn't exist
407
407
  lines.push('## RECYCLED');
408
408
  recycleIndex = lines.length;
409
409
  }
410
-
410
+
411
411
  // Add timestamp and requirement
412
412
  const timestamp = new Date().toISOString();
413
413
  lines.splice(recycleIndex, 0, `### ${requirementText}`, `*Recycled: ${timestamp}*`);
414
-
414
+
415
415
  // Write back to file
416
416
  await fs.writeFile(reqPath, lines.join('\n'), 'utf8');
417
-
417
+
418
418
  console.log(chalk.yellow(`Recycled requirement: ${requirementText}`));
419
419
  } catch (error) {
420
420
  console.error('Error recycling requirement:', error.message);
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Cline Installer - Auto-installation of Cline CLI
3
+ *
4
+ * Extracted from iteration-handlers.js for constitutional compliance (<555 lines per file)
5
+ * Handles auto-installation of Cline CLI when not available on the system.
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const { DirectLLMManager } = require('vibecodingmachine-core');
10
+
11
+ /**
12
+ * Auto-install Cline CLI if not available
13
+ * @param {boolean} forceInstall - Force installation even if already available
14
+ * @returns {Promise<boolean>} - Returns true if Cline CLI is available after installation
15
+ */
16
+ async function ensureClineInstalled(forceInstall = false) {
17
+ const llm = new DirectLLMManager();
18
+
19
+ // Check if already available
20
+ if (!forceInstall && await llm.isClineAvailable()) {
21
+ return true;
22
+ }
23
+
24
+ const ora = require('ora');
25
+ const { execSync } = require('child_process');
26
+
27
+ const spinner = ora('Installing Cline CLI...').start();
28
+
29
+ try {
30
+ // Install Cline CLI globally
31
+ execSync('npm install -g cline', { stdio: 'pipe', encoding: 'utf8' });
32
+
33
+ // Verify installation
34
+ const isAvailable = await llm.isClineAvailable();
35
+
36
+ if (isAvailable) {
37
+ spinner.succeed('Cline CLI installed successfully');
38
+ console.log(chalk.green('✓ Cline CLI is now ready to use'));
39
+ return true;
40
+ } else {
41
+ spinner.fail('Cline CLI installation failed');
42
+ console.log(chalk.yellow('⚠ Installation completed but Cline CLI not found in PATH'));
43
+ console.log(chalk.gray(' You may need to restart your terminal or manually add npm global bin to PATH'));
44
+ return false;
45
+ }
46
+ } catch (error) {
47
+ spinner.fail('Cline CLI installation failed');
48
+ console.log(chalk.red('✗ Failed to install Cline CLI:'), error.message);
49
+ console.log(chalk.yellow(' You can manually install with: npm install -g cline'));
50
+ return false;
51
+ }
52
+ }
53
+
54
+ module.exports = {
55
+ ensureClineInstalled
56
+ };