qa-workflow-cc 1.0.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.
Files changed (39) hide show
  1. package/README.md +461 -0
  2. package/VERSION +1 -0
  3. package/bin/install.js +116 -0
  4. package/commands/qa/continue.md +77 -0
  5. package/commands/qa/full.md +149 -0
  6. package/commands/qa/init.md +105 -0
  7. package/commands/qa/resume.md +91 -0
  8. package/commands/qa/status.md +66 -0
  9. package/package.json +28 -0
  10. package/skills/qa/SKILL.md +420 -0
  11. package/skills/qa/references/continuation-format.md +58 -0
  12. package/skills/qa/references/exit-criteria.md +53 -0
  13. package/skills/qa/references/lifecycle.md +181 -0
  14. package/skills/qa/references/model-profiles.md +77 -0
  15. package/skills/qa/templates/agent-skeleton.md +733 -0
  16. package/skills/qa/templates/component-test.md +1088 -0
  17. package/skills/qa/templates/domain-research-queries.md +101 -0
  18. package/skills/qa/templates/domain-security-profiles.md +182 -0
  19. package/skills/qa/templates/e2e-test.md +1200 -0
  20. package/skills/qa/templates/nielsen-heuristics.md +274 -0
  21. package/skills/qa/templates/performance-benchmarks-base.md +321 -0
  22. package/skills/qa/templates/qa-report-template.md +271 -0
  23. package/skills/qa/templates/security-checklist-owasp.md +451 -0
  24. package/skills/qa/templates/stop-points/bootstrap-complete.md +36 -0
  25. package/skills/qa/templates/stop-points/certified.md +25 -0
  26. package/skills/qa/templates/stop-points/escalated.md +32 -0
  27. package/skills/qa/templates/stop-points/fix-ready.md +43 -0
  28. package/skills/qa/templates/stop-points/phase-transition.md +4 -0
  29. package/skills/qa/templates/stop-points/status-dashboard.md +32 -0
  30. package/skills/qa/templates/test-standards.md +652 -0
  31. package/skills/qa/templates/unit-test.md +998 -0
  32. package/skills/qa/templates/visual-regression.md +418 -0
  33. package/skills/qa/workflows/bootstrap.md +45 -0
  34. package/skills/qa/workflows/decision-gate.md +66 -0
  35. package/skills/qa/workflows/fix-execute.md +132 -0
  36. package/skills/qa/workflows/fix-plan.md +52 -0
  37. package/skills/qa/workflows/report-phase.md +64 -0
  38. package/skills/qa/workflows/test-phase.md +86 -0
  39. package/skills/qa/workflows/verify-phase.md +65 -0
