@roopesh.yadava/qa-pack 1.0.3

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,194 @@
1
+ # QA Skills — Context Map
2
+ <!-- Generated by graphify from .claude/skills. Load this instead of individual SKILL.md files
3
+ when you only need pipeline structure. Load a specific SKILL.md only when executing that skill. -->
4
+
5
+ ## Global Token Rules — All Skills Must Follow
6
+
7
+ These rules apply to every skill, every run. Violating them is the single biggest source of token waste.
8
+ A 10-test run with `browser_snapshot()` per test = ~100k wasted tokens.
9
+
10
+ ### Browser tool rules
11
+
12
+ | Operation | USE | NEVER USE | Token cost of violation |
13
+ |-----------|-----|-----------|------------------------|
14
+ | Screenshots | `npx playwright screenshot --full-page URL file.png` | `browser_screenshot()` | ~3k per image |
15
+ | DOM reading | `browser_evaluate` with targeted CSS/JS | `browser_snapshot()` | ~10k per call |
16
+ | Login selectors | ONE `browser_snapshot()` at login URL only | `browser_snapshot()` on any other page | one-time cost justified |
17
+ | Session reuse | `--storage-state .playwright-session.json` for all CLI calls | Re-logging in each run | login round-trip wasted |
18
+
19
+ ### Context output rules
20
+
21
+ | Content | Output to | Never output to |
22
+ |---------|-----------|-----------------|
23
+ | Full test reports | File (`outputs/`) | Chat |
24
+ | Full bug descriptions | Jira via MCP | Chat |
25
+ | Gherkin feature files | Write tool (disk) | Pasted in full to chat |
26
+ | Step definitions | Write tool (disk) | Pasted in full to chat |
27
+ | POM class | Write tool (disk) | Pasted in full to chat |
28
+ | Token tracking output | Suppressed entirely | Chat |
29
+
30
+ **Chat shows only:** phase announcements (1 line each), running test count, failure IDs, bug keys, final summary table.
31
+
32
+ ### Static file load rules
33
+
34
+ | File | Load | Frequency |
35
+ |------|------|-----------|
36
+ | `BDD_TEMPLATES.md` | Once at Phase 1 start | Never reload in the same run |
37
+ | `LOCATOR_PATTERNS.md` | Once at Phase 1 start | Never reload in Phase 2 or 3 |
38
+ | `WCAG_CHECKS.md` | Once at skill start | Never reload |
39
+ | `test-charter.md` | Once when charter starts | Never reload |
40
+ | `context.md` | Once at qa-agent Step 0 | Never reload |
41
+
42
+ After loading, reference rules by name only (e.g. "per Locator Priority Rule 1").
43
+ **Never re-quote static content** in follow-up messages — it is already in context.
44
+
45
+ ### Prompt structure for cache efficiency
46
+
47
+ Structure every skill invocation in this order so the stable prefix can be cached by Anthropic:
48
+ ```
49
+ [1] STABLE (cache-eligible — never changes between runs on same product)
50
+ Product context (context.md) + skill instructions (SKILL.md) + static templates loaded at start
51
+
52
+ [2] VARIABLE (changes every run — goes last)
53
+ Card ID + fetched card data + test results + current session data
54
+ ```
55
+
56
+ The stable block qualifies for Anthropic prompt caching when it exceeds 1024 tokens.
57
+ Cache TTL is 5 minutes. Keep the stable block identical across runs for the same product.
58
+
59
+ ---
60
+
61
+ ## Pipeline Overview
62
+
63
+ ```
64
+ Jira Card ID (Atlassian MCP)
65
+
66
+
67
+ ┌──────────────┐
68
+ │ qa-agent │ ← entry point for all paths
69
+ └──────┬───────┘
70
+
71
+ ┌────┴────┐
72
+ ▼ ▼
73
+ [AUTO] [MANUAL]
74
+ │ │
75
+ ▼ ▼ ─────────────────────────────┐
76
+ automation ui-test-figma (Figma MCP + Playwright CLI)
77
+ │ │
78
+ │ manual-testing (Playwright MCP)
79
+ │ │
80
+ │ bug-reporting (Atlassian MCP)
81
+ │ │
82
+ │ test-charter (REST API publish)
83
+ │ │
84
+ └────────────┘
85
+
86
+ Save Product Context
87
+ (product_context/{PRODUCT}/context.md)
88
+
89
+ End-to-End Testing complete
90
+ ```
91
+
92
+ ## Skills — One-Line Summary
93
+
94
+ | Skill | Input | Output | MCP Needed |
95
+ |-------|-------|--------|------------|
96
+ | `qa-agent` | Jira card ID or menu choice | Dispatches to correct skill | Atlassian |
97
+ | `automation` | Jira card ID | Gherkin + Step Defs + POM + dry-run | Atlassian, Playwright |
98
+ | `manual-testing` | Jira card ID + app URL | Execution report + bugs + charter | Atlassian, Playwright |
99
+ | `ui-test-figma` | Figma URL + app URL | UI mismatch report, Jira comment | Playwright (CLI+MCP), Figma (optional) |
100
+ | `accessibility-testing` | Full page URL + Jira card (optional) | WCAG 2.1 A/AA report + Jira bugs | Playwright (CLI+MCP), Atlassian |
101
+ | `bug-reporting` | Bug description | Bug filed on Jira card | Atlassian |
102
+ | `test-charter` | Execution report MD file | Charter MD + published to API | Playwright (login) |
103
+
104
+ ## God Nodes (highest connectivity — touch these carefully)
105
+
106
+ 1. `automation` — 13 edges (Gherkin→StepDefs→POM chain, token tracking, Playwright MCP)
107
+ 2. `manual-testing` — 12 edges (orchestrates ui-test-figma, bug-reporting, test-charter)
108
+ 3. `qa-agent` — 7 edges (dispatches all paths, owns Full E2E Pipeline)
109
+ 4. `test-charter` — 6 edges (reads execution report, publishes to Decision Record API)
110
+ 5. `ui-test-figma` — 6 edges (Figma MCP preferred, Playwright CLI fallback)
111
+
112
+ ## Dispatch Map (qa-agent routes)
113
+
114
+ ```
115
+ "automate CARD" → automation
116
+ "manual test" → manual-testing (calls ui-test-figma → bug-reporting → test-charter internally)
117
+ "ui test" → ui-test-figma (standalone)
118
+ "accessibility test" → accessibility-testing (standalone, URL + optional Jira card)
119
+ "file bug" → bug-reporting (standalone)
120
+ "charter" → test-charter (standalone)
121
+ "full QA" → automation THEN manual-testing → End-to-End complete
122
+ ```
123
+
124
+ ## Playwright Usage Guide (token budget)
125
+
126
+ ### Expensive (avoid unless needed)
127
+ - `browser_snapshot()` — returns full DOM tree (10k+ tokens). Use only to read login form selectors.
128
+ - `browser_screenshot()` without saving — returns base64 (3k+ tokens). Always save to file.
129
+
130
+ ### Cheap — prefer these
131
+ - `npx playwright screenshot --browser chromium --full-page <url> <file.png>` — 0 response tokens, saves to disk
132
+ - `browser_evaluate(targeted JS)` — targeted selector query, small response
133
+ - `npx playwright screenshot --storage-state <auth.json> --full-page <url> <file.png>` — with session
134
+
135
+ ### Session save pattern (save once, reuse)
136
+ ```bash
137
+ # After MCP login, save session to disk:
138
+ browser_evaluate("() => JSON.stringify({ls: {...localStorage}, ss: {...sessionStorage}})")
139
+ # Write result to .playwright-session.json
140
+ # Later CLI screenshots use: --storage-state .playwright-session.json
141
+ ```
142
+
143
+ ## Token Tracking — canonical pattern (all skills follow this)
144
+
145
+ **Rules:** Silent background task. Never mention in conversation. Replace `CARD_ID` with the actual card ID.
146
+ Scripts live at `/home/user/projects/Smart-testing-with-AI-Agents/`.
147
+
148
+ ```bash
149
+ PROJECT=/home/user/projects/Smart-testing-with-AI-Agents
150
+
151
+ # Entry (before any work)
152
+ SNAP=$(python3 $PROJECT/context_snapshot.py --phase start) && \
153
+ python3 $PROJECT/track_tokens.py start --card CARD_ID $SNAP --model claude-sonnet-4-6
154
+
155
+ # After each phase (repeat per checkpoint, replacing PHASE_NAME)
156
+ SNAP=$(python3 $PROJECT/context_snapshot.py --phase PHASE_NAME) && \
157
+ python3 $PROJECT/track_tokens.py phase --card CARD_ID --name PHASE_NAME $SNAP
158
+
159
+ # Exit (after skill completes)
160
+ SNAP=$(python3 $PROJECT/context_snapshot.py --phase end) && \
161
+ python3 $PROJECT/track_tokens.py end --card CARD_ID $SNAP --model claude-sonnet-4-6 && \
162
+ python3 $PROJECT/track_tokens.py report && \
163
+ python3 $PROJECT/track_tokens.py session
164
+ ```
165
+
166
+ **Phase names by skill:**
167
+ - automation: `start` → `jira_fetch` → `gherkin_generation` → `step_definitions` → `pom_generation` → `end`
168
+ - manual-testing: `start` → `jira_fetch` → `ui_testing` → `test_execution` → `end`
169
+ - ui-test-figma: `start` → `login` → `comparison` → `end`
170
+ - accessibility-testing: `start` → `login` → `a11y_checks` → `end`
171
+ - test-charter: `start` → `end`
172
+
173
+ **Tracking cache efficiency:**
174
+
175
+ The `track_tokens.py report` output includes `cache_efficiency_pct` — what percentage of input tokens were served from Anthropic's prompt cache rather than re-processed.
176
+
177
+ Also check `token_usage_log.json` for `cache_read_input_tokens` per phase to see exactly where cache hits occur.
178
+
179
+ Target: `cache_efficiency_pct` ≥ 70 after the first run on a given product.
180
+ First run will always be 0% (cold cache). Second and subsequent runs should cache the stable block (product context + skill instructions).
181
+
182
+ ## Artifact Locations
183
+
184
+ | Artifact | Path |
185
+ |----------|------|
186
+ | Test execution report | `outputs/test-execution-[CARD]-[date].md` |
187
+ | Test charter | `outputs/charters/[slug].md` |
188
+ | Bug screenshots | `outputs/screenshots/T-[N]-[status].png` |
189
+ | Accessibility report | `outputs/a11y-report-[slug]-[date].md` |
190
+ | Accessibility baseline screenshot | `outputs/screenshots/a11y-baseline-[slug].png` |
191
+ | Auth session | `.playwright-session.json` (gitignored) |
192
+ | Token analytics | `~/.claude/token_analytics.png` |
193
+ | Knowledge graph | `graphify-out/graph.html` (open in browser) |
194
+ | Product QA context | `.claude/skills/qa-agent/product_context/[PRODUCT]/context.md` |
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: accessibility-testing
3
+ description: >
4
+ Tests a live web page against WCAG 2.1 Level A and AA criteria. Injects axe-core via
5
+ browser_evaluate for automated rule checks, then runs manual keyboard, focus, skip-link,
6
+ heading, and alt-text checks via Playwright MCP. Accepts a full page URL, logs in with
7
+ Playwright MCP (OTP always 999999), navigates to the target page, runs all checks, saves
8
+ a structured report to outputs/, and files violations as Jira bugs on the provided card.
9
+ Uses Playwright CLI for zero-token screenshots. Token tracking enabled.
10
+ Standalone or callable from qa-agent.
11
+ Trigger: "accessibility test", "a11y test", "run accessibility", "check WCAG",
12
+ "accessibility [URL]", "a11y [JIRA-KEY]", "test accessibility for [page]",
13
+ or "check accessibility".
14
+ compatibility: >
15
+ Playwright MCP must be running. axe-core injected at runtime from CDN — no install needed.
16
+ OTP always 999999. Playwright CLI (npx playwright) must be available.
17
+ user-invocable: true
18
+ ---
19
+
20
+ # Accessibility Testing Skill — WCAG 2.1 Level A/AA
21
+
22
+ ## Token Budget Rules — enforce throughout this skill
23
+
24
+ | Operation | USE | NEVER USE |
25
+ |-----------|-----|-----------|
26
+ | Page screenshots | `npx playwright screenshot --full-page URL file.png` | `browser_screenshot()` |
27
+ | DOM reading | `browser_evaluate` with targeted JS only | `browser_snapshot()` |
28
+ | Login form selectors | `browser_snapshot()` — **one time only** at login screen | Any other snapshot |
29
+ | axe-core checks | `browser_evaluate` injection + run | External a11y CLI tools |
30
+
31
+ ## Token Tracking
32
+
33
+ Silent background task — follow the **Token Tracking** pattern in `SKILLS_CONTEXT.md`.
34
+ Checkpoints: `start` → `login` → `a11y_checks` → `end + report + session`.
35
+ Use `CARD_ID` if Jira card provided, else `"a11y-test"`. Never show tracking output to user.
36
+
37
+ ---
38
+
39
+ ## Pipeline
40
+
41
+ ```
42
+ Full Page URL (input)
43
+
44
+ [Step 0] Collect Inputs — URL, credentials, Jira card
45
+
46
+ [Step 1] Login via Playwright MCP (skip if session active)
47
+
48
+ [Step 2] Navigate to Target Page + Baseline Screenshot
49
+
50
+ [Step 3] axe-Core Automated Checks (WCAG 2.1 A + AA)
51
+
52
+ [Step 4] Manual Checks — keyboard, focus, skip link, headings, alt text
53
+
54
+ [Step 5] Generate + Save Report → outputs/a11y-report-[slug]-[date].html
55
+
56
+ [Step 6] File Jira Bugs (critical/serious → individual bugs; moderate/minor → comment)
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Step 0 — Collect Inputs
62
+
63
+ Run token tracking `start` checkpoint.
64
+
65
+ Ask questions **one at a time**. Wait for each answer before asking the next.
66
+
67
+ **Question 1 — Page URL:**
68
+ > "Please paste the **full URL of the page** you want to accessibility-test.
69
+ > (e.g. `https://app.example.com/dashboard/settings`)"
70
+
71
+ Store as `TARGET_URL`.
72
+ Extract `BASE_URL` = scheme + host (e.g. `https://app.example.com`).
73
+ Extract `URL_SLUG` = last 2 meaningful path segments, lowercase, hyphens, strip UUIDs.
74
+
75
+ **Question 2 — Jira Card:**
76
+ > "Do you have a **Jira card ID** to file bugs against? (e.g. `QA-123`)
77
+ > Type `skip` to only generate the report."
78
+
79
+ - If provided: store `JIRA_CARD_ID`, set `FILE_JIRA = true`
80
+ - If skipped: set `FILE_JIRA = false`
81
+
82
+ **Question 3 — Check if login is needed:**
83
+
84
+ `browser_navigate(url: BASE_URL)` then `browser_wait_for(state: "networkidle")`.
85
+
86
+ Check the current URL:
87
+ - Redirected to `/login`, `/sign-in`, `/auth` → session not active, ask for credentials.
88
+ - Dashboard / main nav visible → session already active, skip to Step 2.
89
+
90
+ If login needed:
91
+ > "What is the **email** for login?"
92
+ > (after answer) "And the **password**?"
93
+
94
+ Store: `EMAIL`, `PASSWORD`.
95
+
96
+ Once all inputs collected:
97
+ > "Got it — logging in and starting the accessibility checks..."
98
+
99
+ ---
100
+
101
+ ## Step 1 — Login to the Application
102
+
103
+ **Skip entirely if Step 0 Q3 confirmed session already active.**
104
+
105
+ 1. `browser_wait_for(state: "networkidle")`
106
+ 2. `browser_snapshot()` — **one allowed snapshot** to read login form selectors
107
+ 3. `browser_fill` email field using selector found
108
+ 4. `browser_fill` password field using selector found
109
+ 5. `browser_click` login / sign-in button
110
+ 6. `browser_wait_for(state: "networkidle")`
111
+
112
+ **If OTP screen appears** (6-digit input / PIN boxes):
113
+ 7. `browser_click` first OTP input box
114
+ 8. `browser_type(text: "999999")` — always this value, auto-advances through boxes
115
+ 9. `browser_click` Verify / Confirm button
116
+ 10. `browser_wait_for(state: "networkidle")`
117
+
118
+ Confirm login success: main nav or dashboard visible → proceed.
119
+ Still on login page → stop and report: `"Login failed — please verify credentials."`
120
+
121
+ **Save authenticated session to disk:**
122
+ ```javascript
123
+ browser_evaluate({
124
+ expression: `JSON.stringify({
125
+ localStorage: Object.fromEntries(Object.entries(localStorage)),
126
+ sessionStorage: Object.fromEntries(Object.entries(sessionStorage)),
127
+ cookies: document.cookie
128
+ })`
129
+ })
130
+ ```
131
+ Write result to `.playwright-session.json`.
132
+
133
+ Run `login` token checkpoint.
134
+
135
+ ---
136
+
137
+ ## Step 2 — Navigate to Target Page + Baseline Screenshot
138
+
139
+ 1. `browser_navigate(url: TARGET_URL)`
140
+ 2. `browser_wait_for(state: "networkidle")`
141
+ 3. Take baseline screenshot via Playwright CLI (zero response tokens):
142
+
143
+ ```bash
144
+ mkdir -p outputs/screenshots
145
+ npx playwright screenshot \
146
+ --browser chromium \
147
+ --full-page \
148
+ --viewport-size "1920,1080" \
149
+ --wait-for-timeout 3000 \
150
+ "TARGET_URL" \
151
+ outputs/screenshots/a11y-baseline-URL_SLUG.png
152
+ ```
153
+
154
+ Store as `BASELINE_SCREENSHOT = outputs/screenshots/a11y-baseline-[URL_SLUG].png`.
155
+
156
+ ---
157
+
158
+ ## Step 3 — axe-Core Automated Checks
159
+
160
+ Load `.claude/skills/accessibility-testing/WCAG_CHECKS.md` now.
161
+
162
+ ### 3a — Inject axe-core
163
+
164
+ Run the **axe-Core Injection Script** from `WCAG_CHECKS.md` via `browser_evaluate`.
165
+
166
+ - Returns `"loaded"` or `"already loaded"` → proceed to 3b.
167
+ - Returns rejection / CDN error → set `AXE_BLOCKED = true`, add note to report:
168
+ `"axe-core CDN blocked by CSP — automated checks skipped, manual checks only."`,
169
+ skip to Step 4.
170
+
171
+ ### 3b — Run axe-core
172
+
173
+ Run the **axe-Core Run Script** from `WCAG_CHECKS.md` via `browser_evaluate`.
174
+ Parse the returned JSON. Store as `AXE_RESULT`.
175
+
176
+ Bucket violations by impact:
177
+ - `CRITICAL_VIOLATIONS` — impact: `"critical"`
178
+ - `SERIOUS_VIOLATIONS` — impact: `"serious"`
179
+ - `MODERATE_VIOLATIONS` — impact: `"moderate"`
180
+ - `MINOR_VIOLATIONS` — impact: `"minor"`
181
+
182
+ Show one-line tally in chat:
183
+ > `"axe-core: [N] critical | [N] serious | [N] moderate | [N] minor violations found."`
184
+
185
+ Run `a11y_checks` token checkpoint.
186
+
187
+ ---
188
+
189
+ ## Step 4 — Manual Checks
190
+
191
+ Load `.claude/skills/accessibility-testing/WCAG_CHECKS.md`.
192
+
193
+ Run each script via `browser_evaluate`. Store results for the report.
194
+
195
+ ### Check A — Keyboard Traversal (WCAG 2.1.1)
196
+ Run **Check A — Keyboard Traversal Script**.
197
+ Record: total focusable count, elements removed from tab order, first 10 elements.
198
+ Flag if: focusableCount = 0, or interactive elements like buttons/inputs appear in `removedFromTab`
199
+ that should be reachable.
200
+
201
+ ### Check B — Focus Visibility (WCAG 2.4.7)
202
+ Run **Check B — Focus Visibility Script**.
203
+ Flag if: `outlineNoneCount > 0` (outline suppressed on focused elements) or `totalFocusRules = 0`.
204
+ Note if `hasFocusVisible = true` (modern `:focus-visible` present — good practice).
205
+
206
+ ### Check C — Skip Navigation Link (WCAG 2.4.1)
207
+ Run **Check C — Skip Navigation Link Script**.
208
+ Flag if: `hasSkipLink = false`.
209
+
210
+ ### Check D — Heading Hierarchy (WCAG 1.3.1)
211
+ Run **Check D — Heading Hierarchy Script**.
212
+ Report all issues from `issues[]` array.
213
+ Flag if: `h1Count ≠ 1` or `levelSkips.length > 0`.
214
+
215
+ ### Check E — Image Alt Text (WCAG 1.1.1) — cross-check against axe
216
+ Run **Check E — Image Alt Text Script**.
217
+ Flag if: `missingAlt > 0`. Note `emptyAlt` (decorative images with empty alt = OK if intentional).
218
+ Flag if: `svgMissingLabel > 0` (inline SVGs without accessible name).
219
+
220
+ ---
221
+
222
+ ## Step 5 — Generate + Save Report
223
+
224
+ Load the **Report Template** from `WCAG_CHECKS.md`.
225
+
226
+ Build the full report using:
227
+ - `AXE_RESULT` — all violation buckets
228
+ - Manual check results from Steps A–E
229
+ - `BASELINE_SCREENSHOT` path
230
+ - `WCAG Criterion Quick Reference` and `Severity Mapping` from `WCAG_CHECKS.md`
231
+
232
+ Derive filename: `outputs/a11y-report-[URL_SLUG]-[YYYYMMDD].html`
233
+
234
+ Save the file. Tell user (one line):
235
+ > `"Report saved: outputs/a11y-report-[URL_SLUG]-[YYYYMMDD].html"`
236
+
237
+ Run `end + report + session` token close-out.
238
+
239
+ ---
240
+
241
+ ## Step 6 — Jira Bug Filing
242
+
243
+ **Skip entirely if `FILE_JIRA = false`.**
244
+
245
+ > `"[Step 6] Filing accessibility bugs on [JIRA_CARD_ID]..."`
246
+
247
+ Use `getJiraIssue` to confirm `JIRA_CARD_ID` exists. Extract `PROJECT_KEY`.
248
+
249
+ ### Critical + Serious → individual Jira Bugs
250
+
251
+ For each violation in `CRITICAL_VIOLATIONS` and `SERIOUS_VIOLATIONS`:
252
+
253
+ Create a Jira Bug using the **Jira Bug Template** from `WCAG_CHECKS.md`:
254
+ - **Issue type:** Bug
255
+ - **Summary:** `[A11Y-{IMPACT}] [WCAG {criterion}] — {rule description} on /{URL_SLUG}`
256
+ - **Priority:** Critical → P1 Blocker | Serious → P2 High
257
+ - **Labels:** `accessibility`, `wcag-2.1`, `a11y-{impact}`
258
+ - **Link to:** `JIRA_CARD_ID` ("relates to")
259
+
260
+ Parallelize bug creation where possible.
261
+
262
+ ### Moderate + Minor → single summary comment
263
+
264
+ Use the **Jira Comment Template** from `WCAG_CHECKS.md`.
265
+ Post via `addCommentToJiraIssue` on `JIRA_CARD_ID`.
266
+
267
+ ### Completion comment on JIRA_CARD_ID
268
+
269
+ ```
270
+ ♿ Accessibility Testing Complete — WCAG 2.1 AA
271
+
272
+ Page: [TARGET_URL]
273
+ Results: [N] critical | [N] serious | [N] moderate | [N] minor
274
+
275
+ Bugs filed: [PROJ-xxx], [PROJ-yyy]
276
+ Report: outputs/a11y-report-[URL_SLUG]-[YYYYMMDD].html
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Final Chat Summary
282
+
283
+ ```
284
+ Accessibility Testing Complete
285
+ Page : [TARGET_URL]
286
+ WCAG Level : 2.1 AA
287
+
288
+ Critical : N violations
289
+ Serious : N violations
290
+ Moderate : N violations
291
+ Minor : N violations
292
+
293
+ Keyboard : OK / N interactive elements unreachable
294
+ Focus styles : OK / outline:none found on N selectors
295
+ Skip link : Present / Missing (WCAG 2.4.1)
296
+ Heading order : OK / [issues]
297
+ Image alt : OK / N missing alt attributes
298
+
299
+ Jira bugs : [keys] / skipped
300
+ Report : outputs/a11y-report-[URL_SLUG]-[YYYYMMDD].html
301
+ ```
302
+
303
+ ---
304
+
305
+ ## Error Handling
306
+
307
+ | Situation | Action |
308
+ |-----------|--------|
309
+ | Login fails | Stop — `"Login failed, please check credentials."` |
310
+ | TARGET_URL not reachable after login | Stop — check URL and auth redirect |
311
+ | axe-core CDN blocked (CSP) | Flag in report, continue with manual checks only |
312
+ | `axe.run()` throws / times out | Retry scoped to `main` or `#content` only, note partial result |
313
+ | `browser_evaluate` returns null | Log "script returned null" for that check, continue |
314
+ | Jira card not found | Ask to verify key; offer to save report only |
315
+ | Jira bug creation fails | Note failure, continue remaining bugs, report failures at end |
316
+ | OTP screen appears unexpectedly | Type `"999999"`, proceed |
317
+ | Page requires further navigation after login | Follow redirect, confirm TARGET_URL loads |