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