@@ -0,0 +1,418 @@
1
+ ---
2
+ name: visual-regression
3
+ description: Set up and run visual regression tests for UI consistency. Use when verifying design system compliance and preventing visual regressions.
4
+ context: fork
5
+ agent: test-qa
6
+ allowed-tools:
7
+ - Read
8
+ - Glob
9
+ - Grep
10
+ - Write
11
+ - Edit
12
+ - Bash
13
+ ---
14
+
15
+ # Visual Regression Testing
16
+
17
+ This skill guides setup and execution of visual regression tests.
18
+
19
+ ## Prerequisites
20
+
21
+ - Playwright installed for screenshot capture
22
+ - Baseline screenshots established
23
+ - CI/CD pipeline configured for visual tests
24
+
25
+ ---
26
+
27
+ ## Overview
28
+
29
+ Visual regression testing captures screenshots and compares them against baselines to detect unintended visual changes.
30
+
31
+ ```
32
+ ┌─────────────────────────────────────────────────────────┐
33
+ │ VISUAL REGRESSION WORKFLOW │
34
+ ├─────────────────────────────────────────────────────────┤
35
+ │ │
36
+ │ 1. Capture baseline screenshots (first run) │
37
+ │ 2. Make code changes │
38
+ │ 3. Capture new screenshots │
39
+ │ 4. Compare against baselines │
40
+ │ 5. Review differences (if any) │
41
+ │ 6. Approve changes OR fix regressions │
42
+ │ │
43
+ └─────────────────────────────────────────────────────────┘
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Playwright Visual Testing Setup
49
+
50
+ ```typescript
51
+ // playwright.config.ts
52
+ import { defineConfig } from '@playwright/test'
53
+
54
+ export default defineConfig({
55
+ testDir: './visual-tests',
56
+
57
+ // Screenshot settings
58
+ expect: {
59
+ toHaveScreenshot: {
60
+ maxDiffPixels: 100, // Allow small differences
61
+ maxDiffPixelRatio: 0.01, // 1% pixel difference threshold
62
+ animations: 'disabled', // Disable animations for consistency
63
+ caret: 'hide', // Hide blinking cursor
64
+ },
65
+ },
66
+
67
+ // Use consistent viewport
68
+ use: {
69
+ viewport: { width: 1280, height: 720 },
70
+ deviceScaleFactor: 1,
71
+ },
72
+
73
+ // Only run on chromium for consistency
74
+ projects: [
75
+ {
76
+ name: 'visual-chromium',
77
+ use: { browserName: 'chromium' },
78
+ },
79
+ ],
80
+ })
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Basic Visual Test
86
+
87
+ ```typescript
88
+ // visual-tests/pages.visual.ts
89
+ import { test, expect } from '@playwright/test'
90
+
91
+ test.describe('Page Visual Tests', () => {
92
+ test.beforeEach(async ({ page }) => {
93
+ // Login and navigate (customize per project)
94
+ await page.goto('/')
95
+ await page.waitForLoadState('networkidle')
96
+ })
97
+
98
+ test('homepage matches baseline', async ({ page }) => {
99
+ // Hide dynamic content
100
+ await page.evaluate(() => {
101
+ document.querySelectorAll('[data-testid="timestamp"]').forEach(el => {
102
+ el.textContent = '2024-01-15'
103
+ })
104
+ })
105
+
106
+ await expect(page).toHaveScreenshot('homepage-full.png', {
107
+ fullPage: true,
108
+ })
109
+ })
110
+
111
+ test('navigation matches baseline', async ({ page }) => {
112
+ const nav = page.locator('[data-testid="navigation"]')
113
+ await expect(nav).toHaveScreenshot('navigation.png')
114
+ })
115
+ })
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Component Visual Tests
121
+
122
+ ```typescript
123
+ // visual-tests/components/buttons.visual.ts
124
+ import { test, expect } from '@playwright/test'
125
+
126
+ test.describe('Button Component Visual Tests', () => {
127
+ test('primary button states', async ({ page }) => {
128
+ await page.goto('/') // Navigate to a page with buttons
129
+
130
+ const primaryBtn = page.locator('[data-testid="btn-primary"]')
131
+
132
+ // Default state
133
+ await expect(primaryBtn).toHaveScreenshot('btn-primary-default.png')
134
+
135
+ // Hover state
136
+ await primaryBtn.hover()
137
+ await expect(primaryBtn).toHaveScreenshot('btn-primary-hover.png')
138
+
139
+ // Focus state
140
+ await primaryBtn.focus()
141
+ await expect(primaryBtn).toHaveScreenshot('btn-primary-focus.png')
142
+ })
143
+ })
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Responsive Visual Tests
149
+
150
+ ```typescript
151
+ // visual-tests/responsive.visual.ts
152
+ import { test, expect, devices } from '@playwright/test'
153
+
154
+ const viewports = [
155
+ { name: 'mobile', ...devices['iPhone 13'] },
156
+ { name: 'tablet', viewport: { width: 768, height: 1024 } },
157
+ { name: 'desktop', viewport: { width: 1280, height: 720 } },
158
+ { name: 'wide', viewport: { width: 1920, height: 1080 } },
159
+ ]
160
+
161
+ for (const vp of viewports) {
162
+ test.describe(`${vp.name} viewport`, () => {
163
+ test.use(vp)
164
+
165
+ test('layout', async ({ page }) => {
166
+ await page.goto('/')
167
+ await page.waitForLoadState('networkidle')
168
+
169
+ await expect(page).toHaveScreenshot(`layout-${vp.name}.png`, {
170
+ fullPage: true,
171
+ })
172
+ })
173
+ })
174
+ }
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Theme Visual Tests
180
+
181
+ ```typescript
182
+ // visual-tests/themes.visual.ts
183
+ import { test, expect } from '@playwright/test'
184
+
185
+ test.describe('Theme Visual Tests', () => {
186
+ test('light theme', async ({ page }) => {
187
+ await page.goto('/')
188
+ await page.emulateMedia({ colorScheme: 'light' })
189
+ await page.waitForLoadState('networkidle')
190
+ await expect(page).toHaveScreenshot('theme-light.png')
191
+ })
192
+
193
+ test('dark theme', async ({ page }) => {
194
+ await page.goto('/')
195
+ await page.emulateMedia({ colorScheme: 'dark' })
196
+ await page.waitForLoadState('networkidle')
197
+ await expect(page).toHaveScreenshot('theme-dark.png')
198
+ })
199
+ })
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Handling Dynamic Content
205
+
206
+ ```typescript
207
+ // visual-tests/utils/stabilize.ts
208
+ import { Page } from '@playwright/test'
209
+
210
+ export async function stabilizePage(page: Page) {
211
+ // Disable animations
212
+ await page.addStyleTag({
213
+ content: `
214
+ *, *::before, *::after {
215
+ animation-duration: 0s !important;
216
+ animation-delay: 0s !important;
217
+ transition-duration: 0s !important;
218
+ transition-delay: 0s !important;
219
+ }
220
+ `,
221
+ })
222
+
223
+ // Replace dynamic timestamps
224
+ await page.evaluate(() => {
225
+ document.querySelectorAll('[data-testid*="timestamp"]').forEach(el => {
226
+ el.textContent = '2024-01-15 10:00:00'
227
+ })
228
+ document.querySelectorAll('[data-testid*="relative-time"]').forEach(el => {
229
+ el.textContent = '5 minutes ago'
230
+ })
231
+ })
232
+
233
+ // Replace dynamic counts with stable values
234
+ await page.evaluate(() => {
235
+ document.querySelectorAll('[data-testid*="count"]').forEach(el => {
236
+ el.textContent = '42'
237
+ })
238
+ })
239
+
240
+ // Wait for fonts to load
241
+ await page.evaluate(() => document.fonts.ready)
242
+
243
+ // Wait for images to load
244
+ await page.waitForFunction(() => {
245
+ const images = document.querySelectorAll('img')
246
+ return Array.from(images).every(img => img.complete)
247
+ })
248
+ }
249
+ ```
250
+
251
+ ---
252
+
253
+ ## CI/CD Integration
254
+
255
+ ```yaml
256
+ # .github/workflows/visual-tests.yml
257
+ name: Visual Regression Tests
258
+
259
+ on:
260
+ pull_request:
261
+ branches: [main]
262
+
263
+ jobs:
264
+ visual-tests:
265
+ runs-on: ubuntu-latest
266
+
267
+ steps:
268
+ - uses: actions/checkout@v4
269
+
270
+ - name: Setup Node
271
+ uses: actions/setup-node@v4
272
+ with:
273
+ node-version: '20'
274
+
275
+ - name: Install dependencies
276
+ run: npm install # or pnpm install
277
+
278
+ - name: Install Playwright browsers
279
+ run: npx playwright install chromium
280
+
281
+ - name: Start app
282
+ run: npm run dev &
283
+
284
+ - name: Wait for app
285
+ run: npx wait-on http://localhost:3000
286
+
287
+ - name: Run visual tests
288
+ run: npm run visual-test
289
+
290
+ - name: Upload diff artifacts
291
+ if: failure()
292
+ uses: actions/upload-artifact@v4
293
+ with:
294
+ name: visual-diff
295
+ path: visual-tests/test-results/
296
+ retention-days: 7
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Updating Baselines
302
+
303
+ ```bash
304
+ # Update all baselines
305
+ npx playwright test --update-snapshots
306
+
307
+ # Update specific test baselines
308
+ npx playwright test pages.visual.ts --update-snapshots
309
+
310
+ # Interactive update (approve changes one by one)
311
+ npx playwright test --ui
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Directory Structure
317
+
318
+ ```
319
+ visual-tests/
320
+ ├── playwright.config.ts # Visual test config
321
+ ├── pages.visual.ts # Full page tests
322
+ ├── components/
323
+ │ ├── buttons.visual.ts
324
+ │ ├── cards.visual.ts
325
+ │ └── forms.visual.ts
326
+ ├── responsive.visual.ts # Responsive tests
327
+ ├── themes.visual.ts # Theme tests
328
+ ├── utils/
329
+ │ └── stabilize.ts # Helper functions
330
+ └── screenshots/ # Baseline images (git tracked)
331
+ ├── homepage-full-chromium.png
332
+ └── ...
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Best Practices
338
+
339
+ | Practice | Why |
340
+ |----------|-----|
341
+ | Use consistent viewport sizes | Prevents false positives from resize |
342
+ | Disable animations | Animations cause flaky comparisons |
343
+ | Replace dynamic content | Timestamps, counts change between runs |
344
+ | Wait for network idle | Ensures all data loaded |
345
+ | Wait for fonts | Font loading affects rendering |
346
+ | Use data-testid for locators | More stable than CSS classes |
347
+ | Run only on one browser | Reduces maintenance, ensures consistency |
348
+ | Store baselines in git | Easy to review changes in PRs |
349
+
350
+ ---
351
+
352
+ ## Design System Assertions
353
+
354
+ Visual regression tests should verify design system invariants programmatically:
355
+
356
+ ```typescript
357
+ // visual-tests/design-system.visual.ts
358
+ import { test, expect, Page } from '@playwright/test'
359
+
360
+ async function getComputedStyle(page: Page, selector: string, property: string): Promise<string> {
361
+ return page.evaluate(
362
+ ({ sel, prop }) => {
363
+ const el = document.querySelector(sel)
364
+ if (!el) throw new Error(`Element not found: ${sel}`)
365
+ return window.getComputedStyle(el).getPropertyValue(prop)
366
+ },
367
+ { sel: selector, prop: property }
368
+ )
369
+ }
370
+
371
+ test.describe('Design System Invariants', () => {
372
+ test('touch targets meet 44x44px minimum', async ({ page }) => {
373
+ await page.goto('/')
374
+ await page.waitForLoadState('networkidle')
375
+
376
+ const violations = await page.evaluate(() => {
377
+ const interactive = document.querySelectorAll('button, a, [role="button"], input, select, textarea')
378
+ const small: string[] = []
379
+
380
+ for (const el of interactive) {
381
+ const rect = el.getBoundingClientRect()
382
+ if (rect.width > 0 && rect.height > 0) {
383
+ if (rect.width < 44 || rect.height < 44) {
384
+ small.push(`${el.tagName}${el.id ? '#' + el.id : ''}: ${rect.width}x${rect.height}`)
385
+ }
386
+ }
387
+ }
388
+
389
+ return small
390
+ })
391
+
392
+ expect(violations).toHaveLength(0)
393
+ })
394
+ })
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Checklist
400
+
401
+ Before adding visual tests:
402
+
403
+ - [ ] Identify pages/components to test
404
+ - [ ] Handle dynamic content (timestamps, counts)
405
+ - [ ] Disable animations
406
+ - [ ] Define viewport sizes for responsive tests
407
+ - [ ] Set appropriate diff thresholds
408
+ - [ ] Configure CI/CD for visual test runs
409
+ - [ ] Document baseline update process
410
+
411
+ ---
412
+
413
+ ## See Also
414
+
415
+ - E2E testing skill
416
+ - Component testing skill
417
+ - Test standards
418
+ - QA report template
@@ -0,0 +1,45 @@
1
+ # Workflow: Bootstrap (Phase 0)
2
+
3
+ <purpose>
4
+ Thin interface document for bootstrap. Actual logic lives in SKILL.md (B1-B9). This file exists so commands can reference it consistently alongside other workflows.
5
+ </purpose>
6
+
7
+ <required_context>
8
+ - SKILL: ~/.claude/skills/qa/SKILL.md (contains full B1-B9 protocol)
9
+ </required_context>
10
+
11
+ <process>
12
+
13
+ ## Input
14
+
15
+ - `--rebootstrap` flag: Force re-discovery even if qa-profile.json exists
16
+
17
+ ## Execution
18
+
19
+ Invoke the `/qa` skill which contains the full Phase 0 Bootstrap Protocol:
20
+
21
+ | Step | Description |
22
+ |------|-------------|
23
+ | B1 | Root Discovery (package.json, framework detection, domain detection) |
24
+ | B2 | Parallel Research (app discovery, security context, PRD analysis, Anthropic docs, stack/security/UX research) |
25
+ | B3 | Monorepo structure detection |
26
+ | B4 | Profile assembly (qa-profile.json) |
27
+ | B5 | Directory creation + project-level CLAUDE.md registration |
28
+ | B6 | File generation (skill files, agent files, test matrix) |
29
+ | B7 | Existing file handling (skip user-modified files) |
30
+ | B8 | Validation (check generated files) |
31
+ | B9 | State checkpoint + output |
32
+
33
+ ## Output
34
+
35
+ - `.claude/qa-profile.json` — project profile
36
+ - `.claude/agents/qa-*.md` — 6 agent files
37
+ - `.claude/skills/testing/*.md` — skill files
38
+ - `docs/qa-reports/cycle-state.json` — initial state (`phase: "bootstrap_complete"`)
39
+
40
+ ## Terminal Output
41
+
42
+ Read and output `~/.claude/skills/qa/templates/stop-points/bootstrap-complete.md`
43
+ Substitute all `{placeholder}` values with profile data from B4.
44
+
45
+ </process>
@@ -0,0 +1,66 @@
1
+ # Workflow: Decision Gate (Phase 5)
2
+
3
+ <purpose>
4
+ Evaluate the consolidated report against exit criteria. Return PASS, FAIL, or ESCALATE. Pure logic — no agent spawning.
5
+ </purpose>
6
+
7
+ <required_context>
8
+ - STATE: docs/qa-reports/cycle-state.json (cycle number, previousCycles, blockedDefectIds)
9
+ - REPORT: docs/qa-reports/cycle-{N}-{date}.md (consolidated report)
10
+ - EXIT_CRITERIA: ~/.claude/skills/qa/references/exit-criteria.md
11
+ </required_context>
12
+
13
+ <process>
14
+
15
+ ## 1. Read Exit Criteria
16
+
17
+ Read `~/.claude/skills/qa/references/exit-criteria.md` on-demand.
18
+
19
+ ## 2. Read Consolidated Report
20
+
21
+ Read the cycle report and extract:
22
+ - Total tests, passing, failing
23
+ - Defect counts by severity (critical, major, minor, cosmetic)
24
+ - UX score, Lighthouse scores (if applicable)
25
+ - Tenant isolation results (if applicable)
26
+ - Auth boundary results (if applicable)
27
+
28
+ ## 3. Evaluate Against Thresholds
29
+
30
+ For each gate in exit criteria, compare report values:
31
+
32
+ | Gate | Threshold | Actual | Pass? |
33
+ |------|-----------|--------|-------|
34
+ {evaluate each gate}
35
+
36
+ ## 4. Determine Decision
37
+
38
+ ```
39
+ IF all exit criteria pass:
40
+ → decision = "PASS"
41
+
42
+ ELIF cycle >= 3 AND same defects persist across 2+ cycles:
43
+ → decision = "ESCALATE"
44
+
45
+ ELIF cycle >= 3 AND blockedDefectIds.length > 0 across 2+ cycles:
46
+ → decision = "ESCALATE"
47
+
48
+ ELSE:
49
+ → decision = "FAIL"
50
+ ```
51
+
52
+ ## 5. Write Decision to State
53
+
54
+ Update cycle-state.json with decision BEFORE routing:
55
+ ```json
56
+ { "decision": "PASS|FAIL|ESCALATE", "verdict": "PASS|FAIL" }
57
+ ```
58
+
59
+ ## 6. Return Decision
60
+
61
+ Return the decision to the calling command for phase routing:
62
+ - **PASS** → Phase 8 (certification)
63
+ - **FAIL** → Phase 6 (plan fixes)
64
+ - **ESCALATE** → Phase 9 (escalation)
65
+
66
+ </process>
@@ -0,0 +1,132 @@
1
+ # Workflow: Fix Execution (Phase 7)
2
+
3
+ <purpose>
4
+ Execute approved fix plan by dispatching implementer agents per priority batch (P0 → P1 → P2), with post-implementation validation and correction loops.
5
+ </purpose>
6
+
7
+ <required_context>
8
+ - PROFILE: .claude/qa-profile.json (commands.typeCheck, commands.build, agentRouting.fixRoutes)
9
+ - STATE: docs/qa-reports/cycle-state.json (fixPlanPath, batchProgress)
10
+ - MODEL_MAP: resolved models for fix-implementer and qa-verifier
11
+ - FIX_PLAN: docs/qa-reports/fix-plan-cycle-{N}.md
12
+ </required_context>
13
+
14
+ <process>
15
+
16
+ ## 1. Write State Checkpoint
17
+
18
+ ```json
19
+ {
20
+ "phase": "fixing",
21
+ "batchProgress": {
22
+ "completedBatches": [],
23
+ "currentBatch": null
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## 2. Load Fix Plan
29
+
30
+ Read fix plan from `STATE.fixPlanPath`.
31
+ Read agent routing from `PROFILE.agentRouting.fixRoutes`.
32
+
33
+ ## 3. For Each Priority Batch (P0 → P1 → P2)
34
+
35
+ ### 3a. Parse Batch
36
+
37
+ Extract defect IDs, target files, fix approach, and target agent for each fix in the batch.
38
+
39
+ ### 3b. Pre-Applied Fix Detection
40
+
41
+ For each fix, read target files and check if the fix appears already applied (e.g., from manual user changes). Skip to verification if already applied.
42
+
43
+ ### 3c. Analyze Independence
44
+
45
+ - Fixes touching **different files** → dispatch in parallel
46
+ - Fixes touching **same files** → dispatch sequentially
47
+
48
+ ### 3d. Dispatch Implementers
49
+
50
+ For each fix needing implementation:
51
+
52
+ ```
53
+ Task(
54
+ subagent_type="general-purpose",
55
+ prompt="[FIX] Defect {defect-id} ({severity})
56
+
57
+ Root cause: {root-cause}
58
+ Fix approach: {approach}
59
+ Files to modify: {file-list}
60
+
61
+ PROJECT CONTEXT (inlined):
62
+ - TypeCheck command: {PROFILE.commands.typeCheck}
63
+ - Build command: {PROFILE.commands.build}
64
+
65
+ SCOPE CONSTRAINT: Targeted fix only, not a refactor.
66
+ Do NOT review your own code after writing it.",
67
+ model="{MODEL_MAP['fix-implementer']}",
68
+ description="Fix {defect-id}"
69
+ )
70
+ ```
71
+
72
+ ### 3e. Post-Implementation Validation
73
+
74
+ Orchestrator runs directly (not via agent):
75
+ 1. Type-check: `{PROFILE.commands.typeCheck}` → FAIL: re-dispatch (max 3 retries)
76
+ 2. Build: `{PROFILE.commands.build}` → FAIL: re-dispatch (max 3 retries)
77
+
78
+ ### 3f. Batch Verification
79
+
80
+ Spawn qa-verifier for the batch:
81
+
82
+ ```
83
+ Task(
84
+ subagent_type="general-purpose",
85
+ prompt="[QA-VERIFIER] Read .claude/agents/qa-verifier.md.
86
+ IMPORTANT: Read the Resources section FIRST.
87
+
88
+ Re-run ONLY these previously failed tests: {batch-test-ids}
89
+
90
+ PROJECT CONTEXT (inlined):
91
+ - Test command: {PROFILE.commands.test}
92
+ - Apps: {relevant apps from PROFILE.apps}
93
+
94
+ Return PASS or STILL_FAILING for each test.",
95
+ model="{MODEL_MAP['qa-verifier']}",
96
+ description="Verify batch P{X}"
97
+ )
98
+ ```
99
+
100
+ ### 3g. Correction Loop
101
+
102
+ For STILL_FAILING results: re-dispatch implementer with verifier evidence (max 3 iterations per fix). After 3 failures, mark as BLOCKED and add to `blockedDefectIds`.
103
+
104
+ ### 3h. Batch Checkpoint
105
+
106
+ Update state after each batch completes:
107
+ ```json
108
+ {
109
+ "batchProgress": {
110
+ "completedBatches": ["P0"],
111
+ "currentBatch": "P1"
112
+ }
113
+ }
114
+ ```
115
+
116
+ ## 4. Phase Gate
117
+
118
+ Each batch must complete before the next starts. P0 → P1 → P2 strictly ordered.
119
+
120
+ ## 5. Final State Checkpoint
121
+
122
+ After all batches complete:
123
+ ```json
124
+ { "phase": "verifying" }
125
+ ```
126
+
127
+ ## 6. Output Phase Transition
128
+
129
+ Read and output `~/.claude/skills/qa/templates/stop-points/phase-transition.md`
130
+ Substitute: {X} = 7, {Y} = 7b
131
+
132
+ </process>
@@ -0,0 +1,52 @@
1
+ # Workflow: Fix Plan (Phase 6)
2
+
3
+ <purpose>
4
+ Spawn fix planner agent to analyze defects and produce a prioritized fix plan. Does NOT include stop-point output — the calling command handles that.
5
+ </purpose>
6
+
7
+ <required_context>
8
+ - PROFILE: .claude/qa-profile.json (agentRouting.fixRoutes, apps)
9
+ - STATE: docs/qa-reports/cycle-state.json (cycle number, blockedDefectIds)
10
+ - MODEL_MAP: resolved model for qa-fix-planner
11
+ - REPORT: docs/qa-reports/cycle-{N}-{date}.md (consolidated report with defects)
12
+ </required_context>
13
+
14
+ <process>
15
+
16
+ ## 1. Spawn Fix Planner
17
+
18
+ Inline defect data and agent routing into the prompt:
19
+
20
+ ```
21
+ Task(
22
+ subagent_type="general-purpose",
23
+ prompt="[QA-FIX-PLANNER] Read .claude/agents/qa-fix-planner.md.
24
+ IMPORTANT: Read the Resources section FIRST.
25
+
26
+ PROJECT CONTEXT (inlined from profile):
27
+ - Agent routing: {JSON of PROFILE.agentRouting.fixRoutes}
28
+ - Apps: {JSON summary of PROFILE.apps}
29
+
30
+ DEFECT SOURCE:
31
+ Analyze defects from: docs/qa-reports/cycle-{N}-{date}.md
32
+
33
+ EXCLUSIONS:
34
+ Exclude blocked defect IDs: {STATE.blockedDefectIds}
35
+
36
+ Write fix plan to: docs/qa-reports/fix-plan-cycle-{N}.md",
37
+ model="{MODEL_MAP['qa-fix-planner']}",
38
+ description="QA fix plan cycle {N}"
39
+ )
40
+ ```
41
+
42
+ ## 2. Write State Checkpoint
43
+
44
+ ```json
45
+ { "phase": "awaiting_fix_approval", "fixPlanPath": "docs/qa-reports/fix-plan-cycle-{N}.md" }
46
+ ```
47
+
48
+ ## 3. Verify Files Exist
49
+
50
+ Read back fix plan and cycle-state.json to confirm writes succeeded.
51
+
52
+ </process>