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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qaa-agent",
3
- "version": "1.3.0",
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>