specweave 0.23.2 → 0.23.4
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/CLAUDE.md +268 -0
- package/dist/plugins/specweave/lib/utils/fs-native.d.ts +133 -0
- package/dist/plugins/specweave/lib/utils/fs-native.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/utils/fs-native.js +224 -0
- package/dist/plugins/specweave/lib/utils/fs-native.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.js +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +52 -20
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js +2 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
- package/dist/src/core/ac-test-validator-cli.d.ts +16 -0
- package/dist/src/core/ac-test-validator-cli.d.ts.map +1 -0
- package/dist/src/core/ac-test-validator-cli.js +118 -0
- package/dist/src/core/ac-test-validator-cli.js.map +1 -0
- package/dist/src/core/ac-test-validator.d.ts +111 -0
- package/dist/src/core/ac-test-validator.d.ts.map +1 -0
- package/dist/src/core/ac-test-validator.js +292 -0
- package/dist/src/core/ac-test-validator.js.map +1 -0
- package/dist/src/core/increment/desync-detector.d.ts +142 -0
- package/dist/src/core/increment/desync-detector.d.ts.map +1 -0
- package/dist/src/core/increment/desync-detector.js +270 -0
- package/dist/src/core/increment/desync-detector.js.map +1 -0
- package/dist/src/core/increment/metadata-manager.d.ts +8 -4
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +45 -21
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/qa/qa-runner.js +9 -2
- package/dist/src/core/qa/qa-runner.js.map +1 -1
- package/dist/src/sync/sync-coordinator.d.ts +1 -1
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +40 -2
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/utils/fs-native.d.ts +133 -0
- package/dist/src/utils/fs-native.d.ts.map +1 -0
- package/dist/src/utils/fs-native.js +224 -0
- package/dist/src/utils/fs-native.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +12 -0
- package/plugins/specweave/agents/AGENTS-INDEX.md +216 -0
- package/plugins/specweave/agents/architect/AGENT.md +17 -0
- package/plugins/specweave/agents/code-standards-detective/AGENT.md +16 -0
- package/plugins/specweave/agents/docs-writer/AGENT.md +16 -0
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +704 -0
- package/plugins/specweave/agents/infrastructure/AGENT.md +16 -0
- package/plugins/specweave/agents/performance/AGENT.md +16 -0
- package/plugins/specweave/agents/pm/AGENT.md +17 -0
- package/plugins/specweave/agents/qa-lead/AGENT.md +15 -0
- package/plugins/specweave/agents/reflective-reviewer/AGENT.md +16 -0
- package/plugins/specweave/agents/security/AGENT.md +16 -0
- package/plugins/specweave/agents/tdd-orchestrator/AGENT.md +16 -0
- package/plugins/specweave/agents/tech-lead/AGENT.md +16 -0
- package/plugins/specweave/agents/test-aware-planner/AGENT.md +16 -0
- package/plugins/specweave/agents/translator/AGENT.md +13 -0
- package/plugins/specweave/commands/specweave-done.md +14 -0
- package/plugins/specweave/commands/specweave-qa.md +11 -1
- package/plugins/specweave/commands/specweave-sync-status.md +356 -0
- package/plugins/specweave/commands/specweave-validate.md +10 -1
- package/plugins/specweave/hooks/pre-task-completion.sh +196 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.js +3 -3
- package/plugins/specweave/lib/hooks/git-diff-analyzer.ts +3 -3
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js +3 -2
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +3 -2
- package/plugins/specweave/lib/hooks/prepare-reflection-context.js +3 -3
- package/plugins/specweave/lib/hooks/prepare-reflection-context.ts +3 -3
- package/plugins/specweave/lib/hooks/reflection-config-loader.js +4 -4
- package/plugins/specweave/lib/hooks/reflection-config-loader.ts +4 -4
- package/plugins/specweave/lib/hooks/reflection-storage.js +9 -9
- package/plugins/specweave/lib/hooks/reflection-storage.ts +9 -9
- package/plugins/specweave/lib/hooks/sync-cache.js +9 -8
- package/plugins/specweave/lib/hooks/sync-living-docs.js +57 -6
- package/plugins/specweave/lib/hooks/sync-us-tasks.js +6 -6
- package/plugins/specweave/lib/hooks/translate-file.js +3 -2
- package/plugins/specweave/lib/hooks/translate-file.ts +3 -2
- package/plugins/specweave/lib/hooks/translate-living-docs.js +4 -3
- package/plugins/specweave/lib/hooks/translate-living-docs.ts +4 -3
- package/plugins/specweave/lib/utils/fs-native.js +182 -0
- package/plugins/specweave/lib/utils/fs-native.ts +283 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +8 -4
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +45 -21
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
- package/plugins/specweave/skills/SKILLS-INDEX.md +26 -2
- package/plugins/specweave/skills/increment-planner/SKILL.md +2 -2
- package/plugins/specweave-ado/commands/specweave-ado-close-workitem.md +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-create-workitem.md +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-status.md +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-sync.md +1 -1
- package/plugins/specweave-diagrams/agents/diagrams-architect/AGENT.md +1 -1
- package/plugins/specweave-diagrams/skills/diagrams-generator/SKILL.md +4 -4
- package/plugins/specweave-github/lib/github-client-v2.js +2 -1
- package/plugins/specweave-github/lib/github-client-v2.ts +1 -1
- package/plugins/specweave-github/lib/github-feature-sync.js +30 -17
- package/plugins/specweave-github/lib/github-feature-sync.ts +54 -24
- package/plugins/specweave-mobile/README.md +1 -1
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +72 -0
- package/plugins/specweave/skills/task-builder/README.md +0 -84
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AC Test Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates that all Acceptance Criteria linked to a task have passing tests
|
|
5
|
+
* before allowing the task to be marked complete.
|
|
6
|
+
*
|
|
7
|
+
* **CRITICAL QUALITY GATE**: This is the enforcement point that prevents
|
|
8
|
+
* tasks from being marked complete without validated ACs.
|
|
9
|
+
*
|
|
10
|
+
* Workflow:
|
|
11
|
+
* 1. Task completion requested via TodoWrite
|
|
12
|
+
* 2. Validator extracts task's satisfiesACs field
|
|
13
|
+
* 3. Validator finds corresponding test files from Test Plan section
|
|
14
|
+
* 4. Validator runs tests using configured test runner (vitest/jest)
|
|
15
|
+
* 5. If ALL tests pass → Allow completion, auto-check ACs in spec.md
|
|
16
|
+
* 6. If ANY test fails → Block completion, show detailed error
|
|
17
|
+
*/
|
|
18
|
+
import { exec } from 'child_process';
|
|
19
|
+
import { promisify } from 'util';
|
|
20
|
+
import path from 'path';
|
|
21
|
+
import fs from 'fs-extra';
|
|
22
|
+
import chalk from 'chalk';
|
|
23
|
+
const execAsync = promisify(exec);
|
|
24
|
+
/**
|
|
25
|
+
* AC Test Validator - Core validation engine
|
|
26
|
+
*/
|
|
27
|
+
export class ACTestValidator {
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = {
|
|
30
|
+
timeout: 30000, // 30 second default timeout
|
|
31
|
+
...config
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate all ACs for a task have passing tests
|
|
36
|
+
*
|
|
37
|
+
* @param task - Task to validate (must have satisfiesACs field)
|
|
38
|
+
* @param projectRoot - Project root directory
|
|
39
|
+
* @returns Validation result
|
|
40
|
+
*/
|
|
41
|
+
async validateTask(task, projectRoot) {
|
|
42
|
+
const startTime = Date.now();
|
|
43
|
+
// Initialize result
|
|
44
|
+
const result = {
|
|
45
|
+
passed: false,
|
|
46
|
+
taskId: task.id,
|
|
47
|
+
acIds: task.satisfiesACs || [],
|
|
48
|
+
testResults: new Map(),
|
|
49
|
+
summary: {
|
|
50
|
+
totalACs: 0,
|
|
51
|
+
acsTested: 0,
|
|
52
|
+
acsUntested: 0,
|
|
53
|
+
testsPassed: 0,
|
|
54
|
+
testsFailed: 0
|
|
55
|
+
},
|
|
56
|
+
errors: []
|
|
57
|
+
};
|
|
58
|
+
// Check if task has ACs to validate
|
|
59
|
+
if (!task.satisfiesACs || task.satisfiesACs.length === 0) {
|
|
60
|
+
result.errors.push(`Task ${task.id} has no Acceptance Criteria linked (satisfiesACs field missing or empty)`);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
result.summary.totalACs = task.satisfiesACs.length;
|
|
64
|
+
// Extract test file from task's Test Plan section
|
|
65
|
+
const testFile = this.extractTestFile(task);
|
|
66
|
+
if (!testFile) {
|
|
67
|
+
result.errors.push(`Task ${task.id} has no Test Plan section or test file specified`);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
// Check test file exists
|
|
71
|
+
const testFilePath = path.join(projectRoot, testFile);
|
|
72
|
+
if (!await fs.pathExists(testFilePath)) {
|
|
73
|
+
result.errors.push(`Test file not found: ${testFile}`);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
// Run tests for each AC
|
|
77
|
+
for (const acId of task.satisfiesACs) {
|
|
78
|
+
const acTestResult = await this.validateAC(acId, testFile, projectRoot);
|
|
79
|
+
result.testResults.set(acId, acTestResult);
|
|
80
|
+
if (acTestResult.passed) {
|
|
81
|
+
result.summary.acsTested++;
|
|
82
|
+
result.summary.testsPassed++;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
result.summary.acsUntested++;
|
|
86
|
+
result.summary.testsFailed++;
|
|
87
|
+
result.errors.push(`AC ${acId} tests failed: ${acTestResult.error || 'Unknown error'}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Overall pass/fail
|
|
91
|
+
result.passed = result.summary.testsFailed === 0 && result.summary.acsTested === result.summary.totalACs;
|
|
92
|
+
const duration = Date.now() - startTime;
|
|
93
|
+
console.log(`\n${chalk.blue('[AC Test Validator]')} Validated task ${task.id} in ${duration}ms`);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Validate a single AC has passing tests
|
|
98
|
+
*/
|
|
99
|
+
async validateAC(acId, testFile, projectRoot) {
|
|
100
|
+
const startTime = Date.now();
|
|
101
|
+
const result = {
|
|
102
|
+
acId,
|
|
103
|
+
testFile,
|
|
104
|
+
testCases: [],
|
|
105
|
+
passed: false,
|
|
106
|
+
duration: 0
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
// Run test file with filter for AC-ID
|
|
110
|
+
// Most test runners support filtering: vitest -t "AC-US1-01", jest --testNamePattern="AC-US1-01"
|
|
111
|
+
const command = this.buildTestCommand(testFile, acId);
|
|
112
|
+
console.log(` ${chalk.gray('Running:')} ${command}`);
|
|
113
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
114
|
+
cwd: this.config.cwd,
|
|
115
|
+
env: { ...process.env, ...this.config.env },
|
|
116
|
+
timeout: this.config.timeout
|
|
117
|
+
});
|
|
118
|
+
// Parse test output (basic implementation - can be enhanced)
|
|
119
|
+
const output = stdout + stderr;
|
|
120
|
+
result.testCases = this.extractTestCases(output, acId);
|
|
121
|
+
// Check for test failures
|
|
122
|
+
const hasFailures = output.includes('FAIL') ||
|
|
123
|
+
output.includes('failed') ||
|
|
124
|
+
output.includes('✗') ||
|
|
125
|
+
output.includes('0 passed');
|
|
126
|
+
result.passed = !hasFailures && result.testCases.length > 0;
|
|
127
|
+
if (!result.passed) {
|
|
128
|
+
result.error = this.extractFailureMessage(output);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
result.passed = false;
|
|
133
|
+
result.error = error.message || 'Test execution failed';
|
|
134
|
+
// Check if it's a timeout
|
|
135
|
+
if (error.killed && error.signal === 'SIGTERM') {
|
|
136
|
+
result.error = `Test timeout (exceeded ${this.config.timeout}ms)`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
result.duration = Date.now() - startTime;
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Build test command with AC-ID filter
|
|
144
|
+
*/
|
|
145
|
+
buildTestCommand(testFile, acId) {
|
|
146
|
+
// Detect test runner from config command
|
|
147
|
+
const command = this.config.command.toLowerCase();
|
|
148
|
+
if (command.includes('vitest')) {
|
|
149
|
+
// Vitest: vitest run <file> -t "AC-US1-01"
|
|
150
|
+
return `${this.config.command} ${testFile} -t "${acId}"`;
|
|
151
|
+
}
|
|
152
|
+
else if (command.includes('jest')) {
|
|
153
|
+
// Jest: jest <file> --testNamePattern="AC-US1-01"
|
|
154
|
+
return `${this.config.command} ${testFile} --testNamePattern="${acId}"`;
|
|
155
|
+
}
|
|
156
|
+
else if (command.includes('npm test')) {
|
|
157
|
+
// NPM script - try to pass args
|
|
158
|
+
return `${this.config.command} -- ${testFile} -t "${acId}"`;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Default: assume vitest-style
|
|
162
|
+
return `${this.config.command} ${testFile} -t "${acId}"`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Extract test case names from test output
|
|
167
|
+
*/
|
|
168
|
+
extractTestCases(output, acId) {
|
|
169
|
+
const testCases = [];
|
|
170
|
+
// Look for lines containing the AC-ID and test indicators
|
|
171
|
+
const lines = output.split('\n');
|
|
172
|
+
for (const line of lines) {
|
|
173
|
+
if (line.includes(acId) && (line.includes('✓') || line.includes('PASS') || line.includes('√'))) {
|
|
174
|
+
// Extract test name (basic heuristic)
|
|
175
|
+
const match = line.match(/✓\s+(.+)/) || line.match(/PASS\s+(.+)/);
|
|
176
|
+
if (match) {
|
|
177
|
+
testCases.push(match[1].trim());
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return testCases;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Extract failure message from test output
|
|
185
|
+
*/
|
|
186
|
+
extractFailureMessage(output) {
|
|
187
|
+
const lines = output.split('\n');
|
|
188
|
+
// Find first error/failure message
|
|
189
|
+
for (let i = 0; i < lines.length; i++) {
|
|
190
|
+
const line = lines[i];
|
|
191
|
+
if (line.includes('FAIL') || line.includes('✗') || line.includes('Error:')) {
|
|
192
|
+
// Collect next few lines for context
|
|
193
|
+
const errorLines = lines.slice(i, i + 5).join('\n');
|
|
194
|
+
return errorLines.substring(0, 200); // Truncate long messages
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Fallback: return last few lines
|
|
198
|
+
return lines.slice(-5).join('\n');
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Extract test file path from task description (Test Plan section)
|
|
202
|
+
*/
|
|
203
|
+
extractTestFile(task) {
|
|
204
|
+
if (!task.description)
|
|
205
|
+
return null;
|
|
206
|
+
// Look for Test Plan section with file path
|
|
207
|
+
// Format: **Test Plan**:
|
|
208
|
+
// - **File**: `tests/unit/component.test.ts`
|
|
209
|
+
const testFileRegex = /\*\*File\*\*:\s*`([^`]+)`/;
|
|
210
|
+
const match = task.description.match(testFileRegex);
|
|
211
|
+
return match ? match[1] : null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Format validation result for display
|
|
215
|
+
*/
|
|
216
|
+
formatResult(result) {
|
|
217
|
+
const lines = [];
|
|
218
|
+
lines.push(chalk.bold(`\nAC Test Validation: ${result.taskId}`));
|
|
219
|
+
lines.push(chalk.gray('─'.repeat(60)));
|
|
220
|
+
// Summary
|
|
221
|
+
lines.push(chalk.bold('Summary:'));
|
|
222
|
+
lines.push(` Total ACs: ${result.summary.totalACs}`);
|
|
223
|
+
lines.push(` ACs Tested: ${chalk.green(result.summary.acsTested)}`);
|
|
224
|
+
lines.push(` ACs Untested: ${chalk.red(result.summary.acsUntested)}`);
|
|
225
|
+
lines.push(` Tests Passed: ${chalk.green(result.summary.testsPassed)}`);
|
|
226
|
+
lines.push(` Tests Failed: ${chalk.red(result.summary.testsFailed)}`);
|
|
227
|
+
// Overall status
|
|
228
|
+
lines.push('');
|
|
229
|
+
if (result.passed) {
|
|
230
|
+
lines.push(chalk.green.bold('✓ VALIDATION PASSED'));
|
|
231
|
+
lines.push(chalk.green('All Acceptance Criteria have passing tests. Task can be marked complete.'));
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
lines.push(chalk.red.bold('✗ VALIDATION FAILED'));
|
|
235
|
+
lines.push(chalk.red('Task cannot be marked complete until all AC tests pass.'));
|
|
236
|
+
}
|
|
237
|
+
// Errors
|
|
238
|
+
if (result.errors.length > 0) {
|
|
239
|
+
lines.push('');
|
|
240
|
+
lines.push(chalk.bold('Errors:'));
|
|
241
|
+
result.errors.forEach(error => {
|
|
242
|
+
lines.push(chalk.red(` • ${error}`));
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
// Test details
|
|
246
|
+
if (result.testResults.size > 0) {
|
|
247
|
+
lines.push('');
|
|
248
|
+
lines.push(chalk.bold('Test Results:'));
|
|
249
|
+
result.testResults.forEach((acResult, acId) => {
|
|
250
|
+
const icon = acResult.passed ? chalk.green('✓') : chalk.red('✗');
|
|
251
|
+
const status = acResult.passed ? chalk.green('PASSED') : chalk.red('FAILED');
|
|
252
|
+
lines.push(` ${icon} ${acId}: ${status} (${acResult.duration}ms)`);
|
|
253
|
+
if (acResult.testCases.length > 0) {
|
|
254
|
+
acResult.testCases.forEach(testCase => {
|
|
255
|
+
lines.push(chalk.gray(` - ${testCase}`));
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
if (acResult.error) {
|
|
259
|
+
lines.push(chalk.red(` Error: ${acResult.error}`));
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
lines.push(chalk.gray('─'.repeat(60)));
|
|
264
|
+
return lines.join('\n');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Create AC test validator from project config
|
|
269
|
+
*/
|
|
270
|
+
export async function createACTestValidator(projectRoot) {
|
|
271
|
+
// Read test configuration from package.json or specweave config
|
|
272
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
273
|
+
let testCommand = 'npm test';
|
|
274
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
275
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
276
|
+
// Detect test runner
|
|
277
|
+
if (packageJson.devDependencies?.vitest || packageJson.dependencies?.vitest) {
|
|
278
|
+
testCommand = 'npx vitest run';
|
|
279
|
+
}
|
|
280
|
+
else if (packageJson.devDependencies?.jest || packageJson.dependencies?.jest) {
|
|
281
|
+
testCommand = 'npx jest';
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const config = {
|
|
285
|
+
command: testCommand,
|
|
286
|
+
pattern: 'tests/**/*.test.ts',
|
|
287
|
+
cwd: projectRoot,
|
|
288
|
+
timeout: 30000
|
|
289
|
+
};
|
|
290
|
+
return new ACTestValidator(config);
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=ac-test-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ac-test-validator.js","sourceRoot":"","sources":["../../../src/core/ac-test-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DesyncDetector - Detect and fix status desyncs between metadata.json and spec.md
|
|
3
|
+
*
|
|
4
|
+
* Prevents silent failures by validating source-of-truth consistency.
|
|
5
|
+
* Critical for maintaining data integrity across increment lifecycle.
|
|
6
|
+
*
|
|
7
|
+
* Incident Reference: 2025-11-20 - Silent failure in /specweave:done caused
|
|
8
|
+
* increment 0047 to have metadata.json="completed" while spec.md="active",
|
|
9
|
+
* breaking status line and user trust.
|
|
10
|
+
*
|
|
11
|
+
* CLAUDE.md Rule #7: spec.md and metadata.json are BOTH source of truth and MUST stay in sync.
|
|
12
|
+
*/
|
|
13
|
+
import { IncrementStatus } from '../types/increment-metadata.js';
|
|
14
|
+
import { Logger } from '../../utils/logger.js';
|
|
15
|
+
/**
|
|
16
|
+
* Desync detection result for a single increment
|
|
17
|
+
*/
|
|
18
|
+
export interface DesyncResult {
|
|
19
|
+
incrementId: string;
|
|
20
|
+
hasDesync: boolean;
|
|
21
|
+
metadataStatus: IncrementStatus | null;
|
|
22
|
+
specStatus: IncrementStatus | null;
|
|
23
|
+
metadataPath: string;
|
|
24
|
+
specPath: string;
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Desync scan report for multiple increments
|
|
29
|
+
*/
|
|
30
|
+
export interface DesyncScanReport {
|
|
31
|
+
totalScanned: number;
|
|
32
|
+
totalDesyncs: number;
|
|
33
|
+
desyncs: DesyncResult[];
|
|
34
|
+
healthy: string[];
|
|
35
|
+
errors: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Options for desync detection
|
|
39
|
+
*/
|
|
40
|
+
export interface DesyncDetectorOptions {
|
|
41
|
+
logger?: Logger;
|
|
42
|
+
projectRoot?: string;
|
|
43
|
+
autoFix?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* DesyncDetector - Validates status consistency between metadata.json and spec.md
|
|
47
|
+
*
|
|
48
|
+
* Key Features:
|
|
49
|
+
* - Detects status desyncs across all increments
|
|
50
|
+
* - Provides detailed desync reports
|
|
51
|
+
* - Auto-fix capability (optional)
|
|
52
|
+
* - Validates before critical operations
|
|
53
|
+
*
|
|
54
|
+
* Usage:
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // Check single increment
|
|
57
|
+
* const detector = new DesyncDetector();
|
|
58
|
+
* const result = await detector.checkIncrement('0047-us-task-linkage');
|
|
59
|
+
* if (result.hasDesync) {
|
|
60
|
+
* console.error('Desync detected!', result);
|
|
61
|
+
* }
|
|
62
|
+
*
|
|
63
|
+
* // Scan all increments
|
|
64
|
+
* const report = await detector.scanAll();
|
|
65
|
+
* console.log(`Found ${report.totalDesyncs} desyncs`);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare class DesyncDetector {
|
|
69
|
+
private logger;
|
|
70
|
+
private projectRoot;
|
|
71
|
+
constructor(options?: DesyncDetectorOptions);
|
|
72
|
+
/**
|
|
73
|
+
* Check single increment for status desync
|
|
74
|
+
*
|
|
75
|
+
* @param incrementId - Increment ID (e.g., "0047-us-task-linkage")
|
|
76
|
+
* @returns Desync result with detailed status info
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const result = await detector.checkIncrement('0047-us-task-linkage');
|
|
81
|
+
* if (result.hasDesync) {
|
|
82
|
+
* console.error(`Desync: metadata=${result.metadataStatus}, spec=${result.specStatus}`);
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
checkIncrement(incrementId: string): Promise<DesyncResult>;
|
|
87
|
+
/**
|
|
88
|
+
* Scan all increments for desyncs
|
|
89
|
+
*
|
|
90
|
+
* @returns Comprehensive scan report
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const report = await detector.scanAll();
|
|
95
|
+
* console.log(`Scanned ${report.totalScanned} increments`);
|
|
96
|
+
* console.log(`Found ${report.totalDesyncs} desyncs`);
|
|
97
|
+
* report.desyncs.forEach(d => console.error(`- ${d.incrementId}`));
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
scanAll(): Promise<DesyncScanReport>;
|
|
101
|
+
/**
|
|
102
|
+
* Fix desync by updating spec.md to match metadata.json (source of truth for status)
|
|
103
|
+
*
|
|
104
|
+
* IMPORTANT: metadata.json is considered the source of truth because it's updated
|
|
105
|
+
* atomically and used by the CLI. spec.md should mirror it.
|
|
106
|
+
*
|
|
107
|
+
* @param incrementId - Increment ID to fix
|
|
108
|
+
* @returns true if fixed successfully, false if no desync or fix failed
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const fixed = await detector.fixDesync('0047-us-task-linkage');
|
|
113
|
+
* if (fixed) {
|
|
114
|
+
* console.log('Desync fixed!');
|
|
115
|
+
* }
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
fixDesync(incrementId: string): Promise<boolean>;
|
|
119
|
+
/**
|
|
120
|
+
* Validate increment has no desync, throw if found
|
|
121
|
+
*
|
|
122
|
+
* Use this before critical operations (e.g., closing increment, archiving)
|
|
123
|
+
*
|
|
124
|
+
* @param incrementId - Increment ID to validate
|
|
125
|
+
* @throws Error if desync detected
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* await detector.validateOrThrow('0047-us-task-linkage');
|
|
130
|
+
* // Throws if desync found, continues if healthy
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
validateOrThrow(incrementId: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Generate human-readable report for desyncs
|
|
136
|
+
*
|
|
137
|
+
* @param report - Scan report
|
|
138
|
+
* @returns Formatted report string
|
|
139
|
+
*/
|
|
140
|
+
formatReport(report: DesyncScanReport): string;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=desync-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desync-detector.d.ts","sourceRoot":"","sources":["../../../../src/core/increment/desync-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,eAAe,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,qBAA0B;IAK/C;;;;;;;;;;;;;OAaG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA4DhE;;;;;;;;;;;;OAYG;IACG,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAwC1C;;;;;;;;;;;;;;;;OAgBG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyCtD;;;;;;;;;;;;;OAaG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBzD;;;;;OAKG;IACH,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM;CAoD/C"}
|