@champpaba/claude-agent-kit 3.2.0 → 3.4.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.
@@ -40,39 +40,71 @@ Run: /csetup {change-id}
40
40
 
41
41
  ### Step 2: Read Current Phase
42
42
 
43
- ```typescript
44
- const flags = JSON.parse(Read('openspec/changes/{change-id}/.claude/flags.json'))
45
- const currentPhase = flags.current_phase
46
- const phaseData = flags.phases[currentPhase]
47
-
48
- if (phaseData.status === 'completed') {
49
- // Move to next phase
50
- currentPhase = getNextPhase(flags)
51
- }
43
+ ---
44
+
45
+ #### Step 2.1: Read flags.json
46
+
47
+ 1. Read the file `openspec/changes/{change-id}/.claude/flags.json`
48
+ 2. Extract and note these values:
49
+ - `current_phase` - The current phase name
50
+ - `phases[current_phase].status` - The phase status
51
+ - `phases[current_phase].agent` - The assigned agent
52
+
53
+ ---
54
+
55
+ #### Step 2.2: Check Phase Status
56
+
57
+ **If status equals "completed":**
58
+ 1. Look up the next phase in phases.md
59
+ 2. Update current_phase to the next phase name
60
+
61
+ **If status equals "pending" or "in_progress":**
62
+ 1. Keep using the current phase (no change)
63
+
64
+ ---
65
+
66
+ #### Step 2.3: Report Status
67
+
68
+ Display this information:
52
69
  ```
70
+ šŸ“ Current Phase: {phase_number} - {phase_name}
71
+ Agent: {agent}
72
+ Status: {status}
73
+ ```
74
+
75
+ ---
53
76
 
54
77
  ### Step 3: Check Phase Type
55
78
 
56
- ```typescript
57
- const agent = phaseData.agent
58
-
59
- if (agent === 'user') {
60
- // Manual action required
61
- output(`šŸ›‘ Phase ${phaseData.phase_number} requires manual action`)
62
- output(`Instructions: ${getInstructions(currentPhase)}`)
63
- output(`When done: /cdev ${changeId} --continue`)
64
- return
65
- }
66
-
67
- if (agent.includes('+')) {
68
- // Multiple agents (parallel)
69
- agents = agent.split('+').map(a => a.trim())
70
- invokeMultipleAgents(agents, changeId, currentPhase)
71
- } else {
72
- // Single agent
73
- invokeAgent(agent, changeId, currentPhase)
74
- }
75
- ```
79
+ ---
80
+
81
+ #### Step 3.1: Check for Manual Action
82
+
83
+ **If the agent value equals "user":**
84
+ 1. Display this message:
85
+ ```
86
+ šŸ›‘ Phase {phase_number} requires manual action
87
+
88
+ Instructions:
89
+ {instructions from phases.md}
90
+
91
+ When done: /cdev {change-id} --continue
92
+ ```
93
+ 2. Stop execution and wait for user to complete the task
94
+ 3. Wait for user to run /cdev again
95
+
96
+ ---
97
+
98
+ #### Step 3.2: Check for Multiple Agents
99
+
100
+ **If the agent value contains "+" (example: "backend + database"):**
101
+ 1. Split the agent string by "+" into a list of individual agents
102
+ 2. Invoke all agents in parallel
103
+ 3. Wait for all agents to complete before proceeding
104
+
105
+ **If there is only a single agent:**
106
+ 1. Invoke that single agent
107
+ 2. Wait for completion then proceed to Step 4
76
108
 
77
109
  ### Step 4: Invoke Agent with Retry & Validation
78
110
 
@@ -84,283 +116,268 @@ See: `.claude/lib/agent-executor.md` for full implementation
84
116
 
85
117
  1. **Calculate Context Size** (for model selection)
86
118
  2. **Select Model** (haiku vs sonnet based on complexity)
87
- 3. **Execute Agent with Retry** (automatic retry on failure)
88
- 4. **Validate Pre-Work** (enforce mandatory checklist)
89
- 5. **Validate Output Quality** (check completeness)
90
- 6. **Handle Errors** (retry or escalate)
119
+ 3. **Pre-Flight Design Check** (for visual agents) ← NEW v3.3.0
120
+ 4. **Execute Agent with Retry** (automatic retry on failure)
121
+ 5. **Validate Pre-Work** (enforce mandatory checklist)
122
+ 6. **Validate Output Quality** (check completeness)
123
+ 7. **Handle Errors** (retry or escalate)
91
124
 
92
- **Implementation:**
125
+ ### Step 4.0: Pre-Flight Design Check (v3.3.0)
93
126
 
94
- ```typescript
95
- // Step 4: Invoke Agent with Retry & Validation
127
+ → **Full Protocol:** `.claude/lib/design-validator.md` (Part 2)
96
128
 
