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,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
|
+
};
|