specweave 0.22.2 → 0.22.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 +300 -920
- package/dist/src/cli/commands/repair-status-desync.d.ts +69 -0
- package/dist/src/cli/commands/repair-status-desync.d.ts.map +1 -0
- package/dist/src/cli/commands/repair-status-desync.js +221 -0
- package/dist/src/cli/commands/repair-status-desync.js.map +1 -0
- package/dist/src/cli/commands/sync-specs.d.ts +4 -1
- package/dist/src/cli/commands/sync-specs.d.ts.map +1 -1
- package/dist/src/cli/commands/sync-specs.js +99 -49
- package/dist/src/cli/commands/sync-specs.js.map +1 -1
- package/dist/src/cli/commands/validate-status-sync.d.ts +52 -0
- package/dist/src/cli/commands/validate-status-sync.d.ts.map +1 -0
- package/dist/src/cli/commands/validate-status-sync.js +176 -0
- package/dist/src/cli/commands/validate-status-sync.js.map +1 -0
- package/dist/src/cli/update-status-line.d.ts +16 -0
- package/dist/src/cli/update-status-line.d.ts.map +1 -0
- package/dist/src/cli/update-status-line.js +44 -0
- package/dist/src/cli/update-status-line.js.map +1 -0
- package/dist/src/core/cicd/workflow-monitor.d.ts +4 -0
- package/dist/src/core/cicd/workflow-monitor.d.ts.map +1 -1
- package/dist/src/core/cicd/workflow-monitor.js +6 -2
- package/dist/src/core/cicd/workflow-monitor.js.map +1 -1
- package/dist/src/core/increment/completion-validator.d.ts +56 -0
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -0
- package/dist/src/core/increment/completion-validator.js +102 -0
- package/dist/src/core/increment/completion-validator.js.map +1 -0
- package/dist/src/core/increment/increment-archiver.d.ts +4 -1
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +21 -9
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/metadata-manager.d.ts +22 -0
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +62 -0
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/spec-frontmatter-updater.d.ts +78 -0
- package/dist/src/core/increment/spec-frontmatter-updater.d.ts.map +1 -0
- package/dist/src/core/increment/spec-frontmatter-updater.js +152 -0
- package/dist/src/core/increment/spec-frontmatter-updater.js.map +1 -0
- package/dist/src/core/increment/spec-sync-manager.d.ts +5 -1
- package/dist/src/core/increment/spec-sync-manager.d.ts.map +1 -1
- package/dist/src/core/increment/spec-sync-manager.js +4 -2
- package/dist/src/core/increment/spec-sync-manager.js.map +1 -1
- package/dist/src/core/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment-utils.js +18 -1
- package/dist/src/core/increment-utils.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +5 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +36 -33
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.js +13 -8
- package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -1
- package/dist/src/core/status-line/status-line-manager.d.ts +3 -2
- package/dist/src/core/status-line/status-line-manager.d.ts.map +1 -1
- package/dist/src/core/status-line/status-line-manager.js +42 -17
- package/dist/src/core/status-line/status-line-manager.js.map +1 -1
- package/dist/src/core/status-line/status-line-updater.d.ts +67 -0
- package/dist/src/core/status-line/status-line-updater.d.ts.map +1 -0
- package/dist/src/core/status-line/status-line-updater.js +203 -0
- package/dist/src/core/status-line/status-line-updater.js.map +1 -0
- package/dist/src/core/status-line/types.d.ts +19 -5
- package/dist/src/core/status-line/types.d.ts.map +1 -1
- package/dist/src/core/status-line/types.js +3 -3
- package/dist/src/core/status-line/types.js.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -0
- package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.js +4 -0
- package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
- package/dist/src/utils/logger.d.ts +48 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +53 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/package.json +3 -2
- package/plugins/specweave/agents/code-standards-detective/AGENT.md +828 -0
- package/plugins/specweave/agents/test-aware-planner/templates/task-non-testable.md.template +12 -0
- package/plugins/specweave/agents/test-aware-planner/templates/task-testable.md.template +12 -0
- package/plugins/specweave/commands/specweave-analyze-standards.sh +315 -0
- package/plugins/specweave/commands/specweave-done.md +91 -4
- package/plugins/specweave/commands/specweave-reopen.md +29 -2
- package/plugins/specweave/commands/specweave-sync-docs.md +137 -22
- package/plugins/specweave/commands/specweave-update-status.md +151 -0
- package/plugins/specweave/hooks/lib/update-status-line.sh +39 -8
- package/plugins/specweave/hooks/user-prompt-submit.sh +21 -0
- package/plugins/specweave/hooks/validate-increment-completion.sh +113 -0
- package/plugins/specweave/skills/brownfield-analyzer/SKILL.md +40 -3
- package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +455 -0
- package/plugins/specweave/templates/coding-standards.md.template +447 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +21 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -3222
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { MetadataManager } from '../../core/increment/metadata-manager.js';
|
|
3
|
+
import { SpecFrontmatterUpdater } from '../../core/increment/spec-frontmatter-updater.js';
|
|
4
|
+
import { IncrementStatus } from '../../core/types/increment-metadata.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
/**
|
|
7
|
+
* Severity levels for status desyncs
|
|
8
|
+
*/
|
|
9
|
+
export var DesyncSeverity;
|
|
10
|
+
(function (DesyncSeverity) {
|
|
11
|
+
DesyncSeverity["CRITICAL"] = "CRITICAL";
|
|
12
|
+
DesyncSeverity["HIGH"] = "HIGH";
|
|
13
|
+
DesyncSeverity["MEDIUM"] = "MEDIUM";
|
|
14
|
+
DesyncSeverity["LOW"] = "LOW";
|
|
15
|
+
})(DesyncSeverity || (DesyncSeverity = {}));
|
|
16
|
+
/**
|
|
17
|
+
* Calculate severity of a status desync
|
|
18
|
+
*/
|
|
19
|
+
export function calculateSeverity(metadataStatus, specStatus) {
|
|
20
|
+
// CRITICAL: Status line will show wrong increment (completed marked as active in spec.md)
|
|
21
|
+
if ((metadataStatus === IncrementStatus.COMPLETED ||
|
|
22
|
+
metadataStatus === IncrementStatus.PAUSED ||
|
|
23
|
+
metadataStatus === IncrementStatus.ABANDONED) &&
|
|
24
|
+
specStatus === IncrementStatus.ACTIVE) {
|
|
25
|
+
return {
|
|
26
|
+
severity: DesyncSeverity.CRITICAL,
|
|
27
|
+
impact: 'Status line shows completed/paused/abandoned increment as active. Developers see wrong current work.',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
// HIGH: Inverse desync - metadata says active but spec says completed
|
|
31
|
+
if (metadataStatus === IncrementStatus.ACTIVE &&
|
|
32
|
+
(specStatus === IncrementStatus.COMPLETED ||
|
|
33
|
+
specStatus === IncrementStatus.PAUSED ||
|
|
34
|
+
specStatus === IncrementStatus.ABANDONED)) {
|
|
35
|
+
return {
|
|
36
|
+
severity: DesyncSeverity.HIGH,
|
|
37
|
+
impact: 'Active increment appears completed/paused in spec.md. External tools may close issue prematurely.',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// MEDIUM: Paused/completed confusion
|
|
41
|
+
if (metadataStatus === IncrementStatus.PAUSED &&
|
|
42
|
+
(specStatus === IncrementStatus.COMPLETED || specStatus === IncrementStatus.ACTIVE)) {
|
|
43
|
+
return {
|
|
44
|
+
severity: DesyncSeverity.MEDIUM,
|
|
45
|
+
impact: 'Workflow state confusion. Increment may appear in wrong status.',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// LOW: Other combinations (rare, minimal impact)
|
|
49
|
+
return {
|
|
50
|
+
severity: DesyncSeverity.LOW,
|
|
51
|
+
impact: 'Minor status inconsistency. Limited user impact.',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate status sync across all increments
|
|
56
|
+
*/
|
|
57
|
+
export async function validateStatusSync() {
|
|
58
|
+
const allIncrements = MetadataManager.getAll();
|
|
59
|
+
const desyncs = [];
|
|
60
|
+
let syncedCount = 0;
|
|
61
|
+
for (const metadata of allIncrements) {
|
|
62
|
+
try {
|
|
63
|
+
const specStatus = await SpecFrontmatterUpdater.readStatus(metadata.id);
|
|
64
|
+
// Skip if spec.md missing or status field missing (graceful degradation)
|
|
65
|
+
if (!specStatus) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// Check for desync
|
|
69
|
+
if (specStatus !== metadata.status) {
|
|
70
|
+
const { severity, impact } = calculateSeverity(metadata.status, specStatus);
|
|
71
|
+
desyncs.push({
|
|
72
|
+
incrementId: metadata.id,
|
|
73
|
+
metadataStatus: metadata.status,
|
|
74
|
+
specStatus: specStatus,
|
|
75
|
+
severity,
|
|
76
|
+
impact,
|
|
77
|
+
fix: `Run: npx specweave repair-status-desync ${metadata.id}`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
syncedCount++; // Only count as synced if we validated AND they match
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
// Skip increments with read errors (e.g., corrupted spec.md)
|
|
86
|
+
console.warn(`Warning: Could not read spec.md for ${metadata.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
total: allIncrements.length, // All increments scanned
|
|
92
|
+
synced: syncedCount, // Only increments where spec.md exists AND matches
|
|
93
|
+
desynced: desyncs.length,
|
|
94
|
+
desyncs: desyncs.sort((a, b) => {
|
|
95
|
+
// Sort by severity: CRITICAL > HIGH > MEDIUM > LOW
|
|
96
|
+
const severityOrder = {
|
|
97
|
+
[DesyncSeverity.CRITICAL]: 0,
|
|
98
|
+
[DesyncSeverity.HIGH]: 1,
|
|
99
|
+
[DesyncSeverity.MEDIUM]: 2,
|
|
100
|
+
[DesyncSeverity.LOW]: 3,
|
|
101
|
+
};
|
|
102
|
+
return severityOrder[a.severity] - severityOrder[b.severity];
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Format and print validation report
|
|
108
|
+
*/
|
|
109
|
+
export function formatReport(result) {
|
|
110
|
+
const lines = [];
|
|
111
|
+
lines.push('');
|
|
112
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
113
|
+
lines.push('Status Sync Validation Report');
|
|
114
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push(`Total increments scanned: ${result.total}`);
|
|
117
|
+
lines.push(`Synced (✅): ${result.synced}`);
|
|
118
|
+
lines.push(`Desynced (❌): ${result.desynced}`);
|
|
119
|
+
lines.push('');
|
|
120
|
+
if (result.desynced === 0) {
|
|
121
|
+
lines.push(chalk.green('✅ All increments in sync! No desyncs detected.'));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
lines.push(chalk.red(`❌ ${result.desynced} desync(s) detected:`));
|
|
125
|
+
lines.push('');
|
|
126
|
+
for (const desync of result.desyncs) {
|
|
127
|
+
const severityColor = desync.severity === DesyncSeverity.CRITICAL
|
|
128
|
+
? chalk.red
|
|
129
|
+
: desync.severity === DesyncSeverity.HIGH
|
|
130
|
+
? chalk.yellow
|
|
131
|
+
: desync.severity === DesyncSeverity.MEDIUM
|
|
132
|
+
? chalk.blue
|
|
133
|
+
: chalk.gray;
|
|
134
|
+
lines.push(`Increment: ${chalk.bold(desync.incrementId)}`);
|
|
135
|
+
lines.push(` Severity: ${severityColor(desync.severity)}`);
|
|
136
|
+
lines.push(` metadata.json: "${desync.metadataStatus}"`);
|
|
137
|
+
lines.push(` spec.md: "${desync.specStatus}"`);
|
|
138
|
+
lines.push(` Impact: ${desync.impact}`);
|
|
139
|
+
lines.push(` Fix: ${chalk.cyan(desync.fix)}`);
|
|
140
|
+
lines.push('');
|
|
141
|
+
}
|
|
142
|
+
lines.push('To repair all desyncs:');
|
|
143
|
+
lines.push(chalk.cyan(' npx specweave repair-status-desync --all'));
|
|
144
|
+
lines.push('');
|
|
145
|
+
lines.push('To preview changes without modifying files:');
|
|
146
|
+
lines.push(chalk.cyan(' npx specweave repair-status-desync --all --dry-run'));
|
|
147
|
+
}
|
|
148
|
+
lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
149
|
+
lines.push('');
|
|
150
|
+
return lines.join('\n');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Main CLI entry point
|
|
154
|
+
*/
|
|
155
|
+
export async function main() {
|
|
156
|
+
try {
|
|
157
|
+
console.log('🔍 Validating status sync across all increments...\n');
|
|
158
|
+
const result = await validateStatusSync();
|
|
159
|
+
const report = formatReport(result);
|
|
160
|
+
console.log(report);
|
|
161
|
+
// Exit with error code if desyncs found
|
|
162
|
+
if (result.desynced > 0) {
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error(chalk.red('Error during validation:'));
|
|
168
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Run if called directly
|
|
173
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
174
|
+
main();
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=validate-status-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-status-sync.js","sourceRoot":"","sources":["../../../../src/cli/commands/validate-status-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Update Status Line CLI
|
|
4
|
+
*
|
|
5
|
+
* Force-updates status line cache synchronously.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/update-status-line.js
|
|
9
|
+
* node dist/src/cli/update-status-line.js /path/to/project
|
|
10
|
+
*
|
|
11
|
+
* Exit Codes:
|
|
12
|
+
* 0 - Success (cache updated)
|
|
13
|
+
* 1 - Error (cache update failed)
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=update-status-line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-status-line.d.ts","sourceRoot":"","sources":["../../../src/cli/update-status-line.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Update Status Line CLI
|
|
4
|
+
*
|
|
5
|
+
* Force-updates status line cache synchronously.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/src/cli/update-status-line.js
|
|
9
|
+
* node dist/src/cli/update-status-line.js /path/to/project
|
|
10
|
+
*
|
|
11
|
+
* Exit Codes:
|
|
12
|
+
* 0 - Success (cache updated)
|
|
13
|
+
* 1 - Error (cache update failed)
|
|
14
|
+
*/
|
|
15
|
+
import { StatusLineUpdater } from '../core/status-line/status-line-updater.js';
|
|
16
|
+
async function main() {
|
|
17
|
+
// Get project root from args or default to cwd
|
|
18
|
+
const projectRoot = process.argv[2] || process.cwd();
|
|
19
|
+
try {
|
|
20
|
+
const updater = new StatusLineUpdater(projectRoot);
|
|
21
|
+
await updater.update();
|
|
22
|
+
// Get updated cache to show user-friendly output
|
|
23
|
+
const cache = await updater.getCurrentCache();
|
|
24
|
+
if (!cache || !cache.current) {
|
|
25
|
+
// No active increments - show default state message
|
|
26
|
+
console.log('ℹ️ No active increments');
|
|
27
|
+
console.log(' Start new work with: /specweave:increment "feature name"');
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Active increment exists - show progress
|
|
31
|
+
console.log('✅ Status line updated');
|
|
32
|
+
console.log(` Current increment: ${cache.current.id} (${cache.current.completed}/${cache.current.total} tasks, ${cache.current.percentage}%)`);
|
|
33
|
+
console.log(` Open increments: ${cache.openCount}`);
|
|
34
|
+
}
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// Error output
|
|
39
|
+
console.error('❌ Failed to update status line:', error);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
main();
|
|
44
|
+
//# sourceMappingURL=update-status-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-status-line.js","sourceRoot":"","sources":["../../../src/cli/update-status-line.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAE/E,KAAK,UAAU,IAAI;IACjB,+CAA+C;IAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;QAEvB,iDAAiD;QACjD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC;QAE9C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC7B,oDAAoD;YACpD,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,KAAK,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,WAAW,KAAK,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;YACjJ,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAe;QACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* efficient API usage.
|
|
7
7
|
*/
|
|
8
8
|
import { StateManager } from './state-manager.js';
|
|
9
|
+
import { Logger } from '../../utils/logger.js';
|
|
9
10
|
/**
|
|
10
11
|
* Monitor configuration
|
|
11
12
|
*/
|
|
@@ -20,6 +21,8 @@ export interface MonitorConfig {
|
|
|
20
21
|
pollInterval?: number;
|
|
21
22
|
/** Enable debug logging */
|
|
22
23
|
debug?: boolean;
|
|
24
|
+
/** Logger instance (defaults to consoleLogger) */
|
|
25
|
+
logger?: Logger;
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
28
|
* Poll result
|
|
@@ -51,6 +54,7 @@ export declare class WorkflowMonitor {
|
|
|
51
54
|
private octokit;
|
|
52
55
|
private stateManager;
|
|
53
56
|
private config;
|
|
57
|
+
private logger;
|
|
54
58
|
private pollingTimer;
|
|
55
59
|
private lastModified;
|
|
56
60
|
private isPolling;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-monitor.d.ts","sourceRoot":"","sources":["../../../../src/core/cicd/workflow-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"workflow-monitor.d.ts","sourceRoot":"","sources":["../../../../src/core/cicd/workflow-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOlD,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IAEd,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IAEd,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IAEb,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAElB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IAEpB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IAEnB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IAEnB,2BAA2B;IAC3B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAS;IAE1B;;;;;OAKG;gBAED,MAAM,EAAE,aAAa,EACrB,YAAY,GAAE,YAAiC;IAuBjD;;OAEG;IACH,KAAK,IAAI,IAAI;IAwBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAiBZ;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IA6GjC;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAc5B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,OAAO,CAAC,GAAG;CAKZ"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { Octokit } from '@octokit/rest';
|
|
9
9
|
import { StateManager } from './state-manager.js';
|
|
10
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
10
11
|
/**
|
|
11
12
|
* WorkflowMonitor - Polls GitHub Actions for workflow failures
|
|
12
13
|
*
|
|
@@ -37,10 +38,13 @@ export class WorkflowMonitor {
|
|
|
37
38
|
throw new Error('Repository owner and name are required');
|
|
38
39
|
}
|
|
39
40
|
this.config = {
|
|
40
|
-
|
|
41
|
+
token: config.token,
|
|
42
|
+
owner: config.owner,
|
|
43
|
+
repo: config.repo,
|
|
41
44
|
pollInterval: config.pollInterval ?? 60000, // Default: 60s
|
|
42
45
|
debug: config.debug ?? false
|
|
43
46
|
};
|
|
47
|
+
this.logger = config.logger ?? consoleLogger;
|
|
44
48
|
this.octokit = new Octokit({ auth: config.token });
|
|
45
49
|
this.stateManager = stateManager;
|
|
46
50
|
}
|
|
@@ -168,7 +172,7 @@ export class WorkflowMonitor {
|
|
|
168
172
|
return this.poll();
|
|
169
173
|
}
|
|
170
174
|
// Handle other errors
|
|
171
|
-
|
|
175
|
+
this.logger.error('Poll error:', error.message);
|
|
172
176
|
return {
|
|
173
177
|
totalRuns: 0,
|
|
174
178
|
newFailures: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-monitor.js","sourceRoot":"","sources":["../../../../src/core/cicd/workflow-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"workflow-monitor.js","sourceRoot":"","sources":["../../../../src/core/cicd/workflow-monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation result for increment completion
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationResult {
|
|
5
|
+
isValid: boolean;
|
|
6
|
+
errors: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Validates that an increment is ready for completion
|
|
10
|
+
* by checking that all ACs are completed and all tasks are done.
|
|
11
|
+
*
|
|
12
|
+
* This prevents false completion where status is marked "completed"
|
|
13
|
+
* but work is still open.
|
|
14
|
+
*/
|
|
15
|
+
export declare class IncrementCompletionValidator {
|
|
16
|
+
/**
|
|
17
|
+
* Validate that an increment is ready for completion
|
|
18
|
+
*
|
|
19
|
+
* Checks:
|
|
20
|
+
* 1. All acceptance criteria are checked (- [x] **AC-...)
|
|
21
|
+
* 2. All tasks are completed (**Status**: [x] completed)
|
|
22
|
+
* 3. Required files exist (spec.md, tasks.md)
|
|
23
|
+
*
|
|
24
|
+
* @param incrementId - The increment ID to validate
|
|
25
|
+
* @returns ValidationResult with isValid and errors array
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const result = await IncrementCompletionValidator.validateCompletion('0043-spec-md-desync-fix');
|
|
30
|
+
* if (!result.isValid) {
|
|
31
|
+
* console.error('Cannot complete increment:');
|
|
32
|
+
* result.errors.forEach(err => console.error(` - ${err}`));
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
static validateCompletion(incrementId: string): Promise<ValidationResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Count open (unchecked) acceptance criteria in spec.md
|
|
39
|
+
*
|
|
40
|
+
* Searches for pattern: - [ ] **AC-
|
|
41
|
+
*
|
|
42
|
+
* @param incrementId - The increment ID
|
|
43
|
+
* @returns Number of open ACs
|
|
44
|
+
*/
|
|
45
|
+
static countOpenACs(incrementId: string): Promise<number>;
|
|
46
|
+
/**
|
|
47
|
+
* Count pending tasks in tasks.md
|
|
48
|
+
*
|
|
49
|
+
* Searches for pattern: **Status**: [ ] pending
|
|
50
|
+
*
|
|
51
|
+
* @param incrementId - The increment ID
|
|
52
|
+
* @returns Number of pending tasks
|
|
53
|
+
*/
|
|
54
|
+
static countPendingTasks(incrementId: string): Promise<number>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=completion-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-validator.d.ts","sourceRoot":"","sources":["../../../../src/core/increment/completion-validator.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,4BAA4B;IACvC;;;;;;;;;;;;;;;;;;;OAmBG;WACU,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA6C/E;;;;;;;OAOG;WACU,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAa/D;;;;;;;OAOG;WACU,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAYrE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as fs from 'fs-extra';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Validates that an increment is ready for completion
|
|
5
|
+
* by checking that all ACs are completed and all tasks are done.
|
|
6
|
+
*
|
|
7
|
+
* This prevents false completion where status is marked "completed"
|
|
8
|
+
* but work is still open.
|
|
9
|
+
*/
|
|
10
|
+
export class IncrementCompletionValidator {
|
|
11
|
+
/**
|
|
12
|
+
* Validate that an increment is ready for completion
|
|
13
|
+
*
|
|
14
|
+
* Checks:
|
|
15
|
+
* 1. All acceptance criteria are checked (- [x] **AC-...)
|
|
16
|
+
* 2. All tasks are completed (**Status**: [x] completed)
|
|
17
|
+
* 3. Required files exist (spec.md, tasks.md)
|
|
18
|
+
*
|
|
19
|
+
* @param incrementId - The increment ID to validate
|
|
20
|
+
* @returns ValidationResult with isValid and errors array
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const result = await IncrementCompletionValidator.validateCompletion('0043-spec-md-desync-fix');
|
|
25
|
+
* if (!result.isValid) {
|
|
26
|
+
* console.error('Cannot complete increment:');
|
|
27
|
+
* result.errors.forEach(err => console.error(` - ${err}`));
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
static async validateCompletion(incrementId) {
|
|
32
|
+
const errors = [];
|
|
33
|
+
const incrementPath = path.join(process.cwd(), '.specweave', 'increments', incrementId);
|
|
34
|
+
// Check that required files exist
|
|
35
|
+
const specPath = path.join(incrementPath, 'spec.md');
|
|
36
|
+
const tasksPath = path.join(incrementPath, 'tasks.md');
|
|
37
|
+
const specExists = await fs.pathExists(specPath);
|
|
38
|
+
const tasksExists = await fs.pathExists(tasksPath);
|
|
39
|
+
if (!specExists) {
|
|
40
|
+
errors.push('spec.md not found');
|
|
41
|
+
}
|
|
42
|
+
if (!tasksExists) {
|
|
43
|
+
errors.push('tasks.md not found');
|
|
44
|
+
}
|
|
45
|
+
// If files don't exist, return early
|
|
46
|
+
if (!specExists || !tasksExists) {
|
|
47
|
+
return {
|
|
48
|
+
isValid: false,
|
|
49
|
+
errors
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Count open acceptance criteria
|
|
53
|
+
const openACs = await this.countOpenACs(incrementId);
|
|
54
|
+
if (openACs > 0) {
|
|
55
|
+
errors.push(`${openACs} acceptance criteria still open`);
|
|
56
|
+
}
|
|
57
|
+
// Count pending tasks
|
|
58
|
+
const pendingTasks = await this.countPendingTasks(incrementId);
|
|
59
|
+
if (pendingTasks > 0) {
|
|
60
|
+
errors.push(`${pendingTasks} tasks still pending`);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
isValid: errors.length === 0,
|
|
64
|
+
errors
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Count open (unchecked) acceptance criteria in spec.md
|
|
69
|
+
*
|
|
70
|
+
* Searches for pattern: - [ ] **AC-
|
|
71
|
+
*
|
|
72
|
+
* @param incrementId - The increment ID
|
|
73
|
+
* @returns Number of open ACs
|
|
74
|
+
*/
|
|
75
|
+
static async countOpenACs(incrementId) {
|
|
76
|
+
const specPath = path.join(process.cwd(), '.specweave', 'increments', incrementId, 'spec.md');
|
|
77
|
+
const content = await fs.readFile(specPath, 'utf-8');
|
|
78
|
+
// Match unchecked ACs: - [ ] **AC-
|
|
79
|
+
// Must be at start of line (^), followed by - [ ], then **AC-
|
|
80
|
+
const openACPattern = /^- \[ \] \*\*AC-/gm;
|
|
81
|
+
const matches = content.match(openACPattern) || [];
|
|
82
|
+
return matches.length;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Count pending tasks in tasks.md
|
|
86
|
+
*
|
|
87
|
+
* Searches for pattern: **Status**: [ ] pending
|
|
88
|
+
*
|
|
89
|
+
* @param incrementId - The increment ID
|
|
90
|
+
* @returns Number of pending tasks
|
|
91
|
+
*/
|
|
92
|
+
static async countPendingTasks(incrementId) {
|
|
93
|
+
const tasksPath = path.join(process.cwd(), '.specweave', 'increments', incrementId, 'tasks.md');
|
|
94
|
+
const content = await fs.readFile(tasksPath, 'utf-8');
|
|
95
|
+
// Match pending tasks: **Status**: [ ] pending
|
|
96
|
+
// Case-insensitive, handles variations in whitespace
|
|
97
|
+
const pendingPattern = /\*\*Status\*\*:\s*\[\s*\]\s*pending/gi;
|
|
98
|
+
const matches = content.match(pendingPattern) || [];
|
|
99
|
+
return matches.length;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=completion-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-validator.js","sourceRoot":"","sources":["../../../../src/core/increment/completion-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Keeps the increments folder clean by archiving old/completed increments
|
|
5
5
|
* while preserving active work and maintaining full history.
|
|
6
6
|
*/
|
|
7
|
+
import { Logger } from '../../utils/logger.js';
|
|
7
8
|
export interface ArchiveOptions {
|
|
8
9
|
keepLast?: number;
|
|
9
10
|
olderThanDays?: number;
|
|
@@ -26,7 +27,9 @@ export declare class IncrementArchiver {
|
|
|
26
27
|
private incrementsDir;
|
|
27
28
|
private archiveDir;
|
|
28
29
|
private abandonedDir;
|
|
29
|
-
constructor(rootDir: string
|
|
30
|
+
constructor(rootDir: string, options?: {
|
|
31
|
+
logger?: Logger;
|
|
32
|
+
});
|
|
30
33
|
/**
|
|
31
34
|
* Archive increments based on options
|
|
32
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"increment-archiver.d.ts","sourceRoot":"","sources":["../../../../src/core/increment/increment-archiver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"increment-archiver.d.ts","sourceRoot":"","sources":["../../../../src/core/increment/increment-archiver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAgB9D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;gBAEjB,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAS9D;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAmDnE;;OAEG;YACW,aAAa;IAsB3B;;OAEG;YACW,gBAAgB;IAkD9B;;OAEG;YACW,aAAa;IAkD3B;;OAEG;YACW,gBAAgB;IAsC9B;;OAEG;YACW,WAAW;IAczB;;OAEG;YACW,qBAAqB;IAMnC;;OAEG;YACW,gBAAgB;IA2B9B;;OAEG;YACW,aAAa;IAa3B;;OAEG;YACW,gBAAgB;IAc9B;;OAEG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2C/C;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BvC;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;CAuBH"}
|
|
@@ -9,19 +9,25 @@ import * as path from 'path';
|
|
|
9
9
|
import { glob } from 'glob';
|
|
10
10
|
import { ConfigManager } from '../config-manager.js';
|
|
11
11
|
import { detectDuplicatesByNumber } from './duplicate-detector.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
13
|
+
// Archiver-specific logger with emoji formatting
|
|
14
|
+
class ArchiverLogger {
|
|
15
|
+
constructor(baseLogger) {
|
|
16
|
+
this.baseLogger = baseLogger;
|
|
17
|
+
}
|
|
18
|
+
info(message) { this.baseLogger.log(`ℹ️ ${message}`); }
|
|
19
|
+
success(message) { this.baseLogger.log(`✅ ${message}`); }
|
|
20
|
+
warn(message) { this.baseLogger.warn(`⚠️ ${message}`); }
|
|
21
|
+
error(message, error) { this.baseLogger.error(`❌ ${message}`, error); }
|
|
18
22
|
debug(message) { if (process.env.DEBUG)
|
|
19
|
-
|
|
23
|
+
this.baseLogger.log(`🔍 ${message}`); }
|
|
24
|
+
// Logger interface implementation
|
|
25
|
+
log(message) { this.baseLogger.log(message); }
|
|
20
26
|
}
|
|
21
27
|
export class IncrementArchiver {
|
|
22
|
-
constructor(rootDir) {
|
|
28
|
+
constructor(rootDir, options = {}) {
|
|
23
29
|
this.rootDir = rootDir;
|
|
24
|
-
this.logger = new
|
|
30
|
+
this.logger = new ArchiverLogger(options.logger ?? consoleLogger);
|
|
25
31
|
this.config = new ConfigManager(rootDir);
|
|
26
32
|
this.incrementsDir = path.join(rootDir, '.specweave', 'increments');
|
|
27
33
|
this.archiveDir = path.join(this.incrementsDir, '_archive');
|
|
@@ -206,6 +212,9 @@ export class IncrementArchiver {
|
|
|
206
212
|
}
|
|
207
213
|
// Move the directory
|
|
208
214
|
await fs.move(sourcePath, targetPath, { overwrite: false });
|
|
215
|
+
// Clear increment number cache (numbers changed after archiving)
|
|
216
|
+
const { IncrementNumberManager } = await import('../increment-utils.js');
|
|
217
|
+
IncrementNumberManager.clearCache();
|
|
209
218
|
// Update any references in config or living docs
|
|
210
219
|
await this.updateReferences(increment);
|
|
211
220
|
}
|
|
@@ -314,6 +323,9 @@ export class IncrementArchiver {
|
|
|
314
323
|
}
|
|
315
324
|
}
|
|
316
325
|
await fs.move(sourcePath, targetPath);
|
|
326
|
+
// Clear increment number cache (numbers changed after restoring)
|
|
327
|
+
const { IncrementNumberManager } = await import('../increment-utils.js');
|
|
328
|
+
IncrementNumberManager.clearCache();
|
|
317
329
|
this.logger.success(`Restored ${increment} from archive`);
|
|
318
330
|
}
|
|
319
331
|
/**
|