97
- // 4.1: Build agent prompt (with design reference + best practices - v2.1.2)
98
- function buildAgentPrompt(phase, changeContext) {
99
- let prompt = `
100
- # Phase ${phase.phase_number}: ${phase.name}
129
+ **When to execute:** Before invoking uxui-frontend or frontend agent
130
+
131
+ ---
101
132
 
102
- ## Change Context
103
- ${changeContext.proposal}
133
+ #### Step 4.0.1: Check if Visual Agent
104
134
 
105
- ## Tasks
106
- ${changeContext.tasks}
135
+ 1. Look at the phase.agent value
136
+ 2. Check if it equals `uxui-frontend` or `frontend`
107
137
 
108
- ## Design Decisions (from design.md)
109
- ${changeContext.design || '(no design.md found)'}
138
+ **If NOT a visual agent:**
139
+ - Skip Step 4.0 entirely and proceed to Step 4.1
110
140
 
111
- ${phase.instructions}
141
+ **If it IS a visual agent:**
142
+ - Proceed to next step
112
143
 
113
144
  ---
114
145
 
115
- ## šŸ“¦ Library Requirements
146
+ #### Step 4.0.2: Check for Design System
116
147
 
117
- **Scan for required libraries before implementation:**
148
+ 1. Attempt to read the file `design-system/data.yaml`
118
149
 
119
- 1. **Review tasks.md above** for these patterns:
120
- - "Install X and dependencies" → Use library X
121
- - "Configure X with Y adapter" → Use X with adapter Y
122
- - Backtick packages like \`better-auth\` → Required dependency
150
+ **If the file exists:**
151
+ 1. Display this message:
152
+ ```
153
+ āœ… Design system found: design-system/data.yaml
154
+ ```
155
+ 2. Proceed to Step 4.0.3
123
156
 
124
- 2. **Review "Design Decisions" section above** for:
125
- - "### D1: Use X Library" → Decision to use X
126
- - "**Decision:** Use X" → Chosen library
127
- - Specific configurations (e.g., "JWT 15min", "Redis refresh token 30d")
128
- - Architecture decisions (e.g., "Hybrid Session Strategy")
157
+ **If the file does NOT exist:**
158
+ 1. Display this warning:
159
+ ```
160
+ āš ļø WARNING: No design system found!
161
+ Path: design-system/data.yaml (not found)
129
162
 
130
- 3. **Use the specified libraries**
131
- - WHY: The team chose these for compatibility, features, or constraints
132
- - Custom implementations duplicate effort and miss edge cases the library handles
163
+ Options:
164
+ 1. Run /designsetup first (recommended)
165
+ 2. Continue with fallback design principles
133
166
 
134
- 4. **Implement according to Design Spec (not library defaults)**
135
- - If design.md specifies "JWT 15min + Redis refresh 30d" → Configure library with these values
136
- - If design.md specifies custom endpoints → Implement those endpoints
137
- - Library defaults are starting points, not final implementation
138
- - WHY: Design decisions were made for specific project requirements
167
+ Proceeding with fallback...
168
+ ```
169
+ 2. Skip to Step 4.1 without injecting design system instructions
139
170
 
140
- **Example:**
141
- \`\`\`
142
- design.md says:
143
- "Hybrid Session Strategy: JWT 15min + Redis refresh 30d"
171
+ ---
144
172
 
145
- → Use better-auth library (from tasks.md)
146
- → Configure JWT plugin with 15min expiry
147
- → Configure refresh token with 30d in Redis
148
- → Implement /api/auth/refresh endpoint
173
+ #### Step 4.0.3: Inject Design System Instructions
149
174
 
150
- WHY not defaults? Design spec has project-specific security requirements
151
- that differ from library defaults.
152
- \`\`\`
175
+ When building the agent prompt, include this text:
153
176
 
154
- **Report in validation:**
155
- \`\`\`
156
- Libraries: better-auth, @better-auth/drizzle, ioredis
157
- Design Spec Implementation:
158
- - [x] JWT access token: 15min (design.md D1)
159
- - [x] Redis refresh token: 30d (design.md D2)
160
- - [x] /api/auth/refresh endpoint (design.md D3)
161
- \`\`\`
177
+ ```
178
+ MANDATORY: Read design-system/data.yaml before writing any CSS/Tailwind.
179
+ Report the tokens you loaded before starting implementation.
180
+
181
+ You must report:
182
+ - Colors: primary=#xxx, secondary=#xxx, etc.
183
+ - Spacing scale: 4, 8, 12, 16, 24, 32, 48, 64
184
+ - Animation durations: 150ms, 300ms, 500ms ONLY
185
+
186
+ DO NOT use:
187
+ - Hardcoded colors (#3b82f6, rgb())
188
+ - Arbitrary spacing (p-5, gap-7)
189
+ - Random durations (duration-200, duration-250)
190
+ ```
162
191
 
163
192
  ---
164
- `
165
193
 
166
- // v3.1.0: Add Level 1 Universal Patterns (development-principles.md) for ALL agents
167
- // Source: context-loading-protocol.md - Level 1 patterns apply to ALL agents
168
- const devPrinciplesPath = '.claude/contexts/patterns/development-principles.md'
169
- if (fileExists(devPrinciplesPath)) {
170
- prompt += `
194
+ #### Step 4.0.4: Verify Agent Compliance
171
195
 
172
- ---
196
+ After the agent responds, check the output for this report:
173
197
 
174
- ## šŸ›ļø Development Principles (Level 1 - ALL Agents)
198
+ ```
199
+ āœ… Design System Loaded (STEP 0.5)
200
+ - Source: design-system/data.yaml
201
+ - Colors: [list]
202
+ - Spacing: [list]
203
+ - Animation: [list]
204
+ ```
175
205
 
176
- **REQUIRED READING:** @${devPrinciplesPath}
206
+ **If the report is present:**
207
+ - Validation passed, proceed
177
208
 
178
- These principles apply to ALL code written by ALL agents:
209
+ **If the report is missing:**
210
+ - Ask the agent whether they read the design system
179
211
 
180
- **Quick Reference:**
181
- | Principle | Summary |
182
- |-----------|---------|
183
- | **KISS** | Choose simple solutions over complex ones |
184
- | **YAGNI** | Build only what you need now |
185
- | **SRP** | One responsibility per module |
186
- | **DRY** | Single source of truth for all knowledge |
187
- | **Fail Fast** | Detect and raise errors immediately |
188
- | **Observability** | Log everything that matters |
212
+ ---
189
213
 
190
- **Report format:**
191
- \`\`\`
192
- āœ… Development Principles Applied
193
- - KISS āœ“ (simple implementation)
194
- - DRY āœ“ (no duplication)
195
- - Separation of Concerns āœ“
196
- \`\`\`
214
+ ### Step 4.1: Build Agent Prompt
197
215
 
198
- ---
199
- `
200
- }
216
+ Build the agent prompt by assembling these sections:
201
217
 
202
- // Add best-practices reference for ALL agents
203
- const bpDir = '.claude/contexts/domain/project/best-practices/'
204
- if (fileExists(bpDir)) {
205
- const bpFiles = listFiles(bpDir).filter(f => f.endsWith('.md') && f !== 'index.md')
218
+ ---
206
219
 
207
- // Map agent type to relevant best-practices
208
- const agentBpMapping = {
209
- 'uxui-frontend': ['react', 'nextjs', 'vue', 'tailwind'],
210
- 'frontend': ['react', 'nextjs', 'vue', 'typescript'],
211
- 'backend': ['express', 'fastapi', 'django', 'prisma', 'drizzle'],
212
- 'database': ['prisma', 'drizzle', 'postgres', 'mongodb'],
213
- 'test-debug': ['vitest', 'jest', 'playwright'],
214
- 'integration': ['typescript'], // minimal
215
- 'ux-tester': [] // No best practices needed - uses Chrome DevTools
216
- }
220
+ #### Section 1: Change Context
217
221
 
218
- const relevantTechs = agentBpMapping[phase.agent] || []
219
- const relevantFiles = bpFiles.filter(f =>
220
- relevantTechs.some(tech => f.toLowerCase().includes(tech))
221
- )
222
+ Include information from these files:
223
+ 1. Read `proposal.md` - What we're building and why
224
+ 2. Read `tasks.md` - Tasks for this phase
225
+ 3. Read `design.md` - Design decisions (if the file exists)
226
+ 4. Read `phases.md` - Phase instructions
222
227
 
223
- if (relevantFiles.length > 0) {
224
- prompt += `
228
+ Combine this information into the prompt context.
225
229
 
226
230
  ---
227
231
 
228
- ## šŸ“š Best Practices (STEP 0)
232
+ #### Section 2: Library Requirements (v2.1.2)
229
233
 
230
- Read these files before implementation for quality output:
234
+ Add these instructions to the agent prompt:
235
+ 1. Scan tasks.md for patterns like: "Install X", "Configure X"
236
+ 2. Scan design.md for: "D1: Use X Library", "Decision: Use X"
237
+ 3. Use the specified libraries, not custom implementations
238
+ 4. Implement according to design spec, not library defaults
231
239
 
232
- ${relevantFiles.map(f => `- Read: ${bpDir}${f}`).join('\n')}
240
+ ---
233
241
 
234
- **Report format:**
235
- \`\`\`
236
- āœ… Best Practices Loaded
237
- ${relevantFiles.map(f => `- ${f.replace('.md', '')} āœ“`).join('\n ')}
238
- \`\`\`
242
+ #### Section 3: Development Principles (v3.1.0 - ALL agents)
239
243
 
240
- WHY: Best practices ensure consistency with project patterns.
244
+ **If the file `.claude/contexts/patterns/development-principles.md` exists:**
241
245
 
242
- ---
243
- `
244
- }
245
- }
246
+ Add this section to the prompt:
247
+ ```
248
+ ## šŸ›ļø Development Principles (Level 1 - ALL Agents)
246
249
 
247
- // Add design reference for uxui-frontend agent (not full content!)
248
- if (phase.agent === 'uxui-frontend') {
249
- const tokensPath = 'design-system/data.yaml'
250
- const dataYamlPath = 'design-system/data.yaml'
251
- const hasTokens = fileExists(tokensPath)
250
+ REQUIRED READING: @.claude/contexts/patterns/development-principles.md
252
251
 
253
- if (hasTokens) {
254
- prompt += `
252
+ Quick Reference:
253
+ | Principle | Summary |
254
+ |-----------|---------|
255
+ | KISS | Choose simple solutions |
256
+ | YAGNI | Build only what you need now |
257
+ | SRP | One responsibility per module |
258
+ | DRY | Single source of truth |
259
+ | Fail Fast | Detect errors immediately |
260
+ ```
255
261
 
256
262
  ---
257
263
 
258
- ## šŸŽØ Design System (STEP 0.5)
259
-
260
- **Files to read:**
264
+ #### Section 4: Best Practices (agent-specific)
261
265
 
262
- ${hasTokens ? `- design-system/data.yaml (~500 tokens) - Colors, spacing, typography, psychology` : ''}
266
+ **If the directory `.claude/contexts/domain/project/best-practices/` exists:**
263
267
 
264
- **Style Guidelines:**
268
+ 1. Determine which best-practices files match the current agent:
265
269
 
266
- | Instead of | Use | WHY |
267
- |------------|-----|-----|
268
- | text-gray-500, #64748b | text-foreground/70, bg-muted | Theme-aware |
269
- | p-5, gap-7 | p-4, p-6, gap-8 | Spacing scale |
270
- | mixing shadow-sm/lg | consistent shadow-md | Visual consistency |
270
+ | Agent | Relevant Topics |
271
+ |-------|-----------------|
272
+ | uxui-frontend | react, nextjs, vue, tailwind |
273
+ | frontend | react, nextjs, vue, typescript |
274
+ | backend | express, fastapi, django, prisma, drizzle |
275
+ | database | prisma, drizzle, postgres, mongodb |
276
+ | test-debug | vitest, jest, playwright |
277
+ | integration | typescript |
278
+ | ux-tester | (none) |
271
279
 
272
- **Report format:**
273
- \`\`\`
274
- āœ… Design System Loaded
275
- - data.yaml āœ“
276
- - Design Tokens Extracted: [list key tokens]
277
- \`\`\`
280
+ 2. Add this section to the prompt with the relevant file names:
281
+ ```
282
+ ## šŸ“š Best Practices (STEP 0)
278
283
 
279
- WHY: Design tokens ensure visual consistency across components.
284
+ Read these files before implementation:
285
+ - Read: .claude/contexts/domain/project/best-practices/{relevant-file}.md
286
+ ```
280
287
 
281
288
  ---
282
- `
283
- } else {
284
- prompt += `
285
289
 
286
- ---
290
+ #### Section 5: Design System (uxui-frontend only)
287
291
 
288
- āš ļø **WARNING:** No design system found!
289
- Using fallback: .claude/contexts/design/*.md (universal principles)
292
+ **If the agent equals uxui-frontend:**
290
293
 
291
- Run \`/designsetup\` to generate project-specific design system.
294
+ 1. Check if `design-system/data.yaml` exists
292
295
 
293
- ---
294
- `
295
- }
296
- }
296
+ **If the file exists:**
297
+ Add this section to the prompt:
298
+ ```
299
+ ## šŸŽØ Design System (STEP 0.5)
297
300
 
298
- return prompt
299
- }
301
+ Files to read:
302
+ - design-system/data.yaml
300
303
 
301
- const prompt = buildAgentPrompt(phase, changeContext)
304
+ Style Guidelines:
305
+ | Instead of | Use |
306
+ |------------|-----|
307
+ | text-gray-500, #64748b | text-foreground, bg-muted |
308
+ | p-5, gap-7 | p-4, p-6, gap-8 |
309
+ | mixing shadow-sm/lg | consistent shadow-md |
310
+ ```
302
311
 
