@champpaba/claude-agent-kit 3.2.0 → 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.
- package/.claude/CHANGELOG.md +62 -0
- package/.claude/CLAUDE.md +56 -2
- package/.claude/agents/02-uxui-frontend.md +99 -16
- package/.claude/agents/07-ux-tester.md +307 -108
- package/.claude/commands/cdev.md +465 -492
- package/.claude/lib/README.md +8 -0
- package/.claude/lib/design-validator.md +330 -0
- package/package.json +1 -1
package/.claude/commands/cdev.md
CHANGED
|
@@ -40,39 +40,69 @@ Run: /csetup {change-id}
|
|
|
40
40
|
|
|
41
41
|
### Step 2: Read Current Phase
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
57
|
-
const agent = phaseData.agent
|
|
79
|
+
---
|
|
58
80
|
|
|
59
|
-
|
|
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
|
-
}
|
|
81
|
+
#### ตรวจสอบว่า phase ต้องการ manual action หรือไม่
|
|
66
82
|
|
|
67
|
-
|
|
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
|
-
}
|
|
83
|
+
**ถ้า agent = "user":**
|
|
75
84
|
```
|
|
85
|
+
🛑 Phase {phase_number} requires manual action
|
|
86
|
+
|
|
87
|
+
Instructions:
|
|
88
|
+
{instructions from phases.md}
|
|
89
|
+
|
|
90
|
+
When done: /cdev {change-id} --continue
|
|
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,283 +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. **
|
|
88
|
-
4. **
|
|
89
|
-
5. **Validate
|
|
90
|
-
6. **
|
|
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)
|
|
122
|
+
|
|
123
|
+
### Step 4.0: Pre-Flight Design Check (v3.3.0)
|
|
91
124
|
|
|
92
|
-
**
|
|
125
|
+
→ **Full Protocol:** `.claude/lib/design-validator.md` (Part 2)
|
|
93
126
|
|
|
94
|
-
|
|
95
|
-
// Step 4: Invoke Agent with Retry & Validation
|
|
127
|
+
**เมื่อไหร่ต้องทำ:** ก่อน invoke uxui-frontend หรือ frontend agent ทุกครั้ง
|
|
96
128
|
|
|
97
|
-
|
|
98
|
-
function buildAgentPrompt(phase, changeContext) {
|
|
99
|
-
let prompt = `
|
|
100
|
-
# Phase ${phase.phase_number}: ${phase.name}
|
|
129
|
+
---
|
|
101
130
|
|
|
102
|
-
|
|
103
|
-
${changeContext.proposal}
|
|
131
|
+
#### ขั้นตอนที่ 1: ตรวจสอบว่าเป็น visual agent หรือไม่
|
|
104
132
|
|
|
105
|
-
|
|
106
|
-
${changeContext.tasks}
|
|
133
|
+
ดู phase.agent ว่าเป็น `uxui-frontend` หรือ `frontend` หรือไม่
|
|
107
134
|
|
|
108
|
-
|
|
109
|
-
${changeContext.design || '(no design.md found)'}
|
|
135
|
+
**ถ้าไม่ใช่:** ข้าม Step 4.0 ไปเลย
|
|
110
136
|
|
|
111
|
-
|
|
137
|
+
**ถ้าใช่:** ทำขั้นตอนถัดไป
|
|
112
138
|
|
|
113
139
|
---
|
|
114
140
|
|
|
115
|
-
|
|
141
|
+
#### ขั้นตอนที่ 2: ตรวจสอบว่ามี design system หรือไม่
|
|
116
142
|
|
|
117
|
-
|
|
143
|
+
อ่านไฟล์ `design-system/data.yaml`
|
|
118
144
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
145
|
+
**ถ้ามีไฟล์:**
|
|
146
|
+
```
|
|
147
|
+
✅ Design system found: design-system/data.yaml
|
|
148
|
+
```
|
|
149
|
+
→ ไปขั้นตอนที่ 3
|
|
123
150
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
156
|
+
Options:
|
|
157
|
+
1. Run /designsetup first (recommended)
|
|
158
|
+
2. Continue with fallback design principles
|
|
133
159
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
141
|
-
\`\`\`
|
|
142
|
-
design.md says:
|
|
143
|
-
"Hybrid Session Strategy: JWT 15min + Redis refresh 30d"
|
|
164
|
+
---
|
|
144
165
|
|
|
145
|
-
|
|
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
|
-
|
|
151
|
-
that differ from library defaults.
|
|
152
|
-
\`\`\`
|
|
168
|
+
เมื่อ invoke agent ต้องบอกใน prompt ว่า:
|
|
153
169
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
-
|
|
160
|
-
-
|
|
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
|
-
|
|
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 += `
|
|
187
|
+
#### ขั้นตอนที่ 4: Verify agent compliance หลัง agent ตอบกลับ
|
|
171
188
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
## 🏛️ Development Principles (Level 1 - ALL Agents)
|
|
189
|
+
ตรวจสอบว่า agent output มี report นี้หรือไม่:
|
|
175
190
|
|
|
176
|
-
|
|
191
|
+
```
|
|
192
|
+
✅ Design System Loaded (STEP 0.5)
|
|
193
|
+
- Source: design-system/data.yaml
|
|
194
|
+
- Colors: [list]
|
|
195
|
+
- Spacing: [list]
|
|
196
|
+
- Animation: [list]
|
|
197
|
+
```
|
|
177
198
|
|
|
178
|
-
|
|
199
|
+
**ถ้ามี report:** ผ่าน ไปต่อได้
|
|
179
200
|
|
|
180
|
-
|
|
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 |
|
|
189
|
-
|
|
190
|
-
**Report format:**
|
|
191
|
-
\`\`\`
|
|
192
|
-
✅ Development Principles Applied
|
|
193
|
-
- KISS ✓ (simple implementation)
|
|
194
|
-
- DRY ✓ (no duplication)
|
|
195
|
-
- Separation of Concerns ✓
|
|
196
|
-
\`\`\`
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
`
|
|
200
|
-
}
|
|
201
|
-
|
|
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')
|
|
206
|
-
|
|
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
|
-
}
|
|
217
|
-
|
|
218
|
-
const relevantTechs = agentBpMapping[phase.agent] || []
|
|
219
|
-
const relevantFiles = bpFiles.filter(f =>
|
|
220
|
-
relevantTechs.some(tech => f.toLowerCase().includes(tech))
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
if (relevantFiles.length > 0) {
|
|
224
|
-
prompt += `
|
|
201
|
+
**ถ้าไม่มี report:** ถาม agent ว่าอ่าน design system หรือยัง
|
|
225
202
|
|
|
226
203
|
---
|
|
227
204
|
|
|
228
|
-
|
|
205
|
+
### Step 4.1: Build Agent Prompt
|
|
229
206
|
|
|
230
|
-
|
|
207
|
+
**สร้าง prompt สำหรับ agent โดยประกอบด้วย:**
|
|
231
208
|
|
|
232
|
-
|
|
209
|
+
---
|
|
233
210
|
|
|
234
|
-
|
|
235
|
-
\`\`\`
|
|
236
|
-
✅ Best Practices Loaded
|
|
237
|
-
${relevantFiles.map(f => `- ${f.replace('.md', '')} ✓`).join('\n ')}
|
|
238
|
-
\`\`\`
|
|
211
|
+
#### ส่วนที่ 1: Change Context
|
|
239
212
|
|
|
240
|
-
|
|
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
|
|
241
218
|
|
|
242
219
|
---
|
|
243
|
-
`
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
220
|
|
|
247
|
-
|
|
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)
|
|
221
|
+
#### ส่วนที่ 2: Library Requirements (v2.1.2)
|
|
252
222
|
|
|
253
|
-
|
|
254
|
-
|
|
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
|
|
255
228
|
|
|
256
229
|
---
|
|
257
230
|
|
|
258
|
-
|
|
231
|
+
#### ส่วนที่ 3: Development Principles (v3.1.0 - ALL agents)
|
|
259
232
|
|
|
260
|
-
|
|
233
|
+
**ถ้ามีไฟล์** `.claude/contexts/patterns/development-principles.md`:
|
|
261
234
|
|
|
262
|
-
|
|
235
|
+
เพิ่มใน prompt:
|
|
236
|
+
```
|
|
237
|
+
## 🏛️ Development Principles (Level 1 - ALL Agents)
|
|
263
238
|
|
|
264
|
-
|
|
239
|
+
REQUIRED READING: @.claude/contexts/patterns/development-principles.md
|
|
265
240
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
|
270
|
-
|
|
|
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
|
+
```
|
|
271
250
|
|
|
272
|
-
|
|
273
|
-
\`\`\`
|
|
274
|
-
✅ Design System Loaded
|
|
275
|
-
- data.yaml ✓
|
|
276
|
-
- Design Tokens Extracted: [list key tokens]
|
|
277
|
-
\`\`\`
|
|
251
|
+
---
|
|
278
252
|
|
|
279
|
-
|
|
253
|
+
#### ส่วนที่ 4: Best Practices (agent-specific)
|
|
280
254
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
255
|
+
**ถ้ามี directory** `.claude/contexts/domain/project/best-practices/`:
|
|
256
|
+
|
|
257
|
+
หา best-practices files ที่ตรงกับ agent:
|
|
258
|
+
|
|
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
|
+
```
|
|
285
276
|
|
|
286
277
|
---
|
|
287
278
|
|
|
288
|
-
|
|
289
|
-
|
|
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
|
|
289
|
+
|
|
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
|
+
```
|
|
290
297
|
|
|
291
|
-
|
|
298
|
+
**ถ้าไม่มี:**
|
|
299
|
+
```
|
|
300
|
+
⚠️ WARNING: No design system found!
|
|
301
|
+
Using fallback: .claude/contexts/design/*.md
|
|
302
|
+
```
|
|
292
303
|
|
|
293
304
|
---
|
|
294
|
-
`
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
305
|
|
|
298
|
-
|
|
299
|
-
}
|
|
306
|
+
### Step 4.2: Execute Agent with Retry
|
|
300
307
|
|
|
301
|
-
|
|
308
|
+
---
|
|
302
309
|
|
|
303
|
-
|
|
304
|
-
output(`\n🚀 Invoking ${phase.agent} agent (model: opus)...`)
|
|
310
|
+
#### การ invoke agent
|
|
305
311
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
{
|
|
311
|
-
max_retries: 2,
|
|
312
|
-
retry_delay: 5000,
|
|
313
|
-
timeout: 600000, // 10 minutes
|
|
314
|
-
validate_output: true
|
|
315
|
-
}
|
|
316
|
-
)
|
|
312
|
+
Report ก่อน invoke:
|
|
313
|
+
```
|
|
314
|
+
🚀 Invoking {agent} agent (model: opus)...
|
|
315
|
+
```
|
|
317
316
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
output(`🔄 Retries used: ${result.retries_used}`)
|
|
323
|
-
output(`✅ Validation: ${result.validation_passed ? 'PASSED' : 'SKIPPED'}`)
|
|
317
|
+
Invoke agent ด้วย:
|
|
318
|
+
- Model: opus (fixed)
|
|
319
|
+
- Timeout: 10 นาที
|
|
320
|
+
- Max retries: 2 ครั้ง
|
|
324
321
|
|
|
325
|
-
|
|
326
|
-
} else {
|
|
327
|
-
output(`\n❌ Phase ${phase.phase_number} failed`)
|
|
328
|
-
output(`Error: ${result.error}`)
|
|
329
|
-
output(`Retries used: ${result.retries_used}`)
|
|
322
|
+
---
|
|
330
323
|
|
|
331
|
-
|
|
332
|
-
const action = await escalateToUser(phase.agent, phase, result)
|
|
324
|
+
#### Handle Result
|
|
333
325
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
326
|
+
**ถ้าสำเร็จ:**
|
|
327
|
+
```
|
|
328
|
+
✅ Phase {phase_number} completed successfully!
|
|
329
|
+
⏱️ Execution time: {time}s
|
|
330
|
+
🔄 Retries used: {retries}
|
|
331
|
+
✅ Validation: PASSED
|
|
332
|
+
```
|
|
333
|
+
→ ไป Step 5
|
|
339
334
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
335
|
+
**ถ้าล้มเหลว:**
|
|
336
|
+
```
|
|
337
|
+
❌ Phase {phase_number} failed
|
|
338
|
+
Error: {error}
|
|
339
|
+
Retries used: {retries}
|
|
340
|
+
```
|
|
345
341
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
342
|
+
ถาม user:
|
|
343
|
+
```
|
|
344
|
+
Options:
|
|
345
|
+
[retry] - ลองใหม่
|
|
346
|
+
[skip] - ข้าม phase นี้
|
|
347
|
+
[abort] - หยุดทำงาน
|
|
352
348
|
```
|
|
353
349
|
|
|
354
|
-
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
**Helper Functions:**
|
|
355
353
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
354
|
+
See `.claude/lib/agent-executor.md` for:
|
|
355
|
+
- buildAgentPrompt()
|
|
356
|
+
- executeAgentWithRetry()
|
|
357
|
+
- escalateToUser()
|
|
359
358
|
|
|
360
359
|
**Model Strategy:**
|
|
361
360
|
- All agents use `model: opus` (fixed)
|
|
362
361
|
- Opus 4.5 is the latest Claude model with best performance
|
|
363
|
-
- Quality maintained through comprehensive validation framework
|
|
364
362
|
|
|
365
363
|
---
|
|
366
364
|
|
|
@@ -389,26 +387,32 @@ See `.claude/contexts/patterns/validation-framework.md` for complete checklist p
|
|
|
389
387
|
|
|
390
388
|
### Step 4.6: Approval Gate Handling (v2.7.0)
|
|
391
389
|
|
|
392
|
-
|
|
390
|
+
**สำหรับ phases ที่มี** `requires_approval: true` (เช่น ux-tester Phase 1.5)
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
#### ขั้นตอนที่ 1: ตรวจสอบว่า phase ต้องการ approval หรือไม่
|
|
393
395
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
phase.metadata?.includes('approval-gate')
|
|
396
|
+
ดูใน phases.md ว่า phase ปัจจุบันมี:
|
|
397
|
+
- `requires_approval: true`
|
|
398
|
+
- หรือ metadata มีคำว่า `approval-gate`
|
|
398
399
|
|
|
399
|
-
|
|
400
|
-
// Read all phases for loop back logic
|
|
401
|
-
const phasesPath = `openspec/changes/${changeId}/.claude/phases.md`
|
|
402
|
-
const allPhases = parsePhasesFromMd(Read(phasesPath))
|
|
400
|
+
**ถ้าไม่ต้องการ approval:** ข้าม Step 4.6 ไปเลย
|
|
403
401
|
|
|
404
|
-
|
|
402
|
+
**ถ้าต้องการ approval:** ทำขั้นตอนถัดไป
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
#### ขั้นตอนที่ 2: แสดงผลและรอ user ตัดสินใจ
|
|
407
|
+
|
|
408
|
+
```
|
|
405
409
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
406
|
-
🧪
|
|
410
|
+
🧪 {phase_name} Complete - Awaiting Approval
|
|
407
411
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
408
412
|
|
|
409
|
-
|
|
413
|
+
{result_summary}
|
|
410
414
|
|
|
411
|
-
📄 Full report:
|
|
415
|
+
📄 Full report: openspec/changes/{change-id}/ux-test-report.md
|
|
412
416
|
|
|
413
417
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
414
418
|
|
|
@@ -418,280 +422,249 @@ ${result.summary || 'Report generated successfully'}
|
|
|
418
422
|
❌ "reject [feedback]" → กลับแก้ไข Phase ก่อนหน้า
|
|
419
423
|
|
|
420
424
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
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
425
|
```
|
|
490
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
|
+
|
|
491
463
|
**See:** `.claude/lib/agent-executor.md` → "Approval Gate Execution" section for complete flow
|
|
492
464
|
|
|
493
465
|
---
|
|
494
466
|
|
|
495
467
|
### Step 4.7: Validate Page Plan Compliance (uxui-frontend only)
|
|
496
468
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
**Purpose:**
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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
|
-
}
|
|
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:**
|
|
563
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:**
|
|
543
|
+
```
|
|
544
|
+
⚠️ Skipping validation - proceed with caution
|
|
545
|
+
This may result in incomplete implementation
|
|
546
|
+
```
|
|
547
|
+
→ ไป Step 5
|
|
548
|
+
|
|
549
|
+
---
|
|
564
550
|
|
|
565
551
|
**When to use:**
|
|
566
|
-
-
|
|
567
|
-
-
|
|
568
|
-
-
|
|
552
|
+
- Agent: uxui-frontend
|
|
553
|
+
- page-plan.md exists
|
|
554
|
+
- Phase completed successfully
|
|
569
555
|
|
|
570
556
|
**Common issues caught:**
|
|
571
557
|
- Agent implemented 5/10 sections (missing ProblemSection, ComparisonTable, etc.)
|
|
572
558
|
- Agent followed tasks.md ("4-5 components") instead of page-plan.md (10 sections)
|
|
573
559
|
- Agent skipped sections they thought were "optional"
|
|
574
560
|
|
|
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
561
|
---
|
|
581
562
|
|
|
582
563
|
### Step 5: Post-Execution (Flags Update)
|
|
583
564
|
|
|
584
|
-
**Main Claude
|
|
565
|
+
**Main Claude อัพเดต flags.json หลังจบแต่ละ phase**
|
|
585
566
|
|
|
586
567
|
→ See: `.claude/lib/flags-updater.md` for complete protocol
|
|
587
568
|
|
|
588
569
|
WHY: Immediate updates ensure /cstatus shows accurate progress.
|
|
589
570
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
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
|
-
}
|
|
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
|
+
|
|
694
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
|
+
|
|
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
|
+
---
|
|
695
668
|
|
|
696
669
|
**Key points:**
|
|
697
670
|
- Main Claude updates flags.json (sub-agents don't have access)
|