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.
- package/README.md +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- 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;
|