@champpaba/claude-agent-kit 2.0.0 → 2.1.0
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/CLAUDE.md +253 -31
- package/.claude/agents/01-integration.md +106 -552
- package/.claude/agents/02-uxui-frontend.md +188 -850
- package/.claude/agents/03-test-debug.md +152 -521
- package/.claude/agents/04-frontend.md +169 -549
- package/.claude/agents/05-backend.md +132 -661
- package/.claude/agents/06-database.md +149 -698
- package/.claude/agents/_shared/README.md +57 -0
- package/.claude/agents/_shared/agent-boundaries.md +64 -0
- package/.claude/agents/_shared/documentation-policy.md +47 -0
- package/.claude/agents/_shared/package-manager.md +59 -0
- package/.claude/agents/_shared/pre-work-checklist.md +57 -0
- package/.claude/commands/cdev.md +36 -61
- package/.claude/commands/csetup.md +90 -14
- package/.claude/commands/cstatus.md +153 -60
- package/.claude/commands/cview.md +364 -364
- package/.claude/commands/designsetup.md +1 -1
- package/.claude/commands/pageplan.md +53 -177
- package/.claude/commands/pstatus.md +431 -0
- package/.claude/contexts/design/accessibility.md +611 -611
- package/.claude/contexts/design/box-thinking.md +1 -1
- package/.claude/contexts/design/index.md +1 -1
- package/.claude/contexts/design/layout.md +400 -400
- package/.claude/contexts/design/responsive.md +551 -551
- package/.claude/contexts/design/shadows.md +522 -522
- package/.claude/contexts/design/typography.md +465 -465
- package/.claude/contexts/domain/README.md +164 -164
- package/.claude/contexts/patterns/agent-coordination.md +388 -388
- package/.claude/contexts/patterns/agent-discovery.md +2 -2
- package/.claude/contexts/patterns/animation-patterns.md +1 -1
- package/.claude/contexts/patterns/change-workflow.md +541 -538
- package/.claude/contexts/patterns/code-standards.md +10 -8
- package/.claude/contexts/patterns/development-principles.md +513 -513
- package/.claude/contexts/patterns/error-handling.md +478 -478
- package/.claude/contexts/patterns/error-recovery.md +365 -365
- package/.claude/contexts/patterns/frontend-component-strategy.md +1 -1
- package/.claude/contexts/patterns/logging.md +424 -424
- package/.claude/contexts/patterns/performance-optimization.md +1 -1
- package/.claude/contexts/patterns/task-breakdown.md +452 -452
- package/.claude/contexts/patterns/task-classification.md +523 -523
- package/.claude/contexts/patterns/tdd-classification.md +516 -516
- package/.claude/contexts/patterns/testing.md +413 -413
- package/.claude/contexts/patterns/ui-component-consistency.md +3 -3
- package/.claude/contexts/patterns/validation-framework.md +779 -776
- package/.claude/lib/README.md +4 -4
- package/.claude/lib/agent-executor.md +31 -40
- package/.claude/lib/agent-router.md +450 -572
- package/.claude/lib/context-loading-protocol.md +19 -36
- package/.claude/lib/detailed-guides/agent-system.md +43 -121
- package/.claude/lib/detailed-guides/taskmaster-analysis.md +1 -1
- package/.claude/lib/document-loader.md +22 -25
- package/.claude/lib/flags-updater.md +461 -469
- package/.claude/lib/tdd-classifier.md +345 -345
- package/.claude/lib/validation-gates.md +484 -484
- package/.claude/settings.local.json +42 -42
- package/.claude/templates/STYLE_GUIDE.template.md +1 -1
- package/.claude/templates/context-template.md +45 -45
- package/.claude/templates/design-context-template.md +1 -1
- package/.claude/templates/flags-template.json +42 -42
- package/.claude/templates/phases-sections/accessibility-test.md +17 -17
- package/.claude/templates/phases-sections/api-design.md +37 -37
- package/.claude/templates/phases-sections/backend-tests.md +16 -16
- package/.claude/templates/phases-sections/backend.md +37 -37
- package/.claude/templates/phases-sections/business-logic-validation.md +16 -16
- package/.claude/templates/phases-sections/component-tests.md +17 -17
- package/.claude/templates/phases-sections/contract-backend.md +16 -16
- package/.claude/templates/phases-sections/contract-frontend.md +16 -16
- package/.claude/templates/phases-sections/database.md +35 -35
- package/.claude/templates/phases-sections/e2e-tests.md +16 -16
- package/.claude/templates/phases-sections/fix-implementation.md +17 -17
- package/.claude/templates/phases-sections/frontend-integration.md +18 -18
- package/.claude/templates/phases-sections/frontend-mockup.md +126 -123
- package/.claude/templates/phases-sections/manual-flow-test.md +15 -15
- package/.claude/templates/phases-sections/manual-ux-test.md +16 -16
- package/.claude/templates/phases-sections/refactor-implementation.md +17 -17
- package/.claude/templates/phases-sections/refactor.md +16 -16
- package/.claude/templates/phases-sections/regression-tests.md +15 -15
- package/.claude/templates/phases-sections/responsive-test.md +16 -16
- package/.claude/templates/phases-sections/script-implementation.md +43 -43
- package/.claude/templates/phases-sections/test-coverage.md +16 -16
- package/.claude/templates/phases-sections/user-approval.md +14 -14
- package/LICENSE +21 -21
- package/PROJECT_STATUS.template.yml +105 -0
- package/README.md +103 -1115
- package/lib/init.js +30 -2
- package/package.json +3 -2
- package/.claude/CHANGELOG-v1.1.1.md +0 -259
|
@@ -1,469 +1,461 @@
|
|
|
1
|
-
# Flags.json Update Protocol
|
|
2
|
-
|
|
3
|
-
> **WHO:** Main Claude (orchestrator)
|
|
4
|
-
> **WHEN:** Immediately after sub-agent completes phase
|
|
5
|
-
> **
|
|
6
|
-
> **
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 🎯 Core Principle
|
|
11
|
-
|
|
12
|
-
**Main Claude
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Step
|
|
24
|
-
↓
|
|
25
|
-
Step
|
|
26
|
-
↓
|
|
27
|
-
Step
|
|
28
|
-
↓
|
|
29
|
-
Step
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
flags.meta.
|
|
89
|
-
flags.meta.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
flags.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
output(
|
|
130
|
-
output(`
|
|
131
|
-
output(`
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
]
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
]
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/(?:
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
-
|
|
409
|
-
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
-
|
|
413
|
-
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
//
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
output(`\n📍 Next: Phase ${flags.phases[flags.current_phase].phase_number}`)
|
|
463
|
-
output('Continue? (yes/no)')
|
|
464
|
-
}
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
**💡 Remember:** Main Claude updates flags.json. Always. No exceptions.
|
|
1
|
+
# Flags.json Update Protocol
|
|
2
|
+
|
|
3
|
+
> **WHO:** Main Claude (orchestrator)
|
|
4
|
+
> **WHEN:** Immediately after sub-agent completes phase
|
|
5
|
+
> **PURPOSE:** Real-time progress tracking for users
|
|
6
|
+
> **Version:** 2.0.0 (Claude 4.5 Optimized)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 🎯 Core Principle
|
|
11
|
+
|
|
12
|
+
**Main Claude updates flags.json after each phase.**
|
|
13
|
+
|
|
14
|
+
WHY: Sub-agents don't have direct access to flags.json. Users shouldn't have to manually track progress. Immediate updates ensure accurate /cstatus and /cview output.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🔄 Update Flow
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Step 1: Sub-agent responds with completion message
|
|
22
|
+
↓
|
|
23
|
+
Step 2: Main Claude validates response quality
|
|
24
|
+
↓
|
|
25
|
+
Step 3: Main Claude updates flags.json
|
|
26
|
+
↓
|
|
27
|
+
Step 4: Main Claude reports progress to user
|
|
28
|
+
↓
|
|
29
|
+
Step 5: Main Claude asks to continue (or auto-continue)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
WHY Step 3 is important: Without immediate update, /cstatus shows stale data and users can't track real progress.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 📝 Update Implementation
|
|
37
|
+
|
|
38
|
+
### Function Specification
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
/**
|
|
42
|
+
* Updates flags.json after a phase completes
|
|
43
|
+
*
|
|
44
|
+
* WHEN TO CALL: Immediately after sub-agent responds successfully
|
|
45
|
+
* WHERE: In /cdev command, Step 5 (Post-Execution)
|
|
46
|
+
*/
|
|
47
|
+
function updateFlagsAfterPhase(
|
|
48
|
+
changeId: string,
|
|
49
|
+
phaseName: string,
|
|
50
|
+
agentResponse: string
|
|
51
|
+
): void {
|
|
52
|
+
|
|
53
|
+
// 1. Read current flags
|
|
54
|
+
const flagsPath = `openspec/changes/${changeId}/.claude/flags.json`
|
|
55
|
+
|
|
56
|
+
if (!fileExists(flagsPath)) {
|
|
57
|
+
throw new Error(`flags.json not found at ${flagsPath}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const flags = JSON.parse(Read(flagsPath))
|
|
61
|
+
|
|
62
|
+
// 2. Extract information from agent response
|
|
63
|
+
const filesCreated = extractFilesCreated(agentResponse)
|
|
64
|
+
const filesModified = extractFilesModified(agentResponse)
|
|
65
|
+
const tasksCompleted = extractTaskIds(agentResponse)
|
|
66
|
+
const notes = extractSummary(agentResponse)
|
|
67
|
+
|
|
68
|
+
// Calculate duration
|
|
69
|
+
const startedAt = flags.phases[phaseName].started_at
|
|
70
|
+
const completedAt = new Date().toISOString()
|
|
71
|
+
const actualMinutes = calculateMinutes(startedAt, completedAt)
|
|
72
|
+
|
|
73
|
+
// 3. Update phase status
|
|
74
|
+
flags.phases[phaseName] = {
|
|
75
|
+
...flags.phases[phaseName],
|
|
76
|
+
status: 'completed',
|
|
77
|
+
completed_at: completedAt,
|
|
78
|
+
actual_minutes: actualMinutes,
|
|
79
|
+
files_created: filesCreated,
|
|
80
|
+
files_modified: filesModified,
|
|
81
|
+
tasks_completed: tasksCompleted,
|
|
82
|
+
notes: notes.substring(0, 200) // Limit to 200 chars
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 4. Update meta statistics
|
|
86
|
+
flags.meta.completed_phases++
|
|
87
|
+
flags.meta.pending_phases--
|
|
88
|
+
flags.meta.in_progress_phases = 0 // Reset in-progress
|
|
89
|
+
flags.meta.progress_percentage = Math.round(
|
|
90
|
+
(flags.meta.completed_phases / flags.meta.total_phases) * 100
|
|
91
|
+
)
|
|
92
|
+
flags.meta.total_actual_minutes += actualMinutes
|
|
93
|
+
flags.meta.time_remaining_estimate = calculateTimeRemaining(flags)
|
|
94
|
+
|
|
95
|
+
// Update file counts
|
|
96
|
+
flags.meta.files_created += filesCreated.length
|
|
97
|
+
flags.meta.files_modified += filesModified.length
|
|
98
|
+
|
|
99
|
+
// 5. Move to next phase
|
|
100
|
+
const nextPhase = getNextPhaseName(flags)
|
|
101
|
+
flags.current_phase = nextPhase
|
|
102
|
+
|
|
103
|
+
if (nextPhase && flags.phases[nextPhase]) {
|
|
104
|
+
flags.phases[nextPhase].status = 'pending'
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 6. Check if all complete
|
|
108
|
+
if (flags.meta.completed_phases === flags.meta.total_phases) {
|
|
109
|
+
flags.ready_to_archive = true
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 7. Update timestamp
|
|
113
|
+
flags.updated_at = new Date().toISOString()
|
|
114
|
+
|
|
115
|
+
// 8. Add to history
|
|
116
|
+
flags.history.push({
|
|
117
|
+
timestamp: completedAt,
|
|
118
|
+
action: 'phase_completed',
|
|
119
|
+
phase: phaseName,
|
|
120
|
+
duration_minutes: actualMinutes
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
// 9. Write back to file
|
|
124
|
+
Write(flagsPath, JSON.stringify(flags, null, 2))
|
|
125
|
+
|
|
126
|
+
// 10. Report success (to terminal, visible to user)
|
|
127
|
+
output(`\n📊 Progress Updated:`)
|
|
128
|
+
output(` ✅ Phase "${phaseName}" marked complete`)
|
|
129
|
+
output(` ⏱️ Duration: ${actualMinutes} min (estimated: ${flags.phases[phaseName].estimated_minutes} min)`)
|
|
130
|
+
output(` 📁 Files: ${filesCreated.length} created, ${filesModified.length} modified`)
|
|
131
|
+
output(` 📈 Progress: ${flags.meta.progress_percentage}% (${flags.meta.completed_phases}/${flags.meta.total_phases})`)
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 🔍 Helper Functions
|
|
138
|
+
|
|
139
|
+
### extractFilesCreated()
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
function extractFilesCreated(response: string): string[] {
|
|
143
|
+
const patterns = [
|
|
144
|
+
/(?:Created|created|Created:)\s*(.+)/gi,
|
|
145
|
+
/📁\s*(?:Created|created):\s*(.+)/gi,
|
|
146
|
+
/✅\s*Created\s+file:\s*(.+)/gi,
|
|
147
|
+
/new file:\s*(.+)/gi
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
const files: string[] = []
|
|
151
|
+
|
|
152
|
+
for (const pattern of patterns) {
|
|
153
|
+
const matches = response.matchAll(pattern)
|
|
154
|
+
for (const match of matches) {
|
|
155
|
+
// Extract file paths (one per line or comma-separated)
|
|
156
|
+
const paths = match[1].split(/[,\n]/).map(p => p.trim())
|
|
157
|
+
files.push(...paths.filter(p => p.length > 0))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Remove duplicates
|
|
162
|
+
return [...new Set(files)]
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### extractFilesModified()
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
function extractFilesModified(response: string): string[] {
|
|
170
|
+
const patterns = [
|
|
171
|
+
/(?:Modified|modified|Updated|updated):\s*(.+)/gi,
|
|
172
|
+
/📝\s*(?:Modified|updated):\s*(.+)/gi,
|
|
173
|
+
/✏️\s*Updated\s+file:\s*(.+)/gi
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
const files: string[] = []
|
|
177
|
+
|
|
178
|
+
for (const pattern of patterns) {
|
|
179
|
+
const matches = response.matchAll(pattern)
|
|
180
|
+
for (const match of matches) {
|
|
181
|
+
const paths = match[1].split(/[,\n]/).map(p => p.trim())
|
|
182
|
+
files.push(...paths.filter(p => p.length > 0))
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return [...new Set(files)]
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### extractTaskIds()
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
function extractTaskIds(response: string): string[] {
|
|
194
|
+
// Look for task IDs like "1.1", "1.2", "2.1"
|
|
195
|
+
const pattern = /(?:task|Task)\s*(?:ID|id)?:?\s*([\d\.]+)/gi
|
|
196
|
+
const matches = response.matchAll(pattern)
|
|
197
|
+
|
|
198
|
+
const taskIds: string[] = []
|
|
199
|
+
for (const match of matches) {
|
|
200
|
+
taskIds.push(match[1])
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return taskIds
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### extractSummary()
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
function extractSummary(response: string): string {
|
|
211
|
+
// Look for summary section
|
|
212
|
+
const summaryPatterns = [
|
|
213
|
+
/(?:Summary|SUMMARY):\s*(.+?)(?:\n\n|\n#|$)/si,
|
|
214
|
+
/(?:Notes|NOTES):\s*(.+?)(?:\n\n|\n#|$)/si,
|
|
215
|
+
/(?:Completed|COMPLETED):\s*(.+?)(?:\n\n|\n#|$)/si
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
for (const pattern of summaryPatterns) {
|
|
219
|
+
const match = response.match(pattern)
|
|
220
|
+
if (match) {
|
|
221
|
+
return match[1].trim()
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Fallback: First 200 chars of response
|
|
226
|
+
return response.substring(0, 200).trim()
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### calculateMinutes()
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
function calculateMinutes(startISO: string, endISO: string): number {
|
|
234
|
+
const start = new Date(startISO)
|
|
235
|
+
const end = new Date(endISO)
|
|
236
|
+
const diffMs = end - start
|
|
237
|
+
return Math.round(diffMs / 1000 / 60) // Convert to minutes
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### getNextPhaseName()
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
function getNextPhaseName(flags: Flags): string | null {
|
|
245
|
+
// Get all phase names in order
|
|
246
|
+
const phaseNames = Object.keys(flags.phases).sort((a, b) => {
|
|
247
|
+
return flags.phases[a].phase_number - flags.phases[b].phase_number
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// Find first pending phase
|
|
251
|
+
for (const name of phaseNames) {
|
|
252
|
+
if (flags.phases[name].status === 'pending') {
|
|
253
|
+
return name
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// All phases complete
|
|
258
|
+
return null
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### calculateTimeRemaining()
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
function calculateTimeRemaining(flags: Flags): number {
|
|
266
|
+
let remaining = 0
|
|
267
|
+
|
|
268
|
+
for (const [name, phase] of Object.entries(flags.phases)) {
|
|
269
|
+
if (phase.status === 'pending' || phase.status === 'in_progress') {
|
|
270
|
+
remaining += phase.estimated_minutes || 0
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return remaining
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 📋 Best Practices
|
|
281
|
+
|
|
282
|
+
### Update Timing
|
|
283
|
+
|
|
284
|
+
| When | Action |
|
|
285
|
+
|------|--------|
|
|
286
|
+
| Sub-agent returns success | Update flags.json immediately |
|
|
287
|
+
| Before asking user to continue | Flags should already be updated |
|
|
288
|
+
| After each phase | Update individually (not batched) |
|
|
289
|
+
|
|
290
|
+
WHY: Immediate updates ensure /cstatus always shows accurate progress.
|
|
291
|
+
|
|
292
|
+
### Correct Flow
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
Sub-agent completes
|
|
296
|
+
→ Main Claude updates flags.json
|
|
297
|
+
→ Main Claude reports progress
|
|
298
|
+
→ Main Claude asks user to continue
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Validate Before Update
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
// Check 1: flags.json exists
|
|
305
|
+
if (!fileExists(flagsPath)) {
|
|
306
|
+
output(`❌ Error: flags.json not found`)
|
|
307
|
+
output(`Run: /csetup ${changeId}`)
|
|
308
|
+
return
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Check 2: Phase exists in flags
|
|
312
|
+
if (!flags.phases[phaseName]) {
|
|
313
|
+
output(`❌ Error: Phase "${phaseName}" not found in flags.json`)
|
|
314
|
+
return
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Check 3: Sub-agent actually completed work
|
|
318
|
+
if (!agentResponse.includes('✅') && !agentResponse.includes('Complete')) {
|
|
319
|
+
output(`⚠️ Warning: Agent response does not confirm completion`)
|
|
320
|
+
output(`Proceed with caution`)
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Report to User
|
|
325
|
+
|
|
326
|
+
```markdown
|
|
327
|
+
After updating flags.json, show:
|
|
328
|
+
|
|
329
|
+
📊 Progress Updated:
|
|
330
|
+
✅ Phase "frontend-mockup" marked complete
|
|
331
|
+
⏱️ Duration: 95 min (estimated: 90 min)
|
|
332
|
+
📁 Files: 4 created, 0 modified
|
|
333
|
+
📈 Progress: 9% (1/11)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## 🐛 Error Handling
|
|
339
|
+
|
|
340
|
+
### Scenario 1: flags.json Not Found
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
if (!fileExists(flagsPath)) {
|
|
344
|
+
output(`❌ Error: flags.json not found`)
|
|
345
|
+
output(`Expected at: ${flagsPath}`)
|
|
346
|
+
output(`\nPlease run: /csetup ${changeId}`)
|
|
347
|
+
throw new Error('flags.json not found')
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Scenario 2: Invalid JSON
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
try {
|
|
355
|
+
const flags = JSON.parse(Read(flagsPath))
|
|
356
|
+
} catch (error) {
|
|
357
|
+
output(`❌ Error: flags.json is corrupted (invalid JSON)`)
|
|
358
|
+
output(`\nOptions:`)
|
|
359
|
+
output(`1. Restore from backup`)
|
|
360
|
+
output(`2. Re-run: /csetup ${changeId} (will overwrite)`)
|
|
361
|
+
throw new Error('Invalid flags.json')
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Scenario 3: Phase Not Found
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
if (!flags.phases[phaseName]) {
|
|
369
|
+
output(`❌ Error: Phase "${phaseName}" not found in flags.json`)
|
|
370
|
+
output(`\nAvailable phases:`)
|
|
371
|
+
Object.keys(flags.phases).forEach(name => {
|
|
372
|
+
output(` - ${name}`)
|
|
373
|
+
})
|
|
374
|
+
throw new Error('Phase not found')
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Scenario 4: Cannot Extract Files
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
const filesCreated = extractFilesCreated(agentResponse)
|
|
382
|
+
|
|
383
|
+
if (filesCreated.length === 0) {
|
|
384
|
+
output(`⚠️ Warning: Could not extract created files from agent response`)
|
|
385
|
+
output(`\nPlease manually specify files (comma-separated, or press Enter to skip):`)
|
|
386
|
+
const userInput = await getUserInput()
|
|
387
|
+
if (userInput.trim()) {
|
|
388
|
+
filesCreated = userInput.split(',').map(f => f.trim())
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## 📊 Success Indicators
|
|
396
|
+
|
|
397
|
+
After implementing this protocol, you should see:
|
|
398
|
+
|
|
399
|
+
1. **100% Update Rate**
|
|
400
|
+
- Every phase completion → flags.json updated
|
|
401
|
+
- No manual intervention needed
|
|
402
|
+
|
|
403
|
+
2. **Real-Time Progress**
|
|
404
|
+
- User sees progress after every phase
|
|
405
|
+
- `/cstatus` shows accurate data
|
|
406
|
+
|
|
407
|
+
3. **Accurate Time Tracking**
|
|
408
|
+
- Actual vs estimated time recorded
|
|
409
|
+
- Efficiency metrics available
|
|
410
|
+
|
|
411
|
+
4. **Complete Audit Trail**
|
|
412
|
+
- History log in flags.json
|
|
413
|
+
- Can reconstruct entire workflow
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## 🔗 Integration Points
|
|
418
|
+
|
|
419
|
+
**This protocol is used by:**
|
|
420
|
+
- `/cdev` command (Step 5: Post-Execution)
|
|
421
|
+
- `/cstatus` command (reads updated flags)
|
|
422
|
+
- `/cview` command (reads updated flags)
|
|
423
|
+
|
|
424
|
+
**This protocol depends on:**
|
|
425
|
+
- `flags-template.json` (initial structure)
|
|
426
|
+
- `/csetup` command (creates flags.json)
|
|
427
|
+
- Sub-agents (provide completion responses)
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## 🎯 Quick Reference
|
|
432
|
+
|
|
433
|
+
**Main Claude, after sub-agent completes:**
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
// 1. Validate response
|
|
437
|
+
if (!validateAgentResponse(agentResponse)) {
|
|
438
|
+
// Handle retry or escalation
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// 2. Update flags.json (MANDATORY)
|
|
442
|
+
updateFlagsAfterPhase(changeId, currentPhase, agentResponse)
|
|
443
|
+
|
|
444
|
+
// 3. Read updated flags
|
|
445
|
+
const flags = JSON.parse(Read(`openspec/changes/${changeId}/.claude/flags.json`))
|
|
446
|
+
|
|
447
|
+
// 4. Report to user
|
|
448
|
+
output(`\n📊 Progress: ${flags.meta.progress_percentage}%`)
|
|
449
|
+
|
|
450
|
+
// 5. Ask to continue
|
|
451
|
+
if (flags.ready_to_archive) {
|
|
452
|
+
output('✅ All phases complete!')
|
|
453
|
+
} else {
|
|
454
|
+
output(`\n📍 Next: Phase ${flags.phases[flags.current_phase].phase_number}`)
|
|
455
|
+
output('Continue? (yes/no)')
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
**💡 Summary:** Main Claude updates flags.json immediately after each phase completes. This ensures accurate progress tracking.
|