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
@@ -3,13 +3,16 @@
3
3
  * Extracted from auto-direct.js to reduce file size
4
4
  */
5
5
 
6
- const { getAutoConfig } = require('../../../utils/config');
6
+ const chalk = require('chalk');
7
+ const { getAutoConfig } = require('../../utils/config');
7
8
  const { getProviderPreferences, getProviderDefinition, saveProviderPreferences } = require('../../utils/provider-registry');
8
9
  const ProviderManager = require('vibecodingmachine-core/src/ide-integration/provider-manager.cjs');
9
10
  const { checkAntigravityRateLimit, handleAntigravityRateLimit } = require('../../utils/antigravity-js-handler');
10
11
  const { checkKiroRateLimit, handleKiroRateLimit } = require('../../utils/kiro-js-handler');
11
12
  const { checkClineRateLimit, handleClineRateLimit } = require('../../utils/cline-js-handler');
12
- const { DirectLLMManager } = require('vibecodingmachine-core');
13
+ const { DirectLLMManager, t } = require('vibecodingmachine-core');
14
+ const { sleep } = require('./utils');
15
+ const { printStatusCard } = require('./status-display');
13
16
 
14
17
  // CRITICAL: Shared ProviderManager instance to track rate limits across all function calls
15
18
  const sharedProviderManager = new ProviderManager();
