specweave 0.22.2 → 0.22.3
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 +162 -13
- 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/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/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/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +10 -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/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +2 -1
- package/dist/src/core/living-docs/living-docs-sync.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 +40 -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/package.json +1 -1
- package/plugins/specweave/commands/specweave-done.md +60 -4
- package/plugins/specweave/commands/specweave-reopen.md +29 -2
- package/plugins/specweave/commands/specweave-sync-docs.md +71 -4
- package/plugins/specweave/commands/specweave-update-status.md +151 -0
- package/plugins/specweave/hooks/lib/update-status-line.sh +34 -6
- package/plugins/specweave/hooks/user-prompt-submit.sh +21 -0
- package/plugins/specweave/hooks/validate-increment-completion.sh +113 -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,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Line Updater
|
|
3
|
+
*
|
|
4
|
+
* Synchronously updates status line cache by scanning spec.md files.
|
|
5
|
+
* Equivalent to update-status-line.sh but runs SYNCHRONOUSLY.
|
|
6
|
+
*
|
|
7
|
+
* Purpose: Force-refresh status line when it appears stale
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* 1. Scan all spec.md files for open increments (status = active/planning/in-progress)
|
|
11
|
+
* 2. Sort by creation date (oldest first)
|
|
12
|
+
* 3. Select first as current increment
|
|
13
|
+
* 4. Parse tasks.md for progress (use TaskCounter for accuracy)
|
|
14
|
+
* 5. Write cache atomically (.specweave/state/status-line.json)
|
|
15
|
+
*
|
|
16
|
+
* Performance: ~50-100ms (acceptable for user-facing commands)
|
|
17
|
+
*/
|
|
18
|
+
import fs from 'fs-extra';
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
import { TaskCounter } from './task-counter.js';
|
|
21
|
+
/**
|
|
22
|
+
* Maximum number of active increments to display in status line
|
|
23
|
+
* Aligned with ActiveIncrementManager maximum
|
|
24
|
+
*/
|
|
25
|
+
const MAX_ACTIVE_INCREMENTS_DISPLAY = 2;
|
|
26
|
+
/**
|
|
27
|
+
* Status Line Updater
|
|
28
|
+
*
|
|
29
|
+
* Provides synchronous status line cache updates.
|
|
30
|
+
*/
|
|
31
|
+
export class StatusLineUpdater {
|
|
32
|
+
constructor(rootDir = process.cwd()) {
|
|
33
|
+
this.rootDir = rootDir;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Update status line cache synchronously
|
|
37
|
+
*
|
|
38
|
+
* This is the main entry point for force-refreshing the status line.
|
|
39
|
+
* NOW supports up to 2 active increments (aligned with ActiveIncrementManager).
|
|
40
|
+
*/
|
|
41
|
+
async update() {
|
|
42
|
+
// Step 1: Find all open increments (scan spec.md)
|
|
43
|
+
const openIncrements = await this.findOpenIncrements();
|
|
44
|
+
// Step 2: Sort by creation date (oldest first)
|
|
45
|
+
const sorted = openIncrements.sort((a, b) => {
|
|
46
|
+
const aTime = new Date(a.created).getTime();
|
|
47
|
+
const bTime = new Date(b.created).getTime();
|
|
48
|
+
return aTime - bTime; // Ascending (oldest first)
|
|
49
|
+
});
|
|
50
|
+
// Step 3: Take up to MAX_ACTIVE_INCREMENTS_DISPLAY active increments
|
|
51
|
+
const activeIds = sorted.slice(0, MAX_ACTIVE_INCREMENTS_DISPLAY);
|
|
52
|
+
// Step 4: Parse tasks.md for EACH active increment
|
|
53
|
+
const activeIncrements = await Promise.all(activeIds.map(async (inc) => {
|
|
54
|
+
const progress = await this.parseTaskProgress(inc.id);
|
|
55
|
+
return {
|
|
56
|
+
id: inc.id,
|
|
57
|
+
name: inc.id, // Format: "0043-spec-md-desync-fix"
|
|
58
|
+
completed: progress.completed,
|
|
59
|
+
total: progress.total,
|
|
60
|
+
percentage: progress.percentage
|
|
61
|
+
};
|
|
62
|
+
}));
|
|
63
|
+
// Step 5: Build cache object
|
|
64
|
+
const cache = {
|
|
65
|
+
activeIncrements,
|
|
66
|
+
openCount: openIncrements.length,
|
|
67
|
+
lastUpdate: new Date().toISOString(),
|
|
68
|
+
// BACKWARD COMPATIBILITY: Set 'current' to first active increment
|
|
69
|
+
current: activeIncrements[0] || null,
|
|
70
|
+
// Add default state message when no active increments
|
|
71
|
+
message: openIncrements.length === 0
|
|
72
|
+
? 'No active increments. Start with /specweave:increment "feature name"'
|
|
73
|
+
: undefined
|
|
74
|
+
};
|
|
75
|
+
// Step 6: Write cache atomically
|
|
76
|
+
await this.writeCache(cache);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Find all open increments by scanning spec.md files
|
|
80
|
+
*
|
|
81
|
+
* Logic:
|
|
82
|
+
* - Scan .specweave/increments/[id]/spec.md
|
|
83
|
+
* - Parse YAML frontmatter for status field
|
|
84
|
+
* - Filter: status === 'active' || 'planning' || 'in-progress'
|
|
85
|
+
* - Extract: {id, created, status}
|
|
86
|
+
*/
|
|
87
|
+
async findOpenIncrements() {
|
|
88
|
+
const incrementsDir = path.join(this.rootDir, '.specweave/increments');
|
|
89
|
+
if (!await fs.pathExists(incrementsDir)) {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
const entries = await fs.readdir(incrementsDir);
|
|
93
|
+
const openIncrements = [];
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
// Skip special directories (_archive, etc.)
|
|
96
|
+
if (entry.startsWith('_')) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const specPath = path.join(incrementsDir, entry, 'spec.md');
|
|
100
|
+
if (await fs.pathExists(specPath)) {
|
|
101
|
+
const specContent = await fs.readFile(specPath, 'utf-8');
|
|
102
|
+
const metadata = this.parseSpecMetadata(specContent);
|
|
103
|
+
// Check if increment is open (active, planning, or in-progress)
|
|
104
|
+
// ONLY accepts official IncrementStatus enum values
|
|
105
|
+
if (metadata.status === 'active' ||
|
|
106
|
+
metadata.status === 'planning' ||
|
|
107
|
+
metadata.status === 'in-progress') {
|
|
108
|
+
openIncrements.push({
|
|
109
|
+
id: entry,
|
|
110
|
+
created: metadata.created || '1970-01-01',
|
|
111
|
+
status: metadata.status
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return openIncrements;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Parse spec.md YAML frontmatter
|
|
120
|
+
*
|
|
121
|
+
* Extracts: status, created
|
|
122
|
+
*/
|
|
123
|
+
parseSpecMetadata(content) {
|
|
124
|
+
const metadata = {
|
|
125
|
+
status: '',
|
|
126
|
+
created: '1970-01-01'
|
|
127
|
+
};
|
|
128
|
+
// Extract YAML frontmatter (between --- markers)
|
|
129
|
+
const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
130
|
+
if (!frontmatterMatch) {
|
|
131
|
+
return metadata;
|
|
132
|
+
}
|
|
133
|
+
const frontmatter = frontmatterMatch[1];
|
|
134
|
+
// Parse status field
|
|
135
|
+
const statusMatch = frontmatter.match(/^status:\s*(.+)$/m);
|
|
136
|
+
if (statusMatch) {
|
|
137
|
+
metadata.status = statusMatch[1].trim();
|
|
138
|
+
}
|
|
139
|
+
// Parse created field
|
|
140
|
+
const createdMatch = frontmatter.match(/^created:\s*(.+)$/m);
|
|
141
|
+
if (createdMatch) {
|
|
142
|
+
metadata.created = createdMatch[1].trim();
|
|
143
|
+
}
|
|
144
|
+
return metadata;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Parse tasks.md for progress
|
|
148
|
+
*
|
|
149
|
+
* Uses TaskCounter for accurate counting (fixes overcounting bug)
|
|
150
|
+
*/
|
|
151
|
+
async parseTaskProgress(incrementId) {
|
|
152
|
+
const tasksPath = path.join(this.rootDir, '.specweave/increments', incrementId, 'tasks.md');
|
|
153
|
+
if (!await fs.pathExists(tasksPath)) {
|
|
154
|
+
return { completed: 0, total: 0, percentage: 0 };
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const tasksContent = await fs.readFile(tasksPath, 'utf-8');
|
|
158
|
+
const counts = TaskCounter.countTasks(tasksContent);
|
|
159
|
+
return {
|
|
160
|
+
completed: counts.completed,
|
|
161
|
+
total: counts.total,
|
|
162
|
+
percentage: counts.percentage
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
// Graceful degradation: If TaskCounter fails, return zeros
|
|
167
|
+
console.warn(`⚠️ Failed to parse tasks.md for ${incrementId}:`, error);
|
|
168
|
+
return { completed: 0, total: 0, percentage: 0 };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Write cache atomically
|
|
173
|
+
*
|
|
174
|
+
* Uses temp file → rename pattern to prevent corruption
|
|
175
|
+
*/
|
|
176
|
+
async writeCache(cache) {
|
|
177
|
+
const cacheFile = path.join(this.rootDir, '.specweave/state/status-line.json');
|
|
178
|
+
const cacheDir = path.dirname(cacheFile);
|
|
179
|
+
// Ensure state directory exists
|
|
180
|
+
await fs.ensureDir(cacheDir);
|
|
181
|
+
// Atomic write: temp file → rename
|
|
182
|
+
const tempFile = `${cacheFile}.tmp`;
|
|
183
|
+
await fs.writeFile(tempFile, JSON.stringify(cache, null, 2), 'utf-8');
|
|
184
|
+
await fs.rename(tempFile, cacheFile);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get current cache (for testing)
|
|
188
|
+
*/
|
|
189
|
+
async getCurrentCache() {
|
|
190
|
+
const cacheFile = path.join(this.rootDir, '.specweave/state/status-line.json');
|
|
191
|
+
if (!await fs.pathExists(cacheFile)) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const content = await fs.readFile(cacheFile, 'utf-8');
|
|
196
|
+
return JSON.parse(content);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=status-line-updater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-line-updater.js","sourceRoot":"","sources":["../../../../src/core/status-line/status-line-updater.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Status Line Types
|
|
2
|
+
* Status Line Types
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Shows: [
|
|
4
|
+
* Supports displaying multiple active increments (up to 2).
|
|
5
|
+
* Shows: [inc-1] ████░░░░ X/Y | [inc-2] ██████░░ A/B (Z open)
|
|
6
6
|
*/
|
|
7
7
|
export interface StatusLineCache {
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/** NEW: Array of active increments (up to 2) */
|
|
9
|
+
activeIncrements: CurrentIncrement[];
|
|
10
10
|
/** Total number of open increments (active/in-progress/planning) */
|
|
11
11
|
openCount: number;
|
|
12
12
|
/** ISO timestamp of last cache update */
|
|
13
13
|
lastUpdate: string;
|
|
14
|
+
/**
|
|
15
|
+
* DEPRECATED: Use activeIncrements[0] instead
|
|
16
|
+
* Kept for backward compatibility with old code
|
|
17
|
+
*/
|
|
18
|
+
current?: CurrentIncrement | null;
|
|
19
|
+
/**
|
|
20
|
+
* Optional message to display when no active increments
|
|
21
|
+
* Used for user guidance when openCount === 0
|
|
22
|
+
*/
|
|
23
|
+
message?: string;
|
|
14
24
|
}
|
|
15
25
|
export interface CurrentIncrement {
|
|
16
26
|
/** Increment ID (e.g., "0031-external-tool-status-sync") */
|
|
@@ -23,6 +33,10 @@ export interface CurrentIncrement {
|
|
|
23
33
|
total: number;
|
|
24
34
|
/** Completion percentage (0-100) */
|
|
25
35
|
percentage: number;
|
|
36
|
+
/** Number of completed acceptance criteria (NEW) */
|
|
37
|
+
acsCompleted?: number;
|
|
38
|
+
/** Total number of acceptance criteria (NEW) */
|
|
39
|
+
acsTotal?: number;
|
|
26
40
|
}
|
|
27
41
|
export interface StatusLineConfig {
|
|
28
42
|
/** Enable status line rendering */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/status-line/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/status-line/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IAErC,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAElB,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAElC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;IAEX,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAElB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IAEd,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IAEnB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IAEjB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IAEpB,yCAAyC;IACzC,gBAAgB,EAAE,MAAM,CAAC;IAEzB,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAKxC,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Status Line Types
|
|
2
|
+
* Status Line Types
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Shows: [
|
|
4
|
+
* Supports displaying multiple active increments (up to 2).
|
|
5
|
+
* Shows: [inc-1] ████░░░░ X/Y | [inc-2] ██████░░ A/B (Z open)
|
|
6
6
|
*/
|
|
7
7
|
export const DEFAULT_STATUS_LINE_CONFIG = {
|
|
8
8
|
enabled: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/status-line/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/status-line/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA8DH,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IAC1D,OAAO,EAAE,IAAI;IACb,WAAW,EAAE,KAAK,EAAE,oCAAoC;IACxD,gBAAgB,EAAE,CAAC;IACnB,aAAa,EAAE,EAAE;CAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specweave",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.3",
|
|
4
4
|
"description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -51,7 +51,63 @@ You are acting as the Product Manager to validate increment completion before cl
|
|
|
51
51
|
🎯 Validating readiness for closure...
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
### Step 2:
|
|
54
|
+
### Step 2: Automated Completion Validation (Gate 0)
|
|
55
|
+
|
|
56
|
+
**🔥 CRITICAL: Automated validation runs BEFORE PM validation to catch obvious issues!**
|
|
57
|
+
|
|
58
|
+
**BEFORE** invoking the PM agent, run automated validation using `IncrementCompletionValidator`:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { IncrementCompletionValidator } from '../../../src/core/increment/completion-validator.js';
|
|
62
|
+
|
|
63
|
+
// Validate increment is ready for completion
|
|
64
|
+
const validation = await IncrementCompletionValidator.validateCompletion(incrementId);
|
|
65
|
+
|
|
66
|
+
if (!validation.isValid) {
|
|
67
|
+
// BLOCK completion and show errors
|
|
68
|
+
console.error('❌ CANNOT CLOSE INCREMENT - Automated validation failed');
|
|
69
|
+
console.error('');
|
|
70
|
+
validation.errors.forEach(err => console.error(` • ${err}`));
|
|
71
|
+
console.error('');
|
|
72
|
+
console.error('Fix these issues before running /specweave:done again');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Example validation output** (FAIL):
|
|
78
|
+
```
|
|
79
|
+
❌ CANNOT CLOSE INCREMENT - Automated validation failed
|
|
80
|
+
|
|
81
|
+
• 17 acceptance criteria still open
|
|
82
|
+
• 13 tasks still pending
|
|
83
|
+
|
|
84
|
+
Fix these issues before running /specweave:done again
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Example validation output** (PASS):
|
|
88
|
+
```
|
|
89
|
+
✅ Automated validation passed
|
|
90
|
+
• All acceptance criteria completed
|
|
91
|
+
• All tasks completed
|
|
92
|
+
|
|
93
|
+
Proceeding to PM validation...
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**What Gate 0 validates**:
|
|
97
|
+
- [ ] All acceptance criteria are checked (`- [x] **AC-...`)
|
|
98
|
+
- [ ] All tasks are completed (`**Status**: [x] completed`)
|
|
99
|
+
- [ ] Required files exist (`spec.md`, `tasks.md`)
|
|
100
|
+
|
|
101
|
+
**Why Gate 0 matters**:
|
|
102
|
+
- **Prevents false completion**: Can't mark increment "completed" with open work
|
|
103
|
+
- **Fast feedback**: Fails immediately (< 1s) vs waiting for PM agent (30s+)
|
|
104
|
+
- **Data integrity**: Ensures status matches reality (no spec.md desync)
|
|
105
|
+
|
|
106
|
+
**CRITICAL**: Gate 0 is MANDATORY and CANNOT be bypassed. If validation fails, increment stays "in-progress" and command exits.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### Step 3: PM Validation (3 Gates)
|
|
55
111
|
|
|
56
112
|
**🔥 CRITICAL: PM agent MUST validate all 3 gates before allowing closure!**
|
|
57
113
|
|
|
@@ -288,7 +344,7 @@ Recommendation: ❌ CANNOT close increment
|
|
|
288
344
|
• Estimated effort: 1-2 hours
|
|
289
345
|
```
|
|
290
346
|
|
|
291
|
-
### Step
|
|
347
|
+
### Step 4: PM Decision
|
|
292
348
|
|
|
293
349
|
**Based on 3-gate validation**:
|
|
294
350
|
|
|
@@ -326,7 +382,7 @@ Closing increment 0001-user-authentication...
|
|
|
326
382
|
🎉 Increment 0001 closed successfully!
|
|
327
383
|
```
|
|
328
384
|
|
|
329
|
-
### Step
|
|
385
|
+
### Step 5: Post-Closure Sync (AUTOMATIC)
|
|
330
386
|
|
|
331
387
|
**CRITICAL**: After increment closes, automatically perform these syncs:
|
|
332
388
|
|
|
@@ -651,7 +707,7 @@ Increment remains: in-progress
|
|
|
651
707
|
Try again after fixing blockers: /specweave:done 0001
|
|
652
708
|
```
|
|
653
709
|
|
|
654
|
-
### Step
|
|
710
|
+
### Step 6: Handle Incomplete Work
|
|
655
711
|
|
|
656
712
|
**If increment cannot close due to scope creep**:
|
|
657
713
|
|
|
@@ -13,7 +13,10 @@ Reopen completed work when issues are discovered after completion.
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
# Reopen entire increment
|
|
16
|
+
# Reopen entire increment (natural language - RECOMMENDED)
|
|
17
|
+
/specweave:reopen 0043 Bug found in AC sync implementation
|
|
18
|
+
|
|
19
|
+
# OR with explicit --reason flag
|
|
17
20
|
/specweave:reopen 0031 --reason "GitHub sync failing"
|
|
18
21
|
|
|
19
22
|
# Reopen specific task
|
|
@@ -23,6 +26,23 @@ Reopen completed work when issues are discovered after completion.
|
|
|
23
26
|
/specweave:reopen 0031 --user-story US-001 --reason "Acceptance criteria not met"
|
|
24
27
|
```
|
|
25
28
|
|
|
29
|
+
### Natural Language Syntax (NEW!)
|
|
30
|
+
|
|
31
|
+
You can now use natural language without the `--reason` flag:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# ✅ WORKS: Natural language (everything after increment ID is the reason)
|
|
35
|
+
/specweave:reopen 0043 Bug found in implementation, need to fix
|
|
36
|
+
|
|
37
|
+
# ✅ WORKS: Traditional syntax with flag
|
|
38
|
+
/specweave:reopen 0043 --reason "Bug found in implementation"
|
|
39
|
+
|
|
40
|
+
# ✅ WORKS: With task ID
|
|
41
|
+
/specweave:reopen 0043 --task T-005 Found edge case not covered
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**How it works**: All text after the increment ID (and any flags) is treated as the reason. No quotes needed!
|
|
45
|
+
|
|
26
46
|
## Smart Detection First!
|
|
27
47
|
|
|
28
48
|
**Before using this command manually**, try reporting your issue naturally:
|
|
@@ -119,11 +139,18 @@ Use `--force` to bypass WIP limit checks (use sparingly!).
|
|
|
119
139
|
| Parameter | Required | Description |
|
|
120
140
|
|-----------|----------|-------------|
|
|
121
141
|
| `<increment-id>` | Yes | Increment to reopen (e.g., `0031` or `0031-external-tool-status-sync`) |
|
|
122
|
-
| `--reason <text>` |
|
|
142
|
+
| `--reason <text>` | Optional* | Why reopening (for audit trail). *Can use natural language instead! |
|
|
123
143
|
| `--task <id>` | No | Reopen specific task (e.g., `T-003`) |
|
|
124
144
|
| `--user-story <id>` | No | Reopen user story + related tasks (e.g., `US-001`) |
|
|
125
145
|
| `--force` | No | Bypass WIP limit checks |
|
|
126
146
|
|
|
147
|
+
**Natural Language**: If `--reason` is not provided, all remaining text is used as the reason.
|
|
148
|
+
|
|
149
|
+
Examples:
|
|
150
|
+
- `/specweave:reopen 0043 Bug found` → reason = "Bug found"
|
|
151
|
+
- `/specweave:reopen 0043 --task T-005 Edge case` → reason = "Edge case"
|
|
152
|
+
- `/specweave:reopen 0043 --reason "Formal reason"` → reason = "Formal reason" (explicit)
|
|
153
|
+
|
|
127
154
|
## WIP Limit Validation
|
|
128
155
|
|
|
129
156
|
The command automatically checks WIP limits before reopening increments.
|
|
@@ -243,6 +243,57 @@ Synchronize living documentation in `.specweave/docs/` with learnings and decisi
|
|
|
243
243
|
|
|
244
244
|
### Execution Steps:
|
|
245
245
|
|
|
246
|
+
#### 0. 🔄 SYNC LIVING SPECS (User Stories, ACs, Tasks) - CRITICAL FIRST STEP
|
|
247
|
+
|
|
248
|
+
**🚨 MANDATORY: This MUST run FIRST before syncing strategic docs!**
|
|
249
|
+
|
|
250
|
+
Execute the living specs sync using the TypeScript CLI:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { syncSpecs } from './dist/src/cli/commands/sync-specs.js';
|
|
254
|
+
|
|
255
|
+
console.log('═══════════════════════════════════════════════════════');
|
|
256
|
+
console.log('📋 STEP 0: SYNCING LIVING SPECS');
|
|
257
|
+
console.log('═══════════════════════════════════════════════════════\n');
|
|
258
|
+
console.log('🔄 Syncing user stories, acceptance criteria, and tasks...\n');
|
|
259
|
+
|
|
260
|
+
// Call sync-specs to sync living docs structure
|
|
261
|
+
await syncSpecs(['{increment_id}']);
|
|
262
|
+
|
|
263
|
+
console.log('\n✅ Living specs synced successfully!');
|
|
264
|
+
console.log(' - User stories created/updated in .specweave/docs/internal/specs/');
|
|
265
|
+
console.log(' - Acceptance criteria synchronized with completion status');
|
|
266
|
+
console.log(' - Tasks linked to user stories\n');
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**What this step does**:
|
|
270
|
+
- ✅ Parses increment spec.md and extracts user stories with ACs
|
|
271
|
+
- ✅ Syncs AC completion status from spec.md to user story files
|
|
272
|
+
- ✅ Updates task mappings in user story files
|
|
273
|
+
- ✅ Creates/updates feature files and README
|
|
274
|
+
- ✅ Ensures living specs are in sync BEFORE strategic docs
|
|
275
|
+
|
|
276
|
+
**Output**:
|
|
277
|
+
```
|
|
278
|
+
🎯 Target increment: {increment_id}
|
|
279
|
+
📁 Increment path: .specweave/increments/{increment_id}
|
|
280
|
+
🔄 Mode: Specs-only sync (Universal Hierarchy)
|
|
281
|
+
|
|
282
|
+
Processing...
|
|
283
|
+
📚 Syncing {increment_id} → {FS-XXX}...
|
|
284
|
+
✅ Synced 3 tasks to US-001
|
|
285
|
+
✅ Synced 2 tasks to US-002
|
|
286
|
+
|
|
287
|
+
✅ Synced {increment_id} → {FS-XXX}
|
|
288
|
+
Created: 5 files
|
|
289
|
+
|
|
290
|
+
═══════════════════════════════════════════════════════
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**CRITICAL**: If this step fails, STOP and report error. Do not proceed to strategic docs sync.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
246
297
|
#### 1. Analyze Increment Artifacts
|
|
247
298
|
|
|
248
299
|
```bash
|
|
@@ -510,7 +561,16 @@ Increment: {increment_id} ({title})
|
|
|
510
561
|
Status: {status} → Documentation Updated
|
|
511
562
|
|
|
512
563
|
───────────────────────────────────────────────────────
|
|
513
|
-
|
|
564
|
+
📋 LIVING SPECS SYNCED (Step 0)
|
|
565
|
+
───────────────────────────────────────────────────────
|
|
566
|
+
|
|
567
|
+
✅ User Stories: {count} created/updated in .specweave/docs/internal/specs/
|
|
568
|
+
✅ Acceptance Criteria: Synchronized with completion status from spec.md
|
|
569
|
+
✅ Tasks: Linked to user stories with completion tracking
|
|
570
|
+
✅ Feature Files: Created/updated in .specweave/docs/internal/specs/_features/
|
|
571
|
+
|
|
572
|
+
───────────────────────────────────────────────────────
|
|
573
|
+
📊 STRATEGIC DOCS CHANGES (Steps 1-5)
|
|
514
574
|
───────────────────────────────────────────────────────
|
|
515
575
|
|
|
516
576
|
Created:
|
|
@@ -544,20 +604,27 @@ To restore: cp {file}.backup {file}
|
|
|
544
604
|
───────────────────────────────────────────────────────
|
|
545
605
|
|
|
546
606
|
1. Review updated documentation:
|
|
607
|
+
- Living specs: .specweave/docs/internal/specs/
|
|
547
608
|
- Public docs: .specweave/docs/public/
|
|
548
609
|
- Internal docs: .specweave/docs/internal/
|
|
549
610
|
- New ADRs: .specweave/docs/internal/architecture/adr/
|
|
550
611
|
|
|
551
|
-
2.
|
|
612
|
+
2. Verify living specs sync:
|
|
613
|
+
- Check user story files for updated AC checkboxes
|
|
614
|
+
- Verify tasks are linked correctly
|
|
615
|
+
- Confirm feature files are up to date
|
|
616
|
+
|
|
617
|
+
3. (Optional) Generate Docusaurus site:
|
|
552
618
|
- Use 'docusaurus' skill to publish updated docs
|
|
553
619
|
|
|
554
|
-
|
|
620
|
+
4. Commit changes:
|
|
555
621
|
git add .specweave/docs/
|
|
556
622
|
git commit -m "docs: sync from increment {increment_id}"
|
|
557
623
|
|
|
558
624
|
═══════════════════════════════════════════════════════
|
|
559
625
|
|
|
560
|
-
|
|
626
|
+
ALL documentation is now in sync with increment {increment_id}! 🎉
|
|
627
|
+
(Living specs + Strategic docs)
|
|
561
628
|
```
|
|
562
629
|
|
|
563
630
|
---
|