specweave 1.0.78 β 1.0.80
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 +109 -715
- package/package.json +1 -1
- package/plugins/specweave/commands/jobs.md +3 -445
- package/plugins/specweave/commands/progress.md +4 -78
- package/plugins/specweave/commands/status.md +3 -488
- package/plugins/specweave/hooks/README.md +25 -1
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +56 -0
- package/src/templates/CLAUDE.md.template +75 -614
|
@@ -2,494 +2,9 @@
|
|
|
2
2
|
name: sw:status
|
|
3
3
|
description: Show increment status overview with rich details (active, backlog, paused, completed, abandoned)
|
|
4
4
|
usage: /sw:status [--active|--backlog|--paused|--completed|--abandoned|--stale]
|
|
5
|
+
allowed-tools: Bash(bash:*)
|
|
5
6
|
---
|
|
6
7
|
|
|
7
|
-
# Increment Status
|
|
8
|
+
# Increment Status
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Purpose
|
|
14
|
-
|
|
15
|
-
Display comprehensive increment status overview:
|
|
16
|
-
- **Active** increments (currently working)
|
|
17
|
-
- **Backlog** increments (planned but not started)
|
|
18
|
-
- **Paused** increments (blocked/deprioritized)
|
|
19
|
-
- **Completed** increments (done)
|
|
20
|
-
- **Abandoned** increments (obsolete)
|
|
21
|
-
- **Warnings** for stale increments (paused >7 days, active >30 days)
|
|
22
|
-
- **Suggestions** for next actions
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Output Format
|
|
27
|
-
|
|
28
|
-
### Default (All Increments)
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
/sw:status
|
|
32
|
-
|
|
33
|
-
π Increment Status Overview
|
|
34
|
-
|
|
35
|
-
π₯ Active (2):
|
|
36
|
-
π¨ 0005-payment-hotfix [hotfix]
|
|
37
|
-
Progress: 90% (18/20 tasks)
|
|
38
|
-
Age: 6 hours
|
|
39
|
-
Last: Fixed Stripe webhook signature
|
|
40
|
-
|
|
41
|
-
π§ 0006-i18n [feature]
|
|
42
|
-
Progress: 50% (10/20 tasks)
|
|
43
|
-
Age: 2 days
|
|
44
|
-
Last: Created translation pipeline
|
|
45
|
-
|
|
46
|
-
ποΈ Backlog (2):
|
|
47
|
-
π¦ 0032-feature-a [feature]
|
|
48
|
-
In backlog: 5 days
|
|
49
|
-
Reason: Low priority
|
|
50
|
-
|
|
51
|
-
π¦ 0033-feature-b [feature]
|
|
52
|
-
In backlog: 3 days
|
|
53
|
-
Reason: Waiting for decisions
|
|
54
|
-
|
|
55
|
-
βΈοΈ Paused (1):
|
|
56
|
-
π 0007-stripe-integration [feature]
|
|
57
|
-
Progress: 30% (6/20 tasks)
|
|
58
|
-
Paused: 3 days ago
|
|
59
|
-
Reason: Waiting for Stripe API keys
|
|
60
|
-
β οΈ Review or abandon?
|
|
61
|
-
|
|
62
|
-
β
Completed (4):
|
|
63
|
-
0001-core-framework
|
|
64
|
-
0002-core-enhancements
|
|
65
|
-
0003-intelligent-model-selection
|
|
66
|
-
0004-plugin-architecture
|
|
67
|
-
|
|
68
|
-
π Summary:
|
|
69
|
-
- Active: 2 increments (1 hotfix, 1 feature)
|
|
70
|
-
- Backlog: 2 increments (planned for future)
|
|
71
|
-
- Paused: 1 increment
|
|
72
|
-
- Completed: 4 increments
|
|
73
|
-
- Context switching: 20-40% cost (2 active)
|
|
74
|
-
|
|
75
|
-
π Type Limits (v0.7.0+):
|
|
76
|
-
β
hotfix: 1/unlimited active
|
|
77
|
-
β
feature: 1/2 active
|
|
78
|
-
β
refactor: 0/1 active
|
|
79
|
-
β
bug: 0/unlimited active
|
|
80
|
-
β
change-request: 0/2 active
|
|
81
|
-
β
experiment: 0/unlimited active
|
|
82
|
-
|
|
83
|
-
π‘ Suggestions:
|
|
84
|
-
- Complete 0005 first (90% done, almost there!)
|
|
85
|
-
- Resume or abandon 0007 (stale)
|
|
86
|
-
|
|
87
|
-
Commands:
|
|
88
|
-
/sw:do # Continue current work
|
|
89
|
-
/sw:resume 0007 # Resume paused increment
|
|
90
|
-
/sw:abandon 0007 # Abandon if obsolete
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### Filtered Views
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
# Active only
|
|
97
|
-
/sw:status --active
|
|
98
|
-
|
|
99
|
-
π₯ Active Increments (2):
|
|
100
|
-
π¨ 0005-payment-hotfix [hotfix] (90% done, 6 hours)
|
|
101
|
-
π§ 0006-i18n [feature] (50% done, 2 days)
|
|
102
|
-
|
|
103
|
-
# Paused only
|
|
104
|
-
/sw:status --paused
|
|
105
|
-
|
|
106
|
-
βΈοΈ Paused Increments (1):
|
|
107
|
-
π 0007-stripe [feature] (paused 3 days)
|
|
108
|
-
Reason: Waiting for API keys
|
|
109
|
-
|
|
110
|
-
# Stale only (paused >7 days OR active >30 days)
|
|
111
|
-
/sw:status --stale
|
|
112
|
-
|
|
113
|
-
β οΈ Stale Increments (2):
|
|
114
|
-
π 0008-experiment [experiment] (paused 10 days)
|
|
115
|
-
π¨ AUTO-ABANDON WARNING (14 days inactive)
|
|
116
|
-
|
|
117
|
-
π§ 0009-big-refactor [refactor] (active 35 days)
|
|
118
|
-
β οΈ Long-running - consider breaking into smaller increments
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## Implementation
|
|
124
|
-
|
|
125
|
-
Uses MetadataManager and Limits to query and display:
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
import { MetadataManager, IncrementStatus } from '../src/core/increment/metadata-manager';
|
|
129
|
-
import { checkAllLimits, getLimitsSummary } from '../src/core/increment/limits';
|
|
130
|
-
|
|
131
|
-
// Get all increments
|
|
132
|
-
const allIncrements = MetadataManager.getAll();
|
|
133
|
-
|
|
134
|
-
// Group by status
|
|
135
|
-
const active = allIncrements.filter(m => m.status === IncrementStatus.ACTIVE);
|
|
136
|
-
const backlog = allIncrements.filter(m => m.status === IncrementStatus.BACKLOG);
|
|
137
|
-
const paused = allIncrements.filter(m => m.status === IncrementStatus.PAUSED);
|
|
138
|
-
const completed = allIncrements.filter(m => m.status === IncrementStatus.COMPLETED);
|
|
139
|
-
const abandoned = allIncrements.filter(m => m.status === IncrementStatus.ABANDONED);
|
|
140
|
-
|
|
141
|
-
// Get extended metadata (with progress%)
|
|
142
|
-
const extended = active.map(m => MetadataManager.getExtended(m.id));
|
|
143
|
-
|
|
144
|
-
// Display rich output
|
|
145
|
-
console.log('π Increment Status Overview\n');
|
|
146
|
-
|
|
147
|
-
// Active
|
|
148
|
-
if (active.length > 0) {
|
|
149
|
-
console.log(`π₯ Active (${active.length}):`);
|
|
150
|
-
extended.forEach(inc => {
|
|
151
|
-
const icon = inc.type === 'hotfix' ? 'π¨' : 'π§';
|
|
152
|
-
console.log(` ${icon} ${inc.id} [${inc.type}]`);
|
|
153
|
-
console.log(` Progress: ${inc.progress}% (${inc.completedTasks}/${inc.totalTasks} tasks)`);
|
|
154
|
-
console.log(` Age: ${formatAge(inc.ageInDays)}`);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// ... similar for paused, completed, abandoned
|
|
159
|
-
|
|
160
|
-
// Summary with type limits (v0.7.0+)
|
|
161
|
-
console.log('\nπ Summary:');
|
|
162
|
-
console.log(` - Active: ${active.length} increments`);
|
|
163
|
-
console.log(` - Backlog: ${backlog.length} increments`);
|
|
164
|
-
console.log(` - Paused: ${paused.length} increments`);
|
|
165
|
-
console.log(` - Completed: ${completed.length} increments`);
|
|
166
|
-
|
|
167
|
-
// Type limits breakdown
|
|
168
|
-
console.log('\nπ Type Limits (v0.7.0+):');
|
|
169
|
-
const limitsCheck = checkAllLimits();
|
|
170
|
-
for (const [type, check] of Object.entries(limitsCheck)) {
|
|
171
|
-
const icon = check.exceeded ? 'β οΈ ' : 'β
';
|
|
172
|
-
const limitStr = check.limit === null ? 'unlimited' : check.limit.toString();
|
|
173
|
-
console.log(` ${icon} ${type}: ${check.current}/${limitStr} active`);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Context switching warning if multiple active
|
|
177
|
-
if (active.length > 1) {
|
|
178
|
-
const cost = active.length === 2 ? '20-30%' : '40%';
|
|
179
|
-
console.log(`\nβ οΈ Context switching: ${cost} productivity cost`);
|
|
180
|
-
}
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## Progress Calculation
|
|
186
|
-
|
|
187
|
-
Progress percentage calculated from tasks.md:
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
// Count completed tasks: [x] or [X]
|
|
191
|
-
const completedMatches = tasksContent.match(/\[x\]/gi);
|
|
192
|
-
const completedTasks = completedMatches ? completedMatches.length : 0;
|
|
193
|
-
|
|
194
|
-
// Count total tasks: [ ] or [x]
|
|
195
|
-
const totalMatches = tasksContent.match(/\[ \]|\[x\]/gi);
|
|
196
|
-
const totalTasks = totalMatches ? totalMatches.length : 0;
|
|
197
|
-
|
|
198
|
-
// Calculate percentage
|
|
199
|
-
const progress = Math.round((completedTasks / totalTasks) * 100);
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
## Warnings and Suggestions
|
|
205
|
-
|
|
206
|
-
### Stale Paused Increments
|
|
207
|
-
|
|
208
|
-
Paused >7 days β warning:
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
βΈοΈ Paused (1):
|
|
212
|
-
π 0007-stripe [feature]
|
|
213
|
-
Paused: 10 days ago
|
|
214
|
-
β οΈ STALE! Review or abandon?
|
|
215
|
-
|
|
216
|
-
π‘ Actions:
|
|
217
|
-
/sw:resume 0007 # If unblocked
|
|
218
|
-
/sw:abandon 0007 # If no longer needed
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Long-Running Active Increments
|
|
222
|
-
|
|
223
|
-
Active >30 days β warning:
|
|
224
|
-
|
|
225
|
-
```
|
|
226
|
-
π₯ Active (1):
|
|
227
|
-
π§ 0009-big-refactor [refactor]
|
|
228
|
-
Progress: 45% (23/50 tasks)
|
|
229
|
-
Age: 35 days
|
|
230
|
-
β οΈ Long-running! Consider breaking into smaller increments
|
|
231
|
-
|
|
232
|
-
π‘ Suggestion: Large increments increase risk and reduce velocity
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Context Switching Cost
|
|
236
|
-
|
|
237
|
-
Multiple active features β warning:
|
|
238
|
-
|
|
239
|
-
```
|
|
240
|
-
π Summary:
|
|
241
|
-
- Active: 3 features (0010, 0011, 0012)
|
|
242
|
-
- Context switching: 40-60% productivity cost
|
|
243
|
-
|
|
244
|
-
β οΈ High context switching detected!
|
|
245
|
-
Research shows: 3+ concurrent tasks = 40% productivity loss
|
|
246
|
-
Suggestion: Complete or pause one before continuing
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Auto-Abandon Warning (Experiments)
|
|
250
|
-
|
|
251
|
-
Experiments inactive >14 days β warning:
|
|
252
|
-
|
|
253
|
-
```
|
|
254
|
-
π§ͺ Experiments (1):
|
|
255
|
-
π¬ 0010-graphql-experiment [experiment]
|
|
256
|
-
Last activity: 15 days ago
|
|
257
|
-
π¨ AUTO-ABANDON WARNING
|
|
258
|
-
|
|
259
|
-
π‘ Experiments auto-abandon after 14 days of inactivity
|
|
260
|
-
To prevent: Update via /sw:do or /touch 0010
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## Cross-Project View (v0.33.0+)
|
|
266
|
-
|
|
267
|
-
When an increment has user stories targeting multiple projects, show grouped view:
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
/sw:status 0125
|
|
271
|
-
|
|
272
|
-
π Increment Status: 0125-cross-project-targeting
|
|
273
|
-
|
|
274
|
-
π Cross-Project Increment (spans 3 projects):
|
|
275
|
-
|
|
276
|
-
βββββββββββββββββ¬βββββββββββββ¬βββββββββββ¬βββββββββββββββββ¬ββββββββββββββββββββββ
|
|
277
|
-
β Project β Provider β USs β Status β External Issues β
|
|
278
|
-
βββββββββββββββββΌβββββββββββββΌβββββββββββΌβββββββββββββββββΌββββββββββββββββββββββ€
|
|
279
|
-
β frontend-app β github β US-001, β β
Synced β #45, #46 β
|
|
280
|
-
β β β US-003 β β github.com/org/fe β
|
|
281
|
-
βββββββββββββββββΌβββββββββββββΌβββββββββββΌβββββββββββββββββΌββββββββββββββββββββββ€
|
|
282
|
-
β backend-api β jira β US-002 β β
Synced β SEC-123 β
|
|
283
|
-
β β β β β jira.com/browse β
|
|
284
|
-
βββββββββββββββββΌβββββββββββββΌβββββββββββΌβββββββββββββββββΌββββββββββββββββββββββ€
|
|
285
|
-
β shared-lib β β οΈ None β US-004 β Not mapped β β β
|
|
286
|
-
β β β β β β
|
|
287
|
-
βββββββββββββββββ΄βββββββββββββ΄βββββββββββ΄βββββββββββββββββ΄ββββββββββββββββββββββ
|
|
288
|
-
|
|
289
|
-
π Progress by Project:
|
|
290
|
-
frontend-app: 75% (3/4 tasks)
|
|
291
|
-
backend-api: 50% (2/4 tasks)
|
|
292
|
-
shared-lib: 100% (2/2 tasks)
|
|
293
|
-
|
|
294
|
-
π‘ Unmapped project 'shared-lib':
|
|
295
|
-
Add to .specweave/config.json projectMappings or create issues manually
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### Cross-Project Implementation
|
|
299
|
-
|
|
300
|
-
```typescript
|
|
301
|
-
import { CrossProjectSync } from '../src/core/living-docs/cross-project-sync';
|
|
302
|
-
import { ExternalSyncOrchestrator } from '../src/core/living-docs/external-sync-orchestrator';
|
|
303
|
-
|
|
304
|
-
// Detect cross-project
|
|
305
|
-
const crossProjectSync = new CrossProjectSync(projectRoot);
|
|
306
|
-
const userStories = parseUserStories(specContent);
|
|
307
|
-
const isCrossProject = crossProjectSync.isCrossProject(userStories, defaultProject);
|
|
308
|
-
|
|
309
|
-
if (isCrossProject) {
|
|
310
|
-
// Group by project
|
|
311
|
-
const groups = crossProjectSync.groupByProject(userStories, defaultProject);
|
|
312
|
-
|
|
313
|
-
// Load project mappings
|
|
314
|
-
const orchestrator = new ExternalSyncOrchestrator(projectRoot);
|
|
315
|
-
await orchestrator.loadProjectMappings();
|
|
316
|
-
|
|
317
|
-
// Display per-project status
|
|
318
|
-
for (const [projectId, stories] of groups) {
|
|
319
|
-
const mapping = orchestrator.getProjectMapping(projectId);
|
|
320
|
-
const provider = mapping?.github ? 'github' : mapping?.jira ? 'jira' : mapping?.ado ? 'ado' : null;
|
|
321
|
-
|
|
322
|
-
console.log(`β ${projectId.padEnd(13)} β ${(provider || 'β οΈ None').padEnd(10)} β ...`);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## Filters
|
|
330
|
-
|
|
331
|
-
### --active
|
|
332
|
-
|
|
333
|
-
Show only active increments
|
|
334
|
-
|
|
335
|
-
```bash
|
|
336
|
-
/sw:status --active
|
|
337
|
-
|
|
338
|
-
π₯ Active (2):
|
|
339
|
-
π¨ 0005-hotfix [hotfix] (90% done)
|
|
340
|
-
π§ 0006-i18n [feature] (50% done)
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### --backlog
|
|
344
|
-
|
|
345
|
-
Show only backlog increments
|
|
346
|
-
|
|
347
|
-
```bash
|
|
348
|
-
/sw:status --backlog
|
|
349
|
-
|
|
350
|
-
ποΈ Backlog (3):
|
|
351
|
-
π¦ 0032-feature-a [feature] (in backlog 5 days)
|
|
352
|
-
Reason: Low priority
|
|
353
|
-
|
|
354
|
-
π¦ 0033-feature-b [feature] (in backlog 3 days)
|
|
355
|
-
Reason: Waiting for decisions
|
|
356
|
-
|
|
357
|
-
π¦ 0034-feature-c [feature] (in backlog 1 day)
|
|
358
|
-
Reason: Multiple planned ideas
|
|
359
|
-
|
|
360
|
-
π‘ Start work: /sw:resume <id>
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
### --paused
|
|
364
|
-
|
|
365
|
-
Show only paused increments
|
|
366
|
-
|
|
367
|
-
```bash
|
|
368
|
-
/sw:status --paused
|
|
369
|
-
|
|
370
|
-
βΈοΈ Paused (2):
|
|
371
|
-
π 0007-stripe [feature] (paused 3 days)
|
|
372
|
-
Reason: Waiting for API keys
|
|
373
|
-
|
|
374
|
-
π 0008-refactor [refactor] (paused 10 days)
|
|
375
|
-
Reason: Deprioritized
|
|
376
|
-
β οΈ STALE
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
### --completed
|
|
380
|
-
|
|
381
|
-
Show only completed increments
|
|
382
|
-
|
|
383
|
-
```bash
|
|
384
|
-
/sw:status --completed
|
|
385
|
-
|
|
386
|
-
β
Completed (5):
|
|
387
|
-
0001-core-framework (completed 30 days ago)
|
|
388
|
-
0002-core-enhancements (completed 25 days ago)
|
|
389
|
-
0003-model-selection (completed 20 days ago)
|
|
390
|
-
0004-plugin-architecture (completed 15 days ago)
|
|
391
|
-
0005-cross-platform (completed 10 days ago)
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### --abandoned
|
|
395
|
-
|
|
396
|
-
Show only abandoned increments
|
|
397
|
-
|
|
398
|
-
```bash
|
|
399
|
-
/sw:status --abandoned
|
|
400
|
-
|
|
401
|
-
β Abandoned (3):
|
|
402
|
-
0008-old-approach (Requirements changed)
|
|
403
|
-
0009-failed-experiment (Experiment failed)
|
|
404
|
-
0010-superseded (Replaced by 0011)
|
|
405
|
-
|
|
406
|
-
π Stats:
|
|
407
|
-
- Abandonment rate: 30% (3/10 total)
|
|
408
|
-
- Common reasons: Requirements changed (2), Experiment failed (1)
|
|
409
|
-
|
|
410
|
-
π‘ Periodically review _abandoned/ for learnings
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
### --stale
|
|
414
|
-
|
|
415
|
-
Show only stale increments (paused >7 days OR active >30 days)
|
|
416
|
-
|
|
417
|
-
```bash
|
|
418
|
-
/sw:status --stale
|
|
419
|
-
|
|
420
|
-
β οΈ Stale Increments (3):
|
|
421
|
-
π 0007-stripe [feature] (paused 10 days)
|
|
422
|
-
π 0008-experiment [experiment] (paused 15 days)
|
|
423
|
-
π¨ AUTO-ABANDON WARNING
|
|
424
|
-
π§ 0009-refactor [refactor] (active 35 days)
|
|
425
|
-
β οΈ Long-running
|
|
426
|
-
|
|
427
|
-
π‘ Review stale increments weekly
|
|
428
|
-
Paused >7 days: Resume or abandon
|
|
429
|
-
Active >30 days: Consider breaking into smaller increments
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
---
|
|
433
|
-
|
|
434
|
-
## Related Commands
|
|
435
|
-
|
|
436
|
-
- `/sw:do` - Continue work on active increment
|
|
437
|
-
- `/sw:progress` - Detailed progress for current increment
|
|
438
|
-
- `/sw:backlog <id>` - Move increment to backlog
|
|
439
|
-
- `/sw:pause <id>` - Pause active increment
|
|
440
|
-
- `/sw:resume <id>` - Resume paused or backlog increment
|
|
441
|
-
- `/sw:abandon <id>` - Abandon increment (move to _abandoned/)
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
## Best Practices
|
|
446
|
-
|
|
447
|
-
β
**Check status regularly** - Daily or before starting work
|
|
448
|
-
|
|
449
|
-
β
**Address warnings promptly** - Don't let stale increments pile up
|
|
450
|
-
|
|
451
|
-
β
**Complete before starting new** - Minimize context switching
|
|
452
|
-
|
|
453
|
-
β
**Review abandoned for learnings** - Understand patterns
|
|
454
|
-
|
|
455
|
-
β **Don't ignore stale warnings** - They indicate blocked or forgotten work
|
|
456
|
-
|
|
457
|
-
β **Don't accumulate paused increments** - Resume or abandon
|
|
458
|
-
|
|
459
|
-
---
|
|
460
|
-
|
|
461
|
-
## Statistics and Analytics
|
|
462
|
-
|
|
463
|
-
Future enhancement (v0.8.0+):
|
|
464
|
-
|
|
465
|
-
```bash
|
|
466
|
-
/sw:status --analytics
|
|
467
|
-
|
|
468
|
-
π Increment Analytics (Last 90 Days):
|
|
469
|
-
|
|
470
|
-
Velocity:
|
|
471
|
-
- Completed: 8 increments
|
|
472
|
-
- Avg cycle time: 4.2 days
|
|
473
|
-
- Completion rate: 80%
|
|
474
|
-
|
|
475
|
-
Quality:
|
|
476
|
-
- Avg coverage: 85%
|
|
477
|
-
- Avg tasks/increment: 25
|
|
478
|
-
|
|
479
|
-
Patterns:
|
|
480
|
-
- Most common type: feature (70%)
|
|
481
|
-
- Context switching: 1.5 active avg
|
|
482
|
-
- Stale rate: 15% (paused >7 days)
|
|
483
|
-
|
|
484
|
-
Recommendations:
|
|
485
|
-
- β
Good velocity (8 increments/90 days)
|
|
486
|
-
- β οΈ High abandonment (20%) - review scoping
|
|
487
|
-
- β
Low context switching (1.5 avg)
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
---
|
|
491
|
-
|
|
492
|
-
**Command**: `/sw:status`
|
|
493
|
-
**Plugin**: specweave (core)
|
|
494
|
-
**Version**: v0.7.0+
|
|
495
|
-
**Part of**: Increment 0007 - Smart Status Management
|
|
10
|
+
!`bash "${CLAUDE_PLUGIN_ROOT}/scripts/read-status.sh" $ARGUMENTS`
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
## Purpose
|
|
9
9
|
|
|
10
10
|
Core hooks automate SpecWeave's fundamental workflows:
|
|
11
|
-
- **Sound notifications** when tasks complete
|
|
11
|
+
- **Sound notifications** when tasks complete (v1.0.77+: plays when task marked `[x]` in tasks.md)
|
|
12
12
|
- **Living docs sync** after task completion
|
|
13
13
|
- **Translation** of non-English documentation
|
|
14
14
|
- **Self-reflection** for AI-driven quality improvements
|
|
15
|
+
- **Auto mode loops** for autonomous execution
|
|
15
16
|
|
|
16
17
|
**Note**: External tool sync (GitHub, JIRA, Azure DevOps) has been moved to respective plugin hooks as of v0.13.0. See "Architecture Changes" section below.
|
|
17
18
|
|
|
@@ -147,6 +148,29 @@ Core hooks automate SpecWeave's fundamental workflows:
|
|
|
147
148
|
|
|
148
149
|
---
|
|
149
150
|
|
|
151
|
+
### π Task Completion Sound (v1.0.77+)
|
|
152
|
+
|
|
153
|
+
**Triggers**: Automatically when any task is marked `[x]` in tasks.md
|
|
154
|
+
|
|
155
|
+
**How It Works**:
|
|
156
|
+
- Monitors task completion count in `.specweave/state/.last-task-completion`
|
|
157
|
+
- Plays pleasant sound (Glass.aiff) when count increases
|
|
158
|
+
- Runs in background (never blocks or delays hook execution)
|
|
159
|
+
- **Smart auto mode detection**: Skips during `/sw:auto` (Stop hook plays ONE sound at END)
|
|
160
|
+
|
|
161
|
+
**Behavior by Mode**:
|
|
162
|
+
- **Normal mode**: Sound plays after EACH task completion
|
|
163
|
+
- **Auto mode** (`/sw:auto`): NO sounds during execution, ONE completion sound when main orchestrator finishes
|
|
164
|
+
|
|
165
|
+
**Platforms**:
|
|
166
|
+
- macOS: `Glass.aiff` (built-in system sound)
|
|
167
|
+
- Linux (PulseAudio): `/usr/share/sounds/freedesktop/stereo/complete.oga`
|
|
168
|
+
- Linux (ALSA): `/usr/share/sounds/alsa/Front_Center.wav`
|
|
169
|
+
|
|
170
|
+
**Implementation**: Integrated into `PostToolUse` hook dispatcher (`v2/dispatchers/post-tool-use.sh`)
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
150
174
|
## How Hooks Work (Claude Code Native)
|
|
151
175
|
|
|
152
176
|
**CRITICAL**: Hooks are **NOT copied** to `.claude/hooks/`. They stay in `plugins/specweave/hooks/` and Claude Code discovers them automatically.
|
|
@@ -42,6 +42,8 @@ while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -d "$PROJECT_ROOT/.specweave" ]]; do
|
|
|
42
42
|
done
|
|
43
43
|
[[ ! -d "$PROJECT_ROOT/.specweave" ]] && exit 0
|
|
44
44
|
|
|
45
|
+
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
46
|
+
|
|
45
47
|
# ============================================================================
|
|
46
48
|
# LOGGING INFRASTRUCTURE
|
|
47
49
|
# ============================================================================
|
|
@@ -154,6 +156,57 @@ safe_run_sync() {
|
|
|
154
156
|
return 0 # Always succeed
|
|
155
157
|
}
|
|
156
158
|
|
|
159
|
+
# ============================================================================
|
|
160
|
+
# TASK COMPLETION SOUND (plays when task marked [x])
|
|
161
|
+
# ============================================================================
|
|
162
|
+
|
|
163
|
+
play_task_completion_sound() {
|
|
164
|
+
local tasks_file="$1"
|
|
165
|
+
local state_file="$STATE_DIR/.last-task-completion"
|
|
166
|
+
local session_file="$STATE_DIR/auto-session.json"
|
|
167
|
+
|
|
168
|
+
# CRITICAL: Skip sound if auto mode is active
|
|
169
|
+
# Auto mode has its own completion sound via Stop hook (plays once at END)
|
|
170
|
+
if [[ -f "$session_file" ]]; then
|
|
171
|
+
local auto_status=$(jq -r '.status // "unknown"' "$session_file" 2>/dev/null || echo "unknown")
|
|
172
|
+
if [[ "$auto_status" == "active" ]] || [[ "$auto_status" == "running" ]]; then
|
|
173
|
+
log_debug "Auto mode active - skipping task completion sound (Stop hook will handle it)"
|
|
174
|
+
return 0
|
|
175
|
+
fi
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
# Extract current completion count
|
|
179
|
+
local current_count=$(grep -c '\*\*Status\*\*:.*\[x\]' "$tasks_file" 2>/dev/null || echo "0")
|
|
180
|
+
|
|
181
|
+
# Read previous count
|
|
182
|
+
local previous_count="0"
|
|
183
|
+
if [[ -f "$state_file" ]]; then
|
|
184
|
+
previous_count=$(cat "$state_file" 2>/dev/null || echo "0")
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# If count increased, a task was just completed
|
|
188
|
+
if [[ "$current_count" -gt "$previous_count" ]]; then
|
|
189
|
+
# Save new count
|
|
190
|
+
echo "$current_count" > "$state_file" 2>/dev/null
|
|
191
|
+
|
|
192
|
+
# Play completion sound (background, never blocks)
|
|
193
|
+
(
|
|
194
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
195
|
+
# macOS - use Glass.aiff for pleasant completion sound
|
|
196
|
+
afplay /System/Library/Sounds/Glass.aiff 2>/dev/null &
|
|
197
|
+
elif command -v paplay >/dev/null 2>&1; then
|
|
198
|
+
# Linux with PulseAudio
|
|
199
|
+
paplay /usr/share/sounds/freedesktop/stereo/complete.oga 2>/dev/null &
|
|
200
|
+
elif command -v aplay >/dev/null 2>&1; then
|
|
201
|
+
# Linux with ALSA
|
|
202
|
+
aplay /usr/share/sounds/alsa/Front_Center.wav 2>/dev/null &
|
|
203
|
+
fi
|
|
204
|
+
) &
|
|
205
|
+
|
|
206
|
+
log_debug "Task completion sound played (count: $previous_count β $current_count)"
|
|
207
|
+
fi
|
|
208
|
+
}
|
|
209
|
+
|
|
157
210
|
# ============================================================================
|
|
158
211
|
# INPUT PARSING (with safe fallbacks)
|
|
159
212
|
# ============================================================================
|
|
@@ -217,6 +270,9 @@ case "$FILE_PATH" in
|
|
|
217
270
|
log_debug "Running task-ac-sync guard"
|
|
218
271
|
safe_run_sync "$SYNC_SCRIPT" "task-ac-sync" "$INPUT"
|
|
219
272
|
fi
|
|
273
|
+
|
|
274
|
+
# Play completion sound if task was marked complete (v1.0.77+)
|
|
275
|
+
play_task_completion_sound "$FILE_PATH"
|
|
220
276
|
fi
|
|
221
277
|
|
|
222
278
|
# Tasks or spec changed -> check for US completion (background)
|