vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739

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 (202) hide show
  1. package/README.md +240 -0
  2. package/package.json +10 -2
  3. package/src/agents/Agent.js +300 -0
  4. package/src/agents/AgentAdditionService.js +311 -0
  5. package/src/agents/AgentCheckService.js +690 -0
  6. package/src/agents/AgentInstallationService.js +140 -0
  7. package/src/agents/AgentSetupService.js +467 -0
  8. package/src/agents/AgentStatus.js +183 -0
  9. package/src/agents/AgentVerificationService.js +634 -0
  10. package/src/agents/ConfigurationSchemaValidator.js +543 -0
  11. package/src/agents/EnvironmentConfigurationManager.js +602 -0
  12. package/src/agents/InstallationErrorHandler.js +372 -0
  13. package/src/agents/InstallationLog.js +363 -0
  14. package/src/agents/InstallationMethod.js +510 -0
  15. package/src/agents/InstallationOrchestrator.js +352 -0
  16. package/src/agents/InstallationProgressReporter.js +372 -0
  17. package/src/agents/InstallationRetryManager.js +322 -0
  18. package/src/agents/InstallationType.js +254 -0
  19. package/src/agents/OperationTypes.js +310 -0
  20. package/src/agents/PerformanceMetricsCollector.js +493 -0
  21. package/src/agents/SecurityValidationService.js +534 -0
  22. package/src/agents/VerificationTest.js +354 -0
  23. package/src/agents/VerificationType.js +226 -0
  24. package/src/agents/WindowsPermissionHandler.js +518 -0
  25. package/src/agents/config/AgentConfigManager.js +393 -0
  26. package/src/agents/config/AgentDefaultsRegistry.js +373 -0
  27. package/src/agents/config/ConfigValidator.js +281 -0
  28. package/src/agents/discovery/AgentDiscoveryService.js +707 -0
  29. package/src/agents/logging/AgentLogger.js +511 -0
  30. package/src/agents/status/AgentStatusManager.js +481 -0
  31. package/src/agents/storage/FileManager.js +454 -0
  32. package/src/agents/verification/AgentCommunicationTester.js +474 -0
  33. package/src/agents/verification/BaseVerifier.js +430 -0
  34. package/src/agents/verification/CommandVerifier.js +480 -0
  35. package/src/agents/verification/FileOperationVerifier.js +453 -0
  36. package/src/agents/verification/ResultAnalyzer.js +707 -0
  37. package/src/agents/verification/TestRequirementManager.js +495 -0
  38. package/src/agents/verification/VerificationRunner.js +433 -0
  39. package/src/agents/windows/BaseWindowsInstaller.js +441 -0
  40. package/src/agents/windows/ChocolateyInstaller.js +509 -0
  41. package/src/agents/windows/DirectInstaller.js +443 -0
  42. package/src/agents/windows/InstallerFactory.js +391 -0
  43. package/src/agents/windows/NpmInstaller.js +505 -0
  44. package/src/agents/windows/PowerShellInstaller.js +458 -0
  45. package/src/agents/windows/WinGetInstaller.js +390 -0
  46. package/src/analysis/analysis-reporter.js +132 -0
  47. package/src/analysis/boundary-detector.js +712 -0
  48. package/src/analysis/categorizer.js +340 -0
  49. package/src/analysis/codebase-scanner.js +384 -0
  50. package/src/analysis/line-counter.js +513 -0
  51. package/src/analysis/priority-calculator.js +679 -0
  52. package/src/analysis/report/analysis-report.js +250 -0
  53. package/src/analysis/report/package-analyzer.js +278 -0
  54. package/src/analysis/report/recommendation-generator.js +382 -0
  55. package/src/analysis/report/statistics-generator.js +515 -0
  56. package/src/analysis/reports/analysis-report-model.js +101 -0
  57. package/src/analysis/reports/recommendation-generator.js +283 -0
  58. package/src/analysis/reports/report-generators.js +191 -0
  59. package/src/analysis/reports/statistics-calculator.js +231 -0
  60. package/src/analysis/reports/trend-analyzer.js +219 -0
  61. package/src/analysis/strategy-generator.js +814 -0
  62. package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
  63. package/src/config/refactoring-config.js +307 -0
  64. package/src/health-tracking/json-storage.js +38 -2
  65. package/src/ide-integration/applescript-manager-core.js +233 -0
  66. package/src/ide-integration/applescript-manager.cjs +357 -28
  67. package/src/ide-integration/applescript-manager.js +89 -3599
  68. package/src/ide-integration/cdp-manager.js +306 -0
  69. package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
  70. package/src/ide-integration/continuation-handler.js +337 -0
  71. package/src/ide-integration/ide-status-checker.js +292 -0
  72. package/src/ide-integration/macos-ide-manager.js +627 -0
  73. package/src/ide-integration/macos-text-sender.js +528 -0
  74. package/src/ide-integration/response-reader.js +548 -0
  75. package/src/ide-integration/windows-automation-manager.js +121 -0
  76. package/src/ide-integration/windows-ide-manager.js +373 -0
  77. package/src/index.cjs +25 -3
  78. package/src/index.js +15 -1
  79. package/src/llm/direct-llm-manager.cjs +90 -2
  80. package/src/models/compliance-report.js +538 -0
  81. package/src/models/file-analysis.js +681 -0
  82. package/src/models/refactoring-plan.js +770 -0
  83. package/src/monitoring/alert-system.js +834 -0
  84. package/src/monitoring/compliance-progress-tracker.js +437 -0
  85. package/src/monitoring/continuous-scan-notifications.js +661 -0
  86. package/src/monitoring/continuous-scanner.js +279 -0
  87. package/src/monitoring/file-monitor/file-analyzer.js +262 -0
  88. package/src/monitoring/file-monitor/file-monitor.js +237 -0
  89. package/src/monitoring/file-monitor/watcher.js +194 -0
  90. package/src/monitoring/file-monitor.js +17 -0
  91. package/src/monitoring/notification-manager.js +437 -0
  92. package/src/monitoring/scanner-core.js +368 -0
  93. package/src/monitoring/scanner-events.js +214 -0
  94. package/src/monitoring/violation-notification-system.js +515 -0
  95. package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
  96. package/src/refactoring/boundaries/extraction-result.js +285 -0
  97. package/src/refactoring/boundaries/extraction-strategies.js +392 -0
  98. package/src/refactoring/boundaries/module-boundary.js +209 -0
  99. package/src/refactoring/boundary/boundary-detector.js +741 -0
  100. package/src/refactoring/boundary/boundary-types.js +405 -0
  101. package/src/refactoring/boundary/extraction-strategies.js +554 -0
  102. package/src/refactoring/boundary-extraction-result.js +77 -0
  103. package/src/refactoring/boundary-extraction-strategies.js +330 -0
  104. package/src/refactoring/boundary-extractor.js +384 -0
  105. package/src/refactoring/boundary-types.js +46 -0
  106. package/src/refactoring/circular/circular-dependency.js +88 -0
  107. package/src/refactoring/circular/cycle-detection.js +147 -0
  108. package/src/refactoring/circular/dependency-node.js +82 -0
  109. package/src/refactoring/circular/dependency-result.js +107 -0
  110. package/src/refactoring/circular/dependency-types.js +58 -0
  111. package/src/refactoring/circular/graph-builder.js +213 -0
  112. package/src/refactoring/circular/resolution-strategy.js +72 -0
  113. package/src/refactoring/circular/strategy-generator.js +229 -0
  114. package/src/refactoring/circular-dependency-resolver-original.js +809 -0
  115. package/src/refactoring/circular-dependency-resolver.js +200 -0
  116. package/src/refactoring/code-mover.js +761 -0
  117. package/src/refactoring/file-splitter.js +696 -0
  118. package/src/refactoring/functionality-validator.js +816 -0
  119. package/src/refactoring/import-manager.js +774 -0
  120. package/src/refactoring/module-boundary.js +107 -0
  121. package/src/refactoring/refactoring-executor.js +672 -0
  122. package/src/refactoring/refactoring-rollback.js +614 -0
  123. package/src/refactoring/test-validator.js +631 -0
  124. package/src/requirement-management/default-requirement-manager.js +321 -0
  125. package/src/requirement-management/requirement-file-parser.js +159 -0
  126. package/src/requirement-management/requirement-sequencer.js +221 -0
  127. package/src/rui/commands/AgentCommandParser.js +600 -0
  128. package/src/rui/commands/AgentCommands.js +487 -0
  129. package/src/rui/commands/AgentResponseFormatter.js +832 -0
  130. package/src/scripts/verify-full-compliance.js +269 -0
  131. package/src/sync/sync-engine-core.js +1 -0
  132. package/src/sync/sync-engine-remote-handlers.js +135 -0
  133. package/src/task-generation/automated-task-generator.js +351 -0
  134. package/src/task-generation/prioritizer.js +287 -0
  135. package/src/task-generation/task-list-updater.js +215 -0
  136. package/src/task-generation/task-management-integration.js +480 -0
  137. package/src/task-generation/task-manager-integration.js +270 -0
  138. package/src/task-generation/violation-task-generator.js +474 -0
  139. package/src/task-management/continuous-scan-integration.js +342 -0
  140. package/src/timeout-management/index.js +12 -3
  141. package/src/timeout-management/response-time-tracker.js +167 -0
  142. package/src/timeout-management/timeout-calculator.js +159 -0
  143. package/src/timeout-management/timeout-config-manager.js +172 -0
  144. package/src/utils/ast-analyzer.js +417 -0
  145. package/src/utils/current-requirement-manager.js +276 -0
  146. package/src/utils/current-requirement-operations.js +472 -0
  147. package/src/utils/dependency-mapper.js +456 -0
  148. package/src/utils/download-with-progress.js +4 -2
  149. package/src/utils/electron-update-checker.js +4 -1
  150. package/src/utils/file-size-analyzer.js +272 -0
  151. package/src/utils/import-updater.js +280 -0
  152. package/src/utils/refactoring-tools.js +512 -0
  153. package/src/utils/report-generator.js +569 -0
  154. package/src/utils/reports/report-analysis.js +218 -0
  155. package/src/utils/reports/report-types.js +55 -0
  156. package/src/utils/reports/summary-generators.js +102 -0
  157. package/src/utils/requirement-file-management.js +157 -0
  158. package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
  159. package/src/utils/requirement-helpers/requirement-mover.js +414 -0
  160. package/src/utils/requirement-helpers/requirement-parser.js +326 -0
  161. package/src/utils/requirement-helpers/requirement-status.js +320 -0
  162. package/src/utils/requirement-helpers-new.js +55 -0
  163. package/src/utils/requirement-helpers-refactored.js +367 -0
  164. package/src/utils/requirement-helpers.js +291 -1191
  165. package/src/utils/requirement-movement-operations.js +450 -0
  166. package/src/utils/requirement-movement.js +312 -0
  167. package/src/utils/requirement-parsing-helpers.js +56 -0
  168. package/src/utils/requirement-statistics.js +200 -0
  169. package/src/utils/requirement-text-utils.js +58 -0
  170. package/src/utils/rollback/rollback-handlers.js +125 -0
  171. package/src/utils/rollback/rollback-operation.js +63 -0
  172. package/src/utils/rollback/rollback-recorder.js +166 -0
  173. package/src/utils/rollback/rollback-state-manager.js +175 -0
  174. package/src/utils/rollback/rollback-types.js +33 -0
  175. package/src/utils/rollback/rollback-utils.js +110 -0
  176. package/src/utils/rollback-manager-original.js +569 -0
  177. package/src/utils/rollback-manager.js +202 -0
  178. package/src/utils/smoke-test-cli.js +362 -0
  179. package/src/utils/smoke-test-gui.js +351 -0
  180. package/src/utils/smoke-test-orchestrator.js +321 -0
  181. package/src/utils/smoke-test-runner.js +60 -0
  182. package/src/utils/smoke-test-web.js +347 -0
  183. package/src/utils/specification-helpers.js +39 -13
  184. package/src/utils/specification-migration.js +97 -0
  185. package/src/utils/test-runner.js +579 -0
  186. package/src/utils/validation-framework.js +518 -0
  187. package/src/validation/compliance-analyzer.js +197 -0
  188. package/src/validation/compliance-report-generator.js +343 -0
  189. package/src/validation/compliance-reporter.js +711 -0
  190. package/src/validation/compliance-rules.js +127 -0
  191. package/src/validation/constitution-validator-new.js +196 -0
  192. package/src/validation/constitution-validator.js +17 -0
  193. package/src/validation/file-validators.js +170 -0
  194. package/src/validation/line-limit/file-analyzer.js +201 -0
  195. package/src/validation/line-limit/line-limit-validator.js +208 -0
  196. package/src/validation/line-limit/validation-result.js +144 -0
  197. package/src/validation/line-limit-core.js +225 -0
  198. package/src/validation/line-limit-reporter.js +134 -0
  199. package/src/validation/line-limit-result.js +125 -0
  200. package/src/validation/line-limit-validator.js +41 -0
  201. package/src/validation/metrics-calculator.js +660 -0
  202. package/src/sync/sync-engine-backup.js +0 -559
