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