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,321 @@
1
+ /**
2
+ * Manages default requirement lifecycle (create, edit, delete, pause, resume, status tracking)
3
+ */
4
+ class DefaultRequirementManager {
5
+ constructor(storage) {
6
+ this.storage = storage;
7
+ this.consecutiveFailuresThreshold = 5;
8
+ }
9
+
10
+ /**
11
+ * Create a new default requirement
12
+ * @param {Object} requirement - Requirement data
13
+ * @param {string} requirement.title - Requirement title
14
+ * @param {string} requirement.description - Requirement description
15
+ * @param {number} requirement.maxIterations - Maximum iterations
16
+ * @returns {Object} Created requirement
17
+ */
18
+ async create(requirement) {
19
+ const { title, description, maxIterations } = requirement;
20
+
21
+ if (!title || !description || !maxIterations) {
22
+ throw new Error('Title, description, and maxIterations are required');
23
+ }
24
+
25
+ if (maxIterations < 1 || maxIterations > 1000) {
26
+ throw new Error('maxIterations must be between 1 and 1000');
27
+ }
28
+
29
+ const data = await this.storage.read();
30
+
31
+ if (data.defaultRequirement) {
32
+ throw new Error('Default requirement already exists');
33
+ }
34
+
35
+ const newRequirement = {
36
+ title,
37
+ description,
38
+ maxIterations,
39
+ status: 'ACTIVE',
40
+ createdAt: Date.now(),
41
+ iterationCount: 0,
42
+ consecutiveFailures: 0,
43
+ lastIterationAt: null
44
+ };
45
+
46
+ data.defaultRequirement = newRequirement;
47
+ await this.storage.write(data);
48
+
49
+ return newRequirement;
50
+ }
51
+
52
+ /**
53
+ * Edit existing default requirement
54
+ * @param {Object} updates - Updates to apply
55
+ * @returns {Object} Updated requirement
56
+ */
57
+ async edit(updates) {
58
+ const data = await this.storage.read();
59
+
60
+ if (!data.defaultRequirement) {
61
+ throw new Error('No default requirement exists');
62
+ }
63
+
64
+ const { title, description, maxIterations } = updates;
65
+
66
+ if (title !== undefined) {
67
+ if (!title.trim()) {
68
+ throw new Error('Title cannot be empty');
69
+ }
70
+ data.defaultRequirement.title = title.trim();
71
+ }
72
+
73
+ if (description !== undefined) {
74
+ if (!description.trim()) {
75
+ throw new Error('Description cannot be empty');
76
+ }
77
+ data.defaultRequirement.description = description.trim();
78
+ }
79
+
80
+ if (maxIterations !== undefined) {
81
+ if (maxIterations < 1 || maxIterations > 1000) {
82
+ throw new Error('maxIterations must be between 1 and 1000');
83
+ }
84
+ data.defaultRequirement.maxIterations = maxIterations;
85
+ }
86
+
87
+ data.defaultRequirement.updatedAt = Date.now();
88
+ await this.storage.write(data);
89
+
90
+ return data.defaultRequirement;
91
+ }
92
+
93
+ /**
94
+ * Delete default requirement
95
+ */
96
+ async delete() {
97
+ const data = await this.storage.read();
98
+
99
+ if (!data.defaultRequirement) {
100
+ throw new Error('No default requirement exists');
101
+ }
102
+
103
+ data.defaultRequirement = null;
104
+ await this.storage.write(data);
105
+ }
106
+
107
+ /**
108
+ * Get current status of default requirement
109
+ * @returns {Object|null} Current status or null if no requirement
110
+ */
111
+ async getStatus() {
112
+ const data = await this.storage.read();
113
+ return data.defaultRequirement || null;
114
+ }
115
+
116
+ /**
117
+ * Check if default requirement should stop
118
+ * @returns {boolean} True if should stop
119
+ */
120
+ async shouldStop() {
121
+ const requirement = await this.getStatus();
122
+
123
+ if (!requirement) {
124
+ return true;
125
+ }
126
+
127
+ // Stop if status is DONE
128
+ if (requirement.status === 'DONE') {
129
+ return true;
130
+ }
131
+
132
+ // Stop if max iterations reached
133
+ if (requirement.iterationCount >= requirement.maxIterations) {
134
+ return true;
135
+ }
136
+
137
+ // Stop if consecutive failures threshold reached
138
+ if (requirement.consecutiveFailures >= this.consecutiveFailuresThreshold) {
139
+ return true;
140
+ }
141
+
142
+ return false;
143
+ }
144
+
145
+ /**
146
+ * Pause default requirement
147
+ */
148
+ async pause() {
149
+ const data = await this.storage.read();
150
+
151
+ if (!data.defaultRequirement) {
152
+ throw new Error('No default requirement exists');
153
+ }
154
+
155
+ if (data.defaultRequirement.status === 'PAUSED') {
156
+ return; // Already paused
157
+ }
158
+
159
+ data.defaultRequirement.status = 'PAUSED';
160
+ data.defaultRequirement.pausedAt = Date.now();
161
+ await this.storage.write(data);
162
+ }
163
+
164
+ /**
165
+ * Resume default requirement
166
+ */
167
+ async resume() {
168
+ const data = await this.storage.read();
169
+
170
+ if (!data.defaultRequirement) {
171
+ throw new Error('No default requirement exists');
172
+ }
173
+
174
+ if (data.defaultRequirement.status === 'ACTIVE') {
175
+ return; // Already active
176
+ }
177
+
178
+ data.defaultRequirement.status = 'ACTIVE';
179
+ data.defaultRequirement.resumedAt = Date.now();
180
+ await this.storage.write(data);
181
+ }
182
+
183
+ /**
184
+ * Increment iteration count
185
+ */
186
+ async incrementIteration() {
187
+ const data = await this.storage.read();
188
+
189
+ if (!data.defaultRequirement) {
190
+ throw new Error('No default requirement exists');
191
+ }
192
+
193
+ data.defaultRequirement.iterationCount += 1;
194
+ data.defaultRequirement.lastIterationAt = Date.now();
195
+
196
+ // Reset consecutive failures on successful iteration
197
+ data.defaultRequirement.consecutiveFailures = 0;
198
+
199
+ await this.storage.write(data);
200
+ }
201
+
202
+ /**
203
+ * Record a failure and increment consecutive failures
204
+ */
205
+ async recordFailure() {
206
+ const data = await this.storage.read();
207
+
208
+ if (!data.defaultRequirement) {
209
+ throw new Error('No default requirement exists');
210
+ }
211
+
212
+ data.defaultRequirement.consecutiveFailures += 1;
213
+ await this.storage.write(data);
214
+ }
215
+
216
+ /**
217
+ * Reset consecutive failures to 0
218
+ */
219
+ async resetFailures() {
220
+ const data = await this.storage.read();
221
+
222
+ if (!data.defaultRequirement) {
223
+ throw new Error('No default requirement exists');
224
+ }
225
+
226
+ data.defaultRequirement.consecutiveFailures = 0;
227
+ await this.storage.write(data);
228
+ }
229
+
230
+ /**
231
+ * Mark default requirement as done
232
+ * @param {string} reason - Reason for completion
233
+ */
234
+ async markDone(reason = 'Completed successfully') {
235
+ const data = await this.storage.read();
236
+
237
+ if (!data.defaultRequirement) {
238
+ throw new Error('No default requirement exists');
239
+ }
240
+
241
+ data.defaultRequirement.status = 'DONE';
242
+ data.defaultRequirement.completedAt = Date.now();
243
+ data.defaultRequirement.completionReason = reason;
244
+ await this.storage.write(data);
245
+ }
246
+
247
+ /**
248
+ * Get statistics for default requirement
249
+ * @returns {Object} Statistics
250
+ */
251
+ async getStatistics() {
252
+ const requirement = await this.getStatus();
253
+
254
+ if (!requirement) {
255
+ return null;
256
+ }
257
+
258
+ const now = Date.now();
259
+ const createdAt = requirement.createdAt;
260
+ const ageMs = now - createdAt;
261
+ const ageHours = Math.floor(ageMs / (1000 * 60 * 60));
262
+
263
+ const iterationsPerHour = requirement.iterationCount > 0 && ageHours > 0
264
+ ? (requirement.iterationCount / ageHours).toFixed(2)
265
+ : 0;
266
+
267
+ return {
268
+ title: requirement.title,
269
+ status: requirement.status,
270
+ iterations: requirement.iterationCount,
271
+ maxIterations: requirement.maxIterations,
272
+ consecutiveFailures: requirement.consecutiveFailures,
273
+ completionPercentage: Math.round((requirement.iterationCount / requirement.maxIterations) * 100),
274
+ ageHours,
275
+ iterationsPerHour,
276
+ createdAt: requirement.createdAt,
277
+ lastIterationAt: requirement.lastIterationAt,
278
+ ...(requirement.completedAt && { completedAt: requirement.completedAt }),
279
+ ...(requirement.completionReason && { completionReason: requirement.completionReason })
280
+ };
281
+ }
282
+
283
+ /**
284
+ * Validate default requirement data
285
+ * @param {Object} requirement - Requirement data to validate
286
+ * @returns {Object} Validation result
287
+ */
288
+ validate(requirement) {
289
+ const errors = [];
290
+
291
+ if (!requirement) {
292
+ errors.push('Requirement data is required');
293
+ return { valid: false, errors };
294
+ }
295
+
296
+ if (!requirement.title || typeof requirement.title !== 'string') {
297
+ errors.push('Title is required and must be a string');
298
+ }
299
+
300
+ if (!requirement.description || typeof requirement.description !== 'string') {
301
+ errors.push('Description is required and must be a string');
302
+ }
303
+
304
+ if (!requirement.maxIterations || typeof requirement.maxIterations !== 'number') {
305
+ errors.push('maxIterations is required and must be a number');
306
+ } else if (requirement.maxIterations < 1 || requirement.maxIterations > 1000) {
307
+ errors.push('maxIterations must be between 1 and 1000');
308
+ }
309
+
310
+ if (requirement.status && !['ACTIVE', 'PAUSED', 'DONE'].includes(requirement.status)) {
311
+ errors.push('Status must be one of: ACTIVE, PAUSED, DONE');
312
+ }
313
+
314
+ return {
315
+ valid: errors.length === 0,
316
+ errors
317
+ };
318
+ }
319
+ }
320
+
321
+ module.exports = { DefaultRequirementManager };
@@ -0,0 +1,159 @@
1
+ const fs = require('fs');
2
+
3
+ /**
4
+ * Parses REQUIREMENTS.md files to extract TODO, TO VERIFY, and VERIFIED sections
5
+ */
6
+ class RequirementFileParser {
7
+ constructor() {
8
+ this.sectionHeaders = {
9
+ TODO: /^##\s*TODO\s*$/mi,
10
+ 'TO VERIFY': /^##\s*TO\s+VERIFY\s*$/mi,
11
+ VERIFIED: /^##\s*VERIFIED\s*$/mi
12
+ };
13
+ }
14
+
15
+ /**
16
+ * Parse a REQUIREMENTS.md file and extract items from each section
17
+ * @param {string} filePath - Path to the REQUIREMENTS.md file
18
+ * @returns {Object} Object with todo, toVerify, and verified arrays
19
+ */
20
+ parse(filePath) {
21
+ try {
22
+ const content = fs.readFileSync(filePath, 'utf8');
23
+ return this.parseContent(content);
24
+ } catch (error) {
25
+ throw new Error(`Failed to read requirements file: ${error.message}`);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Parse markdown content and extract requirement items
31
+ * @param {string} content - Markdown content
32
+ * @returns {Object} Object with todo, toVerify, and verified arrays
33
+ */
34
+ parseContent(content) {
35
+ const sections = {
36
+ todo: [],
37
+ toVerify: [],
38
+ verified: []
39
+ };
40
+
41
+ // Split content by section headers
42
+ const lines = content.split('\n');
43
+ let currentSection = null;
44
+ let currentIndentation = 0;
45
+
46
+ for (const line of lines) {
47
+ const trimmedLine = line.trim();
48
+
49
+ // Check for section headers
50
+ if (this.sectionHeaders.TODO.test(trimmedLine)) {
51
+ currentSection = 'todo';
52
+ currentIndentation = 0;
53
+ continue;
54
+ } else if (this.sectionHeaders['TO VERIFY'].test(trimmedLine)) {
55
+ currentSection = 'toVerify';
56
+ currentIndentation = 0;
57
+ continue;
58
+ } else if (this.sectionHeaders.VERIFIED.test(trimmedLine)) {
59
+ currentSection = 'verified';
60
+ currentIndentation = 0;
61
+ continue;
62
+ }
63
+
64
+ // Skip if not in a section
65
+ if (!currentSection) {
66
+ continue;
67
+ }
68
+
69
+ // Parse list items
70
+ const listItemMatch = line.match(/^(\s*)- \[([ x])\]\s*(.+)$/);
71
+ if (listItemMatch) {
72
+ const [, indentation, checkbox, itemText] = listItemMatch;
73
+
74
+ // Only include items at the current indentation level (skip sub-bullets)
75
+ if (indentation.length <= currentIndentation || currentIndentation === 0) {
76
+ currentIndentation = indentation.length;
77
+ // Preserve original text formatting (don't clean markdown)
78
+ sections[currentSection].push(itemText);
79
+ }
80
+ }
81
+ }
82
+
83
+ return sections;
84
+ }
85
+
86
+ /**
87
+ * Clean item text by removing markdown formatting
88
+ * @param {string} text - Raw item text
89
+ * @returns {string} Cleaned text
90
+ */
91
+ cleanItemText(text) {
92
+ return text
93
+ // Remove bold formatting
94
+ .replace(/\*\*(.*?)\*\*/g, '$1')
95
+ // Remove italic formatting
96
+ .replace(/\*(.*?)\*/g, '$1')
97
+ // Remove inline code formatting
98
+ .replace(/`(.*?)`/g, '$1')
99
+ // Remove links but keep text
100
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
101
+ // Remove block quotes
102
+ .replace(/^>\s+/gm, '')
103
+ // Trim whitespace
104
+ .trim();
105
+ }
106
+
107
+ /**
108
+ * Check if there are regular requirements (TODO or TO VERIFY items)
109
+ * @param {Object} parsedData - Parsed requirement data
110
+ * @returns {boolean} True if regular requirements exist
111
+ */
112
+ hasRegularRequirements(parsedData) {
113
+ return parsedData.todo.length > 0 || parsedData.toVerify.length > 0;
114
+ }
115
+
116
+ /**
117
+ * Get completion status for requirements
118
+ * @param {Object} parsedData - Parsed requirement data
119
+ * @returns {Object} Completion statistics
120
+ */
121
+ getCompletionStatus(parsedData) {
122
+ const total = parsedData.todo.length + parsedData.toVerify.length + parsedData.verified.length;
123
+ const completed = parsedData.verified.length;
124
+ const remaining = parsedData.todo.length + parsedData.toVerify.length;
125
+ const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
126
+
127
+ return {
128
+ total,
129
+ completed,
130
+ remaining,
131
+ percentage
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Validate parsed data structure
137
+ * @param {Object} data - Parsed data to validate
138
+ * @returns {boolean} True if data is valid
139
+ */
140
+ validateParsedData(data) {
141
+ return data &&
142
+ typeof data === 'object' &&
143
+ Array.isArray(data.todo) &&
144
+ Array.isArray(data.toVerify) &&
145
+ Array.isArray(data.verified);
146
+ }
147
+
148
+ /**
149
+ * Get summary of parsed requirements
150
+ * @param {Object} parsedData - Parsed requirement data
151
+ * @returns {string} Human-readable summary
152
+ */
153
+ getSummary(parsedData) {
154
+ const status = this.getCompletionStatus(parsedData);
155
+ return `Requirements: ${status.completed}/${status.total} complete (${status.percentage}%)`;
156
+ }
157
+ }
158
+
159
+ module.exports = { RequirementFileParser };
@@ -0,0 +1,221 @@
1
+ const RequirementFileParser = require('./requirement-file-parser');
2
+
3
+ /**
4
+ * Manages the sequencing and lifecycle of default requirements vs regular requirements
5
+ */
6
+ class RequirementSequencer {
7
+ constructor(parser, defaultManager) {
8
+ this.parser = parser;
9
+ this.defaultManager = defaultManager;
10
+ }
11
+
12
+ /**
13
+ * Determine if default requirement should be processed
14
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
15
+ * @returns {boolean} True if default requirement should be processed
16
+ */
17
+ async shouldProcessDefault(requirementsPath) {
18
+ try {
19
+ // Check if regular requirements exist
20
+ const parsedData = this.parser.parse(requirementsPath);
21
+ const hasRegular = this.parser.hasRegularRequirements(parsedData);
22
+
23
+ if (hasRegular) {
24
+ return false;
25
+ }
26
+
27
+ // Check if default requirement exists and is active
28
+ const defaultStatus = await this.defaultManager.getStatus();
29
+ return defaultStatus && defaultStatus.status !== 'DONE';
30
+ } catch (error) {
31
+ console.error('Error checking if should process default:', error);
32
+ return false;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Handle the case when regular requirements are added
38
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
39
+ */
40
+ async handleRegularRequirementsAdded(requirementsPath) {
41
+ try {
42
+ const defaultStatus = await this.defaultManager.getStatus();
43
+
44
+ if (defaultStatus && defaultStatus.status === 'ACTIVE') {
45
+ await this.defaultManager.pause();
46
+ console.log('Default requirement paused due to new regular requirements');
47
+ }
48
+ } catch (error) {
49
+ console.error('Error handling regular requirements added:', error);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Handle the case when regular requirements are completed
55
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
56
+ */
57
+ async handleRegularRequirementsComplete(requirementsPath) {
58
+ try {
59
+ const defaultStatus = await this.defaultManager.getStatus();
60
+
61
+ if (defaultStatus && defaultStatus.status === 'PAUSED') {
62
+ await this.defaultManager.resume();
63
+ console.log('Default requirement resumed after regular requirements completed');
64
+ }
65
+ } catch (error) {
66
+ console.error('Error handling regular requirements completed:', error);
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Check for changes in requirements between two states
72
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
73
+ * @param {Object} previousData - Previous parsed data
74
+ * @returns {Object} Change information
75
+ */
76
+ async checkRequirementsChange(requirementsPath, previousData) {
77
+ try {
78
+ const currentData = this.parser.parse(requirementsPath);
79
+
80
+ const previousHasRegular = this.parser.hasRegularRequirements(previousData);
81
+ const currentHasRegular = this.parser.hasRegularRequirements(currentData);
82
+
83
+ const regularRequirementsAdded = !previousHasRegular && currentHasRegular;
84
+ const regularRequirementsCompleted = previousHasRegular && !currentHasRegular;
85
+
86
+ return {
87
+ regularRequirementsAdded,
88
+ regularRequirementsCompleted,
89
+ previousData,
90
+ currentData
91
+ };
92
+ } catch (error) {
93
+ console.error('Error checking requirements change:', error);
94
+ return {
95
+ regularRequirementsAdded: false,
96
+ regularRequirementsCompleted: false,
97
+ previousData,
98
+ currentData: null
99
+ };
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get processing priority (regular vs default)
105
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
106
+ * @returns {string} 'regular', 'default', or 'none'
107
+ */
108
+ async getProcessingPriority(requirementsPath) {
109
+ try {
110
+ const parsedData = this.parser.parse(requirementsPath);
111
+ const hasRegular = this.parser.hasRegularRequirements(parsedData);
112
+
113
+ if (hasRegular) {
114
+ return 'regular';
115
+ }
116
+
117
+ const defaultStatus = await this.defaultManager.getStatus();
118
+ if (defaultStatus && defaultStatus.status !== 'DONE') {
119
+ return 'default';
120
+ }
121
+
122
+ return 'none';
123
+ } catch (error) {
124
+ console.error('Error getting processing priority:', error);
125
+ return 'none';
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Monitor requirements file for changes and handle sequencing
131
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
132
+ * @param {Function} onChange - Callback for changes
133
+ * @returns {Function} Stop monitoring function
134
+ */
135
+ monitorRequirements(requirementsPath, onChange) {
136
+ let previousData = null;
137
+
138
+ try {
139
+ previousData = this.parser.parse(requirementsPath);
140
+ } catch (error) {
141
+ console.error('Error initial parsing of requirements:', error);
142
+ }
143
+
144
+ const checkInterval = setInterval(async () => {
145
+ try {
146
+ const change = await this.checkRequirementsChange(requirementsPath, previousData);
147
+
148
+ if (change.regularRequirementsAdded) {
149
+ await this.handleRegularRequirementsAdded(requirementsPath);
150
+ if (onChange) onChange('regular-requirements-added', change);
151
+ } else if (change.regularRequirementsCompleted) {
152
+ await this.handleRegularRequirementsComplete(requirementsPath);
153
+ if (onChange) onChange('regular-requirements-completed', change);
154
+ }
155
+
156
+ previousData = change.currentData || previousData;
157
+ } catch (error) {
158
+ console.error('Error in requirements monitoring:', error);
159
+ }
160
+ }, 5000); // Check every 5 seconds
161
+
162
+ return () => clearInterval(checkInterval);
163
+ }
164
+
165
+ /**
166
+ * Get the current state of requirements
167
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
168
+ * @returns {Object} Current state
169
+ */
170
+ async getCurrentState(requirementsPath) {
171
+ try {
172
+ const parsedData = this.parser.parse(requirementsPath);
173
+ const defaultStatus = await this.defaultManager.getStatus();
174
+ const completionStatus = this.parser.getCompletionStatus(parsedData);
175
+
176
+ return {
177
+ hasRegularRequirements: this.parser.hasRegularRequirements(parsedData),
178
+ regularRequirements: parsedData.todo.length + parsedData.toVerify.length,
179
+ completedRequirements: parsedData.verified.length,
180
+ completionPercentage: completionStatus.percentage,
181
+ defaultRequirement: defaultStatus,
182
+ processingPriority: await this.getProcessingPriority(requirementsPath)
183
+ };
184
+ } catch (error) {
185
+ console.error('Error getting current state:', error);
186
+ return null;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Determine if auto mode should continue running
192
+ * @param {string} requirementsPath - Path to REQUIREMENTS.md
193
+ * @returns {boolean} True if auto mode should continue
194
+ */
195
+ async shouldContinueAutoMode(requirementsPath) {
196
+ try {
197
+ const state = await this.getCurrentState(requirementsPath);
198
+
199
+ if (!state) {
200
+ return false;
201
+ }
202
+
203
+ // Continue if there are regular requirements
204
+ if (state.hasRegularRequirements) {
205
+ return true;
206
+ }
207
+
208
+ // Continue if default requirement is active
209
+ if (state.defaultRequirement && state.defaultRequirement.status === 'ACTIVE') {
210
+ return true;
211
+ }
212
+
213
+ return false;
214
+ } catch (error) {
215
+ console.error('Error determining if should continue auto mode:', error);
216
+ return false;
217
+ }
218
+ }
219
+ }
220
+
221
+ module.exports = RequirementSequencer;