qaa-agent 1.6.2 → 1.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.
Files changed (78) hide show
  1. package/.mcp.json +8 -8
  2. package/CHANGELOG.md +93 -71
  3. package/CLAUDE.md +553 -553
  4. package/agents/qa-pipeline-orchestrator.md +1378 -1378
  5. package/agents/qaa-analyzer.md +539 -524
  6. package/agents/qaa-bug-detective.md +479 -446
  7. package/agents/qaa-codebase-mapper.md +935 -935
  8. package/agents/qaa-discovery.md +384 -0
  9. package/agents/qaa-e2e-runner.md +416 -415
  10. package/agents/qaa-executor.md +651 -651
  11. package/agents/qaa-planner.md +405 -390
  12. package/agents/qaa-project-researcher.md +319 -319
  13. package/agents/qaa-scanner.md +424 -424
  14. package/agents/qaa-testid-injector.md +643 -585
  15. package/agents/qaa-validator.md +490 -452
  16. package/bin/install.cjs +200 -198
  17. package/bin/lib/commands.cjs +709 -709
  18. package/bin/lib/config.cjs +307 -307
  19. package/bin/lib/core.cjs +497 -497
  20. package/bin/lib/frontmatter.cjs +299 -299
  21. package/bin/lib/init.cjs +989 -989
  22. package/bin/lib/milestone.cjs +241 -241
  23. package/bin/lib/model-profiles.cjs +60 -60
  24. package/bin/lib/phase.cjs +911 -911
  25. package/bin/lib/roadmap.cjs +306 -306
  26. package/bin/lib/state.cjs +748 -748
  27. package/bin/lib/template.cjs +222 -222
  28. package/bin/lib/verify.cjs +842 -842
  29. package/bin/qaa-tools.cjs +607 -607
  30. package/commands/qa-audit.md +119 -0
  31. package/commands/qa-create-test.md +288 -0
  32. package/commands/qa-fix.md +147 -0
  33. package/commands/qa-map.md +137 -0
  34. package/{.claude/commands → commands}/qa-pr.md +23 -23
  35. package/{.claude/commands → commands}/qa-start.md +22 -22
  36. package/{.claude/commands → commands}/qa-testid.md +19 -19
  37. package/docs/COMMANDS.md +341 -341
  38. package/docs/DEMO.md +182 -182
  39. package/docs/TESTING.md +156 -156
  40. package/package.json +6 -7
  41. package/{.claude/settings.json → settings.json} +1 -2
  42. package/templates/failure-classification.md +391 -391
  43. package/templates/gap-analysis.md +409 -409
  44. package/templates/pr-template.md +48 -48
  45. package/templates/qa-analysis.md +381 -381
  46. package/templates/qa-audit-report.md +465 -465
  47. package/templates/qa-repo-blueprint.md +636 -636
  48. package/templates/scan-manifest.md +312 -312
  49. package/templates/test-inventory.md +582 -582
  50. package/templates/testid-audit-report.md +354 -354
  51. package/templates/validation-report.md +243 -243
  52. package/workflows/qa-analyze.md +296 -296
  53. package/workflows/qa-from-ticket.md +536 -536
  54. package/workflows/qa-gap.md +309 -303
  55. package/workflows/qa-pr.md +389 -389
  56. package/workflows/qa-start.md +1192 -1168
  57. package/workflows/qa-testid.md +384 -356
  58. package/workflows/qa-validate.md +299 -295
  59. package/.claude/commands/create-test.md +0 -164
  60. package/.claude/commands/qa-audit.md +0 -37
  61. package/.claude/commands/qa-blueprint.md +0 -54
  62. package/.claude/commands/qa-fix.md +0 -36
  63. package/.claude/commands/qa-from-ticket.md +0 -24
  64. package/.claude/commands/qa-gap.md +0 -20
  65. package/.claude/commands/qa-map.md +0 -47
  66. package/.claude/commands/qa-pom.md +0 -36
  67. package/.claude/commands/qa-pyramid.md +0 -37
  68. package/.claude/commands/qa-report.md +0 -38
  69. package/.claude/commands/qa-research.md +0 -33
  70. package/.claude/commands/qa-validate.md +0 -42
  71. package/.claude/commands/update-test.md +0 -58
  72. package/.claude/skills/qa-learner/SKILL.md +0 -150
  73. /package/{.claude/skills → skills}/qa-bug-detective/SKILL.md +0 -0
  74. /package/{.claude/skills → skills}/qa-repo-analyzer/SKILL.md +0 -0
  75. /package/{.claude/skills → skills}/qa-self-validator/SKILL.md +0 -0
  76. /package/{.claude/skills → skills}/qa-template-engine/SKILL.md +0 -0
  77. /package/{.claude/skills → skills}/qa-testid-injector/SKILL.md +0 -0
  78. /package/{.claude/skills → skills}/qa-workflow-documenter/SKILL.md +0 -0
