@champpaba/claude-agent-kit 2.6.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 +13 -13
- package/.claude/commands/cview.md +364 -364
- package/.claude/commands/designsetup.md +171 -48
- package/.claude/commands/extract.md +382 -668
- package/.claude/commands/pageplan.md +25 -27
- package/.claude/contexts/design/accessibility.md +611 -611
- 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/layout.md +400 -400
- package/.claude/contexts/design/responsive.md +551 -551
- package/.claude/contexts/design/shadows.md +522 -522
- package/.claude/contexts/design/spacing.md +4 -4
- package/.claude/contexts/design/typography.md +465 -465
- package/.claude/contexts/domain/README.md +164 -164
- package/.claude/contexts/patterns/agent-coordination.md +388 -388
- package/.claude/contexts/patterns/agent-discovery.md +1 -1
- package/.claude/contexts/patterns/animation-patterns.md +3 -3
- package/.claude/contexts/patterns/development-principles.md +513 -513
- package/.claude/contexts/patterns/error-handling.md +478 -478
- package/.claude/contexts/patterns/logging.md +424 -424
- package/.claude/contexts/patterns/tdd-classification.md +516 -516
- package/.claude/contexts/patterns/testing.md +413 -413
- 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/lib/tdd-classifier.md +345 -345
- package/.claude/lib/validation-gates.md +484 -484
- package/.claude/settings.local.json +42 -42
- package/.claude/templates/PROJECT_STATUS.template.yml +1 -1
- package/.claude/templates/STYLE_GUIDE.template.md +7 -7
- package/.claude/templates/context-template.md +45 -45
- package/.claude/templates/design-context-template.md +22 -29
- package/.claude/templates/flags-template.json +42 -42
- package/.claude/templates/page-plan-example.md +9 -9
- package/.claude/templates/phases-sections/accessibility-test.md +17 -17
- package/.claude/templates/phases-sections/api-design.md +37 -37
- package/.claude/templates/phases-sections/backend-tests.md +16 -16
- package/.claude/templates/phases-sections/backend.md +37 -37
- package/.claude/templates/phases-sections/business-logic-validation.md +16 -16
- package/.claude/templates/phases-sections/component-tests.md +17 -17
- package/.claude/templates/phases-sections/contract-backend.md +16 -16
- package/.claude/templates/phases-sections/contract-frontend.md +16 -16
- package/.claude/templates/phases-sections/database.md +35 -35
- package/.claude/templates/phases-sections/e2e-tests.md +16 -16
- package/.claude/templates/phases-sections/fix-implementation.md +17 -17
- package/.claude/templates/phases-sections/frontend-integration.md +18 -18
- package/.claude/templates/phases-sections/manual-flow-test.md +15 -15
- package/.claude/templates/phases-sections/manual-ux-test.md +16 -16
- package/.claude/templates/phases-sections/refactor-implementation.md +17 -17
- package/.claude/templates/phases-sections/refactor.md +16 -16
- package/.claude/templates/phases-sections/regression-tests.md +15 -15
- package/.claude/templates/phases-sections/responsive-test.md +16 -16
- package/.claude/templates/phases-sections/script-implementation.md +43 -43
- package/.claude/templates/phases-sections/test-coverage.md +16 -16
- package/.claude/templates/phases-sections/user-approval.md +14 -14
- package/.claude/templates/phases-sections/ux-testing.md +164 -0
- package/LICENSE +21 -21
- package/README.md +3 -1
- package/package.json +1 -1
|
@@ -31,7 +31,7 @@ Why: Lightweight summary that points to full resources
|
|
|
31
31
|
|
|
32
32
|
### Tier 2: Design Tokens (Load for UI Work)
|
|
33
33
|
```
|
|
34
|
-
File: design-system/
|
|
34
|
+
File: design-system/data.yaml
|
|
35
35
|
Tokens: ~500
|
|
36
36
|
Contains: Colors, spacing, typography, shadows, borders, animations
|
|
37
37
|
|
|
@@ -39,14 +39,14 @@ When: Commands/agents that need design tokens (pageplan, csetup, uxui-frontend)
|
|
|
39
39
|
Why: Lightweight token-only file for quick reference
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
### Tier 3:
|
|
42
|
+
### Tier 3: Human-Readable Summary (Optional)
|
|
43
43
|
```
|
|
44
|
-
File: design-system/
|
|
45
|
-
Tokens: ~
|
|
46
|
-
Contains:
|
|
44
|
+
File: design-system/README.md
|
|
45
|
+
Tokens: ~100 (human-readable summary)
|
|
46
|
+
Contains: Quick reference for humans, not for agents
|
|
47
47
|
|
|
48
|
-
When:
|
|
49
|
-
Why:
|
|
48
|
+
When: Human wants to read design summary
|
|
49
|
+
Why: Short, scannable summary for humans
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
### Tier 4: Universal Principles (Fallback)
|
|
@@ -65,7 +65,7 @@ Why: Universal design principles apply to any project
|
|
|
65
65
|
|
|
66
66
|
### Pattern A: Planning Commands (/pageplan, /csetup)
|
|
67
67
|
|
|
68
|
-
**Goal:** Understand design system
|
|
68
|
+
**Goal:** Understand design system efficiently
|
|
69
69
|
|
|
70
70
|
```typescript
|
|
71
71
|
function loadDesignContext(projectName: string) {
|
|
@@ -77,18 +77,15 @@ function loadDesignContext(projectName: string) {
|
|
|
77
77
|
context.summary = Read(designContextPath) // ~1K tokens
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// 2. Load
|
|
81
|
-
const tokensPath = 'design-system/
|
|
80
|
+
// 2. Load data.yaml (design tokens only)
|
|
81
|
+
const tokensPath = 'design-system/data.yaml'
|
|
82
82
|
if (exists(tokensPath)) {
|
|
83
83
|
context.tokens = JSON.parse(Read(tokensPath)) // ~500 tokens
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
// 3. Validate
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (!context.hasStyleGuide && hasFrontendWork) {
|
|
91
|
-
warn(`โ ๏ธ UI work detected but no STYLE_GUIDE.md
|
|
86
|
+
// 3. Validate data.yaml loaded successfully
|
|
87
|
+
if (!context.tokens && hasFrontendWork) {
|
|
88
|
+
warn(`โ ๏ธ UI work detected but no data.yaml
|
|
92
89
|
Run: /designsetup`)
|
|
93
90
|
}
|
|
94
91
|
|
|
@@ -115,8 +112,7 @@ const spacingScale = designContext.tokens.spacing.scale
|
|
|
115
112
|
```typescript
|
|
116
113
|
function buildDesignReference(projectName: string): string {
|
|
117
114
|
const designContextPath = `.claude/contexts/domain/${projectName}/design-context.md`
|
|
118
|
-
const tokensPath = 'design-system/
|
|
119
|
-
const styleGuidePath = 'design-system/STYLE_GUIDE.md'
|
|
115
|
+
const tokensPath = 'design-system/data.yaml'
|
|
120
116
|
|
|
121
117
|
// Don't load content! Just send paths + minimal summary
|
|
122
118
|
return `
|
|
@@ -128,10 +124,7 @@ function buildDesignReference(projectName: string): string {
|
|
|
128
124
|
โ Project design summary, file paths
|
|
129
125
|
|
|
130
126
|
2. Read: ${tokensPath} (~500 tokens)
|
|
131
|
-
โ Design tokens (colors, spacing, typography)
|
|
132
|
-
|
|
133
|
-
3. Optional: ${styleGuidePath} (selective sections ~2K tokens)
|
|
134
|
-
โ Full guide - load Component Styles, Layout Patterns if needed
|
|
127
|
+
โ Design tokens (colors, spacing, typography, psychology)
|
|
135
128
|
|
|
136
129
|
**Style Guidelines:**
|
|
137
130
|
| Instead of | Use | WHY |
|
|
@@ -140,7 +133,7 @@ function buildDesignReference(projectName: string): string {
|
|
|
140
133
|
| p-5 | p-4 or p-6 | Spacing scale |
|
|
141
134
|
|
|
142
135
|
**Report format:**
|
|
143
|
-
"Design Context Loaded: design-context.md +
|
|
136
|
+
"Design Context Loaded: design-context.md + data.yaml"
|
|
144
137
|
"Design Tokens Extracted: [list key tokens]"
|
|
145
138
|
`
|
|
146
139
|
|
|
@@ -170,13 +163,13 @@ async function loadDesignSystem(projectName: string) {
|
|
|
170
163
|
warn(`โ ๏ธ No design-context.md - using fallback`)
|
|
171
164
|
}
|
|
172
165
|
|
|
173
|
-
// STEP 0.5.2: Load
|
|
174
|
-
const tokensPath = 'design-system/
|
|
166
|
+
// STEP 0.5.2: Load data.yaml
|
|
167
|
+
const tokensPath = 'design-system/data.yaml'
|
|
175
168
|
let tokens = null
|
|
176
169
|
|
|
177
170
|
if (exists(tokensPath)) {
|
|
178
171
|
tokens = JSON.parse(Read(tokensPath)) // ~500 tokens
|
|
179
|
-
report.push(`โ
|
|
172
|
+
report.push(`โ
data.yaml loaded`)
|
|
180
173
|
}
|
|
181
174
|
|
|
182
175
|
// STEP 0.5.3: Extract key tokens
|
|
@@ -192,14 +185,7 @@ async function loadDesignSystem(projectName: string) {
|
|
|
192
185
|
report.push(` - Spacing: ${extractedTokens.spacing.join(', ')}px`)
|
|
193
186
|
report.push(` - Component Library: ${extractedTokens.componentLibrary}`)
|
|
194
187
|
|
|
195
|
-
// STEP 0.5.4:
|
|
196
|
-
const styleGuidePath = 'design-system/STYLE_GUIDE.md'
|
|
197
|
-
if (needsDetailedExamples && exists(styleGuidePath)) {
|
|
198
|
-
// Selective loading: Only Component Styles section
|
|
199
|
-
const fullGuide = Read(styleGuidePath)
|
|
200
|
-
const componentSection = extractSection(fullGuide, '## 6. Component Styles')
|
|
201
|
-
report.push(`โ
STYLE_GUIDE.md (Section 6: Component Styles) loaded`)
|
|
202
|
-
}
|
|
188
|
+
// STEP 0.5.4: data.yaml contains all design info - no need for separate files
|
|
203
189
|
|
|
204
190
|
// Report to user
|
|
205
191
|
output(`
|
|
@@ -220,10 +206,9 @@ ${report.join('\n')}
|
|
|
220
206
|
|
|
221
207
|
| Approach | Tier 1 | Tier 2 | Tier 3 | Total | Use Case |
|
|
222
208
|
|----------|--------|--------|--------|-------|----------|
|
|
223
|
-
| **Planning** (pageplan, csetup) | design-context.md (1K) |
|
|
209
|
+
| **Planning** (pageplan, csetup) | design-context.md (1K) | data.yaml (500) | - | **1.5K** | โ
Efficient |
|
|
224
210
|
| **Execution** (/cdev) | Reference only (200) | - | - | **200** | โ
Very efficient |
|
|
225
|
-
| **Agent** (uxui-frontend) | design-context.md (1K) |
|
|
226
|
-
| **Old approach** | - | - | Full STYLE_GUIDE (5K) | **5K** | โ Wasteful |
|
|
211
|
+
| **Agent** (uxui-frontend) | design-context.md (1K) | data.yaml (500) | - | **1.5K** | โ
Efficient |
|
|
227
212
|
|
|
228
213
|
**Savings: 70-95% reduction in tokens!**
|
|
229
214
|
|
|
@@ -234,8 +219,8 @@ ${report.join('\n')}
|
|
|
234
219
|
| Practice | WHY |
|
|
235
220
|
|----------|-----|
|
|
236
221
|
| Load design-context.md first | Entry point with file paths |
|
|
237
|
-
| Load
|
|
238
|
-
|
|
|
222
|
+
| Load data.yaml for UI work | Lightweight token reference |
|
|
223
|
+
| Use data.yaml for tokens | ~500 tokens, contains all design info |
|
|
239
224
|
| Validate files exist before loading | Prevent errors |
|
|
240
225
|
| Report what was loaded | Transparency for debugging |
|
|
241
226
|
| Skip design files for backend/database | Not needed, saves tokens |
|
|
@@ -252,13 +237,13 @@ function loadDesignFallback() {
|
|
|
252
237
|
warn(`โ ๏ธ No design-context.md found
|
|
253
238
|
Attempting fallback...`)
|
|
254
239
|
|
|
255
|
-
// Option 1: Load
|
|
256
|
-
if (exists('design-system/
|
|
257
|
-
return { tokens: JSON.parse(Read('design-system/
|
|
240
|
+
// Option 1: Load data.yaml directly
|
|
241
|
+
if (exists('design-system/data.yaml')) {
|
|
242
|
+
return { tokens: JSON.parse(Read('design-system/data.yaml')) }
|
|
258
243
|
}
|
|
259
244
|
|
|
260
245
|
// Option 2: Load universal design principles
|
|
261
|
-
warn(`โ ๏ธ No
|
|
246
|
+
warn(`โ ๏ธ No data.yaml - using universal principles`)
|
|
262
247
|
return {
|
|
263
248
|
universal: [
|
|
264
249
|
Read('.claude/contexts/design/box-thinking.md'),
|
|
@@ -286,8 +271,8 @@ if (designContext.tokens) {
|
|
|
286
271
|
output(`Using primary color: ${primary}`)
|
|
287
272
|
}
|
|
288
273
|
|
|
289
|
-
if (!designContext.
|
|
290
|
-
warn(`โ ๏ธ No
|
|
274
|
+
if (!designContext.tokens) {
|
|
275
|
+
warn(`โ ๏ธ No data.yaml - run /designsetup first`)
|
|
291
276
|
}
|
|
292
277
|
```
|
|
293
278
|
|
|
@@ -339,8 +324,8 @@ const Button = `
|
|
|
339
324
|
- [ ] Identify if command deals with UI/design
|
|
340
325
|
- [ ] Use appropriate loading pattern (A, B, or C)
|
|
341
326
|
- [ ] Load design-context.md first
|
|
342
|
-
- [ ] Load
|
|
343
|
-
- [ ]
|
|
327
|
+
- [ ] Load data.yaml if needed
|
|
328
|
+
- [ ] Load data.yaml for design tokens
|
|
344
329
|
- [ ] Validate files exist
|
|
345
330
|
- [ ] Report what was loaded
|
|
346
331
|
- [ ] Handle fallback gracefully
|
|
@@ -255,7 +255,7 @@ function detectResearchNeeds(task: Task, changeContext: any): ResearchRequiremen
|
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
// Special case: If no design system exists and UI work detected
|
|
258
|
-
if (task.type === 'uxui-frontend' && !fileExists('design-system/
|
|
258
|
+
if (task.type === 'uxui-frontend' && !fileExists('design-system/data.yaml')) {
|
|
259
259
|
detectedPatterns.push({
|
|
260
260
|
category: 'missingDesignSystem',
|
|
261
261
|
reason: 'No design system found - component library selection needed',
|
|
@@ -1087,4 +1087,197 @@ function calculateBuffer(complexity: number, risk: RiskLevel): number {
|
|
|
1087
1087
|
|
|
1088
1088
|
---
|
|
1089
1089
|
|
|
1090
|
+
## ๐งช UX Testing Phase Injection (v2.7.0)
|
|
1091
|
+
|
|
1092
|
+
> **NEW:** Auto-inject Phase 1.5 (UX Testing) after uxui-frontend phase
|
|
1093
|
+
|
|
1094
|
+
### Purpose
|
|
1095
|
+
|
|
1096
|
+
Ensure UI is tested from user perspectives before proceeding to backend development.
|
|
1097
|
+
|
|
1098
|
+
### Detection Logic
|
|
1099
|
+
|
|
1100
|
+
```typescript
|
|
1101
|
+
function shouldInjectUXTesting(phases: Phase[]): boolean {
|
|
1102
|
+
// Check if any phase uses uxui-frontend agent
|
|
1103
|
+
return phases.some(p => p.agent === 'uxui-frontend')
|
|
1104
|
+
}
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
### Injection Logic
|
|
1108
|
+
|
|
1109
|
+
```typescript
|
|
1110
|
+
function injectUXTestingPhase(phases: Phase[], context?: ChangeContext): Phase[] {
|
|
1111
|
+
// Step 1: Check if should inject
|
|
1112
|
+
if (!shouldInjectUXTesting(phases)) {
|
|
1113
|
+
return phases // No UI work, skip injection
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// Step 2: Check skip conditions (optional context)
|
|
1117
|
+
if (context && shouldSkipUXTesting(phases, context)) {
|
|
1118
|
+
return phases // Skip due to context conditions
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// Step 3: Find the last uxui-frontend phase
|
|
1122
|
+
const lastUxuiFrontendIndex = phases
|
|
1123
|
+
.map((p, i) => p.agent === 'uxui-frontend' ? i : -1)
|
|
1124
|
+
.filter(i => i >= 0)
|
|
1125
|
+
.pop()
|
|
1126
|
+
|
|
1127
|
+
if (lastUxuiFrontendIndex === undefined) {
|
|
1128
|
+
return phases
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// Step 4: Create UX Testing phase
|
|
1132
|
+
const uxTestingPhase: Phase = {
|
|
1133
|
+
number: `${phases[lastUxuiFrontendIndex].number}.5`, // e.g., "1.5"
|
|
1134
|
+
name: 'UX Testing',
|
|
1135
|
+
agent: 'ux-tester',
|
|
1136
|
+
estimatedTime: 30,
|
|
1137
|
+
metadata: ['approval-gate', 'user-testing', 'persona-based'],
|
|
1138
|
+
requires_approval: true,
|
|
1139
|
+
description: 'Test UI from user perspectives before backend development'
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// Step 5: Insert after the last uxui-frontend phase
|
|
1143
|
+
const newPhases = [...phases]
|
|
1144
|
+
newPhases.splice(lastUxuiFrontendIndex + 1, 0, uxTestingPhase)
|
|
1145
|
+
|
|
1146
|
+
// Step 6: Renumber subsequent phases if needed
|
|
1147
|
+
return renumberPhases(newPhases)
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
function renumberPhases(phases: Phase[]): Phase[] {
|
|
1151
|
+
// Keep .5 phases as-is, renumber whole numbers
|
|
1152
|
+
let wholeNumber = 1
|
|
1153
|
+
|
|
1154
|
+
return phases.map(phase => {
|
|
1155
|
+
if (phase.number.toString().includes('.5')) {
|
|
1156
|
+
return phase // Keep .5 as-is
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
const newPhase = { ...phase, number: wholeNumber }
|
|
1160
|
+
wholeNumber++
|
|
1161
|
+
return newPhase
|
|
1162
|
+
})
|
|
1163
|
+
}
|
|
1164
|
+
```
|
|
1165
|
+
|
|
1166
|
+
### Integration Point
|
|
1167
|
+
|
|
1168
|
+
**In `/csetup` command, after phase generation:**
|
|
1169
|
+
|
|
1170
|
+
```typescript
|
|
1171
|
+
// STEP 4: Generate phases from template
|
|
1172
|
+
let phases = generatePhasesFromTemplate(templateName, analyzedTasks)
|
|
1173
|
+
|
|
1174
|
+
// STEP 4.5: Inject UX Testing phase (NEW v2.7.0)
|
|
1175
|
+
phases = injectUXTestingPhase(phases)
|
|
1176
|
+
|
|
1177
|
+
output(`
|
|
1178
|
+
๐ Phases Generated:
|
|
1179
|
+
${phases.map(p => ` Phase ${p.number}: ${p.name} (${p.agent})`).join('\n')}
|
|
1180
|
+
|
|
1181
|
+
${phases.some(p => p.agent === 'ux-tester') ?
|
|
1182
|
+
'๐งช UX Testing phase auto-injected after uxui-frontend' : ''}
|
|
1183
|
+
`)
|
|
1184
|
+
|
|
1185
|
+
// STEP 5: Write phases.md
|
|
1186
|
+
writePhasesFile(phases, changeId)
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
### Output Example
|
|
1190
|
+
|
|
1191
|
+
**Before injection:**
|
|
1192
|
+
```
|
|
1193
|
+
Phase 1: Frontend Mockup (uxui-frontend)
|
|
1194
|
+
Phase 2: Backend API (backend)
|
|
1195
|
+
Phase 3: Database Schema (database)
|
|
1196
|
+
Phase 4: Frontend Integration (frontend)
|
|
1197
|
+
Phase 5: Testing (test-debug)
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
**After injection:**
|
|
1201
|
+
```
|
|
1202
|
+
Phase 1: Frontend Mockup (uxui-frontend)
|
|
1203
|
+
Phase 1.5: UX Testing (ux-tester) โ AUTO-INJECTED
|
|
1204
|
+
Phase 2: Backend API (backend)
|
|
1205
|
+
Phase 3: Database Schema (database)
|
|
1206
|
+
Phase 4: Frontend Integration (frontend)
|
|
1207
|
+
Phase 5: Testing (test-debug)
|
|
1208
|
+
```
|
|
1209
|
+
|
|
1210
|
+
### Approval Gate Behavior
|
|
1211
|
+
|
|
1212
|
+
When `/cdev` reaches Phase 1.5:
|
|
1213
|
+
|
|
1214
|
+
1. `ux-tester` agent runs and generates report
|
|
1215
|
+
2. Workflow **PAUSES** - waits for user
|
|
1216
|
+
3. User options:
|
|
1217
|
+
- `approve` โ Continue to Phase 2
|
|
1218
|
+
- `reject [feedback]` โ Loop back to Phase 1
|
|
1219
|
+
|
|
1220
|
+
```
|
|
1221
|
+
Phase 1 (uxui-frontend) โโโบ Phase 1.5 (ux-tester) โโโบ [PAUSE]
|
|
1222
|
+
โฒ โ
|
|
1223
|
+
โ โผ
|
|
1224
|
+
โโโโโโโโโโโโโ reject โโโโโโโโโโโโโโโโโโโ User Decision
|
|
1225
|
+
โ
|
|
1226
|
+
โผ
|
|
1227
|
+
approve โโโบ Phase 2
|
|
1228
|
+
```
|
|
1229
|
+
|
|
1230
|
+
### Skip Conditions
|
|
1231
|
+
|
|
1232
|
+
**Do NOT inject UX Testing if:**
|
|
1233
|
+
|
|
1234
|
+
```typescript
|
|
1235
|
+
function shouldSkipUXTesting(phases: Phase[], context: ChangeContext): boolean {
|
|
1236
|
+
// 1. No UI work detected (redundant with shouldInjectUXTesting but kept for clarity)
|
|
1237
|
+
if (!phases.some(p => p.agent === 'uxui-frontend')) {
|
|
1238
|
+
return true
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// 2. Backend-only or API-only change (detected from proposal/tasks)
|
|
1242
|
+
const changeType = detectChangeType(context.proposal, context.tasks)
|
|
1243
|
+
if (changeType === 'backend-only' || changeType === 'api-only') {
|
|
1244
|
+
return true
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// 3. User explicitly disabled (via flags.json)
|
|
1248
|
+
if (context.flags?.skip_ux_testing === true) {
|
|
1249
|
+
return true
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// 4. Minor UI fix (average complexity < 3)
|
|
1253
|
+
const uiPhases = phases.filter(p => p.agent === 'uxui-frontend')
|
|
1254
|
+
if (uiPhases.length > 0) {
|
|
1255
|
+
const avgComplexity = uiPhases.reduce((sum, p) => sum + (p.complexity || 5), 0) / uiPhases.length
|
|
1256
|
+
if (avgComplexity < 3) {
|
|
1257
|
+
return true
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
return false
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
// Helper: Detect change type from content
|
|
1265
|
+
function detectChangeType(proposal: string, tasks: string): string {
|
|
1266
|
+
const content = `${proposal} ${tasks}`.toLowerCase()
|
|
1267
|
+
|
|
1268
|
+
// Check for UI indicators
|
|
1269
|
+
const hasUI = content.match(/landing|page|component|ui|frontend|form|button|modal|dashboard/i)
|
|
1270
|
+
|
|
1271
|
+
// Check for backend-only indicators
|
|
1272
|
+
const isBackendOnly = content.match(/api.only|backend.only|no.ui|cli|cron|migration|script/i)
|
|
1273
|
+
|
|
1274
|
+
if (isBackendOnly && !hasUI) return 'backend-only'
|
|
1275
|
+
if (!hasUI) return 'api-only'
|
|
1276
|
+
|
|
1277
|
+
return 'full-stack' // default
|
|
1278
|
+
}
|
|
1279
|
+
```
|
|
1280
|
+
|
|
1281
|
+
---
|
|
1282
|
+
|
|
1090
1283
|
**This framework transforms simple tasks.md into intelligent, analyzed workflows! ๐**
|