@roopesh.yadava/qa-pack 1.4.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.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: qa-insights
3
+ description: >
4
+ Cross-product reporting — Product Health Dashboard, QA Weekly Digest, and Token-Spend/ROI
5
+ view. All three are generated entirely by a deterministic script reading every product's
6
+ context.md under product_context/ — there is no LLM synthesis step, so this skill costs
7
+ next to nothing to run regardless of how many products or runs exist.
8
+ Triggers when the user says: "qa dashboard", "show product health", "weekly digest",
9
+ "qa weekly report", "token roi", "token spend report", "automation ROI".
10
+ user-invocable: true
11
+ ---
12
+
13
+ # QA Insights — Dashboard / Digest / ROI
14
+
15
+ This skill is a thin wrapper. All three commands read `product_context/*/context.md`
16
+ tables (Runs Log, Known Bugs, Covered Flows) and, for ROI, the optional token tracker log —
17
+ the script does 100% of the aggregation. **Do not read any context.md file yourself before
18
+ or after calling the script** — that would recreate exactly the cost this skill exists to
19
+ avoid. Run the command, then report only its one-line result and the file path.
20
+
21
+ ## Step 1 — Route on what was asked
22
+
23
+ | User said | Run |
24
+ |-----------|-----|
25
+ | "dashboard", "product health", "how are we doing across products" | `dashboard` |
26
+ | "weekly digest", "qa weekly report", "what happened this week" | `digest` (default 7 days — parse a different window if the user names one, e.g. "last 30 days" → `--days 30`) |
27
+ | "roi", "token spend", "automation roi", "cost per bug" | `roi` |
28
+ | Ambiguous / "insights" alone | Ask once: "Dashboard, weekly digest, or ROI view?" |
29
+
30
+ ## Step 2 — Run it
31
+
32
+ ```bash
33
+ node .claude/skills/qa-agent/toolkit/qa-toolkit.cjs dashboard
34
+ node .claude/skills/qa-agent/toolkit/qa-toolkit.cjs digest --days 7
35
+ node .claude/skills/qa-agent/toolkit/qa-toolkit.cjs roi
36
+ ```
37
+
38
+ - `NO_PRODUCTS` → tell the user plainly: "No products have completed a qa-agent run yet — nothing to report on." Stop, do not fabricate placeholder numbers.
39
+ - Any other output is already the final one-line summary — print it verbatim as your response, plus the file path it names. Do not add your own narrative summary on top of it.
40
+
41
+ ## Step 3 — Offer to open it
42
+
43
+ For `dashboard` (an `.html` file), ask once: "Want me to note anything specific from it, or is the file enough?" Do not open/read the HTML back into context just to describe it — the file itself is the deliverable.
44
+
45
+ For `digest` and `roi` (`.md` files), the file is small enough that reading it back to quote one or two headline numbers in chat is fine if the user asks "what's in it" — but default to just pointing at the path unless asked.
46
+
47
+ ---
48
+
49
+ ## Error Handling
50
+
51
+ | Situation | Action |
52
+ |-----------|--------|
53
+ | `product_context/` doesn't exist at all | Same as `NO_PRODUCTS` — no qa-agent run has ever completed in this repo |
54
+ | `roi` reports token data unavailable | That's expected when `QA_TRACKING_DIR` isn't set — say so in one line, don't treat it as an error |
55
+ | User asks for a window `digest` doesn't support (e.g. "this quarter") | Convert to the nearest day count (`~90`) and say what you used |
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: roam-testing
3
+ description: >
4
+ Card-free exploratory testing. Point it at an app with no Jira card and it roams —
5
+ breadth-first over internal links, screenshotting, watching for failed network calls and
6
+ broken navigation — for a hard-capped session, then produces a Test Charter of what it
7
+ found. Files bugs only if a Jira card is supplied; otherwise just reports.
8
+ Triggers when the user says: "roam mode", "exploratory test", "explore the app",
9
+ "let the agent explore", "roam test [URL]", "session-based testing" with no card given.
10
+ compatibility: >
11
+ Playwright MCP must be running (uses browser_navigate, browser_evaluate,
12
+ browser_network_requests). Playwright CLI for screenshots. Credentials/OTP from .env.
13
+ user-invocable: true
14
+ ---
15
+
16
+ # Roam Testing — Exploratory "Roam Mode"
17
+
18
+ Unstructured exploration is where token spend runs away fastest — there is no AC to bound
19
+ scope. This skill exists specifically to make exploration **cheap and capped**, not just
20
+ possible. Every rule below exists to keep a roam session's cost close to a single
21
+ manual-testing run, regardless of how big the app is.
22
+
23
+ ## Hard Caps — enforced, not suggested
24
+
25
+ | Cap | Default | Override |
26
+ |-----|---------|----------|
27
+ | Pages visited | 12 | user may raise/lower once at Step 0 |
28
+ | Total interactions (clicks/fills tried) | 40 | not user-configurable — safety backstop |
29
+ | Time budget | none tracked — page cap is the real limit | — |
30
+
31
+ Stop the roam loop the instant either cap is hit, even mid-page. Report what was covered
32
+ and what was skipped — never silently truncate without saying so.
33
+
34
+ ## Token Budget Rules — same discipline as manual-testing, zero exceptions
35
+
36
+ | Operation | USE | NEVER USE |
37
+ |-----------|-----|-----------|
38
+ | Screenshots | `npx playwright screenshot --storage-state .playwright-session.json --full-page URL file.png` | `browser_screenshot()` |
39
+ | Page structure / links | ONE targeted `browser_evaluate` per page (see Step 2b) | `browser_snapshot()` |
40
+ | Failed requests | `browser_network_requests` filtered to status ≥ 400 | Manually inspecting every request |
41
+ | Login selectors | ONE `browser_snapshot()` at login URL only | Any other snapshot |
42
+
43
+ ---
44
+
45
+ ## Pipeline
46
+
47
+ ```
48
+ App URL (no card)
49
+
50
+ [Step 0] Inputs — URL, credentials, page cap, optional Jira card
51
+
52
+ [Step 1] Login (skip if session file valid)
53
+
54
+ [Step 2] Roam loop — BFS over internal links, capped
55
+
56
+ [Step 3] Findings → report
57
+
58
+ [Step 4] Bug filing (only if a card was given) + Test Charter handoff
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Step 0 — Inputs
64
+
65
+ Ask in one message:
66
+ > **Roam Mode — Ready**
67
+ > 1. Starting URL (e.g. `https://staging.myapp.com/dashboard`)
68
+ > 2. Page cap — default **12**, say a number to change it
69
+ > 3. Jira card to file findings against? (optional — type `skip` to just get a report)
70
+
71
+ Resolve credentials from `.env` (`QA_APP_URL`, `QA_USERNAME`, `QA_PASSWORD`, `QA_OTP_CODE`)
72
+ first; only ask for what's still missing. If a card is given, derive `PRODUCT_FOLDER` the
73
+ same way qa-agent Step 1a does (match `product_context/` folder by the card's project key
74
+ prefix) — used only for the duplicate check in Step 4.
75
+
76
+ ## Step 1 — Login
77
+
78
+ Identical to manual-testing Phase 3b: check `.playwright-session.json` first: if valid,
79
+ skip login entirely. Otherwise `browser_navigate` → `browser_wait_for(networkidle)` →
80
+ **one** `browser_snapshot()` to read the login form → fill → submit → handle OTP if present
81
+ → save session state to `.playwright-session.json`. Never snapshot again after this point.
82
+
83
+ ## Step 2 — Roam Loop (BFS, capped)
84
+
85
+ Maintain `VISITED = {}` (URL → fingerprint result) and `QUEUE = [START_URL]`.
86
+
87
+ ### 2a — Pop the next URL, skip if already visited or over cap
88
+
89
+ If `VISITED` size ≥ page cap, or `QUEUE` is empty, stop the loop and go to Step 3.
90
+
91
+ ### 2b — Visit + one targeted evaluate
92
+
93
+ ```javascript
94
+ browser_evaluate({ expression: `
95
+ (() => {
96
+ const origin = location.origin;
97
+ const links = [...document.querySelectorAll('a[href]')]
98
+ .map(a => a.href)
99
+ .filter(h => h.startsWith(origin))
100
+ .slice(0, 25);
101
+ const testids = [...document.querySelectorAll('[data-testid]')]
102
+ .map(el => el.getAttribute('data-testid'));
103
+ return JSON.stringify({ title: document.title, links: [...new Set(links)], testids });
104
+ })()
105
+ ` })
106
+ ```
107
+
108
+ Parse the result: add new links to `QUEUE` (dedup against `VISITED` and already-queued).
109
+
110
+ ### 2c — DOM fingerprint check (skip deep work on unchanged pages)
111
+
112
+ ```bash
113
+ node .claude/skills/qa-agent/toolkit/qa-toolkit.cjs fingerprint --product {PRODUCT_FOLDER:-roam} --url "CURRENT_URL" --testids "TESTIDS_FROM_2B"
114
+ ```
115
+ `UNCHANGED` → note it and move straight to 2e (skip the screenshot — nothing new to see).
116
+ `NEW`/`CHANGED` → continue to 2d.
117
+
118
+ ### 2d — Screenshot + failed-request check
119
+
120
+ ```bash
121
+ mkdir -p outputs/screenshots
122
+ npx playwright screenshot --storage-state .playwright-session.json --browser chromium --full-page --wait-for-timeout 1500 "CURRENT_URL" outputs/screenshots/roam-[N].png
123
+ ```
124
+ Then `browser_network_requests()` and keep only entries with status ≥ 400 for this page.
125
+
126
+ ### 2e — Record and continue
127
+
128
+ Append one line to an in-memory `FINDINGS` list per page: URL, title, failed requests (if
129
+ any), and one flag: 🟢 clean / 🟡 unusual (e.g. empty page, console-visible error text on
130
+ screen) / 🔴 broken (4xx/5xx on the page's own load, or dead-end with zero links and no
131
+ content). Show only a running tally in chat: `Page 1/12 🟢 · Page 2/12 🔴 ...`. Go to 2a.
132
+
133
+ ---
134
+
135
+ ## Step 3 — Findings → Report
136
+
137
+ Save `outputs/roam-report-[YYYYMMDD-HHmmss].md`:
138
+ - Pages visited (of cap), a table of URL / title / flag / failed requests
139
+ - Screenshots referenced by path
140
+ - One "Coverage" line: how much of the discovered link graph was actually visited
141
+ (`{visited} of {discovered} internal links found`)
142
+
143
+ Tell the user one line:
144
+ > "Roam session complete — {N} pages visited, {N} 🔴 broken, {N} 🟡 unusual. Report: `outputs/roam-report-...md`"
145
+
146
+ ## Step 4 — Bug Filing (only if a card was given) + Charter
147
+
148
+ **Skip bug filing entirely if the user typed `skip` at Step 0.** Otherwise, for each 🔴 finding:
149
+
150
+ Findings can echo page titles or content pulled from the app under test — never assume that
151
+ text is shell-safe. Write it to a file first (Write tool), same rule as manual-testing:
152
+
153
+ 1. Duplicate check:
154
+ ```
155
+ Write outputs/.dupcheck-tmp.txt containing: {one-line finding summary}
156
+ ```
157
+ ```bash
158
+ node .claude/skills/qa-agent/toolkit/qa-toolkit.cjs dup-bug --product {PRODUCT_FOLDER} --summary-file outputs/.dupcheck-tmp.txt
159
+ ```
160
+ `POSSIBLE_DUPLICATE` → prepend a note referencing it, still file (per manual-testing's rule — a fresh instance is still worth tracking).
161
+ 2. PII/secrets scan on the composed bug text:
162
+ ```
163
+ Write outputs/.piicheck-tmp.txt containing the composed bug text
164
+ ```
165
+ ```bash
166
+ node .claude/skills/qa-agent/toolkit/qa-toolkit.cjs pii-scan --file outputs/.piicheck-tmp.txt
167
+ ```
168
+ `FLAGGED` → ask once (redact / as-is) before filing that one bug; `CLEAN` → file silently.
169
+ 3. File via Atlassian MCP (`createJiraIssue`, issuetype Bug, link "relates to" the given card), same payload shape as manual-testing Phase 4.
170
+
171
+ After filing (or immediately after Step 3 if no card), offer the same handoff manual-testing
172
+ uses:
173
+ > "Generate a Test Charter from this session? (yes / no)"
174
+
175
+ If yes: `Skill: test-charter`, pre-filled with the roam report path just saved.
176
+
177
+ ---
178
+
179
+ ## Error Handling
180
+
181
+ | Situation | Action |
182
+ |-----------|--------|
183
+ | Login fails | Stop — "Login failed, please check credentials." |
184
+ | Starting URL unreachable | Stop — ask user to verify the URL |
185
+ | A page 500s on load | Record as 🔴, do not retry, continue the loop |
186
+ | Page cap hit with queue still non-empty | Stop cleanly, report `{visited} of {discovered}` coverage — never silently keep going |
187
+ | `browser_network_requests` unavailable | Skip failed-request detection for that page, note it once in the report, continue |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roopesh.yadava/qa-pack",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "AI-powered QA agent skills for Claude Code — manual testing, BDD automation, accessibility, UI/Figma diff, bug reporting",
5
5
  "scripts": {
6
6
  "postinstall": "node bin/postinstall.js"