@@ -1,356 +1,384 @@
1
- <purpose>
2
- Scan a frontend codebase, audit every interactive UI element for data-testid coverage, and inject missing data-testid attributes following the `{context}-{description}-{element-type}` naming convention from CLAUDE.md. Operates on a separate branch (`qa/testid-{project}-{date}`) to keep the working copy clean. Produces TESTID_AUDIT_REPORT.md with coverage scores, proposed values, and a decision gate. The user reviews and approves proposed changes before injection. Use this workflow to prepare a frontend codebase for reliable Tier 1 test selectors.
3
- </purpose>
4
-
5
- <required_reading>
6
- - `CLAUDE.md` -- data-testid Convention (naming pattern, context derivation, element-type suffix table, third-party handling), Locator Strategy (Tier 1 includes data-testid)
7
- - `data-testid-SKILL.md` -- Complete naming convention reference, framework-specific injection syntax, edge case handling
8
- - `agents/qaa-scanner.md` -- Scanner agent definition (detects frontend framework, enumerates component files)
9
- - `agents/qaa-testid-injector.md` -- TestID injector agent definition (4-phase: SCAN, AUDIT, INJECT, VALIDATE)
10
- - `templates/scan-manifest.md` -- SCAN_MANIFEST.md format contract
11
- - `templates/testid-audit-report.md` -- TESTID_AUDIT_REPORT.md format contract
12
- </required_reading>
13
-
14
- <process>
15
-
16
- <step name="parse_arguments">
17
- ## Step 1: Parse Arguments
18
-
19
- Parse `$ARGUMENTS` for the source directory path.
20
-
21
- **Supported arguments:**
22
- - `<path>` -- Path to the frontend source directory (positional)
23
- - No arguments -- auto-detect frontend directories
24
-
25
- **Parsing logic:**
26
-
27
- ```bash
28
- SOURCE_DIR=""
29
-
30
- # Parse positional path argument from $ARGUMENTS
31
- ```
32
-
33
- **Validation:**
34
- - If a path is provided, verify it exists and is a directory. If not, print error: `"Error: Source directory does not exist: {path}"` and STOP.
35
- - If no path provided, proceed to auto-detection in the next step.
36
- </step>
37
-
38
- <step name="detect_frontend">
39
- ## Step 2: Detect Frontend Directory and Framework
40
-
41
- If no source directory was specified, auto-detect by searching for common frontend directory patterns.
42
-
43
- **Directory detection order:**
44
-
45
- 1. `src/` -- Most common source directory
46
- 2. `app/` -- Next.js app directory, or generic app directory
47
- 3. `components/` -- Component-focused projects
48
- 4. `pages/` -- File-based routing frameworks (Next.js, Nuxt)
49
- 5. `lib/` -- Library projects
50
- 6. `client/` -- Monorepo client directory
51
-
52
- **Detection logic:**
53
-
54
- ```bash
55
- if SOURCE_DIR is empty:
56
- for dir in src app components pages lib client:
57
- if directory exists at "${dir}":
58
- SOURCE_DIR="${dir}"
59
- break
60
- ```
61
-
62
- **If no frontend directory found:**
63
-
64
- Print error and STOP:
65
- ```
66
- Error: No frontend source directory found.
67
- Searched for: src/, app/, components/, pages/, lib/, client/
68
- Provide the source directory path as an argument: /qa-testid <path>
69
- ```
70
-
71
- **Detect frontend framework:**
72
-
73
- Check for framework indicators in the project root:
74
-
75
- | Framework | Detection Method |
76
- |-----------|-----------------|
77
- | React | `react` or `react-dom` in package.json dependencies; `*.jsx` or `*.tsx` files present |
78
- | Vue | `vue` in package.json dependencies; `*.vue` files present |
79
- | Angular | `@angular/core` in package.json dependencies; `*.component.ts` and `*.component.html` files present |
80
- | Svelte | `svelte` in package.json dependencies; `*.svelte` files present |
81
- | Plain HTML | None of the above; `*.html` files present (excluding build output) |
82
-
83
- ```bash
84
- FRONTEND_FRAMEWORK=""
85
-
86
- # Check package.json for framework dependencies
87
- # Check for framework-specific file extensions in SOURCE_DIR
88
- ```
89
-
90
- **If no frontend framework detected:**
91
-
92
- Print error and STOP:
93
- ```
94
- Error: No frontend framework detected.
95
- Checked package.json dependencies and file extensions in {SOURCE_DIR}.
96
- No React (.jsx/.tsx), Vue (.vue), Angular (.component.ts), Svelte (.svelte), or HTML files found.
97
-
98
- This workflow requires a frontend codebase with UI components to inject data-testid attributes.
99
- ```
100
-
101
- **Count component files:**
102
-
103
- ```bash
104
- # Count files matching the detected framework's extensions
105
- COMPONENT_COUNT=$(find "${SOURCE_DIR}" -type f \( -name "*.tsx" -o -name "*.jsx" -o -name "*.vue" -o -name "*.svelte" -o -name "*.component.html" \) \
106
- ! -path "*/node_modules/*" ! -path "*/dist/*" ! -path "*/build/*" \
107
- ! -name "*.test.*" ! -name "*.spec.*" ! -name "*.stories.*" | wc -l)
108
- ```
109
-
110
- If `COMPONENT_COUNT` is 0, print error and STOP:
111
- ```
112
- Error: No component files found in {SOURCE_DIR}.
113
- Framework detected: {FRONTEND_FRAMEWORK}
114
- Expected file patterns: {patterns for that framework}
115
- ```
116
-
117
- **Print detection results:**
118
-
119
- ```
120
- Frontend Detection:
121
- Source Directory: {SOURCE_DIR}
122
- Framework: {FRONTEND_FRAMEWORK}
123
- Component Files: {COMPONENT_COUNT}
124
- ```
125
- </step>
126
-
127
- <step name="run_scanner">
128
- ## Step 3: Spawn Scanner Agent
129
-
130
- Spawn the scanner agent to produce SCAN_MANIFEST.md with the frontend component file list.
131
-
132
- ```
133
- Task(
134
- prompt="
135
- <objective>Scan frontend repository and produce SCAN_MANIFEST.md with component file enumeration</objective>
136
- <execution_context>@agents/qaa-scanner.md</execution_context>
137
- <files_to_read>
138
- - CLAUDE.md
139
- </files_to_read>
140
- <parameters>
141
- dev_repo_path: {project root}
142
- qa_repo_path: null
143
- output_path: {OUTPUT_DIR}/SCAN_MANIFEST.md
144
- </parameters>
145
- "
146
- )
147
- ```
148
-
149
- **Set output directory:**
150
-
151
- ```bash
152
- OUTPUT_DIR=".qa-output"
153
- mkdir -p "${OUTPUT_DIR}"
154
- ```
155
-
156
- **Handle scanner return:**
157
-
158
- - Extract `has_frontend` -- MUST be `true`. If `false`, print error and STOP:
159
- ```
160
- Error: Scanner reports has_frontend: false.
161
- The detected framework ({FRONTEND_FRAMEWORK}) and component files ({COMPONENT_COUNT}) suggest frontend is present,
162
- but the scanner could not classify them as frontend components.
163
- Check SCAN_MANIFEST.md for details: {OUTPUT_DIR}/SCAN_MANIFEST.md
164
- ```
165
-
166
- **Verify SCAN_MANIFEST.md exists:**
167
-
168
- ```bash
169
- [ -f "${OUTPUT_DIR}/SCAN_MANIFEST.md" ] && echo "FOUND" || echo "MISSING"
170
- ```
171
-
172
- If missing, print error and STOP.
173
- </step>
174
-
175
- <step name="run_testid_injector">
176
- ## Step 4: Spawn TestID Injector Agent
177
-
178
- Spawn the testid-injector agent which operates in 4 phases: SCAN, AUDIT, INJECT, VALIDATE.
179
-
180
- ```
181
- Task(
182
- prompt="
183
- <objective>Audit frontend components for data-testid coverage and inject missing attributes</objective>
184
- <execution_context>@agents/qaa-testid-injector.md</execution_context>
185
- <files_to_read>
186
- - {OUTPUT_DIR}/SCAN_MANIFEST.md
187
- - CLAUDE.md
188
- - data-testid-SKILL.md
189
- </files_to_read>
190
- <parameters>
191
- source_dir: {SOURCE_DIR}
192
- frontend_framework: {FRONTEND_FRAMEWORK}
193
- output_path: {OUTPUT_DIR}/TESTID_AUDIT_REPORT.md
194
- </parameters>
195
- "
196
- )
197
- ```
198
-
199
- **Injector agent phases:**
200
-
201
- 1. **SCAN phase:** The injector detects the framework, lists component files, classifies them by interaction density (HIGH/MEDIUM/LOW), and sorts by priority.
202
-
203
- 2. **AUDIT phase:** For each component file, the injector identifies every interactive element (buttons, inputs, selects, forms, links, modals, etc.), checks for existing data-testid attributes, proposes values for missing attributes following `{context}-{description}-{element-type}` convention, classifies elements by priority (P0/P1/P2), and calculates the coverage score.
204
-
205
- 3. **CHECKPOINT:** The injector presents the TESTID_AUDIT_REPORT.md to the user for review before injecting. The user can:
206
- - Approve all proposed values
207
- - Reject specific elements
208
- - Rename proposed values
209
- - Approve renaming of non-compliant existing values
210
- - Change priority classifications
211
-
212
- 4. **INJECT phase (after approval):** Creates a separate branch `qa/testid-inject-{YYYY-MM-DD}`, injects approved data-testid attributes using framework-specific syntax (JSX attributes for React, HTML attributes for Vue templates, `[attr.data-testid]` binding for Angular), preserves all existing formatting, and preserves existing data-testid values.
213
-
214
- 5. **VALIDATE phase:** Runs syntax checks on all modified files, verifies uniqueness of data-testid values per page/route scope, checks naming convention compliance, and verifies no unintended source code changes (non-interference check). If syntax fails, reverts the specific file.
215
-
216
- **Handle injector return:**
217
-
218
- Extract:
219
- - `report_path` -- Path to TESTID_AUDIT_REPORT.md
220
- - `changelog_path` -- Path to INJECTION_CHANGELOG.md
221
- - `branch` -- Name of the injection branch
222
- - `coverage_before` -- Coverage before injection
223
- - `coverage_after` -- Coverage after injection
224
- - `elements_injected` -- Count of injected attributes
225
- - `elements_deferred` -- Count of deferred elements
226
- - `files_modified` -- Count of modified files
227
- - `validation_passed` -- Whether all validation checks passed
228
- </step>
229
-
230
- <step name="create_branch_and_commit">
231
- ## Step 5: Create Branch and Commit
232
-
233
- The testid-injector agent handles branch creation and commits internally on the `qa/testid-inject-{YYYY-MM-DD}` branch. Verify the branch was created and commits exist.
234
-
235
- **Verify branch:**
236
-
237
- ```bash
238
- git branch --list "qa/testid-inject-*"
239
- ```
240
-
241
- If the branch does not exist, the injector may not have reached the injection phase (stopped at audit checkpoint). This is expected behavior -- the audit report is still produced.
242
-
243
- **Verify commit (if injection was performed):**
244
-
245
- ```bash
246
- git log --oneline -3 "qa/testid-inject-*" 2>/dev/null
247
- ```
248
- </step>
249
-
250
- <step name="print_summary">
251
- ## Step 6: Print Summary
252
-
253
- Print a comprehensive summary of the testid injection results.
254
-
255
- ```
256
- === TestID Injection Complete ===
257
-
258
- Frontend:
259
- Framework: {FRONTEND_FRAMEWORK}
260
- Source Directory: {SOURCE_DIR}
261
- Component Files: {COMPONENT_COUNT}
262
-
263
- Coverage:
264
- Before: {coverage_before}%
265
- After: {coverage_after}%
266
- Change: +{coverage_after - coverage_before}%
267
-
268
- Elements:
269
- Total Interactive: {total_elements}
270
- Already Had TestID: {existing_count}
271
- Injected: {elements_injected}
272
- Deferred (P1/P2): {elements_deferred}
273
-
274
- By Priority:
275
- P0 (inputs, buttons, forms): {p0_count} ({p0_injected} injected)
276
- P1 (links, alerts, toggles): {p1_count} ({p1_injected} injected)
277
- P2 (images, badges, tables): {p2_count} ({p2_injected} injected)
278
-
279
- Validation:
280
- Syntax Check: {PASS|FAIL}
281
- Uniqueness Check: {PASS|FAIL}
282
- Convention Check: {PASS|FAIL}
283
- Non-Interference: {PASS|FAIL}
284
-
285
- Branch: {branch_name}
286
- Files Modified: {files_modified}
287
-
288
- Artifacts:
289
- - {OUTPUT_DIR}/SCAN_MANIFEST.md
290
- - {OUTPUT_DIR}/TESTID_AUDIT_REPORT.md
291
- - {OUTPUT_DIR}/INJECTION_CHANGELOG.md (after injection)
292
-
293
- Next Steps:
294
- 1. Review changes on branch: git diff main..{branch_name}
295
- 2. If approved, merge: git merge {branch_name}
296
- 3. Run tests to verify no regressions
297
- =================================
298
- ```
299
-
300
- **If injection was not performed (stopped at audit checkpoint):**
301
-
302
- ```
303
- === TestID Audit Complete (Injection Pending) ===
304
-
305
- The audit report has been produced. Review the proposed data-testid values
306
- in {OUTPUT_DIR}/TESTID_AUDIT_REPORT.md and re-run with approvals to inject.
307
-
308
- Coverage Score: {coverage_before}%
309
- Decision: {SELECTIVE|TARGETED|FULL PASS|P0 FIRST}
310
- Missing TestIDs: {missing_count} ({p0_missing} P0, {p1_missing} P1, {p2_missing} P2)
311
- =============================================
312
- ```
313
- </step>
314
-
315
- </process>
316
-
317
- <output>
318
- This workflow audits and injects data-testid attributes into frontend components.
319
-
320
- **Artifacts produced:**
321
-
322
- | Artifact | When Produced | Description |
323
- |----------|---------------|-------------|
324
- | SCAN_MANIFEST.md | Always | Repository scan with component file list and framework detection |
325
- | TESTID_AUDIT_REPORT.md | Always | Comprehensive audit: coverage score, per-element tables, naming compliance, decision gate |
326
- | INJECTION_CHANGELOG.md | After injection approval | Per-file log of every injection action with validation results |
327
- | Modified source files | After injection approval | Component files with data-testid attributes added, on separate branch |
328
-
329
- **Branch management:**
330
- - Injection branch: `qa/testid-inject-{YYYY-MM-DD}`
331
- - Working copy on the original branch is NOT modified
332
- - User merges the injection branch if approved
333
-
334
- **Decision gate thresholds (from CLAUDE.md):**
335
-
336
- | Current Coverage | Decision | Strategy |
337
- |-----------------|----------|----------|
338
- | > 90% | SELECTIVE | Inject only P0 missing elements |
339
- | 50% - 90% | TARGETED | Inject P0 and P1 missing elements |
340
- | 1% - 49% | FULL PASS | Inject all P0, P1, P2 elements |
341
- | 0% | P0 FIRST | Inject P0 elements only, then re-audit |
342
- </output>
343
-
344
- <error_handling>
345
- | Error | Cause | Action |
346
- |-------|-------|--------|
347
- | Source directory does not exist | Invalid path argument | Print error with path, STOP |
348
- | No frontend directory found | No common frontend dirs in project | Print error listing searched dirs, suggest providing path, STOP |
349
- | No frontend framework detected | Missing framework deps and file extensions | Print error with detection details, STOP |
350
- | No component files found | Directory exists but no components | Print error with expected patterns for the detected framework, STOP |
351
- | Scanner reports has_frontend: false | Scanner classification issue | Print error with suggestion to check SCAN_MANIFEST.md, STOP |
352
- | SCAN_MANIFEST.md missing | Scanner failed | Print error, STOP |
353
- | Syntax check fails after injection | Injection broke file syntax | Injector reverts the specific file automatically, reports in changelog |
354
- | Duplicate data-testid detected | Same value on same rendered page | Injector renames the newer injection to disambiguate |
355
- | Non-compliant existing values | Existing data-testid does not follow convention | Reported in audit but NOT auto-renamed (user decides) |
356
- </error_handling>
1
+ <purpose>
2
+ Scan a frontend codebase, audit every interactive UI element for data-testid coverage, and inject missing data-testid attributes following the `{context}-{description}-{element-type}` naming convention from CLAUDE.md. Operates on a separate branch (`qa/testid-{project}-{date}`) to keep the working copy clean. Produces TESTID_AUDIT_REPORT.md with coverage scores, proposed values, and a decision gate. The user reviews and approves proposed changes before injection. Use this workflow to prepare a frontend codebase for reliable Tier 1 test selectors.
3
+ </purpose>
4
+
5
+ <required_reading>
6
+ - `CLAUDE.md` -- data-testid Convention (naming pattern, context derivation, element-type suffix table, third-party handling), Locator Strategy (Tier 1 includes data-testid)
7
+ - `data-testid-SKILL.md` -- Complete naming convention reference, framework-specific injection syntax, edge case handling
8
+ - `agents/qaa-scanner.md` -- Scanner agent definition (detects frontend framework, enumerates component files)
9
+ - `agents/qaa-testid-injector.md` -- TestID injector agent definition (4-phase: SCAN, AUDIT, INJECT, VALIDATE)
10
+ - `templates/scan-manifest.md` -- SCAN_MANIFEST.md format contract
11
+ - `templates/testid-audit-report.md` -- TESTID_AUDIT_REPORT.md format contract
12
+ </required_reading>
13
+
14
+ <process>
15
+
16
+ <step name="parse_arguments">
17
+ ## Step 1: Parse Arguments
18
+
19
+ Parse `$ARGUMENTS` for the source directory path.
20
+
21
+ **Supported arguments:**
22
+ - `<path>` -- Path to the frontend source directory (positional)
23
+ - No arguments -- auto-detect frontend directories
24
+
25
+ **Parsing logic:**
26
+
27
+ ```bash
28
+ SOURCE_DIR=""
29
+
30
+ # Parse positional path argument from $ARGUMENTS
31
+ ```
32
+
33
+ **Validation:**
34
+ - If a path is provided, verify it exists and is a directory. If not, print error: `"Error: Source directory does not exist: {path}"` and STOP.
35
+ - If no path provided, proceed to auto-detection in the next step.
36
+ </step>
37
+
38
+ <step name="detect_frontend">
39
+ ## Step 2: Detect Frontend Directory and Framework
40
+
41
+ If no source directory was specified, auto-detect by searching for common frontend directory patterns.
42
+
43
+ **Directory detection order:**
44
+
45
+ 1. `src/` -- Most common source directory
46
+ 2. `app/` -- Next.js app directory, or generic app directory
47
+ 3. `components/` -- Component-focused projects
48
+ 4. `pages/` -- File-based routing frameworks (Next.js, Nuxt)
49
+ 5. `lib/` -- Library projects
50
+ 6. `client/` -- Monorepo client directory
51
+
52
+ **Detection logic:**
53
+
54
+ ```bash
55
+ if SOURCE_DIR is empty:
56
+ for dir in src app components pages lib client:
57
+ if directory exists at "${dir}":
58
+ SOURCE_DIR="${dir}"
59
+ break
60
+ ```
61
+
62
+ **If no frontend directory found:**
63
+
64
+ Print error and STOP:
65
+ ```
66
+ Error: No frontend source directory found.
67
+ Searched for: src/, app/, components/, pages/, lib/, client/
68
+ Provide the source directory path as an argument: /qa-testid <path>
69
+ ```
70
+
71
+ **Detect frontend framework:**
72
+
73
+ Check for framework indicators in the project root:
74
+
75
+ | Framework | Detection Method |
76
+ |-----------|-----------------|
77
+ | React | `react` or `react-dom` in package.json dependencies; `*.jsx` or `*.tsx` files present |
78
+ | Vue | `vue` in package.json dependencies; `*.vue` files present |
79
+ | Angular | `@angular/core` in package.json dependencies; `*.component.ts` and `*.component.html` files present |
80
+ | Svelte | `svelte` in package.json dependencies; `*.svelte` files present |
81
+ | Plain HTML | None of the above; `*.html` files present (excluding build output) |
82
+
83
+ ```bash
84
+ FRONTEND_FRAMEWORK=""
85
+
86
+ # Check package.json for framework dependencies
87
+ # Check for framework-specific file extensions in SOURCE_DIR
88
+ ```
89
+
90
+ **If no frontend framework detected:**
91
+
92
+ Print error and STOP:
93
+ ```
94
+ Error: No frontend framework detected.
95
+ Checked package.json dependencies and file extensions in {SOURCE_DIR}.
96
+ No React (.jsx/.tsx), Vue (.vue), Angular (.component.ts), Svelte (.svelte), or HTML files found.
97
+
98
+ This workflow requires a frontend codebase with UI components to inject data-testid attributes.
99
+ ```
100
+
101
+ **Count component files:**
102
+
103
+ ```bash
104
+ # Count files matching the detected framework's extensions
105
+ COMPONENT_COUNT=$(find "${SOURCE_DIR}" -type f \( -name "*.tsx" -o -name "*.jsx" -o -name "*.vue" -o -name "*.svelte" -o -name "*.component.html" \) \
106
+ ! -path "*/node_modules/*" ! -path "*/dist/*" ! -path "*/build/*" \
107
+ ! -name "*.test.*" ! -name "*.spec.*" ! -name "*.stories.*" | wc -l)
108
+ ```
109
+
110
+ If `COMPONENT_COUNT` is 0, print error and STOP:
111
+ ```
112
+ Error: No component files found in {SOURCE_DIR}.
113
+ Framework detected: {FRONTEND_FRAMEWORK}
114
+ Expected file patterns: {patterns for that framework}
115
+ ```
116
+
117
+ **Print detection results:**
118
+
119
+ ```
120
+ Frontend Detection:
121
+ Source Directory: {SOURCE_DIR}
122
+ Framework: {FRONTEND_FRAMEWORK}
123
+ Component Files: {COMPONENT_COUNT}
124
+ ```
125
+ </step>
126
+
127
+ <step name="run_scanner">
128
+ ## Step 3: Spawn Scanner Agent
129
+
130
+ Spawn the scanner agent to produce SCAN_MANIFEST.md with the frontend component file list.
131
+
132
+ ```
133
+ Task(
134
+ prompt="
135
+ <objective>Scan frontend repository and produce SCAN_MANIFEST.md with component file enumeration</objective>
136
+ <execution_context>@agents/qaa-scanner.md</execution_context>
137
+ <files_to_read>
138
+ - CLAUDE.md
139
+ </files_to_read>
140
+ <parameters>
141
+ dev_repo_path: {project root}
142
+ qa_repo_path: null
143
+ output_path: {OUTPUT_DIR}/SCAN_MANIFEST.md
144
+ </parameters>
145
+ "
146
+ )
147
+ ```
148
+
149
+ **Set output directory:**
150
+
151
+ ```bash
152
+ OUTPUT_DIR=".qa-output"
153
+ mkdir -p "${OUTPUT_DIR}"
154
+ ```
155
+
156
+ **Handle scanner return:**
157
+
158
+ - Extract `has_frontend` -- MUST be `true`. If `false`, print error and STOP:
159
+ ```
160
+ Error: Scanner reports has_frontend: false.
161
+ The detected framework ({FRONTEND_FRAMEWORK}) and component files ({COMPONENT_COUNT}) suggest frontend is present,
162
+ but the scanner could not classify them as frontend components.
163
+ Check SCAN_MANIFEST.md for details: {OUTPUT_DIR}/SCAN_MANIFEST.md
164
+ ```
165
+
166
+ **Verify SCAN_MANIFEST.md exists:**
167
+
168
+ ```bash
169
+ [ -f "${OUTPUT_DIR}/SCAN_MANIFEST.md" ] && echo "FOUND" || echo "MISSING"
170
+ ```
171
+
172
+ If missing, print error and STOP.
173
+ </step>
174
+
175
+ <step name="run_testid_injector">
176
+ ## Step 4: Spawn TestID Injector Agent
177
+
178
+ Spawn the testid-injector agent which operates in 4 phases: SCAN, AUDIT, INJECT, VALIDATE.
179
+
180
+ ```
181
+ Task(
182
+ prompt="
183
+ <objective>Audit frontend components for data-testid coverage and inject missing attributes. Use Playwright MCP to verify against live DOM. Use codebase map for component structure context. Update locator registry with discovered and injected locators.</objective>
184
+ <execution_context>@agents/qaa-testid-injector.md</execution_context>
185
+ <files_to_read>
186
+ - {OUTPUT_DIR}/SCAN_MANIFEST.md
187
+ - CLAUDE.md
188
+ - data-testid-SKILL.md
189
+ - .qa-output/locators/LOCATOR_REGISTRY.md (if exists -- existing locators to cross-reference)
190
+ - .qa-output/codebase/CODE_PATTERNS.md (if exists -- component naming conventions for context derivation)
191
+ - .qa-output/codebase/TEST_SURFACE.md (if exists -- UI component list with props/events)
192
+ - .qa-output/codebase/TESTABILITY.md (if exists -- component testability for injection priority)
193
+ </files_to_read>
194
+ <parameters>
195
+ source_dir: {SOURCE_DIR}
196
+ frontend_framework: {FRONTEND_FRAMEWORK}
197
+ output_path: {OUTPUT_DIR}/TESTID_AUDIT_REPORT.md
198
+ app_url: {auto-detect from dev server or ask user}
199
+ </parameters>
200
+ "
201
+ )
202
+ ```
203
+
204
+ **Injector agent phases:**
205
+
206
+ 1. **SCAN phase:** The injector detects the framework, lists component files, classifies them by interaction density (HIGH/MEDIUM/LOW), and sorts by priority.
207
+
208
+ 2. **AUDIT phase:** For each component file, the injector identifies every interactive element (buttons, inputs, selects, forms, links, modals, etc.), checks for existing data-testid attributes, proposes values for missing attributes following `{context}-{description}-{element-type}` convention, classifies elements by priority (P0/P1/P2), and calculates the coverage score.
209
+
210
+ 3. **CHECKPOINT:** The injector presents the TESTID_AUDIT_REPORT.md to the user for review before injecting. The user can:
211
+ - Approve all proposed values
212
+ - Reject specific elements
213
+ - Rename proposed values
214
+ - Approve renaming of non-compliant existing values
215
+ - Change priority classifications
216
+
217
+ 4. **INJECT phase (after approval):** Creates a separate branch `qa/testid-inject-{YYYY-MM-DD}`, injects approved data-testid attributes using framework-specific syntax (JSX attributes for React, HTML attributes for Vue templates, `[attr.data-testid]` binding for Angular), preserves all existing formatting, and preserves existing data-testid values.
218
+
219
+ 5. **VALIDATE phase:** Runs syntax checks on all modified files, verifies uniqueness of data-testid values per page/route scope, checks naming convention compliance, and verifies no unintended source code changes (non-interference check). If syntax fails, reverts the specific file.
220
+
221
+ 6. **BROWSER VERIFY phase (if app URL available and Playwright MCP connected):**
222
+
223
+ After injection and static validation, use Playwright MCP to verify the injected `data-testid` attributes are present in the rendered DOM:
224
+
225
+ 1. Navigate to each page/route that has injected components:
226
+ ```
227
+ mcp__playwright__browser_navigate({ url: "{app_url}/{route}" })
228
+ ```
229
+
230
+ 2. Take an accessibility snapshot to inspect the rendered DOM:
231
+ ```
232
+ mcp__playwright__browser_snapshot()
233
+ ```
234
+
235
+ 3. Cross-reference: for each injected `data-testid`, verify it appears in the snapshot. Report:
236
+ - **CONFIRMED**: `data-testid` found in rendered DOM
237
+ - **NOT RENDERED**: Component exists in source but not rendered on this route (may appear conditionally)
238
+ - **MISSING**: `data-testid` expected but not found in DOM (possible injection error)
239
+
240
+ 4. Add browser verification results to the TESTID_AUDIT_REPORT.md as a "Browser Verification" section.
241
+
242
+ This step is **optional** -- if no app URL is available or the app is not running, skip and rely on static validation only.
243
+
244
+ **Handle injector return:**
245
+
246
+ Extract:
247
+ - `report_path` -- Path to TESTID_AUDIT_REPORT.md
248
+ - `changelog_path` -- Path to INJECTION_CHANGELOG.md
249
+ - `branch` -- Name of the injection branch
250
+ - `coverage_before` -- Coverage before injection
251
+ - `coverage_after` -- Coverage after injection
252
+ - `elements_injected` -- Count of injected attributes
253
+ - `elements_deferred` -- Count of deferred elements
254
+ - `files_modified` -- Count of modified files
255
+ - `validation_passed` -- Whether all validation checks passed
256
+ </step>
257
+
258
+ <step name="create_branch_and_commit">
259
+ ## Step 5: Create Branch and Commit
260
+
261
+ The testid-injector agent handles branch creation and commits internally on the `qa/testid-inject-{YYYY-MM-DD}` branch. Verify the branch was created and commits exist.
262
+
263
+ **Verify branch:**
264
+
265
+ ```bash
266
+ git branch --list "qa/testid-inject-*"
267
+ ```
268
+
269
+ If the branch does not exist, the injector may not have reached the injection phase (stopped at audit checkpoint). This is expected behavior -- the audit report is still produced.
270
+
271
+ **Verify commit (if injection was performed):**
272
+
273
+ ```bash
274
+ git log --oneline -3 "qa/testid-inject-*" 2>/dev/null
275
+ ```
276
+ </step>
277
+
278
+ <step name="print_summary">
279
+ ## Step 6: Print Summary
280
+
281
+ Print a comprehensive summary of the testid injection results.
282
+
283
+ ```
284
+ === TestID Injection Complete ===
285
+
286
+ Frontend:
287
+ Framework: {FRONTEND_FRAMEWORK}
288
+ Source Directory: {SOURCE_DIR}
289
+ Component Files: {COMPONENT_COUNT}
290
+
291
+ Coverage:
292
+ Before: {coverage_before}%
293
+ After: {coverage_after}%
294
+ Change: +{coverage_after - coverage_before}%
295
+
296
+ Elements:
297
+ Total Interactive: {total_elements}
298
+ Already Had TestID: {existing_count}
299
+ Injected: {elements_injected}
300
+ Deferred (P1/P2): {elements_deferred}
301
+
302
+ By Priority:
303
+ P0 (inputs, buttons, forms): {p0_count} ({p0_injected} injected)
304
+ P1 (links, alerts, toggles): {p1_count} ({p1_injected} injected)
305
+ P2 (images, badges, tables): {p2_count} ({p2_injected} injected)
306
+
307
+ Validation:
308
+ Syntax Check: {PASS|FAIL}
309
+ Uniqueness Check: {PASS|FAIL}
310
+ Convention Check: {PASS|FAIL}
311
+ Non-Interference: {PASS|FAIL}
312
+
313
+ Branch: {branch_name}
314
+ Files Modified: {files_modified}
315
+
316
+ Artifacts:
317
+ - {OUTPUT_DIR}/SCAN_MANIFEST.md
318
+ - {OUTPUT_DIR}/TESTID_AUDIT_REPORT.md
319
+ - {OUTPUT_DIR}/INJECTION_CHANGELOG.md (after injection)
320
+
321
+ Next Steps:
322
+ 1. Review changes on branch: git diff main..{branch_name}
323
+ 2. If approved, merge: git merge {branch_name}
324
+ 3. Run tests to verify no regressions
325
+ =================================
326
+ ```
327
+
328
+ **If injection was not performed (stopped at audit checkpoint):**
329
+
330
+ ```
331
+ === TestID Audit Complete (Injection Pending) ===
332
+
333
+ The audit report has been produced. Review the proposed data-testid values
334
+ in {OUTPUT_DIR}/TESTID_AUDIT_REPORT.md and re-run with approvals to inject.
335
+
336
+ Coverage Score: {coverage_before}%
337
+ Decision: {SELECTIVE|TARGETED|FULL PASS|P0 FIRST}
338
+ Missing TestIDs: {missing_count} ({p0_missing} P0, {p1_missing} P1, {p2_missing} P2)
339
+ =============================================
340
+ ```
341
+ </step>
342
+
343
+ </process>
344
+
345
+ <output>
346
+ This workflow audits and injects data-testid attributes into frontend components.
347
+
348
+ **Artifacts produced:**
349
+
350
+ | Artifact | When Produced | Description |
351
+ |----------|---------------|-------------|
352
+ | SCAN_MANIFEST.md | Always | Repository scan with component file list and framework detection |
353
+ | TESTID_AUDIT_REPORT.md | Always | Comprehensive audit: coverage score, per-element tables, naming compliance, decision gate |
354
+ | INJECTION_CHANGELOG.md | After injection approval | Per-file log of every injection action with validation results |
355
+ | Modified source files | After injection approval | Component files with data-testid attributes added, on separate branch |
356
+
357
+ **Branch management:**
358
+ - Injection branch: `qa/testid-inject-{YYYY-MM-DD}`
359
+ - Working copy on the original branch is NOT modified
360
+ - User merges the injection branch if approved
361
+
362
+ **Decision gate thresholds (from CLAUDE.md):**
363
+
364
+ | Current Coverage | Decision | Strategy |
365
+ |-----------------|----------|----------|
366
+ | > 90% | SELECTIVE | Inject only P0 missing elements |
367
+ | 50% - 90% | TARGETED | Inject P0 and P1 missing elements |
368
+ | 1% - 49% | FULL PASS | Inject all P0, P1, P2 elements |
369
+ | 0% | P0 FIRST | Inject P0 elements only, then re-audit |
370
+ </output>
371
+
372
+ <error_handling>
373
+ | Error | Cause | Action |
374
+ |-------|-------|--------|
375
+ | Source directory does not exist | Invalid path argument | Print error with path, STOP |
376
+ | No frontend directory found | No common frontend dirs in project | Print error listing searched dirs, suggest providing path, STOP |
377
+ | No frontend framework detected | Missing framework deps and file extensions | Print error with detection details, STOP |
378
+ | No component files found | Directory exists but no components | Print error with expected patterns for the detected framework, STOP |
379
+ | Scanner reports has_frontend: false | Scanner classification issue | Print error with suggestion to check SCAN_MANIFEST.md, STOP |
380
+ | SCAN_MANIFEST.md missing | Scanner failed | Print error, STOP |
381
+ | Syntax check fails after injection | Injection broke file syntax | Injector reverts the specific file automatically, reports in changelog |
382
+ | Duplicate data-testid detected | Same value on same rendered page | Injector renames the newer injection to disambiguate |
383
+ | Non-compliant existing values | Existing data-testid does not follow convention | Reported in audit but NOT auto-renamed (user decides) |
384
+ </error_handling>