@champpaba/claude-agent-kit 2.5.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +103 -58
- package/.claude/agents/02-uxui-frontend.md +5 -6
- package/.claude/agents/07-ux-tester.md +407 -0
- package/.claude/commands/cdev.md +113 -8
- package/.claude/commands/csetup.md +86 -28
- package/.claude/commands/designsetup.md +171 -48
- package/.claude/commands/extract.md +382 -668
- package/.claude/commands/pageplan.md +43 -27
- package/.claude/contexts/design/box-thinking.md +4 -4
- package/.claude/contexts/design/color-theory.md +5 -5
- package/.claude/contexts/design/index.md +9 -9
- package/.claude/contexts/design/spacing.md +4 -4
- package/.claude/contexts/patterns/agent-discovery.md +1 -1
- package/.claude/contexts/patterns/animation-patterns.md +3 -3
- package/.claude/contexts/patterns/ui-component-consistency.md +3 -3
- package/.claude/lib/README.md +1 -1
- package/.claude/lib/agent-executor.md +223 -0
- package/.claude/lib/context-loading-protocol.md +5 -6
- package/.claude/lib/detailed-guides/agent-system.md +4 -4
- package/.claude/lib/detailed-guides/best-practices-system.md +5 -4
- package/.claude/lib/detailed-guides/context-optimization.md +21 -22
- package/.claude/lib/detailed-guides/design-system.md +6 -5
- package/.claude/lib/detailed-guides/page-planning.md +6 -6
- package/.claude/lib/document-loader.md +32 -47
- package/.claude/lib/task-analyzer.md +194 -1
- package/.claude/templates/PROJECT_STATUS.template.yml +1 -1
- package/.claude/templates/STYLE_GUIDE.template.md +7 -7
- package/.claude/templates/design-context-template.md +22 -29
- package/.claude/templates/page-plan-example.md +9 -9
- package/.claude/templates/phases-sections/ux-testing.md +164 -0
- package/README.md +3 -1
- package/package.json +1 -1
|
@@ -24,8 +24,9 @@
|
|
|
24
24
|
1. **Reads User-Specified Context:**
|
|
25
25
|
- Only reads files that user mentions with `@` prefix
|
|
26
26
|
- Always reads `openspec/changes/{change-id}/proposal.md` (if exists)
|
|
27
|
-
-
|
|
28
|
-
-
|
|
27
|
+
- Always reads `openspec/changes/{change-id}/tasks.md` (for page type detection)
|
|
28
|
+
- **Always reads `openspec/changes/{change-id}/.claude/phases.md`** (if exists - for phase info) ✅ NEW v2.6.0
|
|
29
|
+
- **Always reads `design-system/data.yaml`** (design tokens + psychology, ~500 tokens) ✅
|
|
29
30
|
|
|
30
31
|
2. **Searches Existing Components:**
|
|
31
32
|
- Glob: `**/{Navbar,Footer,Sidebar,Header}*.{tsx,jsx,vue}`
|
|
@@ -70,8 +71,8 @@ const userFiles = extractMentionedFiles(userMessage) // @prd.md, @brief.md
|
|
|
70
71
|
|
|
71
72
|
// Always read (if exists)
|
|
72
73
|
const proposalPath = `openspec/changes/${changeId}/proposal.md`
|
|
73
|
-
const tokensPath = `design-system/
|
|
74
|
-
|
|
74
|
+
const tokensPath = `design-system/data.yaml` // Design tokens + psychology
|
|
75
|
+
// data.yaml contains all design information - single source of truth
|
|
75
76
|
|
|
76
77
|
const contextFiles = [
|
|
77
78
|
...userFiles,
|
|
@@ -97,6 +98,22 @@ if (fileExists(tasksPath)) {
|
|
|
97
98
|
tasksContent = Read(tasksPath)
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
// 🆕 v2.6.0: Read phases.md if exists (for phase info, UI detection)
|
|
102
|
+
const phasesPath = `openspec/changes/${changeId}/.claude/phases.md`
|
|
103
|
+
let phasesContent = ''
|
|
104
|
+
if (fileExists(phasesPath)) {
|
|
105
|
+
phasesContent = Read(phasesPath)
|
|
106
|
+
output(`✅ phases.md Found - reading phase information`)
|
|
107
|
+
|
|
108
|
+
// Extract UI phases from phases.md
|
|
109
|
+
const uiPhaseMatch = phasesContent.match(/uxui-frontend|frontend-mockup|Frontend Mockup/gi)
|
|
110
|
+
if (uiPhaseMatch) {
|
|
111
|
+
output(` - UI phases detected: ${uiPhaseMatch.length}`)
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
output(`ℹ️ phases.md not found - run /csetup first if you want phase-aware planning`)
|
|
115
|
+
}
|
|
116
|
+
|
|
100
117
|
// Extract brief from user files
|
|
101
118
|
const briefFile = userFiles.find(f => f.toLowerCase().includes('brief'))
|
|
102
119
|
if (briefFile && fileExists(briefFile)) {
|
|
@@ -106,20 +123,19 @@ if (briefFile && fileExists(briefFile)) {
|
|
|
106
123
|
// 🆕 Load design tokens (lightweight)
|
|
107
124
|
if (fileExists(tokensPath)) {
|
|
108
125
|
const tokens = JSON.parse(Read(tokensPath))
|
|
109
|
-
context += `\n\n---\n\n# Design Tokens (
|
|
126
|
+
context += `\n\n---\n\n# Design Tokens (data.yaml)\n\n`
|
|
110
127
|
context += `Primary Color: ${tokens.tokens.colors.primary.DEFAULT}\n`
|
|
111
128
|
context += `Spacing Scale: ${tokens.tokens.spacing.scale.join(', ')}px\n`
|
|
112
129
|
context += `Component Library: ${tokens.component_library.name}\n`
|
|
113
130
|
context += `Shadows: ${Object.keys(tokens.tokens.shadows).join(', ')}\n`
|
|
114
131
|
}
|
|
115
132
|
|
|
116
|
-
// Validate
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
warn(`⚠️ No STYLE_GUIDE.md found - run /designsetup first`)
|
|
133
|
+
// Validate data.yaml exists
|
|
134
|
+
if (!fileExists(tokensPath)) {
|
|
135
|
+
warn(`⚠️ No data.yaml found - run /designsetup first`)
|
|
120
136
|
}
|
|
121
137
|
|
|
122
|
-
// Total context: ~1.5K tokens (
|
|
138
|
+
// Total context: ~1.5K tokens (data.yaml is lightweight)
|
|
123
139
|
```
|
|
124
140
|
|
|
125
141
|
### STEP 3: Search Existing Components
|
|
@@ -294,12 +310,12 @@ Based on context + found components, generate:
|
|
|
294
310
|
## 2.6. 🎬 Animation Blueprint (Micro-interactions)
|
|
295
311
|
|
|
296
312
|
> **Purpose:** Define animation strategy BEFORE implementation to ensure consistency and polish
|
|
297
|
-
> **Source:** `design-system/
|
|
313
|
+
> **Source:** `design-system/data.yaml` (animation tokens)
|
|
298
314
|
> **Philosophy:** Match Flow Engineer Step 3 - Design animations systematically, not randomly
|
|
299
315
|
|
|
300
316
|
### Animation Principles
|
|
301
317
|
|
|
302
|
-
**From
|
|
318
|
+
**From data.yaml:**
|
|
303
319
|
- **Durations:** 150ms (quick), 300ms (normal), 500ms (slow)
|
|
304
320
|
- **Easing:** ease-in-out (default), cubic-bezier for custom
|
|
305
321
|
- **Properties:** GPU-accelerated ONLY (transform, opacity) - NOT width, height, top, left
|
|
@@ -494,7 +510,7 @@ className="hover:scale-105 transform"
|
|
|
494
510
|
- [ ] All buttons use scale + shadow pattern (150ms)
|
|
495
511
|
- [ ] All cards use shadow elevation pattern (300ms)
|
|
496
512
|
- [ ] All inputs use ring pattern (200ms)
|
|
497
|
-
- [ ] All durations from
|
|
513
|
+
- [ ] All durations from data.yaml (150/300/500ms)
|
|
498
514
|
- [ ] All properties GPU-accelerated (transform, opacity)
|
|
499
515
|
- [ ] No random durations (e.g., 200ms, 400ms) unless intentional
|
|
500
516
|
- [ ] Tested on mobile (animations not janky)
|
|
@@ -510,7 +526,7 @@ className="hover:scale-105 transform"
|
|
|
510
526
|
4. **Short Durations (150-300ms):** Feels responsive, not sluggish
|
|
511
527
|
5. **GPU Properties:** 60fps smooth animations, no jank
|
|
512
528
|
|
|
513
|
-
**Inspiration:** Based on extracted animations from reference sites +
|
|
529
|
+
**Inspiration:** Based on extracted animations from reference sites + data.yaml
|
|
514
530
|
|
|
515
531
|
---
|
|
516
532
|
|
|
@@ -555,7 +571,7 @@ className="hover:scale-105 transform"
|
|
|
555
571
|
→ **Format:** SVG (preferred) or PNG sprite (if 10+ icons)
|
|
556
572
|
→ **Optimization:** Remove unnecessary metadata (use SVGO)
|
|
557
573
|
→ **Place at:** `/public/icons/` or inline in component
|
|
558
|
-
→ **Style:** Match
|
|
574
|
+
→ **Style:** Match data.yaml colors
|
|
559
575
|
→ **Estimated size:** 1-3KB per icon
|
|
560
576
|
|
|
561
577
|
**If using 10+ icons:** Consider SVG sprite sheet (combine → 1 HTTP request)
|
|
@@ -570,18 +586,18 @@ className="hover:scale-105 transform"
|
|
|
570
586
|
## 4. Design Notes
|
|
571
587
|
|
|
572
588
|
**Design System Files:**
|
|
573
|
-
- Tokens
|
|
574
|
-
-
|
|
589
|
+
- Tokens + Psychology: \`design-system/data.yaml\` (agent reads this)
|
|
590
|
+
- Human summary: \`design-system/README.md\` (for humans)
|
|
575
591
|
|
|
576
592
|
**Key Design Tokens:**
|
|
577
|
-
- Primary color: [from
|
|
578
|
-
- Font family: [from
|
|
579
|
-
- Spacing scale: [from
|
|
580
|
-
- Component library: [from
|
|
581
|
-
- Shadows: [from
|
|
593
|
+
- Primary color: [from data.yaml]
|
|
594
|
+
- Font family: [from data.yaml]
|
|
595
|
+
- Spacing scale: [from data.yaml]
|
|
596
|
+
- Component library: [from data.yaml]
|
|
597
|
+
- Shadows: [from data.yaml]
|
|
582
598
|
|
|
583
599
|
**Agent Instructions:**
|
|
584
|
-
- uxui-frontend reads
|
|
600
|
+
- uxui-frontend reads data.yaml in STEP 0.5
|
|
585
601
|
- Use theme tokens (text-foreground/70) for theme-awareness
|
|
586
602
|
- Use spacing scale (p-4, p-6) for consistency
|
|
587
603
|
|
|
@@ -684,8 +700,8 @@ Result:
|
|
|
684
700
|
- Warning: "This change appears to be backend/API work. /pageplan is for UI tasks."
|
|
685
701
|
- Ask: "Continue anyway? (Y/N)"
|
|
686
702
|
|
|
687
|
-
4. **
|
|
688
|
-
- Warning: "No
|
|
703
|
+
4. **data.yaml missing:**
|
|
704
|
+
- Warning: "No data.yaml found. Run /designsetup first for best results."
|
|
689
705
|
- Continue: Use general design principles as fallback
|
|
690
706
|
|
|
691
707
|
---
|
|
@@ -711,9 +727,9 @@ Result:
|
|
|
711
727
|
```
|
|
712
728
|
/designsetup → /pageplan → /csetup → /cdev
|
|
713
729
|
↓ ↓ ↓ ↓
|
|
714
|
-
|
|
730
|
+
data.yaml page-plan.md research uxui-frontend
|
|
715
731
|
patterns/ (visual) -checklist reads both
|
|
716
|
-
|
|
732
|
+
README.md (content)
|
|
717
733
|
```
|
|
718
734
|
|
|
719
735
|
**Separation of Concerns:**
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
**This file contains layout analysis METHODOLOGY** (applies to all projects).
|
|
10
10
|
|
|
11
|
-
**If your project has a
|
|
12
|
-
→
|
|
13
|
-
→
|
|
11
|
+
**If your project has a data.yaml:**
|
|
12
|
+
→ Use data.yaml spacing values when implementing boxes
|
|
13
|
+
→ Apply Box Thinking methodology with project-specific tokens
|
|
14
14
|
|
|
15
15
|
Box Thinking = **How to think about layout**
|
|
16
|
-
|
|
16
|
+
data.yaml = **What values to use**
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -9,20 +9,20 @@
|
|
|
9
9
|
|
|
10
10
|
**This file contains GENERIC color theory principles.**
|
|
11
11
|
|
|
12
|
-
**If your project has a
|
|
13
|
-
→
|
|
12
|
+
**If your project has a data.yaml:**
|
|
13
|
+
→ data.yaml colors take **priority** (use exact hex values from it)
|
|
14
14
|
→ This file = **reference** for color theory concepts only
|
|
15
15
|
|
|
16
|
-
**Check:**
|
|
16
|
+
**Check:** `design-system/data.yaml`
|
|
17
17
|
|
|
18
18
|
**Priority order:**
|
|
19
|
-
1. `
|
|
19
|
+
1. `data.yaml` (project-specific hex values) ← **Use this if exists!**
|
|
20
20
|
2. Existing components (brownfield) ← Extract colors from code
|
|
21
21
|
3. This file (generic principles) ← Theory and fallback defaults
|
|
22
22
|
|
|
23
23
|
**When using this file:**
|
|
24
24
|
- Apply **concepts** (60-30-10 rule, accessibility, harmony)
|
|
25
|
-
- Don't use **example colors** if
|
|
25
|
+
- Don't use **example colors** if data.yaml exists
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
**uxui-frontend agents should check this priority order:**
|
|
10
10
|
|
|
11
|
-
### Priority 1: Project-Specific
|
|
11
|
+
### Priority 1: Project-Specific Design Tokens (Highest)
|
|
12
12
|
```
|
|
13
|
-
design-system/
|
|
13
|
+
design-system/data.yaml
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
**If this file exists:**
|
|
17
|
-
- ✅ Use
|
|
18
|
-
- Contains: Complete design
|
|
17
|
+
- ✅ Use data.yaml as **PRIMARY source of truth**
|
|
18
|
+
- Contains: Complete design tokens + psychology (colors, typography, spacing, components)
|
|
19
19
|
- Generated by: `/designsetup` command (from reference/codebase/AI)
|
|
20
20
|
- **DO NOT** override with universal principles below
|
|
21
21
|
|
|
@@ -29,7 +29,7 @@ design-system/STYLE_GUIDE.md
|
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
**Use these when:**
|
|
32
|
-
- No
|
|
32
|
+
- No data.yaml exists
|
|
33
33
|
- Need general design theory
|
|
34
34
|
- Understanding design concepts (box thinking, color theory)
|
|
35
35
|
|
|
@@ -38,7 +38,7 @@ design-system/STYLE_GUIDE.md
|
|
|
38
38
|
.claude/contexts/domain/[project]/design-tokens.md
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
**Note:** This is being replaced by
|
|
41
|
+
**Note:** This is being replaced by data.yaml
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
@@ -46,8 +46,8 @@ design-system/STYLE_GUIDE.md
|
|
|
46
46
|
|
|
47
47
|
**Before ANY design recommendation, ask:**
|
|
48
48
|
|
|
49
|
-
1. **Do we have a
|
|
50
|
-
- Check: `design-system/
|
|
49
|
+
1. **Do we have a design tokens file?**
|
|
50
|
+
- Check: `design-system/data.yaml`
|
|
51
51
|
- If YES → Use it (Priority 1)
|
|
52
52
|
- If NO → Use universal principles (Priority 2)
|
|
53
53
|
|
|
@@ -60,7 +60,7 @@ design-system/STYLE_GUIDE.md
|
|
|
60
60
|
- Box Relationships
|
|
61
61
|
|
|
62
62
|
3. **What context?**
|
|
63
|
-
- Project-specific
|
|
63
|
+
- Project-specific design tokens (data.yaml)
|
|
64
64
|
- Universal design principles (this directory)
|
|
65
65
|
|
|
66
66
|
4. **What's the user goal?**
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
**This file contains GENERIC spacing guidelines.**
|
|
10
10
|
|
|
11
|
-
**If your project has a
|
|
12
|
-
→
|
|
11
|
+
**If your project has a data.yaml:**
|
|
12
|
+
→ data.yaml values take **priority** (use its spacing values)
|
|
13
13
|
→ This file = **reference** for concepts and principles only
|
|
14
14
|
|
|
15
|
-
**Check:**
|
|
15
|
+
**Check:** `design-system/data.yaml`
|
|
16
16
|
|
|
17
17
|
**Priority order:**
|
|
18
|
-
1. `
|
|
18
|
+
1. `data.yaml` (project-specific) ← **Use this if exists!**
|
|
19
19
|
2. Existing components (brownfield) ← Extract from code
|
|
20
20
|
3. This file (generic defaults) ← Fallback only
|
|
21
21
|
|
|
@@ -110,7 +110,7 @@ ls openspec/changes/{change-id}/.claude/
|
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
> **Note:** `design.md` = Technical/Architecture decisions (API structure, data flow)
|
|
113
|
-
> This is DIFFERENT from `
|
|
113
|
+
> This is DIFFERENT from `data.yaml` which is Visual Design (colors, fonts, tokens)
|
|
114
114
|
> See CLAUDE.md "File Naming Conventions" for details.
|
|
115
115
|
|
|
116
116
|
**If change context doesn't exist:**
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
**Priority:**
|
|
20
20
|
1. **Page-specific plan:** `openspec/changes/{id}/page-plan.md` Section 2.6 (if exists)
|
|
21
|
-
2. **Project tokens:** `design-system/
|
|
21
|
+
2. **Project tokens:** `design-system/data.yaml` (animation tokens)
|
|
22
22
|
3. **General guidelines:** This file (fallback when above don't exist)
|
|
23
23
|
|
|
24
24
|
**When to read:**
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
|
|
68
68
|
## 🎯 Animation Duration Guidelines
|
|
69
69
|
|
|
70
|
-
**Standard Durations (from
|
|
70
|
+
**Standard Durations (from data.yaml):**
|
|
71
71
|
|
|
72
72
|
| Token | Duration | Use Case | Example |
|
|
73
73
|
|-------|----------|----------|---------|
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
## 🧩 Component Animation Patterns
|
|
102
102
|
|
|
103
103
|
> **Purpose:** Standard animation patterns for common components
|
|
104
|
-
> **Source:** Based on
|
|
104
|
+
> **Source:** Based on data.yaml + `/pageplan` Section 2.6
|
|
105
105
|
> **Principle:** Same component type = same animation pattern (consistency)
|
|
106
106
|
|
|
107
107
|
### Button Components
|
|
@@ -91,7 +91,7 @@ const ANIMATION_TOKENS = {
|
|
|
91
91
|
hover: {
|
|
92
92
|
properties: ['transform', 'box-shadow'], // GPU-accelerated only
|
|
93
93
|
values: ['scale(1.05)', 'shadow-lg'],
|
|
94
|
-
duration: '150ms', // From
|
|
94
|
+
duration: '150ms', // From data.yaml
|
|
95
95
|
easing: 'ease-in-out',
|
|
96
96
|
classes: 'hover:scale-105 hover:shadow-lg transition-all duration-150'
|
|
97
97
|
},
|
|
@@ -121,7 +121,7 @@ const ANIMATION_TOKENS = {
|
|
|
121
121
|
|
|
122
122
|
**Critical Rules:**
|
|
123
123
|
1. ✅ Extract animation from reference component (same as colors, spacing)
|
|
124
|
-
2. ✅ Use durations from
|
|
124
|
+
2. ✅ Use durations from data.yaml (150ms, 300ms, 500ms)
|
|
125
125
|
3. ✅ Use GPU-accelerated properties (transform, opacity) - NOT width, height, top, left
|
|
126
126
|
4. ✅ Same component type = same animation pattern (buttons scale, cards elevate shadow)
|
|
127
127
|
5. ❌ NO random durations (200ms, 250ms) - only 150/300/500ms
|
|
@@ -308,7 +308,7 @@ transition: 'transition-colors'
|
|
|
308
308
|
- [ ] Found similar reference component in codebase
|
|
309
309
|
- [ ] Extracted all design tokens (icon, spacing, colors, states, **animations**)
|
|
310
310
|
- [ ] Extracted animation tokens (hover, focus, active, durations)
|
|
311
|
-
- [ ] Verified durations match
|
|
311
|
+
- [ ] Verified durations match data.yaml (150/300/500ms)
|
|
312
312
|
- [ ] Verified animation properties are GPU-accelerated (transform, opacity)
|
|
313
313
|
- [ ] Applied tokens exactly (no guessing, no random values)
|
|
314
314
|
- [ ] Tested visual appearance in browser
|
package/.claude/lib/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Standardized handoff formats for agent-to-agent communication. Includes all 15 h
|
|
|
39
39
|
Complete TDD implementation examples (Stripe integration, user auth). Used by frontend, backend, database agents.
|
|
40
40
|
|
|
41
41
|
**`document-loader.md`** - Token-efficient document loading
|
|
42
|
-
Unified pattern for loading design system files. 3-tier strategy:
|
|
42
|
+
Unified pattern for loading design system files. 3-tier strategy: data.yaml → design-context.md → README.md (fallback).
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
@@ -154,6 +154,7 @@ WHY: Pre-work validation ensures agents loaded context before implementing. This
|
|
|
154
154
|
| backend | Patterns Loaded ✓, Existing Endpoints Search ✓, TDD Workflow (if required) |
|
|
155
155
|
| database | Schema Analysis ✓ |
|
|
156
156
|
| test-debug | Test Infrastructure ✓ |
|
|
157
|
+
| ux-tester | Personas Generated ✓, Dev Server Found ✓, Chrome DevTools Connected ✓ |
|
|
157
158
|
|
|
158
159
|
**Validation Logic:**
|
|
159
160
|
```typescript
|
|
@@ -978,4 +979,226 @@ async function executePhase(phase: Phase, changeId: string) {
|
|
|
978
979
|
|
|
979
980
|
---
|
|
980
981
|
|
|
982
|
+
## 🛑 Approval Gate Execution (v2.7.0)
|
|
983
|
+
|
|
984
|
+
> **NEW:** Handle phases with `requires_approval: true` (e.g., ux-tester)
|
|
985
|
+
|
|
986
|
+
### Detection
|
|
987
|
+
|
|
988
|
+
```typescript
|
|
989
|
+
function isApprovalGatePhase(phase: Phase): boolean {
|
|
990
|
+
return phase.requires_approval === true ||
|
|
991
|
+
phase.metadata?.includes('approval-gate')
|
|
992
|
+
}
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
### Execution Flow
|
|
996
|
+
|
|
997
|
+
```typescript
|
|
998
|
+
async function executeApprovalGatePhase(phase: Phase, changeId: string): Promise<ApprovalResult> {
|
|
999
|
+
// Step 1: Execute the agent (e.g., ux-tester)
|
|
1000
|
+
const agentResult = await executeAgent(phase.agent, buildPrompt(phase))
|
|
1001
|
+
|
|
1002
|
+
// Step 2: Validate agent output
|
|
1003
|
+
if (!agentResult.success) {
|
|
1004
|
+
return { status: 'failed', error: agentResult.error }
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// Step 3: Update flags to "awaiting_approval"
|
|
1008
|
+
updateFlags(changeId, {
|
|
1009
|
+
[`phase_${phase.number}`]: {
|
|
1010
|
+
status: 'awaiting_approval',
|
|
1011
|
+
report_path: agentResult.reportPath
|
|
1012
|
+
}
|
|
1013
|
+
})
|
|
1014
|
+
|
|
1015
|
+
// Step 4: Display report summary to user
|
|
1016
|
+
output(`
|
|
1017
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1018
|
+
🧪 ${phase.name} Complete - Awaiting Approval
|
|
1019
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1020
|
+
|
|
1021
|
+
${agentResult.summary}
|
|
1022
|
+
|
|
1023
|
+
📄 Full report: ${agentResult.reportPath}
|
|
1024
|
+
|
|
1025
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1026
|
+
|
|
1027
|
+
กรุณาตัดสินใจ:
|
|
1028
|
+
|
|
1029
|
+
✅ "approve" → ไป Phase ${getNextPhase(phase).number}
|
|
1030
|
+
❌ "reject [feedback]" → กลับ Phase ${getPreviousPhase(phase).number} แก้ไข
|
|
1031
|
+
|
|
1032
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1033
|
+
`)
|
|
1034
|
+
|
|
1035
|
+
// Step 5: PAUSE and wait for user response
|
|
1036
|
+
const userResponse = await waitForUserInput()
|
|
1037
|
+
|
|
1038
|
+
// Step 6: Handle response
|
|
1039
|
+
return handleApprovalResponse(userResponse, phase, changeId)
|
|
1040
|
+
}
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
### Response Handling
|
|
1044
|
+
|
|
1045
|
+
```typescript
|
|
1046
|
+
function handleApprovalResponse(
|
|
1047
|
+
response: string,
|
|
1048
|
+
phase: Phase,
|
|
1049
|
+
changeId: string,
|
|
1050
|
+
allPhases: Phase[] // Added: need all phases for loop back
|
|
1051
|
+
): ApprovalResult {
|
|
1052
|
+
const normalized = response.trim().toLowerCase()
|
|
1053
|
+
|
|
1054
|
+
// Approve patterns
|
|
1055
|
+
if (normalized.match(/^(approve|approved|ok|yes|ใช่|อนุมัติ|ผ่าน|ลุย)$/)) {
|
|
1056
|
+
updateFlags(changeId, {
|
|
1057
|
+
[`phase_${phase.number}`]: {
|
|
1058
|
+
status: 'approved',
|
|
1059
|
+
approved_at: new Date().toISOString()
|
|
1060
|
+
}
|
|
1061
|
+
})
|
|
1062
|
+
|
|
1063
|
+
output(`✅ ${phase.name} approved! Continuing to next phase...`)
|
|
1064
|
+
|
|
1065
|
+
return {
|
|
1066
|
+
status: 'approved',
|
|
1067
|
+
nextAction: 'continue'
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// Reject patterns
|
|
1072
|
+
if (normalized.startsWith('reject') || normalized.startsWith('ไม่') ||
|
|
1073
|
+
normalized.startsWith('แก้') || normalized.startsWith('no')) {
|
|
1074
|
+
|
|
1075
|
+
// Extract feedback from rejection
|
|
1076
|
+
const feedback = response.replace(/^(reject|ไม่อนุมัติ|แก้ไข|no)\s*/i, '').trim()
|
|
1077
|
+
|
|
1078
|
+
updateFlags(changeId, {
|
|
1079
|
+
[`phase_${phase.number}`]: {
|
|
1080
|
+
status: 'rejected',
|
|
1081
|
+
rejected_at: new Date().toISOString(),
|
|
1082
|
+
rejection_feedback: feedback || 'No specific feedback provided'
|
|
1083
|
+
}
|
|
1084
|
+
})
|
|
1085
|
+
|
|
1086
|
+
// Find the phase to loop back to
|
|
1087
|
+
const loopBackPhase = findLoopBackPhase(phase, allPhases)
|
|
1088
|
+
|
|
1089
|
+
updateFlags(changeId, {
|
|
1090
|
+
[`phase_${loopBackPhase.number}`]: {
|
|
1091
|
+
status: 'pending',
|
|
1092
|
+
rerun_reason: `Rejected from ${phase.name}: ${feedback}`
|
|
1093
|
+
}
|
|
1094
|
+
})
|
|
1095
|
+
|
|
1096
|
+
output(`
|
|
1097
|
+
🔄 ${phase.name} rejected
|
|
1098
|
+
|
|
1099
|
+
📝 Feedback: ${feedback || 'None provided'}
|
|
1100
|
+
🔙 Looping back to: Phase ${loopBackPhase.number} - ${loopBackPhase.name}
|
|
1101
|
+
|
|
1102
|
+
${loopBackPhase.agent} agent จะได้รับ feedback นี้เพื่อแก้ไข
|
|
1103
|
+
`)
|
|
1104
|
+
|
|
1105
|
+
return {
|
|
1106
|
+
status: 'rejected',
|
|
1107
|
+
feedback,
|
|
1108
|
+
nextAction: 'loop_back',
|
|
1109
|
+
loopBackTo: loopBackPhase
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
// Unknown response - ask again
|
|
1114
|
+
output(`
|
|
1115
|
+
⚠️ ไม่เข้าใจคำตอบ
|
|
1116
|
+
|
|
1117
|
+
กรุณาตอบ:
|
|
1118
|
+
- "approve" เพื่อดำเนินการต่อ
|
|
1119
|
+
- "reject [feedback]" เพื่อกลับไปแก้ไข
|
|
1120
|
+
`)
|
|
1121
|
+
|
|
1122
|
+
return {
|
|
1123
|
+
status: 'pending',
|
|
1124
|
+
nextAction: 'ask_again'
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
### Loop Back Logic
|
|
1130
|
+
|
|
1131
|
+
```typescript
|
|
1132
|
+
function findLoopBackPhase(currentPhase: Phase, allPhases: Phase[]): Phase {
|
|
1133
|
+
// For ux-tester (Phase 1.5), loop back to uxui-frontend (Phase 1)
|
|
1134
|
+
if (currentPhase.agent === 'ux-tester') {
|
|
1135
|
+
const uxuiFrontendPhase = allPhases.find(p => p.agent === 'uxui-frontend')
|
|
1136
|
+
if (uxuiFrontendPhase) {
|
|
1137
|
+
return uxuiFrontendPhase
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// Default: loop back to previous phase
|
|
1142
|
+
const currentIndex = allPhases.findIndex(p => p.number === currentPhase.number)
|
|
1143
|
+
if (currentIndex > 0) {
|
|
1144
|
+
return allPhases[currentIndex - 1]
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// Fallback: first phase
|
|
1148
|
+
return allPhases[0]
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// Helper: Read phases from phases.md file
|
|
1152
|
+
function getPhasesFromFile(changeId: string): Phase[] {
|
|
1153
|
+
const phasesPath = `openspec/changes/${changeId}/.claude/phases.md`
|
|
1154
|
+
const content = Read(phasesPath)
|
|
1155
|
+
return parsePhasesFromMd(content)
|
|
1156
|
+
}
|
|
1157
|
+
```
|
|
1158
|
+
|
|
1159
|
+
### Rejection Loop Cycle
|
|
1160
|
+
|
|
1161
|
+
```
|
|
1162
|
+
Cycle 1:
|
|
1163
|
+
Phase 1 (uxui-frontend) → Phase 1.5 (ux-tester) → [REJECT]
|
|
1164
|
+
→ Back to Phase 1 with feedback
|
|
1165
|
+
|
|
1166
|
+
Cycle 2:
|
|
1167
|
+
Phase 1 (uxui-frontend) [with feedback] → Phase 1.5 (ux-tester) → [APPROVE]
|
|
1168
|
+
→ Continue to Phase 2
|
|
1169
|
+
|
|
1170
|
+
No limit on cycles - user decides when to stop
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
### Feedback Injection
|
|
1174
|
+
|
|
1175
|
+
When looping back, inject rejection feedback into agent prompt:
|
|
1176
|
+
|
|
1177
|
+
```typescript
|
|
1178
|
+
function buildPromptWithFeedback(phase: Phase, changeId: string): string {
|
|
1179
|
+
const flags = readFlags(changeId)
|
|
1180
|
+
const feedback = flags[`phase_${phase.number}`]?.rerun_reason
|
|
1181
|
+
|
|
1182
|
+
let prompt = buildBasePrompt(phase)
|
|
1183
|
+
|
|
1184
|
+
if (feedback) {
|
|
1185
|
+
prompt += `
|
|
1186
|
+
|
|
1187
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1188
|
+
⚠️ REJECTION FEEDBACK FROM UX TESTING
|
|
1189
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1190
|
+
|
|
1191
|
+
${feedback}
|
|
1192
|
+
|
|
1193
|
+
Please address this feedback in your implementation.
|
|
1194
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1195
|
+
`
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
return prompt
|
|
1199
|
+
}
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
---
|
|
1203
|
+
|
|
981
1204
|
**This incremental execution framework transforms high-risk tasks into manageable, validated steps! 🚀**
|
|
@@ -250,15 +250,14 @@ Each agent loads additional contexts based on their role.
|
|
|
250
250
|
- `@.claude/contexts/patterns/frontend-component-strategy.md` (when to create vs reuse)
|
|
251
251
|
|
|
252
252
|
**Project-specific (if exists):**
|
|
253
|
-
- `design-system/
|
|
254
|
-
- `design-system/
|
|
253
|
+
- `design-system/data.yaml` (tokens + psychology, ~500 tokens)
|
|
254
|
+
- `design-system/README.md` (human-readable summary, ~100 tokens)
|
|
255
255
|
- `openspec/changes/{change-id}/page-plan.md` (from /pageplan command)
|
|
256
256
|
|
|
257
257
|
**Loading strategy:**
|
|
258
258
|
```
|
|
259
|
-
1.
|
|
260
|
-
2.
|
|
261
|
-
3. Fall back to design/*.md if no style guide
|
|
259
|
+
1. Load data.yaml (contains all design tokens)
|
|
260
|
+
2. Fall back to design/*.md if no data.yaml
|
|
262
261
|
```
|
|
263
262
|
|
|
264
263
|
### backend Agent:
|
|
@@ -333,7 +332,7 @@ Each agent loads additional contexts based on their role.
|
|
|
333
332
|
🎨 Level 3: Agent-Specific (uxui-frontend)
|
|
334
333
|
→ Loading: design/*.md ✓
|
|
335
334
|
→ Loading: patterns/ui-component-consistency.md ✓
|
|
336
|
-
→ Loading: design-system/
|
|
335
|
+
→ Loading: design-system/data.yaml ✓
|
|
337
336
|
→ Loading: openspec/changes/landing-page/page-plan.md ✓
|
|
338
337
|
✅ Design contexts loaded
|
|
339
338
|
|
|
@@ -102,13 +102,13 @@ WHY routing matters: Specialist agents have domain-specific validation (design t
|
|
|
102
102
|
### STEP 0.5: Design Context (uxui-frontend only)
|
|
103
103
|
|
|
104
104
|
```
|
|
105
|
-
6. Check: design-system/
|
|
106
|
-
- If YES → Read
|
|
105
|
+
6. Check: design-system/data.yaml exists?
|
|
106
|
+
- If YES → Read data.yaml (project-specific tokens + psychology)
|
|
107
107
|
- If NO → Read .claude/contexts/design/*.md (fallback)
|
|
108
|
-
7. Report: "✅
|
|
108
|
+
7. Report: "✅ Design Tokens Loaded"
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
WHY:
|
|
111
|
+
WHY: data.yaml has project-specific tokens. design/*.md has universal principles.
|
|
112
112
|
|
|
113
113
|
**Fallback:** If discovery fails, suggest `/csetup` or `/designsetup`
|
|
114
114
|
|
|
@@ -85,11 +85,12 @@
|
|
|
85
85
|
- Asks: Application type (SaaS, Marketing, E-commerce, etc.)
|
|
86
86
|
- Output: Modern, best-practice style guide
|
|
87
87
|
|
|
88
|
-
### Generated
|
|
88
|
+
### Generated Files
|
|
89
89
|
|
|
90
90
|
```
|
|
91
91
|
design-system/
|
|
92
|
-
|
|
92
|
+
├── data.yaml ← Design tokens + psychology (agent reads this)
|
|
93
|
+
└── README.md ← Human-readable summary
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
**All 17 Sections (Complete):**
|
|
@@ -122,14 +123,14 @@ design-system/
|
|
|
122
123
|
# 2. Setup change and project (discovers style guide, auto-detects tech stack)
|
|
123
124
|
/csetup feature-login
|
|
124
125
|
|
|
125
|
-
# 3. Start development (agents use
|
|
126
|
+
# 3. Start development (agents use data.yaml)
|
|
126
127
|
/cdev feature-login
|
|
127
128
|
```
|
|
128
129
|
|
|
129
130
|
### Agent Discovery
|
|
130
131
|
|
|
131
132
|
**uxui-frontend agent automatically reads:**
|
|
132
|
-
1. `design-system/
|
|
133
|
+
1. `design-system/data.yaml` (if exists) ← **Priority #1**
|
|
133
134
|
2. `.claude/contexts/design/*.md` (general principles) ← Fallback
|
|
134
135
|
|
|
135
136
|
**Why this matters:**
|