@@ -0,0 +1,450 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { getRequirementsPath } = require('./repo-helpers.cjs');
4
+ const { logger } = require('./logger.cjs');
5
+ const { addTryAgainPrefix, parseRequirementLine } = require('./requirement-parsing-helpers');
6
+
7
+ /**
8
+ * Move requirement from TO VERIFY section to VERIFIED (CHANGELOG)
9
+ * @param {string} reqPath - Path to REQUIREMENTS file
10
+ * @param {string} requirementTitle - Title of requirement to move
11
+ * @returns {Promise<boolean>} Success status
12
+ */
13
+ async function promoteToVerified(reqPath, requirementTitle) {
14
+ try {
15
+ const content = await fs.readFile(reqPath, 'utf-8');
16
+ const lines = content.split('\n');
17
+ let inVerifySection = false;
18
+ let requirementStartIndex = -1;
19
+ let requirementEndIndex = -1;
20
+ const normalizedTitle = requirementTitle.trim();
21
+
22
+ // Find the requirement in TO VERIFY section (new ### format)
23
+ for (let i = 0; i < lines.length; i++) {
24
+ const line = lines[i];
25
+ const trimmed = line.trim();
26
+
27
+ // Check if we're entering TO VERIFY section (multiple variants)
28
+ if (trimmed.startsWith('##') && !trimmed.startsWith('###') &&
29
+ (trimmed.includes('TO VERIFY') || trimmed.includes('Verified by AI screenshot'))) {
30
+ inVerifySection = true;
31
+ continue;
32
+ }
33
+
34
+ // Check if we're leaving TO VERIFY section
35
+ if (inVerifySection && trimmed.startsWith('##') && !trimmed.startsWith('###')) {
36
+ inVerifySection = false;
37
+ }
38
+
39
+ // Look for requirement in TO VERIFY section (### header format)
40
+ if (inVerifySection && trimmed.startsWith('###')) {
41
+ const title = trimmed.replace(/^###\s*/, '').trim();
42
+ if (title === normalizedTitle || title.includes(normalizedTitle) || normalizedTitle.includes(title)) {
43
+ requirementStartIndex = i;
44
+
45
+ // Find the end of this requirement block
46
+ for (let j = i + 1; j < lines.length; j++) {
47
+ const nextLine = lines[j].trim();
48
+ if (nextLine.startsWith('###') || (nextLine.startsWith('##') && !nextLine.startsWith('###'))) {
49
+ requirementEndIndex = j;
50
+ break;
51
+ }
52
+ }
53
+ if (requirementEndIndex === -1) {
54
+ requirementEndIndex = lines.length;
55
+ }
56
+ break;
57
+ }
58
+ }
59
+ }
60
+
61
+ if (requirementStartIndex === -1) {
62
+ return false;
63
+ }
64
+
65
+ // Extract requirement block
66
+ const requirementBlock = lines.slice(requirementStartIndex, requirementEndIndex);
67
+ const extractedTitle = lines[requirementStartIndex].replace(/^###\s*/, '').trim();
68
+
69
+ // Remove requirement from TO VERIFY section
70
+ lines.splice(requirementStartIndex, requirementEndIndex - requirementStartIndex);
71
+
72
+ // Add to CHANGELOG.md
73
+ const allnightDir = path.dirname(reqPath);
74
+ const repoRoot = path.dirname(allnightDir);
75
+ const changelogPath = path.join(repoRoot, 'CHANGELOG.md');
76
+ const timestamp = new Date().toISOString().split('T')[0];
77
+ const changelogEntry = `- ${extractedTitle} (${timestamp})`;
78
+
79
+ let changelogContent = '';
80
+ if (await fs.pathExists(changelogPath)) {
81
+ changelogContent = await fs.readFile(changelogPath, 'utf-8');
82
+ } else {
83
+ changelogContent = '# Changelog\n\n## Verified Requirements\n\n';
84
+ }
85
+
86
+ if (changelogContent.includes('## Verified Requirements')) {
87
+ changelogContent = changelogContent.replace(
88
+ '## Verified Requirements\n',
89
+ `## Verified Requirements\n${changelogEntry}\n`
90
+ );
91
+ } else {
92
+ changelogContent += `\n## Verified Requirements\n${changelogEntry}\n`;
93
+ }
94
+
95
+ await fs.writeFile(changelogPath, changelogContent);
96
+ await fs.writeFile(reqPath, lines.join('\n'));
97
+ return true;
98
+ } catch (error) {
99
+ throw new Error(`Failed to promote requirement to verified: ${error.message}`);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Move requirement from VERIFIED (CHANGELOG) back to TODO with TRY AGAIN prefix
105
+ * @param {string} reqPath - Path to REQUIREMENTS file
106
+ * @param {string} requirementTitle - Title of requirement to move
107
+ * @returns {Promise<boolean>} Success status
108
+ */
109
+ async function demoteFromVerifiedToTodo(reqPath, requirementTitle) {
110
+ try {
111
+ // CHANGELOG.md should be at repository root, not in .vibecodingmachine directory
112
+ const allnightDir = path.dirname(reqPath); // .vibecodingmachine directory
113
+ const repoRoot = path.dirname(allnightDir); // repository root (one level up)
114
+ const changelogPath = path.join(repoRoot, 'CHANGELOG.md');
115
+
116
+ if (!(await fs.pathExists(changelogPath))) {
117
+ return false;
118
+ }
119
+
120
+ let changelogContent = await fs.readFile(changelogPath, 'utf-8');
121
+ const changelogLines = changelogContent.split('\n');
122
+ const updatedChangelogLines = [];
123
+ let requirementToMove = null;
124
+
125
+ for (const line of changelogLines) {
126
+ if (line.startsWith('- ')) {
127
+ const lineText = parseRequirementLine(line);
128
+ // Extract title part (before timestamp in parentheses)
129
+ const titleMatch = lineText.match(/^(.+?)\s*\([\d-]+\)$/);
130
+ const lineTitle = titleMatch ? titleMatch[1] : lineText;
131
+
132
+ // Check if this line matches the requirement title
133
+ // Handle both cases: requirementTitle might include timestamp or not
134
+ const reqTitleMatch = requirementTitle.match(/^(.+?)\s*\([\d-]+\)$/);
135
+ const reqTitleOnly = reqTitleMatch ? reqTitleMatch[1] : requirementTitle;
136
+
137
+ if (lineTitle === reqTitleOnly || lineTitle.includes(reqTitleOnly) || reqTitleOnly.includes(lineTitle)) {
138
+ requirementToMove = lineTitle;
139
+ continue;
140
+ }
141
+ }
142
+ updatedChangelogLines.push(line);
143
+ }
144
+
145
+ if (!requirementToMove) {
146
+ return false;
147
+ }
148
+
149
+ await fs.writeFile(changelogPath, updatedChangelogLines.join('\n'));
150
+
151
+ const content = await fs.readFile(reqPath, 'utf-8');
152
+ const lines = content.split('\n');
153
+ const updatedLines = [];
154
+ let foundTodoSection = false;
155
+
156
+ for (let i = 0; i < lines.length; i++) {
157
+ const line = lines[i];
158
+
159
+ if (line.includes('## ⏳ Requirements not yet completed')) {
160
+ foundTodoSection = true;
161
+ updatedLines.push(line);
162
+ const requirementText = addTryAgainPrefix(requirementToMove);
163
+ updatedLines.push(`- ${requirementText}`);
164
+ continue;
165
+ }
166
+
167
+ updatedLines.push(line);
168
+ }
169
+
170
+ if (!foundTodoSection) {
171
+ updatedLines.push('## ⏳ Requirements not yet completed');
172
+ const requirementText = addTryAgainPrefix(requirementToMove);
173
+ updatedLines.push(`- ${requirementText}`);
174
+ }
175
+
176
+ await fs.writeFile(reqPath, updatedLines.join('\n'));
177
+ return true;
178
+ } catch (error) {
179
+ throw new Error(`Failed to demote requirement from verified: ${error.message}`);
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Move requirement from TODO to TO VERIFY section
185
+ * @param {string} reqPath - Path to REQUIREMENTS file
186
+ * @param {string} requirementTitle - Title of requirement to move
187
+ * @returns {Promise<boolean>} Success status
188
+ */
189
+ async function promoteTodoToVerify(reqPath, requirementTitle) {
190
+ try {
191
+ const content = await fs.readFile(reqPath, 'utf-8');
192
+ const lines = content.split('\n');
193
+
194
+ // Find the requirement block (### header format)
195
+ let requirementStartIndex = -1;
196
+ let requirementEndIndex = -1;
197
+ let inTodoSection = false;
198
+
199
+ for (let i = 0; i < lines.length; i++) {
200
+ const line = lines[i].trim();
201
+
202
+ if (line.includes('## ⏳ Requirements not yet completed')) {
203
+ inTodoSection = true;
204
+ continue;
205
+ }
206
+
207
+ if (inTodoSection && line.startsWith('##') && !line.startsWith('###')) {
208
+ break;
209
+ }
210
+
211
+ if (inTodoSection && line.startsWith('###')) {
212
+ const title = line.replace(/^###\s*/, '').trim();
213
+ if (title && (title === requirementTitle || title.includes(requirementTitle) || requirementTitle.includes(title))) {
214
+ requirementStartIndex = i;
215
+ // Find the end of this requirement (next ### or ## header)
216
+ for (let j = i + 1; j < lines.length; j++) {
217
+ const nextLine = lines[j].trim();
218
+ if (nextLine.startsWith('###') || (nextLine.startsWith('##') && !nextLine.startsWith('###'))) {
219
+ requirementEndIndex = j;
220
+ break;
221
+ }
222
+ }
223
+ if (requirementEndIndex === -1) {
224
+ requirementEndIndex = lines.length;
225
+ }
226
+ break;
227
+ }
228
+ }
229
+ }
230
+
231
+ if (requirementStartIndex === -1) {
232
+ return false;
233
+ }
234
+
235
+ // Extract the requirement block
236
+ const requirementBlock = lines.slice(requirementStartIndex, requirementEndIndex);
237
+
238
+ // Remove the requirement from its current location
239
+ const updatedLines = [
240
+ ...lines.slice(0, requirementStartIndex),
241
+ ...lines.slice(requirementEndIndex)
242
+ ];
243
+
244
+ // Find or create TO VERIFY section
245
+ const verifySectionVariants = [
246
+ '## 🔍 TO VERIFY BY HUMAN',
247
+ '## 🔍 TO VERIFY',
248
+ '## TO VERIFY',
249
+ '## ✅ TO VERIFY',
250
+ '## ✅ Verified by AI screenshot'
251
+ ];
252
+
253
+ let verifyIndex = -1;
254
+ for (let i = 0; i < updatedLines.length; i++) {
255
+ if (verifySectionVariants.some(variant => updatedLines[i].includes(variant))) {
256
+ verifyIndex = i;
257
+ break;
258
+ }
259
+ }
260
+
261
+ if (verifyIndex === -1) {
262
+ // Create TO VERIFY section before CHANGELOG or at end
263
+ const changelogIndex = updatedLines.findIndex(line => line.includes('## CHANGELOG'));
264
+ const insertIndex = changelogIndex > 0 ? changelogIndex : updatedLines.length;
265
+ updatedLines.splice(insertIndex, 0, '', '## 🔍 TO VERIFY BY HUMAN', '');
266
+ verifyIndex = insertIndex + 1;
267
+ }
268
+
269
+ // Insert requirement block after section header
270
+ let insertIndex = verifyIndex + 1;
271
+ while (insertIndex < updatedLines.length && updatedLines[insertIndex].trim() === '') {
272
+ insertIndex++;
273
+ }
274
+ updatedLines.splice(insertIndex, 0, ...requirementBlock);
275
+ // Add blank line after if needed
276
+ if (insertIndex + requirementBlock.length < updatedLines.length && updatedLines[insertIndex + requirementBlock.length].trim() !== '') {
277
+ updatedLines.splice(insertIndex + requirementBlock.length, 0, '');
278
+ }
279
+
280
+ await fs.writeFile(reqPath, updatedLines.join('\n'));
281
+ return true;
282
+ } catch (error) {
283
+ throw new Error(`Failed to promote requirement from TODO to TO VERIFY: ${error.message}`);
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Move requirement from TO VERIFY back to TODO section
289
+ * @param {string} reqPath - Path to REQUIREMENTS file
290
+ * @param {string} requirementTitle - Title of requirement to move
291
+ * @param {string} explanation - Optional explanation of what went wrong
292
+ * @returns {Promise<boolean>} Success status
293
+ */
294
+ async function demoteVerifyToTodo(reqPath, requirementTitle, explanation = '') {
295
+ try {
296
+ const content = await fs.readFile(reqPath, 'utf-8');
297
+ const lines = content.split('\n');
298
+
299
+ // Find ALL matching requirements in TO VERIFY section and remove them
300
+ // We'll collect all requirement blocks to remove, then process them
301
+ const requirementsToRemove = [];
302
+ let inVerifySection = false;
303
+
304
+ const verifySectionVariants = [
305
+ '## 🔍 TO VERIFY BY HUMAN',
306
+ '## 🔍 TO VERIFY',
307
+ '## TO VERIFY',
308
+ '## ✅ TO VERIFY',
309
+ '## ✅ Verified by AI screenshot. Needs Human to Verify and move to CHANGELOG',
310
+ '## ✅ Verified by AI screenshot'
311
+ ];
312
+
313
+ // First pass: find all matching requirements in TO VERIFY section
314
+ for (let i = 0; i < lines.length; i++) {
315
+ const line = lines[i];
316
+ const trimmed = line.trim();
317
+
318
+ // Check if this is a TO VERIFY section header
319
+ if (trimmed.startsWith('##') && !trimmed.startsWith('###')) {
320
+ const isToVerifyHeader = verifySectionVariants.some(variant => {
321
+ return trimmed === variant || trimmed.startsWith(variant) ||
322
+ (trimmed.includes('Verified by AI screenshot') && trimmed.includes('Needs Human to Verify'));
323
+ });
324
+
325
+ if (isToVerifyHeader) {
326
+ // Make sure it's not a VERIFIED section (without TO VERIFY)
327
+ if (!trimmed.includes('## 📝 VERIFIED') && !trimmed.match(/^##\s+VERIFIED$/i) && !trimmed.includes('📝 VERIFIED')) {
328
+ inVerifySection = true;
329
+ continue;
330
+ }
331
+ } else if (inVerifySection) {
332
+ // Check if we're leaving TO VERIFY section (hit a different section)
333
+ if (trimmed.includes('⏳ Requirements not yet completed') ||
334
+ trimmed.includes('## 📝 VERIFIED') ||
335
+ trimmed.includes('## ♻️ RECYCLED') ||
336
+ trimmed.includes('## 📦 RECYCLED') ||
337
+ trimmed.includes('## ❓ Requirements needing')) {
338
+ // We've left the TO VERIFY section
339
+ inVerifySection = false;
340
+ }
341
+ }
342
+ }
343
+
344
+ // Look for requirement in TO VERIFY section
345
+ if (inVerifySection && trimmed.startsWith('###')) {
346
+ const title = trimmed.replace(/^###\s*/, '').trim();
347
+ // Normalize titles for matching (handle TRY AGAIN prefixes)
348
+ const normalizedTitle = title.replace(/^TRY AGAIN \(\d+(st|nd|rd|th) time\):\s*/i, '').trim();
349
+ const normalizedRequirementTitle = requirementTitle.replace(/^TRY AGAIN \(\d+(st|nd|rd|th) time\):\s*/i, '').trim();
350
+
351
+ if (title && (title === requirementTitle ||
352
+ normalizedTitle === normalizedRequirementTitle ||
353
+ title.includes(requirementTitle) ||
354
+ requirementTitle.includes(title) ||
355
+ normalizedTitle.includes(normalizedRequirementTitle) ||
356
+ normalizedRequirementTitle.includes(normalizedTitle))) {
357
+ // Find the end of this requirement (next ### or ## header)
358
+ let requirementEndIndex = lines.length;
359
+ for (let j = i + 1; j < lines.length; j++) {
360
+ const nextLine = lines[j].trim();
361
+ if (nextLine.startsWith('###') || (nextLine.startsWith('##') && !nextLine.startsWith('###'))) {
362
+ requirementEndIndex = j;
363
+ break;
364
+ }
365
+ }
366
+
367
+ // Store this requirement to remove (we'll use the first one for moving to TODO)
368
+ requirementsToRemove.push({
369
+ start: i,
370
+ end: requirementEndIndex,
371
+ block: lines.slice(i, requirementEndIndex)
372
+ });
373
+ }
374
+ }
375
+ }
376
+
377
+ if (requirementsToRemove.length === 0) {
378
+ return false;
379
+ }
380
+
381
+ // Use the first matching requirement for moving to TODO (with TRY AGAIN prefix)
382
+ const firstRequirement = requirementsToRemove[0];
383
+ const requirementBlock = [...firstRequirement.block];
384
+
385
+ // Update title with TRY AGAIN prefix
386
+ const originalTitle = requirementBlock[0].replace(/^###\s*/, '').trim();
387
+ const titleWithPrefix = addTryAgainPrefix(originalTitle);
388
+ requirementBlock[0] = `### ${titleWithPrefix}`;
389
+
390
+ // Add explanation to the requirement description if provided
391
+ if (explanation && explanation.trim()) {
392
+ // Find where to insert the explanation (after the title, before any existing content)
393
+ // Insert after first line (title) with a blank line and "What went wrong:" section
394
+ const explanationLines = [
395
+ '',
396
+ '**What went wrong (from previous attempt):**',
397
+ explanation.trim(),
398
+ ''
399
+ ];
400
+ requirementBlock.splice(1, 0, ...explanationLines);
401
+ }
402
+
403
+ // Remove ALL matching requirements from TO VERIFY section (work backwards to preserve indices)
404
+ const updatedLines = [...lines];
405
+ for (let i = requirementsToRemove.length - 1; i >= 0; i--) {
406
+ const req = requirementsToRemove[i];
407
+ updatedLines.splice(req.start, req.end - req.start);
408
+ }
409
+
410
+ // Find or create TODO section
411
+ let todoIndex = -1;
412
+ for (let i = 0; i < updatedLines.length; i++) {
413
+ if (updatedLines[i].includes('## ⏳ Requirements not yet completed')) {
414
+ todoIndex = i;
415
+ break;
416
+ }
417
+ }
418
+
419
+ if (todoIndex === -1) {
420
+ // Create TODO section at the top (after initial headers)
421
+ const firstSectionIndex = updatedLines.findIndex(line => line.startsWith('##') && !line.startsWith('###'));
422
+ const insertIndex = firstSectionIndex > 0 ? firstSectionIndex : updatedLines.length;
423
+ updatedLines.splice(insertIndex, 0, '## ⏳ Requirements not yet completed', '');
424
+ todoIndex = insertIndex;
425
+ }
426
+
427
+ // Insert requirement block after section header
428
+ let insertIndex = todoIndex + 1;
429
+ while (insertIndex < updatedLines.length && updatedLines[insertIndex].trim() === '') {
430
+ insertIndex++;
431
+ }
432
+ updatedLines.splice(insertIndex, 0, ...requirementBlock);
433
+ // Add blank line after if needed
434
+ if (insertIndex + requirementBlock.length < updatedLines.length && updatedLines[insertIndex + requirementBlock.length].trim() !== '') {
435
+ updatedLines.splice(insertIndex + requirementBlock.length, 0, '');
436
+ }
437
+
438
+ await fs.writeFile(reqPath, updatedLines.join('\n'));
439
+ return true;
440
+ } catch (error) {
441
+ throw new Error(`Failed to demote requirement from TO VERIFY to TODO: ${error.message}`);
442
+ }
443
+ }
444
+
445
+ module.exports = {
446
+ promoteToVerified,
447
+ demoteFromVerifiedToTodo,
448
+ promoteTodoToVerify,
449
+ demoteVerifyToTodo
450
+ };