303
- // 4.2: Execute agent with retry & validation
304
- output(`\nšŸš€ Invoking ${phase.agent} agent (model: opus)...`)
312
+ **If the file does NOT exist:**
313
+ Add this warning to the prompt:
314
+ ```
315
+ āš ļø WARNING: No design system found!
316
+ Using fallback: .claude/contexts/design/*.md
317
+ ```
318
+
319
+ ---
305
320
 
306
- const result = await executeAgentWithRetry(
307
- phase.agent,
308
- phase,
309
- changeContext,
310
- {
311
- max_retries: 2,
312
- retry_delay: 5000,
313
- timeout: 600000, // 10 minutes
314
- validate_output: true
315
- }
316
- )
321
+ ### Step 4.2: Execute Agent with Retry
317
322
 
318
- // 4.3: Handle result
319
- if (result.success) {
320
- output(`\nāœ… Phase ${phase.phase_number} completed successfully!`)
321
- output(`ā±ļø Execution time: ${(result.execution_time / 1000).toFixed(1)}s`)
322
- output(`šŸ”„ Retries used: ${result.retries_used}`)
323
- output(`āœ… Validation: ${result.validation_passed ? 'PASSED' : 'SKIPPED'}`)
323
+ ---
324
324
 
325
- // Continue to Step 5: Post-Execution
326
- } else {
327
- output(`\nāŒ Phase ${phase.phase_number} failed`)
328
- output(`Error: ${result.error}`)
329
- output(`Retries used: ${result.retries_used}`)
325
+ #### Step 4.2.1: Invoke the Agent
330
326
 
331
- // Escalate to user
332
- const action = await escalateToUser(phase.agent, phase, result)
327
+ 1. Display this message before invoking:
328
+ ```
329
+ šŸš€ Invoking {agent} agent (model: opus)...
330
+ ```
333
331
 
334
- switch (action) {
335
- case 'retry':
336
- output(`Retrying Phase ${phase.phase_number}...`)
337
- // Restart Step 4
338
- return executePhaseAgain(changeId, phase)
332
+ 2. Invoke the agent with these settings:
333
+ - Model: opus (fixed)
334
+ - Timeout: 10 minutes
335
+ - Max retries: 2 attempts
339
336
 
340
- case 'skip':
341
- output(`āš ļø Skipping Phase ${phase.phase_number}`)
342
- await markPhaseAsSkipped(changeId, phase, result.error)
343
- // Continue to next phase
344
- break
337
+ ---
345
338
 
346
- case 'abort':
347
- output(`šŸ›‘ Workflow aborted`)
348
- output(`Resume with: /cdev ${changeId}`)
349
- return
350
- }
351
- }
352
- ```
339
+ #### Step 4.2.2: Handle Result
340
+
341
+ **If execution succeeded:**
342
+ 1. Display this success message:
343
+ ```
344
+ āœ… Phase {phase_number} completed successfully!
345
+ ā±ļø Execution time: {time}s
346
+ šŸ”„ Retries used: {retries}
347
+ āœ… Validation: PASSED
348
+ ```
349
+ 2. Proceed to Step 5
350
+
351
+ **If execution failed:**
352
+ 1. Display this error message:
353
+ ```
354
+ āŒ Phase {phase_number} failed
355
+ Error: {error}
356
+ Retries used: {retries}
357
+ ```
358
+
359
+ 2. Ask the user for their choice:
360
+ ```
361
+ Options:
362
+ [retry] - Try again
363
+ [skip] - Skip this phase
364
+ [abort] - Stop execution
365
+ ```
366
+
367
+ 3. Wait for user response and act accordingly
353
368
 
354
- **Helper Functions Used:**
369
+ ---
355
370
 
356
- 1. **buildAgentPrompt()**: See `.claude/lib/agent-executor.md`
357
- 2. **executeAgentWithRetry()**: See `.claude/lib/agent-executor.md`
358
- 3. **escalateToUser()**: See `.claude/lib/agent-executor.md`
371
+ **Helper Functions:**
372
+
373
+ See `.claude/lib/agent-executor.md` for:
374
+ - buildAgentPrompt()
375
+ - executeAgentWithRetry()
376
+ - escalateToUser()
359
377
 
360
378
  **Model Strategy:**
361
379
  - All agents use `model: opus` (fixed)
362
380
  - Opus 4.5 is the latest Claude model with best performance
363
- - Quality maintained through comprehensive validation framework
364
381
 
365
382
  ---
366
383
 
@@ -389,309 +406,302 @@ See `.claude/contexts/patterns/validation-framework.md` for complete checklist p
389
406
 
390
407
  ### Step 4.6: Approval Gate Handling (v2.7.0)
391
408
 
392
- **NEW:** Handle phases with `requires_approval: true` (e.g., ux-tester Phase 1.5)
409
+ **For phases with** `requires_approval: true` (example: ux-tester Phase 1.5)
410
+
411
+ ---
412
+
413
+ #### Step 4.6.1: Check if Approval Required
414
+
415
+ 1. Look in phases.md at the current phase
416
+ 2. Check if it has:
417
+ - `requires_approval: true`
418
+ - OR metadata contains the word `approval-gate`
419
+
420
+ **If approval is NOT required:**
421
+ - Skip Step 4.6 entirely
422
+
423
+ **If approval IS required:**
424
+ - Proceed to next step
393
425
 
394
- ```typescript
395
- // Check if this phase requires user approval
396
- const isApprovalGate = phase.requires_approval === true ||
397
- phase.metadata?.includes('approval-gate')
426
+ ---
398
427
 
