qaa-agent 1.3.0 → 1.5.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/commands/create-test.md +42 -4
- package/.claude/commands/qa-analyze.md +8 -10
- package/.claude/commands/qa-map.md +18 -7
- package/.claude/commands/qa-pr.md +23 -0
- package/.claude/commands/qa-validate.md +25 -3
- package/.claude/skills/qa-learner/SKILL.md +8 -0
- package/CLAUDE.md +23 -13
- package/README.md +20 -7
- package/agents/qa-pipeline-orchestrator.md +171 -10
- package/agents/qaa-analyzer.md +16 -0
- package/agents/qaa-bug-detective.md +2 -0
- package/agents/qaa-e2e-runner.md +415 -0
- package/agents/qaa-executor.md +14 -0
- package/agents/qaa-planner.md +17 -1
- package/agents/qaa-scanner.md +2 -0
- package/agents/qaa-testid-injector.md +2 -0
- package/agents/qaa-validator.md +2 -0
- package/bin/install.cjs +12 -4
- package/docs/COMMANDS.md +341 -0
- package/docs/DEMO.md +182 -0
- package/docs/TESTING.md +156 -0
- package/package.json +2 -1
- package/workflows/qa-pr.md +389 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qaa-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "QA Automation Agent for Claude Code — multi-agent pipeline that analyzes repos, generates tests, validates, and creates PRs",
|
|
5
5
|
"bin": {
|
|
6
6
|
"qaa-agent": "./bin/install.cjs"
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"agents/",
|
|
27
27
|
"workflows/",
|
|
28
28
|
"templates/",
|
|
29
|
+
"docs/",
|
|
29
30
|
".claude/commands/",
|
|
30
31
|
".claude/skills/",
|
|
31
32
|
".claude/settings.json",
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
<purpose>
|
|
2
|
+
Create a draft PR from QA artifacts (test files, POMs, fixtures, reports) already on disk. Detects git platform (GitHub, Azure DevOps, GitLab), applies the team's branch naming convention (saved in preferences), stages only test/QA files, and creates a draft PR with a summary. Standalone command -- does not require the full pipeline to have run.
|
|
3
|
+
</purpose>
|
|
4
|
+
|
|
5
|
+
<required_reading>
|
|
6
|
+
- `CLAUDE.md` -- Git workflow section (branch naming, commit conventions, PR template)
|
|
7
|
+
- `~/.claude/qaa/MY_PREFERENCES.md` -- Branch naming convention (if saved)
|
|
8
|
+
- `templates/pr-template.md` -- PR body template
|
|
9
|
+
</required_reading>
|
|
10
|
+
|
|
11
|
+
<process>
|
|
12
|
+
|
|
13
|
+
<step name="parse_arguments">
|
|
14
|
+
## Step 1: Parse Arguments
|
|
15
|
+
|
|
16
|
+
Parse `$ARGUMENTS` to extract optional flags.
|
|
17
|
+
|
|
18
|
+
**Supported arguments:**
|
|
19
|
+
|
|
20
|
+
| Flag | Example | Description |
|
|
21
|
+
|------|---------|-------------|
|
|
22
|
+
| `--ticket` | `--ticket PROJ-123` | Ticket/issue ID for branch name |
|
|
23
|
+
| `--title` | `--title "login tests"` | Short description for branch and PR title |
|
|
24
|
+
| `--scope` | `--scope unit` | Limit to file type: unit, api, e2e, all (default: all) |
|
|
25
|
+
| `--files` | `--files tests/unit/auth*` | Explicit file glob to include |
|
|
26
|
+
| `--base` | `--base develop` | Target branch for PR (default: auto-detect) |
|
|
27
|
+
|
|
28
|
+
**If no arguments provided:**
|
|
29
|
+
|
|
30
|
+
Scan for QA artifacts to include:
|
|
31
|
+
1. Check `.qa-output/` for generated test files, POMs, fixtures
|
|
32
|
+
2. Check current git status for unstaged/untracked test files
|
|
33
|
+
3. If nothing found, print error and STOP:
|
|
34
|
+
```
|
|
35
|
+
Error: No QA artifacts found to deliver.
|
|
36
|
+
Run /qa-start, /create-test, or /qa-map first to generate artifacts.
|
|
37
|
+
```
|
|
38
|
+
</step>
|
|
39
|
+
|
|
40
|
+
<step name="detect_platform">
|
|
41
|
+
## Step 2: Detect Git Platform
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Platform detection from remote URL:**
|
|
48
|
+
|
|
49
|
+
| Pattern | Platform | CLI Tool | PR Command |
|
|
50
|
+
|---------|----------|----------|------------|
|
|
51
|
+
| `github.com` or `gh:` | GitHub | `gh` | `gh pr create` |
|
|
52
|
+
| `dev.azure.com` or `visualstudio.com` or `azure` | Azure DevOps | `az` | `az repos pr create` |
|
|
53
|
+
| `gitlab.com` or `gitlab` | GitLab | `glab` | `glab mr create` |
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
PLATFORM=""
|
|
57
|
+
PR_CLI=""
|
|
58
|
+
|
|
59
|
+
if echo "$REMOTE_URL" | grep -qi "github"; then
|
|
60
|
+
PLATFORM="github"
|
|
61
|
+
PR_CLI="gh"
|
|
62
|
+
elif echo "$REMOTE_URL" | grep -qi "dev.azure.com\|visualstudio.com\|azure"; then
|
|
63
|
+
PLATFORM="azure"
|
|
64
|
+
PR_CLI="az"
|
|
65
|
+
elif echo "$REMOTE_URL" | grep -qi "gitlab"; then
|
|
66
|
+
PLATFORM="gitlab"
|
|
67
|
+
PR_CLI="glab"
|
|
68
|
+
else
|
|
69
|
+
PLATFORM="unknown"
|
|
70
|
+
fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**If platform is unknown:**
|
|
74
|
+
```
|
|
75
|
+
CHECKPOINT:
|
|
76
|
+
type: human-action
|
|
77
|
+
blocking: "Cannot detect git platform from remote URL"
|
|
78
|
+
details: "Remote URL: ${REMOTE_URL}"
|
|
79
|
+
awaiting: "Which platform? (github / azure / gitlab)"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Verify CLI tool is available and authenticated:**
|
|
83
|
+
|
|
84
|
+
For GitHub:
|
|
85
|
+
```bash
|
|
86
|
+
gh auth status 2>/dev/null
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
For Azure DevOps:
|
|
90
|
+
```bash
|
|
91
|
+
az account show 2>/dev/null
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For GitLab:
|
|
95
|
+
```bash
|
|
96
|
+
glab auth status 2>/dev/null
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If CLI tool is not installed or not authenticated:
|
|
100
|
+
```
|
|
101
|
+
Error: ${PR_CLI} CLI not found or not authenticated.
|
|
102
|
+
|
|
103
|
+
GitHub: Install from https://cli.github.com, then run: gh auth login
|
|
104
|
+
Azure: Install from https://aka.ms/azure-cli, then run: az login
|
|
105
|
+
GitLab: Install from https://gitlab.com/gitlab-org/cli, then run: glab auth login
|
|
106
|
+
```
|
|
107
|
+
</step>
|
|
108
|
+
|
|
109
|
+
<step name="resolve_branch_convention">
|
|
110
|
+
## Step 3: Resolve Branch Naming Convention
|
|
111
|
+
|
|
112
|
+
**Check saved preferences:**
|
|
113
|
+
```bash
|
|
114
|
+
BRANCH_PATTERN=""
|
|
115
|
+
if [ -f ~/.claude/qaa/MY_PREFERENCES.md ]; then
|
|
116
|
+
# Look for branch pattern in Workflow section
|
|
117
|
+
BRANCH_PATTERN=$(grep -A1 "branch.*pattern\|branch.*convention\|branch.*naming" ~/.claude/qaa/MY_PREFERENCES.md | tail -1)
|
|
118
|
+
fi
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**If no saved convention, ask the user:**
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
No branch naming convention configured.
|
|
125
|
+
What pattern does your team use?
|
|
126
|
+
|
|
127
|
+
1) feature/{ticket}-{description}
|
|
128
|
+
2) test/{ticket}-{description}
|
|
129
|
+
3) qa/{ticket}-{description}
|
|
130
|
+
4) {user}/{ticket}-{description}
|
|
131
|
+
5) feature/QAA-{date}-{description}
|
|
132
|
+
6) Custom (write your own with placeholders)
|
|
133
|
+
|
|
134
|
+
Placeholders: {ticket}, {date}, {description}, {user}, {scope}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**On user response:**
|
|
138
|
+
- Save the chosen pattern to `~/.claude/qaa/MY_PREFERENCES.md` under `## Workflow` section
|
|
139
|
+
- Format: `- Branch naming convention: {pattern} — (added {date}, context: "user configured branch pattern via /qa-pr")`
|
|
140
|
+
|
|
141
|
+
**Build actual branch name from pattern:**
|
|
142
|
+
|
|
143
|
+
Replace placeholders with real values:
|
|
144
|
+
- `{ticket}` -- from `--ticket` flag, or prompt user if pattern requires it
|
|
145
|
+
- `{date}` -- today's date YYYY-MM-DD
|
|
146
|
+
- `{description}` -- from `--title` flag, sanitized to kebab-case (lowercase, hyphens, no special chars)
|
|
147
|
+
- `{user}` -- from `git config user.name`, sanitized to kebab-case
|
|
148
|
+
- `{scope}` -- from `--scope` flag or "qa"
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
BRANCH_NAME=$(echo "$BRANCH_PATTERN" | sed \
|
|
152
|
+
-e "s/{ticket}/${TICKET}/g" \
|
|
153
|
+
-e "s/{date}/${DATE}/g" \
|
|
154
|
+
-e "s/{description}/${DESCRIPTION}/g" \
|
|
155
|
+
-e "s/{user}/${USER}/g" \
|
|
156
|
+
-e "s/{scope}/${SCOPE}/g")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**If ticket is required by pattern but not provided:**
|
|
160
|
+
```
|
|
161
|
+
Your branch pattern requires a ticket ID: {pattern}
|
|
162
|
+
Provide ticket ID (e.g., PROJ-123):
|
|
163
|
+
```
|
|
164
|
+
</step>
|
|
165
|
+
|
|
166
|
+
<step name="collect_files">
|
|
167
|
+
## Step 4: Collect Files to Include
|
|
168
|
+
|
|
169
|
+
Gather all QA artifacts that should go into the PR.
|
|
170
|
+
|
|
171
|
+
**If `--files` flag provided:** Use that glob directly.
|
|
172
|
+
|
|
173
|
+
**Otherwise, auto-detect:**
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
QA_FILES=()
|
|
177
|
+
|
|
178
|
+
# 1. Generated test files
|
|
179
|
+
find . -path '*/tests/*' -name '*.spec.*' -o -name '*.test.*' -o -name '*.e2e.*' -o -name '*.cy.*' | while read f; do
|
|
180
|
+
QA_FILES+=("$f")
|
|
181
|
+
done
|
|
182
|
+
|
|
183
|
+
# 2. Page Object Models
|
|
184
|
+
find . -path '*/pages/*' -o -path '*/page-objects/*' | grep -E '\.(ts|js|py)$' | while read f; do
|
|
185
|
+
QA_FILES+=("$f")
|
|
186
|
+
done
|
|
187
|
+
|
|
188
|
+
# 3. Fixtures
|
|
189
|
+
find . -path '*/fixtures/*' -name '*-data.*' | while read f; do
|
|
190
|
+
QA_FILES+=("$f")
|
|
191
|
+
done
|
|
192
|
+
|
|
193
|
+
# 4. Config files (test configs only)
|
|
194
|
+
for cfg in playwright.config.* jest.config.* vitest.config.* cypress.config.* pytest.ini conftest.py; do
|
|
195
|
+
[ -f "$cfg" ] && QA_FILES+=("$cfg")
|
|
196
|
+
done
|
|
197
|
+
|
|
198
|
+
# 5. QA output reports
|
|
199
|
+
find .qa-output -name '*.md' 2>/dev/null | while read f; do
|
|
200
|
+
QA_FILES+=("$f")
|
|
201
|
+
done
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Apply scope filter if `--scope` provided:**
|
|
205
|
+
- `unit` -- only `*.unit.spec.*`, `*.test.*` files
|
|
206
|
+
- `api` -- only `*.api.spec.*` files
|
|
207
|
+
- `e2e` -- only `*.e2e.spec.*`, `*.cy.*` files + POMs
|
|
208
|
+
- `all` -- everything (default)
|
|
209
|
+
|
|
210
|
+
**If no files found:** Print error and STOP.
|
|
211
|
+
|
|
212
|
+
**Security check:**
|
|
213
|
+
- Exclude any `.env`, `credentials.*`, `secrets.*`, `*.key`, `*.pem` files
|
|
214
|
+
- Warn if any file contains hardcoded passwords/tokens (grep for common patterns)
|
|
215
|
+
</step>
|
|
216
|
+
|
|
217
|
+
<step name="confirm_with_user">
|
|
218
|
+
## Step 5: Confirmation Checkpoint
|
|
219
|
+
|
|
220
|
+
Present the plan to the user and wait for confirmation.
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
╔══════════════════════════════════════════╗
|
|
224
|
+
║ /qa-pr — Create QA Pull Request ║
|
|
225
|
+
╠══════════════════════════════════════════╣
|
|
226
|
+
║ ║
|
|
227
|
+
║ Platform: {PLATFORM} ║
|
|
228
|
+
║ Branch: {BRANCH_NAME} ║
|
|
229
|
+
║ Target: {DEFAULT_BRANCH} ║
|
|
230
|
+
║ Type: Draft PR ║
|
|
231
|
+
║ ║
|
|
232
|
+
║ Files ({FILE_COUNT}): ║
|
|
233
|
+
║ {N} test specs ║
|
|
234
|
+
║ {N} page objects ║
|
|
235
|
+
║ {N} fixtures ║
|
|
236
|
+
║ {N} config files ║
|
|
237
|
+
║ {N} QA reports ║
|
|
238
|
+
║ ║
|
|
239
|
+
╚══════════════════════════════════════════╝
|
|
240
|
+
|
|
241
|
+
Proceed? (y/n)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**If user says no:** Print "Cancelled." and STOP.
|
|
245
|
+
</step>
|
|
246
|
+
|
|
247
|
+
<step name="create_branch_and_commit">
|
|
248
|
+
## Step 6: Create Branch and Commit
|
|
249
|
+
|
|
250
|
+
**Detect default branch:**
|
|
251
|
+
```bash
|
|
252
|
+
# GitHub
|
|
253
|
+
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null)
|
|
254
|
+
|
|
255
|
+
# Azure DevOps
|
|
256
|
+
if [ -z "$DEFAULT_BRANCH" ]; then
|
|
257
|
+
DEFAULT_BRANCH=$(az repos show --query 'defaultBranch' -o tsv 2>/dev/null | sed 's|refs/heads/||')
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
# GitLab
|
|
261
|
+
if [ -z "$DEFAULT_BRANCH" ]; then
|
|
262
|
+
DEFAULT_BRANCH=$(glab repo view --json default_branch --jq '.default_branch' 2>/dev/null)
|
|
263
|
+
fi
|
|
264
|
+
|
|
265
|
+
# Fallback
|
|
266
|
+
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Override with `--base` flag if provided.**
|
|
270
|
+
|
|
271
|
+
**Create branch:**
|
|
272
|
+
```bash
|
|
273
|
+
git checkout -b "$BRANCH_NAME" "origin/$DEFAULT_BRANCH"
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Handle collision:**
|
|
277
|
+
```bash
|
|
278
|
+
if git rev-parse --verify "$BRANCH_NAME" 2>/dev/null; then
|
|
279
|
+
SUFFIX=2
|
|
280
|
+
while git rev-parse --verify "${BRANCH_NAME}-${SUFFIX}" 2>/dev/null; do
|
|
281
|
+
SUFFIX=$((SUFFIX + 1))
|
|
282
|
+
done
|
|
283
|
+
BRANCH_NAME="${BRANCH_NAME}-${SUFFIX}"
|
|
284
|
+
git checkout -b "$BRANCH_NAME" "origin/$DEFAULT_BRANCH"
|
|
285
|
+
fi
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Stage and commit:**
|
|
289
|
+
```bash
|
|
290
|
+
git add ${QA_FILES[@]}
|
|
291
|
+
git commit -m "qa(pr): add ${FILE_COUNT} QA artifacts — ${DESCRIPTION}"
|
|
292
|
+
```
|
|
293
|
+
</step>
|
|
294
|
+
|
|
295
|
+
<step name="push_and_create_pr">
|
|
296
|
+
## Step 7: Push and Create PR
|
|
297
|
+
|
|
298
|
+
**Push branch:**
|
|
299
|
+
```bash
|
|
300
|
+
git push -u origin "$BRANCH_NAME"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Build PR body from template (if available) or minimal summary:**
|
|
304
|
+
|
|
305
|
+
If `templates/pr-template.md` exists and QA reports are available, populate it.
|
|
306
|
+
Otherwise use minimal body:
|
|
307
|
+
|
|
308
|
+
```markdown
|
|
309
|
+
## QA Artifacts
|
|
310
|
+
|
|
311
|
+
${FILE_COUNT} files added:
|
|
312
|
+
- ${test_count} test specs
|
|
313
|
+
- ${pom_count} page objects
|
|
314
|
+
- ${fixture_count} fixtures
|
|
315
|
+
|
|
316
|
+
${TICKET_REF}
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
Generated by QAA (QA Automation Agent)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Create PR by platform:**
|
|
323
|
+
|
|
324
|
+
**GitHub:**
|
|
325
|
+
```bash
|
|
326
|
+
PR_URL=$(gh pr create \
|
|
327
|
+
--draft \
|
|
328
|
+
--title "qa: ${DESCRIPTION}" \
|
|
329
|
+
--body "${PR_BODY}")
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Azure DevOps:**
|
|
333
|
+
```bash
|
|
334
|
+
PR_URL=$(az repos pr create \
|
|
335
|
+
--draft \
|
|
336
|
+
--title "qa: ${DESCRIPTION}" \
|
|
337
|
+
--description "${PR_BODY}" \
|
|
338
|
+
--source-branch "$BRANCH_NAME" \
|
|
339
|
+
--target-branch "$DEFAULT_BRANCH" \
|
|
340
|
+
--query 'url' -o tsv)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**GitLab:**
|
|
344
|
+
```bash
|
|
345
|
+
PR_URL=$(glab mr create \
|
|
346
|
+
--draft \
|
|
347
|
+
--title "qa: ${DESCRIPTION}" \
|
|
348
|
+
--description "${PR_BODY}" \
|
|
349
|
+
--source-branch "$BRANCH_NAME" \
|
|
350
|
+
--target-branch "$DEFAULT_BRANCH" \
|
|
351
|
+
--yes)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**On failure:** Print error with branch name so user can create PR manually.
|
|
355
|
+
</step>
|
|
356
|
+
|
|
357
|
+
<step name="print_result">
|
|
358
|
+
## Step 8: Print Result
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
╔══════════════════════════════════════════╗
|
|
362
|
+
║ PR Created ✓ ║
|
|
363
|
+
╠══════════════════════════════════════════╣
|
|
364
|
+
║ ║
|
|
365
|
+
║ ${PR_URL} ║
|
|
366
|
+
║ ║
|
|
367
|
+
║ Branch: ${BRANCH_NAME} ║
|
|
368
|
+
║ Target: ${DEFAULT_BRANCH} ║
|
|
369
|
+
║ Files: ${FILE_COUNT} ║
|
|
370
|
+
║ Status: Draft ║
|
|
371
|
+
║ ║
|
|
372
|
+
╚══════════════════════════════════════════╝
|
|
373
|
+
```
|
|
374
|
+
</step>
|
|
375
|
+
|
|
376
|
+
</process>
|
|
377
|
+
|
|
378
|
+
<error_handling>
|
|
379
|
+
| Error | Cause | Action |
|
|
380
|
+
|-------|-------|--------|
|
|
381
|
+
| No QA artifacts found | Nothing generated yet | Print error, suggest /qa-start or /create-test |
|
|
382
|
+
| Platform not detected | Unusual remote URL | Ask user to specify platform |
|
|
383
|
+
| CLI not installed | gh/az/glab missing | Print install instructions for detected platform |
|
|
384
|
+
| CLI not authenticated | Not logged in | Print auth command for detected platform |
|
|
385
|
+
| Branch already exists | Name collision | Auto-append numeric suffix |
|
|
386
|
+
| Push fails | Permission or network | Print error, keep local commits |
|
|
387
|
+
| PR creation fails | API error | Print error with branch name for manual PR creation |
|
|
388
|
+
| Ticket required but missing | Pattern uses {ticket} | Prompt user for ticket ID |
|
|
389
|
+
</error_handling>
|