@@ -146,7 +149,7 @@ async function acquireProviderConfig(excludeProvider = null, excludeModel = null
146
149
 
147
150
  const config = await getAutoConfig();
148
151
  const providerConfig = config.providers[forcedProvider];
149
-
152
+
150
153
  if (!providerConfig || !providerConfig.enabled) {
151
154
  return {
152
155
  success: false,
@@ -154,7 +157,7 @@ async function acquireProviderConfig(excludeProvider = null, excludeModel = null
154
157
  };
155
158
  }
156
159
 
157
- const availableModels = providerConfig.models.filter(m =>
160
+ const availableModels = providerConfig.models.filter(m =>
158
161
  m.enabled && m.name !== excludeModel
159
162
  );
160
163
 
@@ -187,7 +190,7 @@ async function acquireProviderConfig(excludeProvider = null, excludeModel = null
187
190
  */
188
191
  async function ensureClineInstalled(forceInstall = false) {
189
192
  const llm = new DirectLLMManager();
190
-
193
+
191
194
  try {
192
195
  const isAvailable = await llm.checkClineAvailability();
193
196
  if (isAvailable && !forceInstall) {
@@ -196,7 +199,7 @@ async function ensureClineInstalled(forceInstall = false) {
196
199
 
197
200
  console.log('Installing Cline CLI...');
198
201
  const installResult = await llm.installCline();
199
-
202
+
200
203
  if (installResult.success) {
201
204
  console.log('✅ Cline CLI installed successfully');
202
205
  return true;
@@ -210,10 +213,133 @@ async function ensureClineInstalled(forceInstall = false) {
210
213
  }
211
214
  }
212
215
 
216
+ /**
217
+ * Handle rate limit scenarios with agent switching and waiting
218
+ */
219
+ async function handleRateLimitWithAgentSwitching(selection, currentTitle, currentStatus) {
220
+ console.log(chalk.yellow(`\n⚠️ ${t('auto.direct.provider.all.rate.limited')}`));
221
+
222
+ // Notify GUI about waiting mode if available
223
+ try {
224
+ // Try to send status to GUI via IPC if running in Electron context
225
+ if (process.versions && process.versions.electron) {
226
+ const { ipcRenderer } = require('electron');
227
+ if (ipcRenderer) {
228
+ ipcRenderer.send('requirements-progress', {
229
+ stage: currentStatus,
230
+ requirement: currentTitle,
231
+ mode: 'waiting',
232
+ timestamp: new Date().toISOString()
233
+ });
234
+ }
235
+ }
236
+ } catch (e) {
237
+ // Ignore if not in Electron context
238
+ }
239
+
240
+ // Check if we have any providers that will be available soon
241
+ if (selection.nextResetTime && selection.nextResetMs) {
242
+ const waitMinutes = Math.max(1, Math.ceil(selection.nextResetMs / 60000));
243
+
244
+ console.log(chalk.yellow(`🔄 All enabled providers are currently rate limited.`));
245
+
246
+ if (selection.nextProvider && selection.nextResetTime) {
247
+ const resetTime = new Date(selection.nextResetTime).toLocaleTimeString();
248
+ const resetDate = new Date(selection.nextResetTime).toLocaleDateString();
249
+ console.log(chalk.yellow(` Waiting for the next available agent (${selection.nextProvider.displayName}) to reset rate limit at ${resetTime} MST on ${resetDate}`));
250
+ } else {
251
+ console.log(chalk.yellow(` Waiting for rate limits to reset...`));
252
+ }
253
+
254
+ // Update status card to waiting mode
255
+ printStatusCard(currentTitle, currentStatus, 'waiting');
256
+
257
+ // Note: CLI cannot directly send IPC events to Electron app
258
+ // The Electron app's emitAutoModeProgress function will handle rate limit detection
259
+
260
+ // Check for any provider becoming available within the next minute
261
+ const nearFutureProviders = selection.providers?.filter(p => {
262
+ if (!p.rateLimitResetTime) return false;
263
+ const resetMs = new Date(p.rateLimitResetTime).getTime() - Date.now();
264
+ return resetMs > 0 && resetMs <= 60000; // Within 1 minute
265
+ });
266
+
267
+ if (nearFutureProviders && nearFutureProviders.length > 0) {
268
+ const nextProvider = nearFutureProviders[0];
269
+ const nextResetMs = new Date(nextProvider.rateLimitResetTime).getTime() - Date.now();
270
+ const nextWaitMinutes = Math.max(1, Math.ceil(nextResetMs / 60000));
271
+ const resetTime = new Date(nextProvider.rateLimitResetTime).toLocaleTimeString();
272
+ const resetDate = new Date(nextProvider.rateLimitResetTime).toLocaleDateString();
273
+
274
+ console.log(chalk.cyan(`⏱️ ${nextProvider.displayName} will be available at ${resetTime} on ${resetDate}`));
275
+ console.log(chalk.gray(` Waiting for ${nextProvider.displayName} to become available...\n`));
276
+
277
+ // Wait for the next available provider (max 1 minute chunks)
278
+ const waitChunks = Math.ceil(Math.min(nextResetMs, 60000) / 10000);
279
+ for (let i = 0; i < waitChunks; i++) {
280
+ await sleep(10000);
281
+ // Re-check provider status in case rate limits reset early
282
+ const freshSelection = await getProviderConfig();
283
+ if (freshSelection.status === 'ok') {
284
+ console.log(chalk.green(`✅ ${nextProvider.displayName} is now available!\n`));
285
+
286
+ // Notify GUI about returning to active mode
287
+ try {
288
+ if (process.versions && process.versions.electron) {
289
+ const { ipcRenderer } = require('electron');
290
+ if (ipcRenderer) {
291
+ ipcRenderer.send('requirements-progress', {
292
+ stage: currentStatus,
293
+ requirement: currentTitle,
294
+ mode: 'active',
295
+ timestamp: new Date().toISOString()
296
+ });
297
+ }
298
+ }
299
+ } catch (e) {
300
+ // Ignore if not in Electron context
301
+ }
302
+
303
+ return freshSelection;
304
+ }
305
+ }
306
+ } else {
307
+ // No providers available soon, wait for the next reset
308
+ console.log(chalk.gray(` DEBUG: selection = ${JSON.stringify(selection, null, 2)}\n`));
309
+ if (selection.nextProvider && selection.nextResetTime) {
310
+ const resetTime = new Date(selection.nextResetTime).toLocaleTimeString();
311
+ const resetDate = new Date(selection.nextResetTime).toLocaleDateString();
312
+ console.log(chalk.gray(` Waiting for ${selection.nextProvider.displayName} to reset at ${resetTime} MST on ${resetDate}...\n`));
313
+ } else {
314
+ console.log(chalk.gray(` Waiting for rate limits to reset...\n`));
315
+ }
316
+ await sleep(Math.min(selection.nextResetMs, 60000));
317
+ }
318
+ } else {
319
+ // No reset time info, wait default 1 minute
320
+ const nextAvailableProvider = selection.providers?.find(p => p.rateLimitResetTime && p.rateLimitResetTime > Date.now());
321
+ if (nextAvailableProvider) {
322
+ const resetTime = new Date(nextAvailableProvider.rateLimitResetTime).toLocaleTimeString();
323
+ const resetDate = new Date(nextAvailableProvider.rateLimitResetTime).toLocaleDateString();
324
+ console.log(chalk.gray(` Waiting for ${nextAvailableProvider.displayName} to reset at ${resetTime} MST on ${resetDate}...\n`));
325
+
326
+ // Note: CLI cannot directly send IPC events to Electron app
327
+ // The Electron app's emitAutoModeProgress function will handle rate limit detection
328
+ } else {
329
+ console.log(chalk.gray(` Waiting for rate limits to reset...\n`));
330
+ }
331
+ printStatusCard(currentTitle, currentStatus, 'waiting');
332
+ await sleep(60000);
333
+ }
334
+
335
+ return null; // Signal to retry provider selection
336
+ }
337
+
213
338
  module.exports = {
214
339
  getAllAvailableProviders,
215
340
  getProviderConfig,
216
341
  acquireProviderConfig,
217
342
  ensureClineInstalled,
343
+ handleRateLimitWithAgentSwitching,
218
344
  sharedProviderManager
219
345
  };
@@ -1,15 +1,30 @@
1
1
  /**
2
- * Requirement management functions for auto-direct command
3
- * Extracted from auto-direct.js to reduce file size
2
+ * Requirement Management Functions
3
+ * Extracted from auto-direct.js for better modularity
4
+ * Handles all operations related to requirements file management
4
5
  */
5
6
 
6
7
  const fs = require('fs-extra');
7
8
  const path = require('path');
8
- const { getRequirementsPath, readRequirements } = require('vibecodingmachine-core');
9
9
  const chalk = require('chalk');
10
+ const { getRequirementsPath } = require('vibecodingmachine-core');
11
+ const { t } = require('vibecodingmachine-core');
12
+ const { getStages, DEFAULT_STAGES } = require('../../utils/config');
13
+ const { moveRequirementToVerify, moveRequirementToRecycle } = require('./requirement-mover');
14
+
15
+ // Configured stages (will be loaded in handleAutoStart)
16
+ let configuredStages = DEFAULT_STAGES;
10
17
 
11
18
  /**
12
- * Update requirements file status
19
+ * Set configured stages for status updates
20
+ * @param {Array} stages - Array of stage names
21
+ */
22
+ function setConfiguredStages(stages) {
23
+ configuredStages = stages;
24
+ }
25
+
26
+ /**
27
+ * Update status section in requirements file
13
28
  * @param {string} repoPath - Repository path
14
29
  * @param {string} status - Status to set (PREPARE, ACT, CLEAN UP, VERIFY, DONE)
15
30
  */
@@ -20,24 +35,59 @@ async function updateRequirementsStatus(repoPath, status) {
20
35
  return;
21
36
  }
22
37
 
23
- let content = await fs.readFile(reqPath, 'utf8');
24
-
25
- // Find and replace the status section
26
- const statusSectionRegex = /## 🚦 Current Status\s*\n\s*\n(.+?)(?=\n##|\n$)/s;
27
- const match = content.match(statusSectionRegex);
28
-
29
- if (match) {
30
- content = content.replace(statusSectionRegex, `## 🚦 Current Status\n\n${status}`);
38
+ const content = await fs.readFile(reqPath, 'utf-8');
39
+ const lines = content.split('\n');
40
+ let inStatusSection = false;
41
+ let statusLineIndex = -1;
42
+
43
+ // Find the status section and the line with the status
44
+ for (let i = 0; i < lines.length; i++) {
45
+ const line = lines[i];
46
+
47
+ if (line.includes('🚦 Current Status')) {
48
+ inStatusSection = true;
49
+ continue;
50
+ }
51
+
52
+ if (inStatusSection && line.startsWith('##') && !line.startsWith('###')) {
53
+ // End of status section, status line not found
54
+ break;
55
+ }
56
+
57
+ // Check against configured stages
58
+ if (inStatusSection && configuredStages.includes(line.trim())) {
59
+ statusLineIndex = i;
60
+ break;
61
+ }
62
+ }
63
+
64
+ // Update or add the status line
65
+ if (statusLineIndex >= 0) {
66
+ // Replace existing status
67
+ lines[statusLineIndex] = status;
68
+ } else if (inStatusSection) {
69
+ // Add status after the section header
70
+ for (let i = 0; i < lines.length; i++) {
71
+ if (lines[i].includes('🚦 Current Status')) {
72
+ lines.splice(i + 1, 0, status);
73
+ break;
74
+ }
75
+ }
31
76
  } else {
32
- // If no status section found, add it after the first line
33
- const lines = content.split('\n');
34
- lines.splice(1, 0, '', '## 🚦 Current Status', '', status);
35
- content = lines.join('\n');
77
+ // Status section doesn't exist - find the requirement and add it
78
+ for (let i = 0; i < lines.length; i++) {
79
+ if (lines[i].startsWith('### ') && !lines[i].includes('🚦 Current Status')) {
80
+ // Found a requirement header, add status section after it
81
+ lines.splice(i + 1, 0, '', '#### 🚦 Current Status', status);
82
+ break;
83
+ }
84
+ }
36
85
  }
37
-
38
- await fs.writeFile(reqPath, content);
86
+
87
+ await fs.writeFile(reqPath, lines.join('\n'));
39
88
  } catch (error) {
40
- console.error('Error updating requirements status:', error.message);
89
+ // Silently fail - don't break execution if status update fails
90
+ console.error(chalk.gray(` ${t('auto.direct.status.update.warning')} ${error.message}`));
41
91
  }
42
92
  }
43
93
 
@@ -52,15 +102,78 @@ async function getCurrentRequirement(repoPath) {
52
102
  }
53
103
 
54
104
  const content = await fs.readFile(reqPath, 'utf8');
55
- const currentSection = content.match(/## 🔨 Current In Progress Requirement\s*\n([\s\S]*?)(?=\n## |\n$)/);
56
-
57
- if (currentSection) {
58
- return currentSection[1].trim();
105
+
106
+ // Always skip DISABLED: requirements (user can toggle via TRUI Space key)
107
+
108
+ // Extract first TODO requirement (new header format)
109
+ const lines = content.split('\n');
110
+ let inTodoSection = false;
111
+
112
+ for (let i = 0; i < lines.length; i++) {
113
+ const line = lines[i].trim();
114
+
115
+ // Check if we're in the TODO section
116
+ if (line.includes('## ⏳ Requirements not yet completed') ||
117
+ line.includes('Requirements not yet completed')) {
118
+ inTodoSection = true;
119
+ continue;
120
+ }
121
+
122
+ // If we hit another section header, stop looking
123
+ if (inTodoSection && line.startsWith('##') && !line.startsWith('###')) {
124
+ break;
125
+ }
126
+
127
+ // If we're in TODO section and find a requirement header (###)
128
+ if (inTodoSection && line.startsWith('###')) {
129
+ const title = line.replace(/^###\s*/, '').trim();
130
+ // Skip empty titles
131
+ if (title && title.length > 0) {
132
+ // Always skip DISABLED: requirements
133
+ if (title.startsWith('DISABLED:')) {
134
+ continue;
135
+ }
136
+
137
+ // Read package and description (optional)
138
+ let pkg = null;
139
+ let description = '';
140
+ let j = i + 1;
141
+
142
+ // Read next few lines for package and description
143
+ while (j < lines.length && j < i + 20) {
144
+ const nextLine = lines[j].trim();
145
+ // Stop if we hit another requirement or section
146
+ if (nextLine.startsWith('###') || (nextLine.startsWith('##') && !nextLine.startsWith('###'))) {
147
+ break;
148
+ }
149
+ // Check for PACKAGE line
150
+ if (nextLine.startsWith('PACKAGE:')) {
151
+ pkg = nextLine.replace(/^PACKAGE:\s*/, '').trim();
152
+ } else if (nextLine && !nextLine.startsWith('PACKAGE:')) {
153
+ // Description line (not empty, not package)
154
+ if (description) {
155
+ description += '\n' + nextLine;
156
+ } else {
157
+ description = nextLine;
158
+ }
159
+ }
160
+ j++;
161
+ }
162
+
163
+ return {
164
+ text: title,
165
+ fullLine: lines[i],
166
+ package: pkg,
167
+ description: description,
168
+ disabled: false
169
+ };
170
+ }
171
+ }
59
172
  }
60
-
173
+
61
174
  return null;
62
- } catch (error) {
63
- console.error('Error getting current requirement:', error.message);
175
+ } catch (err) {
176
+ console.error(t('auto.direct.requirement.read.error'), err.message);
64
177
  return null;
65
178
  }
66
179
  }
@@ -76,94 +189,46 @@ async function countTodoRequirements(repoPath) {
76
189
  }
77
190
 
78
191
  const content = await fs.readFile(reqPath, 'utf8');
79
- const todoSection = content.match(/## Requirements not yet completed\s*\n([\s\S]*?)(?=\n## |\n$)/);
80
-
81
- if (todoSection) {
82
- const todoItems = todoSection[1].match(/^- \[ \]/g);
83
- return todoItems ? todoItems.length : 0;
84
- }
85
-
86
- return 0;
87
- } catch (error) {
88
- console.error('Error counting TODO requirements:', error.message);
89
- return 0;
90
- }
91
- }
192
+ const lines = content.split('\n');
193
+ let inTodoSection = false;
194
+ let count = 0;
92
195
 
93
- /**
94
- * Move requirement from TODO to TO VERIFY BY HUMAN
95
- */
96
- async function moveRequirementToVerify(repoPath, requirementText) {
97
- try {
98
- const reqPath = await getRequirementsPath(repoPath);
99
- if (!reqPath || !await fs.pathExists(reqPath)) {
100
- return;
101
- }
196
+ for (let i = 0; i < lines.length; i++) {
197
+ const line = lines[i].trim();
102
198
 
103
- let content = await fs.readFile(reqPath, 'utf8');
104
-
105
- // Remove from TODO section
106
- const todoSection = content.match(/## Requirements not yet completed\s*\n([\s\S]*?)(?=\n## |\n$)/);
107
- if (todoSection) {
108
- const updatedTodo = todoSection[1].replace(new RegExp(`- \\[ \\] ${escapeRegExp(requirementText)}`, 'g'), '');
109
- content = content.replace(todoSection[0], `## Requirements not yet completed\n${updatedTodo}`);
110
- }
111
-
112
- // Add to verify section
113
- const verifySection = content.match(/## Verified by AI screenshot\. Needs Human to Verify and move to CHANGELOG\s*\n([\s\S]*?)(?=\n## |\n$)/);
114
- if (verifySection) {
115
- const newVerifyItem = `- [ ] ${requirementText}`;
116
- const updatedVerify = verifySection[1] + '\n' + newVerifyItem;
117
- content = content.replace(verifySection[0], `## Verified by AI screenshot. Needs Human to Verify and move to CHANGELOG\n${updatedVerify}`);
118
- }
119
-
120
- await fs.writeFile(reqPath, content);
121
- } catch (error) {
122
- console.error('Error moving requirement to verify:', error.message);
123
- }
124
- }
199
+ // Check if we're in the TODO section
200
+ if (line.includes('## ⏳ Requirements not yet completed') ||
201
+ line.includes('Requirements not yet completed')) {
202
+ inTodoSection = true;
203
+ continue;
204
+ }
125
205
 
126
- /**
127
- * Move requirement to recycled section
128
- */
129
- async function moveRequirementToRecycle(repoPath, requirementText) {
130
- try {
131
- const reqPath = await getRequirementsPath(repoPath);
132
- if (!reqPath || !await fs.pathExists(reqPath)) {
133
- return;
134
- }
206
+ // If we hit another section header, stop looking
207
+ if (inTodoSection && line.startsWith('##') && !line.startsWith('###')) {
208
+ break;
209
+ }
135
210
 
136
- let content = await fs.readFile(reqPath, 'utf8');
137
-
138
- // Remove from TODO section
139
- const todoSection = content.match(/## Requirements not yet completed\s*\n([\s\S]*?)(?=\n## |\n$)/);
140
- if (todoSection) {
141
- const updatedTodo = todoSection[1].replace(new RegExp(`- \\[ \\] ${escapeRegExp(requirementText)}`, 'g'), '');
142
- content = content.replace(todoSection[0], `## Requirements not yet completed\n${updatedTodo}`);
143
- }
144
-
145
- // Add to recycled section
146
- const recycledSection = content.match(/## Recycled Requirements \(do not work on\)\s*\n([\s\S]*?)(?=\n## |\n$)/);
147
- if (recycledSection) {
148
- const newRecycledItem = `- [ ] ${requirementText}`;
149
- const updatedRecycled = recycledSection[1] + '\n' + newRecycledItem;
150
- content = content.replace(recycledSection[0], `## Recycled Requirements (do not work on)\n${updatedRecycled}`);
211
+ // If we're in TODO section and find a requirement header (###)
212
+ if (inTodoSection && line.startsWith('###')) {
213
+ const title = line.replace(/^###\s*/, '').trim();
214
+ // Only count non-empty titles
215
+ if (title && title.length > 0) {
216
+ count++;
217
+ }
218
+ }
151
219
  }
152
-
153
- await fs.writeFile(reqPath, content);
154
- } catch (error) {
155
- console.error('Error moving requirement to recycle:', error.message);
220
+
221
+ return count;
222
+ } catch (err) {
223
+ console.error(t('auto.direct.requirement.count.error'), err.message);
224
+ return 0;
156
225
  }
157
226
  }
158
227
 
159
- /**
160
- * Escape special characters for regex
161
- */
162
- function escapeRegExp(string) {
163
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
164
- }
228
+ // moveRequirementToVerify and moveRequirementToRecycle are imported from requirement-mover.js
165
229
 
166
230
  module.exports = {
231
+ setConfiguredStages,
167
232
  updateRequirementsStatus,
168
233
  getCurrentRequirement,
169
234
  countTodoRequirements,