vibecodingmachine-cli 2026.3.14-1537 → 2026.6.17-1956

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
@@ -0,0 +1,493 @@
1
+ /**
2
+ * Auto Start Phase Handlers
3
+ *
4
+ * Extracted from auto-direct.js handleAutoStart function for constitutional compliance
5
+ * Contains initialization and processing loop logic for autonomous mode
6
+ */
7
+
8
+ const chalk = require('chalk');
9
+ const path = require('path');
10
+ const fs = require('fs-extra');
11
+ const { spawn } = require('child_process');
12
+ const vibecodingmachineCore = require('vibecodingmachine-core');
13
+ const {
14
+ AppleScriptManager,
15
+ t,
16
+ RequirementFileParser,
17
+ RequirementSequencer,
18
+ DefaultRequirementManager,
19
+ JSONStorage
20
+ } = vibecodingmachineCore;
21
+
22
+ const { getEffectiveRepoPath, getAutoConfig, setAutoConfig, getStages } = require('../../utils/config');
23
+ const { getRequirementsPath } = require('vibecodingmachine-core');
24
+ const { createKeyboardHandler } = require('../../utils/keyboard-handler');
25
+ const { startAutoMode, updateAutoModeStatus } = require('../../utils/auto-mode');
26
+
27
+ // Import modular functions
28
+ const { isRateLimitMessage } = require('./utils');
29
+ const {
30
+ updateRequirementsStatus,
31
+ getCurrentRequirement,
32
+ countTodoRequirements
33
+ } = require('./requirement-manager');
34
+ const {
35
+ printStatusCard
36
+ } = require('./status-display');
37
+ const {
38
+ runIteration,
39
+ runSpecIdeIteration
40
+ } = require('./iteration-handlers');
41
+ const {
42
+ countSpecCheckboxes,
43
+ getNextSpecTask,
44
+ loadEnabledIncompleteSpecs,
45
+ processDefaultRequirement
46
+ } = require('./spec-handlers');
47
+ const {
48
+ acquireProviderConfig
49
+ } = require('./provider-config');
50
+ const {
51
+ handleSpecPlanning,
52
+ handleTasksRegeneration
53
+ } = require('./spec-processing');
54
+
55
+ /**
56
+ * Initialize auto mode - authentication, config, keyboard handler, repository setup
57
+ *
58
+ * @param {Object} options - Command line options
59
+ * @param {Object} sharedRefs - Shared references for keyboard handler and status
60
+ * @returns {Promise<Object>} Initialized state object
61
+ */
62
+ async function initializeAutoMode(options, sharedRefs) {
63
+ // STRICT AUTH CHECK
64
+ const auth = require('../../utils/auth');
65
+ const isAuth = await auth.isAuthenticated();
66
+ if (!isAuth) {
67
+ console.log(chalk.cyan('\nšŸ” Opening browser for authentication...\n'));
68
+ try {
69
+ await auth.login();
70
+ console.log(chalk.green('\nāœ“ Authentication successful!\n'));
71
+ } catch (error) {
72
+ console.log(chalk.red('\nāœ— Authentication failed:'), error.message);
73
+ process.exit(1);
74
+ }
75
+ }
76
+
77
+ console.log(chalk.bold.cyan('\n' + t('auto.direct.title') + '\n'));
78
+ console.log(chalk.gray('═'.repeat(80)));
79
+ console.log();
80
+
81
+ const repoPath = await getEffectiveRepoPath();
82
+ if (!repoPath) {
83
+ console.log(chalk.red('āœ— No repository configured'));
84
+ console.log(chalk.gray(t('auto.direct.config.repo.not.set')));
85
+ throw new Error('No repository configured');
86
+ }
87
+
88
+ // Create keyboard handler for 'x' key exit
89
+ sharedRefs.keyboardHandler = createKeyboardHandler({
90
+ onExit: () => {
91
+ updateAutoModeStatus(repoPath, { running: false });
92
+ console.log(chalk.gray('Auto mode stopped'));
93
+ if (sharedRefs.storedStatusTitle && sharedRefs.storedStatus) {
94
+ printStatusCard(sharedRefs.storedStatusTitle, sharedRefs.storedStatus, 'stopped');
95
+ }
96
+ }
97
+ });
98
+
99
+ // Start keyboard handler
100
+ sharedRefs.keyboardHandler.start();
101
+
102
+ // Ensure keyboard handler is cleaned up on exit
103
+ const cleanup = () => {
104
+ if (sharedRefs.keyboardHandler) {
105
+ sharedRefs.keyboardHandler.stop();
106
+ }
107
+ };
108
+
109
+ process.on('exit', cleanup);
110
+ process.on('SIGINT', () => {
111
+ cleanup();
112
+ process.exit(0);
113
+ });
114
+ process.on('SIGTERM', () => {
115
+ cleanup();
116
+ process.exit(0);
117
+ });
118
+
119
+ // Start Auto Mode status tracking
120
+ const config = await getAutoConfig();
121
+
122
+ // Save extension to config if provided
123
+ if (options.extension) {
124
+ config.extension = options.extension;
125
+ await setAutoConfig(config);
126
+ }
127
+
128
+ await startAutoMode(repoPath, { ide: options.ide || config.ide });
129
+
130
+ // Load configured stages
131
+ const configuredStages = await getStages();
132
+
133
+ // Initialize requirement monitoring for default requirement management
134
+ const requirementsPath = await getRequirementsPath(repoPath);
135
+ const storage = new JSONStorage();
136
+ const parser = new RequirementFileParser();
137
+ const defaultManager = new DefaultRequirementManager(storage);
138
+ const sequencer = new RequirementSequencer(parser, defaultManager);
139
+
140
+ // Start monitoring requirements file for changes
141
+ const stopMonitoring = sequencer.monitorRequirements(requirementsPath, async (changeType, change) => {
142
+ if (changeType === 'regular-requirements-added') {
143
+ console.log(chalk.bold.yellow('\nšŸ“ New regular requirements detected'));
144
+ console.log(chalk.gray('Default requirement will be paused to process regular requirements first\n'));
145
+ } else if (changeType === 'regular-requirements-completed') {
146
+ console.log(chalk.bold.green('\nāœ… All regular requirements completed'));
147
+ console.log(chalk.gray('Default requirement will be resumed\n'));
148
+ }
149
+ });
150
+
151
+ console.log(chalk.white(t('auto.repository')), chalk.cyan(repoPath));
152
+
153
+ // Use the agent that was already determined by provider preferences
154
+ const effectiveAgent = options.ide;
155
+
156
+ // Get provider configuration — options.provider forces a specific provider
157
+ let providerConfig = await acquireProviderConfig(null, null, options.provider || null);
158
+ if (!providerConfig) {
159
+ throw new Error('No provider configuration available');
160
+ }
161
+
162
+ console.log(chalk.white('Provider:'), chalk.cyan(providerConfig.displayName));
163
+
164
+ // Get max chats
165
+ const unlimited = !options.maxChats && !config.maxChats && config.neverStop;
166
+ const maxChats = unlimited ? Number.MAX_SAFE_INTEGER : (options.maxChats || config.maxChats || 1);
167
+ console.log(chalk.white(`${t('auto.direct.config.max.iterations')}`), unlimited ? chalk.cyan('āˆž (never stop)') : chalk.cyan(maxChats));
168
+
169
+ // Update initial status
170
+ await updateAutoModeStatus(repoPath, { chatCount: 0, maxChats: unlimited ? 0 : maxChats });
171
+ console.log();
172
+ console.log(chalk.gray('═'.repeat(80)));
173
+
174
+ // Calculate initial total for consistent display throughout the session
175
+ const initialTodoCount = await countTodoRequirements(repoPath);
176
+ const initialEffectiveMax = unlimited ? initialTodoCount : Math.min(maxChats, initialTodoCount);
177
+
178
+ return {
179
+ repoPath,
180
+ config,
181
+ configuredStages,
182
+ effectiveAgent,
183
+ providerConfig,
184
+ unlimited,
185
+ maxChats,
186
+ initialTodoCount,
187
+ initialEffectiveMax,
188
+ stopMonitoring,
189
+ sequencer,
190
+ defaultManager,
191
+ requirementsPath
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Process incomplete specs loop - iterates through all enabled incomplete specs
197
+ *
198
+ * @param {Object} state - Current state object
199
+ * @returns {Promise<Object>} Result with completedCount and failedCount
200
+ */
201
+ async function processSpecsLoop(state) {
202
+ let completedCount = 0;
203
+ let failedCount = 0;
204
+
205
+ const incompleteSpecs = await loadEnabledIncompleteSpecs(state.repoPath);
206
+ if (incompleteSpecs.length === 0) {
207
+ return { completedCount, failedCount, specsProcessed: false };
208
+ }
209
+
210
+ console.log(chalk.bold.cyan(`\nšŸ“‹ Processing ${incompleteSpecs.length} incomplete spec(s) before requirements...\n`));
211
+
212
+ for (const spec of incompleteSpecs) {
213
+ // Initialize IDE attempts tracking for this spec
214
+ spec.totalIdeAttempts = 0;
215
+
216
+ const { done: doneStart, total: totalStart } = countSpecCheckboxes(spec.path);
217
+ console.log(chalk.bold.magenta(`\n${'━'.repeat(80)}`));
218
+ console.log(chalk.bold.magenta(` šŸ“‹ SPEC: ${spec.directory} (${spec.title || spec.directory})`));
219
+ if (totalStart > 0) {
220
+ const pctStart = Math.round((doneStart / totalStart) * 100);
221
+ console.log(chalk.bold.magenta(` Progress: ${doneStart}/${totalStart} tasks (${pctStart}%) complete`));
222
+ } else {
223
+ console.log(chalk.bold.magenta(' No tasks.md yet — will plan and implement'));
224
+ }
225
+ console.log(chalk.bold.magenta(`${'━'.repeat(80)}\n`));
226
+
227
+ let specProviderAttempts = 0;
228
+ const MAX_SPEC_TASK_ATTEMPTS = 3;
229
+ let lastSpecTaskText = null;
230
+ let sameTaskAttempts = 0;
231
+
232
+ // If spec has no tasks.md yet, add a special planning task
233
+ if (!spec.hasTasks) {
234
+ const planResult = await handleSpecPlanning(spec, state.providerConfig, state.repoPath);
235
+ if (planResult.success) {
236
+ completedCount++;
237
+ spec.hasTasks = fs.existsSync(path.join(spec.path, 'tasks.md'));
238
+ } else {
239
+ failedCount++;
240
+ continue;
241
+ }
242
+ }
243
+
244
+ // Verify tasks.md has checkbox-format tasks
245
+ const { done: doneCheck, total: totalCheck } = countSpecCheckboxes(spec.path);
246
+ if (totalCheck === 0 && spec.hasTasks) {
247
+ const regenResult = await handleTasksRegeneration(spec, state.providerConfig);
248
+ if (!regenResult.success) {
249
+ failedCount++;
250
+ continue;
251
+ }
252
+ }
253
+
254
+ // Loop until spec is done or stalled
255
+ while (true) {
256
+ const task = getNextSpecTask(spec.path);
257
+ if (!task) {
258
+ const { done: doneFinal, total: totalFinal } = countSpecCheckboxes(spec.path);
259
+ console.log(chalk.bold.green(`\nāœ… Spec "${spec.directory}" complete! (${doneFinal}/${totalFinal} tasks)\n`));
260
+ break;
261
+ }
262
+
263
+ // Detect same task repeated
264
+ if (task.text === lastSpecTaskText) {
265
+ sameTaskAttempts++;
266
+ if (sameTaskAttempts >= MAX_SPEC_TASK_ATTEMPTS) {
267
+ console.log(chalk.red(`\nāœ— Task "${task.text}" not completing after ${MAX_SPEC_TASK_ATTEMPTS} attempts — skipping spec\n`));
268
+ break;
269
+ }
270
+ } else {
271
+ sameTaskAttempts = 0;
272
+ lastSpecTaskText = task.text;
273
+ }
274
+
275
+ const { done: doneCurrent, total: totalCurrent } = countSpecCheckboxes(spec.path);
276
+ const pctCurrent = totalCurrent > 0 ? Math.round((doneCurrent / totalCurrent) * 100) : 0;
277
+
278
+ console.log(chalk.cyan(`\nšŸ“Œ Task ${doneCurrent + 1}/${totalCurrent || '?'}: ${task.text}`));
279
+ console.log(chalk.gray(` Spec progress: ${doneCurrent}/${totalCurrent} (${pctCurrent}%)\n`));
280
+
281
+ // Route spec tasks differently depending on provider type
282
+ let result;
283
+ if (state.providerConfig.type === 'ide') {
284
+ result = await runSpecIdeIteration(spec, task.text, task.line, state.providerConfig);
285
+ } else {
286
+ const specTaskText = [
287
+ task.text,
288
+ `[Spec: ${spec.directory} — task ${doneCurrent + 1}/${totalCurrent || '?'}]`,
289
+ `[After implementing, mark the task done in ${spec.path}/tasks.md:`,
290
+ ` change: ${task.line}`,
291
+ ` to: - [x] ${task.text}]`
292
+ ].join('\n');
293
+ const specRequirement = { text: specTaskText, package: null, disabled: false };
294
+ result = await runIteration(specRequirement, state.providerConfig, state.repoPath);
295
+ }
296
+
297
+ if (result.success) {
298
+ specProviderAttempts = 0;
299
+ spec.totalIdeAttempts = 0;
300
+ completedCount++;
301
+ const { done, total } = countSpecCheckboxes(spec.path);
302
+ const pct = total > 0 ? Math.round((done / total) * 100) : 0;
303
+ console.log(chalk.bold.green(`šŸ“Š Spec progress: ${done}/${total} tasks (${pct}%) complete`));
304
+ } else {
305
+ const isRateLimitError = isRateLimitMessage(result.error);
306
+ const isMaxAttemptsExceeded = result.error === 'max_ide_attempts_exceeded';
307
+ const isNoProgress = result.error === 'no_progress';
308
+
309
+ let errorType = 'Error';
310
+ if (isRateLimitError) errorType = 'Rate limit';
311
+ else if (isMaxAttemptsExceeded) errorType = 'Max IDE attempts exceeded';
312
+ else if (isNoProgress) errorType = 'No progress';
313
+
314
+ if (result.totalAttempts) {
315
+ spec.totalIdeAttempts = result.totalAttempts;
316
+ }
317
+
318
+ specProviderAttempts++;
319
+ failedCount++;
320
+
321
+ if (isMaxAttemptsExceeded) {
322
+ console.log(chalk.red(`\nāœ— ${errorType} — auto mode stopped\n`));
323
+ return { completedCount, failedCount, specsProcessed: true, shouldExit: true };
324
+ }
325
+
326
+ if (specProviderAttempts > MAX_SPEC_TASK_ATTEMPTS) {
327
+ console.log(chalk.red(`\nāœ— Max provider attempts reached — moving to next spec\n`));
328
+ break;
329
+ }
330
+
331
+ if (isNoProgress) {
332
+ console.log(chalk.yellow(`āš ļø ${errorType} on ${state.providerConfig.displayName}, switching IDE...`));
333
+ } else {
334
+ console.log(chalk.yellow(`āš ļø ${errorType} on spec task, switching provider...`));
335
+ }
336
+
337
+ const newProviderConfig = await acquireProviderConfig(state.providerConfig.provider, state.providerConfig.model);
338
+ if (newProviderConfig) {
339
+ state.providerConfig = newProviderConfig;
340
+ console.log(chalk.green(`āœ“ Switched to: ${state.providerConfig.displayName}\n`));
341
+ } else {
342
+ console.log(chalk.red(`āœ— No alternative providers available\n`));
343
+ break;
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ console.log(chalk.bold.cyan('\nšŸ“‹ All specs processed. Continuing to requirements...\n'));
350
+ console.log(chalk.gray('═'.repeat(80)));
351
+
352
+ return { completedCount, failedCount, specsProcessed: true };
353
+ }
354
+
355
+ /**
356
+ * Process requirements loop - iterates through regular requirements
357
+ *
358
+ * @param {Object} state - Current state object
359
+ * @param {number} completedCount - Number of completed items (from specs phase)
360
+ * @param {number} failedCount - Number of failed items (from specs phase)
361
+ * @returns {Promise<Object>} Result with updated counts
362
+ */
363
+ async function processRequirementsLoop(state, completedCount, failedCount) {
364
+ let providerAttempts = 0;
365
+ let lastRequirementText = null;
366
+ const MAX_PROVIDER_ATTEMPTS = 3;
367
+
368
+ for (let i = 0; i < state.maxChats; i++) {
369
+ const requirement = await getCurrentRequirement(state.repoPath);
370
+ if (!requirement) {
371
+ // No regular requirements - check for default requirement
372
+ const shouldProcessDefault = await state.sequencer.shouldProcessDefault(state.requirementsPath);
373
+
374
+ if (shouldProcessDefault) {
375
+ console.log(chalk.bold.cyan('\n⭐ Default Requirement Mode'));
376
+ console.log(chalk.gray('All regular requirements completed, processing default requirement...\n'));
377
+ await processDefaultRequirement(state.sequencer, state.defaultManager, state.providerConfig, state.repoPath);
378
+ } else {
379
+ if (completedCount > 0 || failedCount > 0) {
380
+ console.log(chalk.bold.yellow('\nšŸŽ‰ All requirements completed!'));
381
+ } else {
382
+ console.log(chalk.bold.yellow('\nšŸŽ‰ No requirements to process.'));
383
+ }
384
+ console.log(chalk.gray(`${t('auto.direct.no.more.todo.items')}\n`));
385
+ }
386
+ break;
387
+ }
388
+
389
+ // Check if this is a new requirement or retry
390
+ if (requirement.text !== lastRequirementText) {
391
+ providerAttempts = 0;
392
+ lastRequirementText = requirement.text;
393
+ }
394
+
395
+ providerAttempts++;
396
+
397
+ // Check if maximum attempts exceeded
398
+ if (providerAttempts > MAX_PROVIDER_ATTEMPTS) {
399
+ console.log(chalk.red(`\nāœ— Maximum provider attempts (${MAX_PROVIDER_ATTEMPTS}) reached for this requirement`));
400
+ console.log(chalk.yellow(' All available providers have failed or are rate limited'));
401
+ console.log(chalk.gray(' Skipping this requirement and moving to next...\n'));
402
+
403
+ failedCount++;
404
+ providerAttempts = 0;
405
+ lastRequirementText = null;
406
+ continue;
407
+ }
408
+
409
+ // Calculate current requirement number
410
+ const currentReqNumber = completedCount + failedCount + 1;
411
+
412
+ console.log(chalk.bold.magenta(`\n${'━'.repeat(80)}`));
413
+ console.log(chalk.bold.magenta(` ${t('auto.direct.requirement.header', { current: currentReqNumber, total: state.initialEffectiveMax })}`));
414
+ console.log(chalk.bold.magenta(`${'━'.repeat(80)}\n`));
415
+
416
+ await updateAutoModeStatus(state.repoPath, { chatCount: currentReqNumber });
417
+
418
+ // Run iteration with full workflow
419
+ const result = await runIteration(requirement, state.providerConfig, state.repoPath);
420
+
421
+ if (result.success) {
422
+ completedCount++;
423
+ providerAttempts = 0;
424
+ lastRequirementText = null;
425
+ console.log(chalk.bold.green(`āœ… Requirement ${currentReqNumber}/${state.initialEffectiveMax} COMPLETE`));
426
+ console.log(chalk.gray('Moving to next requirement...\n'));
427
+
428
+ // Check if restart CLI is enabled
429
+ if (state.config.restartCLI && i < state.maxChats - 1) {
430
+ await handleCliRestart(state.maxChats, i);
431
+ } else if (i < state.maxChats - 1) {
432
+ await new Promise(resolve => setTimeout(resolve, 2000));
433
+ }
434
+ } else {
435
+ const isRateLimitError = isRateLimitMessage(result.error);
436
+ const errorType = isRateLimitError ? 'Rate limit' : 'Error';
437
+ const failedProvider = state.providerConfig.displayName;
438
+
439
+ console.log(chalk.yellow(`āš ļø ${errorType} detected, switching to next provider in your list...\n`));
440
+
441
+ const newProviderConfig = await acquireProviderConfig(state.providerConfig.provider, state.providerConfig.model);
442
+ if (newProviderConfig) {
443
+ state.providerConfig = newProviderConfig;
444
+ console.log(chalk.yellow(`āš ļø ${failedProvider} hit ${errorType.toLowerCase()}`));
445
+ console.log(chalk.green(`āœ“ Switched to: ${state.providerConfig.displayName}\n`));
446
+ i--;
447
+ continue;
448
+ } else {
449
+ console.log(chalk.red('āœ— No alternative providers available\n'));
450
+ }
451
+
452
+ failedCount++;
453
+ console.log(chalk.bold.red(`āŒ Requirement ${currentReqNumber}/${state.initialEffectiveMax} FAILED`));
454
+ console.log(chalk.red(`Error: ${result.error}\n`));
455
+ console.log(chalk.yellow('Continuing to next requirement...\n'));
456
+ }
457
+ }
458
+
459
+ return { completedCount, failedCount };
460
+ }
461
+
462
+ /**
463
+ * Handle CLI restart for long-running sessions
464
+ */
465
+ async function handleCliRestart(maxChats, currentIteration) {
466
+ const { stopAutoMode } = require('../../utils/auto-mode');
467
+ console.log(chalk.cyan('šŸ”„ Restarting CLI to pick up latest changes...\n'));
468
+
469
+ const remainingIterations = maxChats - (currentIteration + 1);
470
+ const cliScriptPath = path.join(__dirname, '../../../bin/vibecodingmachine.js');
471
+ const args = ['auto:direct', '--max-chats', remainingIterations.toString()];
472
+
473
+ const child = spawn(process.execPath, [cliScriptPath, ...args], {
474
+ stdio: 'inherit',
475
+ cwd: process.cwd(),
476
+ env: process.env
477
+ });
478
+
479
+ child.on('error', (err) => {
480
+ console.error(chalk.red(t('auto.direct.config.restart.error')), err.message);
481
+ });
482
+
483
+ child.unref();
484
+ await new Promise(resolve => setTimeout(resolve, 300));
485
+ await stopAutoMode('restarting');
486
+ process.exit(0);
487
+ }
488
+
489
+ module.exports = {
490
+ initializeAutoMode,
491
+ processSpecsLoop,
492
+ processRequirementsLoop
493
+ };