399
- if (isApprovalGate && result.success) {
400
- // Read all phases for loop back logic
401
- const phasesPath = `openspec/changes/${changeId}/.claude/phases.md`
402
- const allPhases = parsePhasesFromMd(Read(phasesPath))
428
+ #### Step 4.6.2: Display Results and Wait for Decision
403
429
 
404
- output(`
430
+ Display this message:
431
+ ```
405
432
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
406
- 🧪 ${phase.name} Complete - Awaiting Approval
433
+ 🧪 {phase_name} Complete - Awaiting Approval
407
434
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
408
435
 
409
- ${result.summary || 'Report generated successfully'}
436
+ {result_summary}
410
437
 
411
- šŸ“„ Full report: ${result.reportPath || `openspec/changes/${changeId}/ux-test-report.md`}
438
+ šŸ“„ Full report: openspec/changes/{change-id}/ux-test-report.md
412
439
 
413
440
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
414
441
 
415
- ąøąø£ąøøąø“ąø²ąø•ąø±ąø”ąøŖąø“ąø™ą¹ƒąøˆ:
442
+ Please decide:
416
443
 
417
- āœ… "approve" → ไป Phase ถัดไป
418
- āŒ "reject [feedback]" → ąøąø„ąø±ąøšą¹ąøą¹‰ą¹„ąø‚ Phase ąøą¹ˆąø­ąø™ąø«ąø™ą¹‰ąø²
444
+ āœ… "approve" → Continue to next phase
445
+ āŒ "reject [feedback]" → Go back and fix previous phase
419
446
 
420
447
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
421
- `)
422
-
423
- // PAUSE - Main Claude waits for user's next message
424
- // User responds with "approve" or "reject [feedback]"
425
- return { status: 'awaiting_approval', phase, changeId }
426
- }
427
-
428
- // When user responds (in next message):
429
- function handleUserApprovalResponse(userResponse: string, phase: Phase, changeId: string, allPhases: Phase[]) {
430
- const normalized = userResponse.trim().toLowerCase()
431
-
432
- // Handle APPROVE
433
- if (normalized.match(/^(approve|approved|ok|yes|ใช่|อนุดัตณ|ąøœą¹ˆąø²ąø™|ąø„ąøøąø¢|ได้|ดี)$/)) {
434
- output(`āœ… ${phase.name} approved! Continuing to next phase...`)
435
- updateFlags(changeId, {
436
- [`phase_${phase.phase_number}`]: {
437
- status: 'approved',
438
- approved_at: new Date().toISOString()
439
- }
440
- })
441
- // Continue to Step 5
442
- return { action: 'continue' }
443
- }
444
-
445
- // Handle REJECT
446
- if (normalized.startsWith('reject') || normalized.startsWith('ą¹„ąø”ą¹ˆ') ||
447
- normalized.startsWith('แก้') || normalized.startsWith('no')) {
448
-
449
- const feedback = userResponse.replace(/^(reject|ą¹„ąø”ą¹ˆąø­ąø™ąøøąø”ąø±ąø•ąø“|แก้ไข|no)\s*/i, '').trim()
450
-
451
- // Find the phase to loop back to
452
- const loopBackPhase = allPhases.find(p => p.agent === 'uxui-frontend') || allPhases[0]
453
-
454
- output(`
455
- šŸ”„ ${phase.name} rejected
456
-
457
- šŸ“ Feedback: ${feedback || 'None provided'}
458
- šŸ”™ Looping back to: Phase ${loopBackPhase.phase_number} - ${loopBackPhase.name}
459
-
460
- ${loopBackPhase.agent} agent ąøˆąø°ą¹„ąø”ą¹‰ąø£ąø±ąøš feedback ąø™ąøµą¹‰ą¹€ąøžąø·ą¹ˆąø­ą¹ąøą¹‰ą¹„ąø‚
461
- `)
462
-
463
- // Update flags for rejection
464
- updateFlags(changeId, {
465
- [`phase_${phase.phase_number}`]: {
466
- status: 'rejected',
467
- rejected_at: new Date().toISOString(),
468
- rejection_feedback: feedback
469
- },
470
- [`phase_${loopBackPhase.phase_number}`]: {
471
- status: 'pending',
472
- rerun_reason: `Rejected from UX Testing: ${feedback}`
473
- }
474
- })
475
-
476
- // Loop back to uxui-frontend phase
477
- output(`\nšŸ”„ Restarting Phase ${loopBackPhase.phase_number}: ${loopBackPhase.name}`)
478
- return {
479
- action: 'loop_back',
480
- loopBackPhase,
481
- feedback
482
- }
483
- }
484
-
485
- // Unknown response - ask again
486
- output(`āš ļø ą¹„ąø”ą¹ˆą¹€ąø‚ą¹‰ąø²ą¹ƒąøˆąø„ąø³ąø•ąø­ąøš ąøąø£ąøøąø“ąø²ąø•ąø­ąøš "approve" หรือ "reject [feedback]"`)
487
- return { action: 'ask_again' }
488
- }
489
448
  ```
490
449
 
450
+ Wait for user response.
451
+
452
+ ---
453
+
454
+ #### Step 4.6.3: Handle User Response
455
+
456
+ **If user approves:**
457
+ 1. Recognize these words as approval: approve, approved, ok, yes, ใช่, อนุดัตณ, ąøœą¹ˆąø²ąø™, ąø„ąøøąø¢, ได้, ดี
458
+ 2. Display: `āœ… {phase_name} approved! Continuing to next phase...`
459
+ 3. Update flags.json: set status = "approved"
460
+ 4. Proceed to Step 5
461
+
462
+ **If user rejects:**
463
+ 1. Recognize these words as rejection: reject, ą¹„ąø”ą¹ˆ, แก้, no (followed by feedback)
464
+ 2. Extract the feedback text from the user's message
465
+ 3. Identify which phase needs to be fixed (uxui-frontend)
466
+ 4. Display:
467
+ ```
468
+ šŸ”„ {phase_name} rejected
469
+
470
+ šŸ“ Feedback: {feedback}
471
+ šŸ”™ Looping back to: Phase {X} - {phase_name}
472
+
473
+ {agent} agent will receive this feedback for fixes
474
+ ```
475
+ 5. Update flags.json: set status = "rejected"
476
+ 6. Return to run the phase that needs fixing
477
+
478
+ **If response is unclear:**
479
+ 1. Display:
480
+ ```
481
+ āš ļø Response unclear. Please answer "approve" or "reject [feedback]"
482
+ ```
483
+ 2. Ask the user again
484
+
485
+ ---
486
+
491
487
  **See:** `.claude/lib/agent-executor.md` → "Approval Gate Execution" section for complete flow
492
488
 
493
489
  ---
494
490
 
495
491
  ### Step 4.7: Validate Page Plan Compliance (uxui-frontend only)
496
492
 
497
- **Only runs for uxui-frontend agent when page-plan.md exists:**
498
-
499
- **Purpose:** Verify agent implemented ALL sections from page-plan.md, not a subset.
500
-
501
- ```typescript
502
- // Check if page-plan.md exists
503
- const pagePlanPath = `openspec/changes/${changeId}/page-plan.md`
504
- const hasPagePlan = fileExists(pagePlanPath)
505
-
506
- if (phase.agent === 'uxui-frontend' && hasPagePlan) {
507
- output(`\nšŸ” Validating page-plan.md compliance...`)
508
-
509
- // Extract sections from page-plan.md Section 2 (Page Structure)
510
- const pagePlan = Read(pagePlanPath)
511
- const section2Match = pagePlan.match(/## 2\. Page Structure[\s\S]*?(?=## 3\.|## 2\.5|## 2\.6|$)/)
512
-
513
- if (section2Match) {
514
- // Count expected sections (extract component names from JSX)
515
- const componentMatches = section2Match[0].match(/<([A-Z]\w+)/g) || []
516
- const expectedComponents = componentMatches
517
- .map(m => m.replace('<', ''))
518
- .filter(name => name !== 'Layout' && name !== 'div') // Exclude wrappers
519
-
520
- const uniqueComponents = [...new Set(expectedComponents)] // Remove duplicates
521
-
522
- output(`\nšŸ“‹ Page Plan Analysis:`)
523
- output(` Expected sections: ${uniqueComponents.length}`)
524
- output(` Components: ${uniqueComponents.join(', ')}`)
525
-
526
- // Prompt user to verify agent compliance
527
- output(`\nāš ļø VALIDATION REQUIRED:`)
528
- output(`\nDid the agent implement ALL ${uniqueComponents.length} sections?`)
529
- output(`\nPlease verify the implementation includes:`)
530
- uniqueComponents.forEach(c => output(` - ${c}`))
531
-
532
- output(`\nOptions:`)
533
- output(` [yes] - All sections implemented āœ“`)
534
- output(` [retry] - Agent skipped sections, retry with strict enforcement`)
535
- output(` [skip] - Skip validation (not recommended)`)
536
-
537
- const answer = await askUser(`\nConfirm all sections implemented?`)
538
-
539
- if (answer === 'retry') {
540
- output(`\nšŸ”„ Retrying phase with enhanced enforcement...`)
541
- output(`Agent will be explicitly instructed to implement all ${uniqueComponents.length} sections`)
542
-
543
- // Restart phase with enhanced prompt
544
- return executePhaseAgain(changeId, phase, {
545
- enforce_page_plan: true,
546
- required_sections: uniqueComponents
547
- })
548
- } else if (answer === 'skip') {
549
- warn(`\nāš ļø Skipping validation - proceed with caution`)
550
- warn(` This may result in incomplete implementation`)
551
- } else {
552
- output(`\nāœ… Page plan compliance confirmed`)
553
- output(` All ${uniqueComponents.length} sections implemented`)
554
- }
555
- } else {
556
- warn(`\nāš ļø Could not parse page-plan.md Section 2`)
557
- warn(` Skipping compliance validation`)
558
- }
559
- } else {
560
- // Not uxui-frontend or no page-plan.md - skip validation
561
- output(`\nā„¹ļø Page plan validation: N/A (agent: ${phase.agent}, has plan: ${hasPagePlan})`)
562
- }
493
+ **Only for uxui-frontend agent when page-plan.md exists**
494
+
495
+ **Purpose:** Verify that agent implemented all sections from page-plan.md
496
+
497
+ ---
498
+
499
+ #### Step 4.7.1: Check Prerequisites
500
+
501
+ **If agent is NOT uxui-frontend OR page-plan.md does NOT exist:**
502
+ 1. Display:
503
+ ```
504
+ ā„¹ļø Page plan validation: N/A (agent: {agent}, has plan: {true/false})
505
+ ```
506
+ 2. Skip Step 4.7 entirely
507
+
508
+ **If agent equals uxui-frontend AND page-plan.md exists:**
509
+ - Proceed to next step
510
+
511
+ ---
512
+
513
+ #### Step 4.7.2: Analyze page-plan.md
514
+
515
+ 1. Read `openspec/changes/{change-id}/page-plan.md`
516
+ 2. Find Section 2 (Page Structure)
517
+ 3. Count the components:
518
+ - Look for JSX elements starting with uppercase (example: `<HeroSection>`, `<PricingTable>`)
519
+ - Do NOT count Layout, div (wrapper elements)
520
+ - Remove duplicates
521
+
522
+ 4. Display:
523
+ ```
524
+ šŸ“‹ Page Plan Analysis:
525
+ Expected sections: {count}
526
+ Components: {list}
527
+ ```
528
+
529
+ ---
530
+
531
+ #### Step 4.7.3: Ask User for Confirmation
532
+
533
+ Display this prompt:
534
+ ```
535
+ āš ļø VALIDATION REQUIRED:
536
+
537
+ Did the agent implement ALL {count} sections?
538
+
539
+ Please verify the implementation includes:
540
+ - {Component1}
541
+ - {Component2}
542
+ - ...
543
+
544
+ Options:
545
+ [yes] - All sections implemented āœ“
546
+ [retry] - Agent skipped sections, retry with strict enforcement
547
+ [skip] - Skip validation (not recommended)
563
548
  ```
564
549
 
550
+ Wait for user response.
551
+
552
+ ---
553
+
554
+ #### Step 4.7.4: Handle User Response
555
+
556
+ **If user answers yes:**
557
+ 1. Display:
558
+ ```
559
+ āœ… Page plan compliance confirmed
560
+ All {count} sections implemented
561
+ ```
562
+ 2. Proceed to Step 5
563
+
564
+ **If user answers retry:**
565
+ 1. Display:
566
+ ```
567
+ šŸ”„ Retrying phase with enhanced enforcement...
568
+ Agent will be explicitly instructed to implement all {count} sections
569
+ ```
570
+ 2. Return to run the phase again with enhanced prompt
571
+
572
+ **If user answers skip:**
573
+ 1. Display:
574
+ ```
575
+ āš ļø Skipping validation - proceed with caution
576
+ This may result in incomplete implementation
577
+ ```
578
+ 2. Proceed to Step 5
579
+
580
+ ---
581
+
565
582
  **When to use:**
566
- - āœ… Agent: uxui-frontend
567
- - āœ… page-plan.md exists
568
- - āœ… Phase completed successfully
583
+ - Agent: uxui-frontend
584
+ - page-plan.md exists
585
+ - Phase completed successfully
569
586
 
570
587
  **Common issues caught:**
571
588
  - Agent implemented 5/10 sections (missing ProblemSection, ComparisonTable, etc.)
572
589
  - Agent followed tasks.md ("4-5 components") instead of page-plan.md (10 sections)
573
590
  - Agent skipped sections they thought were "optional"
574
591
 
575
- **Remediation:**
576
- - If validation fails → Retry with `enforce_page_plan: true`
577
- - Agent will receive enhanced prompt with explicit section list
578
- - Validation runs again after retry
579
-
580
592
  ---
581
593
 
582
594
  ### Step 5: Post-Execution (Flags Update)
583
595
 
584
- **Main Claude updates flags.json after each phase completion.**
596
+ **Main Claude updates flags.json after each phase**
585
597
 
586
598
  → See: `.claude/lib/flags-updater.md` for complete protocol
587
599
 
588
600
  WHY: Immediate updates ensure /cstatus shows accurate progress.
589
601
 
590
- **Execution Order:**
591
-
592
- ```typescript
593
- // 1. Update flags.json
594
- output(`\nšŸ”„ Updating progress tracking...`)
595
-
596
- // See flags-updater.md for updateFlagsAfterPhase() implementation
597
- updateFlagsAfterPhase(changeId, currentPhase, agentResponse)
598
-
599
- // This function:
600
- // - Marks phase as completed
601
- // - Records actual duration
602
- // - Extracts files created/modified
603
- // - Updates meta statistics (progress %, time remaining)
604
- // - Moves current_phase to next phase
605
- // - Writes back to flags.json
606
- // - Reports progress to user
607
-
608
- // 2. Read updated flags
609
- const flagsPath = `openspec/changes/${changeId}/.claude/flags.json`
610
- const flags = JSON.parse(Read(flagsPath))
611
-
612
- // 3. Report progress to user
613
- output(`\nšŸ“Š Progress Update:`)
614
- output(` āœ… ${flags.meta.completed_phases}/${flags.meta.total_phases} phases complete`)
615
- output(` šŸ“ˆ ${flags.meta.progress_percentage}% progress`)
616
- output(` ā±ļø ${formatDuration(flags.meta.total_actual_minutes)} spent`)
617
- output(` ā±ļø ${formatDuration(flags.meta.time_remaining_estimate)} remaining`)
618
-
619
- // 4. Check next phase
620
- if (flags.ready_to_archive) {
621
- // šŸ†• v1.2.0: Verbose Summary Output (replaces documentation/report phases)
622
- output(`\n`)
623
- output(`╔════════════════════════════════════════════════════════════╗`)
624
- output(`ā•‘ āœ… CHANGE COMPLETED SUCCESSFULLY ā•‘`)
625
- output(`ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•`)
626
- output(``)
627
- output(`šŸ“¦ Change: ${changeId}`)
628
- output(`šŸ“‹ Template: ${flags.template} (${flags.meta.total_phases} phases)`)
629
- output(``)
630
- output(`═══════════════════════════════════════════════════════════════`)
631
- output(`šŸ“Š EXECUTION SUMMARY`)
632
- output(`═══════════════════════════════════════════════════════════════`)
633
- output(``)
634
- output(`ā±ļø Time:`)
635
- output(` • Estimated: ${formatDuration(flags.meta.total_estimated_minutes)}`)
636
- output(` • Actual: ${formatDuration(flags.meta.total_actual_minutes)}`)
637
- output(` • Variance: ${calculateVariance(flags.meta)}`)
638
- output(``)
639
- output(`šŸ“ˆ Phases Completed: ${flags.meta.completed_phases}/${flags.meta.total_phases}`)
640
-
641
- // List all phases with status
642
- Object.entries(flags.phases).forEach(([phaseId, phase]) => {
643
- const status = phase.status === 'completed' ? 'āœ…' :
644
- phase.status === 'skipped' ? 'ā­ļø' : 'āŒ'
645
- const time = phase.actual_minutes ? `(${phase.actual_minutes}m)` : ''
646
- output(` ${status} ${phase.phase_number}. ${phaseId} ${time}`)
647
- })
648
-
649
- output(``)
650
- output(`═══════════════════════════════════════════════════════════════`)
651
- output(`šŸ“ FILES CREATED/MODIFIED`)
652
- output(`═══════════════════════════════════════════════════════════════`)
653
-
654
- // Collect all files from phase outputs
655
- const allFiles = collectFilesFromPhases(flags.phases)
656
- if (allFiles.created.length > 0) {
657
- output(``)
658
- output(`✨ Created (${allFiles.created.length}):`)
659
- allFiles.created.forEach(f => output(` • ${f}`))
660
- }
661
- if (allFiles.modified.length > 0) {
662
- output(``)
663
- output(`šŸ“ Modified (${allFiles.modified.length}):`)
664
- allFiles.modified.forEach(f => output(` • ${f}`))
665
- }
666
-
667
- output(``)
668
- output(`═══════════════════════════════════════════════════════════════`)
669
- output(`šŸš€ NEXT STEPS`)
670
- output(`═══════════════════════════════════════════════════════════════`)
671
- output(``)
672
- output(`1. Review changes: /cview ${changeId}`)
673
- output(`2. Test manually: Verify the implementation works`)
674
- output(`3. Mark complete: Update tasks.md (mark all [x])`)
675
- output(`4. Archive: openspec archive ${changeId}`)
676
- output(``)
677
- output(`šŸ’” Note: flags.json contains full execution history`)
678
- output(` Path: openspec/changes/${changeId}/.claude/flags.json`)
679
- output(``)
680
- } else {
681
- const nextPhase = flags.phases[flags.current_phase]
682
-
683
- output(`\nšŸ“ Next: Phase ${nextPhase.phase_number}: ${flags.current_phase}`)
684
- output(` Agent: ${nextPhase.agent}`)
685
- output(` Estimated: ${nextPhase.estimated_minutes} min`)
686
-
687
- if (nextPhase.agent === 'user') {
688
- output('\nšŸ›‘ Next phase requires your action')
689
- output(`When done: /cdev ${changeId} --continue`)
690
- } else {
691
- output('\nContinue? (yes/no)')
692
- }
693
- }
602
+ ---
603
+
604
+ #### Step 5.1: Update flags.json
605
+
606
+ 1. Display:
607
+ ```
608
+ šŸ”„ Updating progress tracking...
609
+ ```
610
+
611
+ 2. Update these fields in flags.json:
612
+ - Mark the phase as completed
613
+ - Record actual duration
614
+ - Extract files created/modified
615
+ - Update meta statistics (progress %, time remaining)
616
+ - Move current_phase to next phase
617
+
618
+ ---
619
+
620
+ #### Step 5.2: Report Progress
621
+
622
+ Display this progress summary:
694
623
  ```
624
+ šŸ“Š Progress Update:
625
+ āœ… {completed}/{total} phases complete
626
+ šŸ“ˆ {percentage}% progress
627
+ ā±ļø {time_spent} spent
628
+ ā±ļø {time_remaining} remaining
629
+ ```
630
+
631
+ ---
632
+
633
+ #### Step 5.3: Check Next Phase
634
+
635
+ **If all phases are complete (ready_to_archive equals true):**
636
+
637
+ Display this completion report:
638
+ ```
639
+ ╔════════════════════════════════════════════════════════════╗
640
+ ā•‘ āœ… CHANGE COMPLETED SUCCESSFULLY ā•‘
641
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
642
+
643
+ šŸ“¦ Change: {change-id}
644
+ šŸ“‹ Template: {template} ({total_phases} phases)
645
+
646
+ ═══════════════════════════════════════════════════════════════
647
+ šŸ“Š EXECUTION SUMMARY
648
+ ═══════════════════════════════════════════════════════════════
649
+
650
+ ā±ļø Time:
651
+ • Estimated: {estimated}
652
+ • Actual: {actual}
653
+ • Variance: {variance}
654
+
655
+ šŸ“ˆ Phases Completed: {completed}/{total}
656
+ āœ… 1. phase-name (Xm)
657
+ āœ… 2. phase-name (Xm)
658
+ ...
659
+
660
+ ═══════════════════════════════════════════════════════════════
661
+ šŸ“ FILES CREATED/MODIFIED
662
+ ═══════════════════════════════════════════════════════════════
663
+
664
+ ✨ Created ({count}):
665
+ • {file1}
666
+ • {file2}
667
+
668
+ šŸ“ Modified ({count}):
669
+ • {file1}
670
+ • {file2}
671
+
672
+ ═══════════════════════════════════════════════════════════════
673
+ šŸš€ NEXT STEPS
674
+ ═══════════════════════════════════════════════════════════════
675
+
676
+ 1. Review changes: /cview {change-id}
677
+ 2. Test manually: Verify the implementation works
678
+ 3. Mark complete: Update tasks.md (mark all [x])
679
+ 4. Archive: openspec archive {change-id}
680
+ ```
681
+
682
+ **If there are still incomplete phases:**
683
+
684
+ Display the next phase information:
685
+ ```
686
+ šŸ“ Next: Phase {X}: {phase_name}
687
+ Agent: {agent}
688
+ Estimated: {X} min
689
+ ```
690
+
691
+ **If the next phase requires manual action:**
692
+ Display:
693
+ ```
694
+ šŸ›‘ Next phase requires your action
695
+ When done: /cdev {change-id} --continue
696
+ ```
697
+
698
+ **If the next phase is an agent:**
699
+ Ask the user:
700
+ ```
701
+ Continue? (yes/no)
702
+ ```
703
+
704
+ ---
695
705
 
696
706
  **Key points:**
697
707
  - Main Claude updates flags.json (sub-agents don't have access)