docs(plan): A11y rescan — live portal authenticated routes
11-task plan для повторного a11y-аудита: extend Pa11y от 7 guest URLs к 21 URLs (включая 14 authenticated через per-URL actions login flow), + axe-core cross-validation via Playwright MCP, + inline fixes для real prod findings. Closes Audit #3 Phase 7 «authenticated pages out of scope» clause per explicit user request «Pa11y был настроен на старые HTML-эскизы, проведи повторно аудит в этой части, чтобы он проверил реальный портал». Plan: docs/superpowers/plans/2026-05-14-a11y-rescan-live-portal.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,552 @@
|
||||
# A11y Rescan — Live Portal (Authenticated + Guest) Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Provide accurate, current a11y coverage for the entire live Vue portal (guest + authenticated routes), close any real production findings, and document the new baseline. Continuation of Audit #3 Phase 7 + deferred-fixes sprint Task 1 — closes the `out-of-scope` clause for authenticated routes.
|
||||
|
||||
**Architecture:** Three-pillar a11y verification — (1) Pa11y on guest pages (existing baseline, verify holds); (2) Pa11y on authenticated pages via per-URL `actions` login flow (new); (3) axe-core via Playwright MCP sweep on the same authenticated routes (cross-validation against Pa11y). Real findings are fixed inline; known temp (DevIndexBadge) and Vuetify-structural patterns are documented as ignored.
|
||||
|
||||
**Tech Stack:** pa11y-ci 4.1 (chromium + axe rules) + Playwright MCP (browser_navigate + browser_evaluate for axe-core CDN) + Laravel 13 dev-server (`php artisan serve :8000`) + Vue Router (createWebHistory) + Sanctum SPA cookie auth + DemoSeeder credentials `admin@demo.local:password`.
|
||||
|
||||
**Scope:**
|
||||
|
||||
- **In scope:** All 26 SPA routes registered in `app/routes/web.php` (7 guest already in baseline + 14 authenticated + 3 error views + 2 already counted).
|
||||
- **Out of scope:** Static HTML handoff prototypes (already relocated to opt-in `pa11y-handoff.config.json` in deferred-fixes sprint). Mobile viewport (1440×900 desktop baseline is sufficient for first authenticated baseline).
|
||||
- **Branch:** work on `main` (current 🟢 GREEN, HEAD `ae20033`). Atomic commit per logical change.
|
||||
|
||||
**Pre-flight assumptions to verify in Task 1:**
|
||||
|
||||
- Dev-server up on `http://localhost:8000` (status 200 on `/login`).
|
||||
- Demo tenant + `admin@demo.local` user present (DemoSeeder runs auto in local env per commit `e746b3c` Task 2.4).
|
||||
- Vite production build current (Task 1 will rebuild to be safe — quirk #81 from `feedback_environment.md`: `php artisan serve` serves built assets, not Vite HMR).
|
||||
|
||||
---
|
||||
|
||||
## Task 1 — Pre-flight + verify guest baseline holds
|
||||
|
||||
**Files:**
|
||||
|
||||
- No modifications — verification only.
|
||||
|
||||
### Step 1.1 — Verify dev-server up + DemoSeeder applied
|
||||
|
||||
- [ ] Run from `c:/моя/проекты/портал crm/Документация`:
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/login
|
||||
```
|
||||
|
||||
Expected: `200`. If not 200 → start `cd app && php artisan serve --port=8000 &`.
|
||||
|
||||
- [ ] Verify user count:
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация/app" && php artisan tinker --execute='echo \App\Models\User::count();'
|
||||
```
|
||||
|
||||
Expected: `>= 1`. If `0` → `php artisan migrate:fresh --seed`.
|
||||
|
||||
### Step 1.2 — Rebuild Vite (quirk #81)
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация/app" && npx vite build
|
||||
```
|
||||
|
||||
Expected: build OK, ~2s, `app/public/build/assets/*.js` files updated.
|
||||
|
||||
### Step 1.3 — Run Pa11y guest baseline
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && npm run a11y
|
||||
```
|
||||
|
||||
Expected: `✔ 7/7 URLs passed`. If anything fails, treat as regression — investigate before continuing.
|
||||
|
||||
### Step 1.4 — Capture & commit nothing (verification only)
|
||||
|
||||
- [ ] Note timing in scratch — no file changes yet.
|
||||
|
||||
---
|
||||
|
||||
## Task 2 — Discover login form selectors
|
||||
|
||||
**Files:**
|
||||
|
||||
- Read: `app/resources/js/views/auth/LoginView.vue` (selectors for email/password inputs + submit button)
|
||||
- Read: `app/resources/js/views/auth/TwoFactorView.vue` (for 2FA flow if applicable — DemoSeeder user has `totp_enabled: false`, so 2FA can be skipped)
|
||||
|
||||
### Step 2.1 — Read LoginView for `data-testid` / `id` / `name` attributes
|
||||
|
||||
- [ ] Read full file:
|
||||
|
||||
```text
|
||||
app/resources/js/views/auth/LoginView.vue
|
||||
```
|
||||
|
||||
Identify:
|
||||
|
||||
- Email input selector (e.g. `input[type="email"]` or `#email` or `[data-testid="login-email"]`)
|
||||
- Password input selector
|
||||
- Submit button selector
|
||||
- Success-redirect target (likely `/dashboard`)
|
||||
|
||||
### Step 2.2 — Verify DemoSeeder credentials in code
|
||||
|
||||
- [ ] Grep `app/database/seeders/DemoSeeder.php`:
|
||||
|
||||
```bash
|
||||
grep -n "admin@demo.local\|password" app/database/seeders/DemoSeeder.php
|
||||
```
|
||||
|
||||
Expected: confirmation that email is `admin@demo.local` and `Hash::make('password')` is used.
|
||||
|
||||
### Step 2.3 — Document selectors
|
||||
|
||||
- [ ] Write findings in scratch (no commit yet):
|
||||
|
||||
```text
|
||||
Login flow:
|
||||
- POST /login
|
||||
- email input: <selector>
|
||||
- password input: <selector>
|
||||
- submit button: <selector>
|
||||
- on success: redirect to /dashboard (Vue Router auth-guard pulls user via /api/auth/me)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3 — Extend Pa11y config with authenticated URLs (actions-based login)
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `pa11y.config.json` (add 14+ authenticated URLs with per-URL `actions` block for login)
|
||||
|
||||
### Step 3.1 — Verify Pa11y `actions` API works locally on a single auth URL
|
||||
|
||||
- [ ] Create temporary `pa11y-test.config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"defaults": {
|
||||
"standard": "WCAG2AA",
|
||||
"timeout": 30000,
|
||||
"wait": 1500,
|
||||
"hideElements": ".js-skip-a11y, [data-a11y-skip], .dev-index-badge, .dev-index-num, .v-overlay-container",
|
||||
"ignore": ["warning", "notice"],
|
||||
"chromeLaunchConfig": {
|
||||
"args": ["--no-sandbox", "--disable-dev-shm-usage"]
|
||||
},
|
||||
"viewport": { "width": 1440, "height": 900 }
|
||||
},
|
||||
"urls": [
|
||||
{
|
||||
"url": "http://localhost:8000/dashboard",
|
||||
"screenCapture": "./bin/a11y-screenshots/live-auth-dashboard.png",
|
||||
"actions": [
|
||||
"navigate to http://localhost:8000/login",
|
||||
"wait for element <SELECTOR_FROM_TASK_2> to be visible",
|
||||
"set field <EMAIL_SELECTOR> to admin@demo.local",
|
||||
"set field <PASSWORD_SELECTOR> to password",
|
||||
"click element <SUBMIT_SELECTOR>",
|
||||
"wait for path to be /dashboard",
|
||||
"navigate to http://localhost:8000/dashboard",
|
||||
"wait for element <DASHBOARD_LANDMARK> to be visible"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Replace `<SELECTOR_FROM_TASK_2>` with selectors discovered in Task 2.
|
||||
|
||||
### Step 3.2 — Run test config
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && npx pa11y-ci --config pa11y-test.config.json
|
||||
```
|
||||
|
||||
Expected: `1/1 URL passed` (or violations listed). If Pa11y errors with «navigation timeout» or «selector not found» — debug login-flow selectors before proceeding.
|
||||
|
||||
### Step 3.3 — If Step 3.2 succeeds, merge auth URLs into main config
|
||||
|
||||
- [ ] Add 14 authenticated URL blocks (one per route) to `pa11y.config.json`. Each block shares the same `actions` login template (only target URL + screenshot filename change).
|
||||
|
||||
Routes from `app/routes/web.php` (Route::view + auth-guarded — verify in Vue Router meta):
|
||||
|
||||
1. `/dashboard` (always auth)
|
||||
2. `/deals` (auth)
|
||||
3. `/kanban` (auth)
|
||||
4. `/projects` (auth)
|
||||
5. `/billing` (auth)
|
||||
6. `/settings` (auth)
|
||||
7. `/reports` (auth)
|
||||
8. `/reminders` (auth)
|
||||
9. `/admin/tenants` (admin-auth)
|
||||
10. `/admin/billing` (admin)
|
||||
11. `/admin/incidents` (admin)
|
||||
12. `/admin/system` (admin)
|
||||
13. `/admin/pricing-tiers` (admin)
|
||||
14. `/admin/supplier-prices` (admin)
|
||||
|
||||
`/admin/impersonation` — covered by separate flow (`saas_admin` SSO not present on MVP per `routes/web.php:74`); for MVP, treat as authenticated like other admin.
|
||||
|
||||
### Step 3.4 — Delete the temporary test config
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && rm pa11y-test.config.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4 — Run extended Pa11y baseline + capture findings
|
||||
|
||||
**Files:**
|
||||
|
||||
- Output: terminal log + `bin/a11y-screenshots/live-auth-*.png` (auto-generated by Pa11y)
|
||||
|
||||
### Step 4.1 — Full Pa11y run
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && npm run a11y 2>&1 | tee /tmp/pa11y-extended-baseline.log
|
||||
```
|
||||
|
||||
Expected: at least one of two outcomes:
|
||||
|
||||
- All ≥21 URLs pass → straight to documentation (Task 8)
|
||||
- Some URLs fail with violations → categorize in Task 5
|
||||
|
||||
### Step 4.2 — Tally pass/fail per URL
|
||||
|
||||
- [ ] From log, build a table:
|
||||
|
||||
| URL | Status | Violations count | Notes |
|
||||
|---|---|---|---|
|
||||
| /login | pass/fail | N | |
|
||||
| /dashboard | | | |
|
||||
| ... | | | |
|
||||
|
||||
### Step 4.3 — For each failing URL, capture violation details
|
||||
|
||||
- [ ] Per-violation: rule name (color-contrast, label, region, etc.), DOM selector, expected ratio/text, recommendation.
|
||||
|
||||
---
|
||||
|
||||
## Task 5 — Categorize findings (real prod vs known temp vs structural)
|
||||
|
||||
**Files:**
|
||||
|
||||
- Output: classification table in scratch + decision matrix for Task 7.
|
||||
|
||||
### Step 5.1 — Triage each finding
|
||||
|
||||
For each violation, decide:
|
||||
|
||||
- **REAL_PROD** — fix in code (Task 7)
|
||||
- **KNOWN_TEMP** — DevIndexBadge / DevIndex* — already in `hideElements`; if it leaks through, investigate why
|
||||
- **STRUCTURAL_VUETIFY** — `.v-overlay-container` / portal — already ignored; investigate if new
|
||||
- **CONTENT_DATA** — depends on DemoSeeder content (e.g. empty table state) — fix in test data OR component fallback
|
||||
- **MIGRATED_KNOWN** — already known from Audit #3 Phase 7 (empty-table-header on /admin/tenants — should be CLOSED now since title='Действия' was set in deferred-fixes sprint commit `c524227`)
|
||||
|
||||
### Step 5.2 — Decision matrix output
|
||||
|
||||
```text
|
||||
REAL_PROD → fix in Task 7 (atomic commit per finding)
|
||||
KNOWN_TEMP → no fix; verify hideElements covers selector
|
||||
STRUCTURAL → no fix; document in audit-baseline-pa11y.md
|
||||
CONTENT_DATA → fix in seed/component fallback if production-relevant
|
||||
MIGRATED_KNOWN→ verify fix from c524227 holds; if regressed, re-fix
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 6 — axe-core cross-validation via Playwright MCP
|
||||
|
||||
**Files:**
|
||||
|
||||
- No file changes — Playwright MCP session output.
|
||||
|
||||
### Step 6.1 — Launch Playwright + login
|
||||
|
||||
- [ ] Open Playwright MCP browser to `http://localhost:8000/login`
|
||||
- [ ] Fill email `admin@demo.local`, password `password`, submit
|
||||
- [ ] Wait for `/dashboard`
|
||||
|
||||
### Step 6.2 — Inject axe-core CDN + run on each route
|
||||
|
||||
For each of the 18 routes in scope:
|
||||
|
||||
- [ ] `browser_navigate http://localhost:8000/<route>`
|
||||
- [ ] `browser_wait_for` until main content rendered
|
||||
- [ ] `browser_evaluate`:
|
||||
|
||||
```javascript
|
||||
() => {
|
||||
return new Promise((resolve) => {
|
||||
if (!window.axe) {
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.10.0/axe.min.js';
|
||||
script.onload = () => window.axe.run(document).then(resolve);
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
window.axe.run(document).then(resolve);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] Capture `violations[]` array per route.
|
||||
|
||||
### Step 6.3 — Cross-compare Pa11y vs axe-core findings
|
||||
|
||||
Build a table:
|
||||
|
||||
| Route | Pa11y violations | axe-core violations | Agreement? |
|
||||
|---|---|---|---|
|
||||
|
||||
Pa11y uses axe-core rules under the hood, so they should largely agree. Discrepancies signal:
|
||||
|
||||
- Pa11y standard (WCAG2AA) vs axe default (axe-core baseline incl. best-practice) — axe surfaces more.
|
||||
- Timing differences (Pa11y waits, axe runs once snapshot).
|
||||
- Visual diff (Pa11y full screencap renders Vuetify portals empty vs axe sees populated DOM).
|
||||
|
||||
---
|
||||
|
||||
## Task 7 — Fix real production findings (one atomic commit per finding)
|
||||
|
||||
**Files:**
|
||||
|
||||
- TBD based on findings — likely Vue components in `app/resources/js/components/**`, `app/resources/js/views/**`, or scoped styles.
|
||||
|
||||
### Step 7.1 — For each REAL_PROD finding, write TDD-style fix
|
||||
|
||||
Per finding:
|
||||
|
||||
- [ ] Identify the source file containing the offending element
|
||||
- [ ] Make minimal change (scoped CSS color override / aria-label / label association / etc.)
|
||||
- [ ] Rebuild Vite: `cd "/c/моя/проекты/портал crm/Документация/app" && npx vite build`
|
||||
- [ ] Re-run pa11y on the affected URL only:
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && npx pa11y-ci --config pa11y.config.json --include "<full-url>"
|
||||
```
|
||||
|
||||
- [ ] Verify violation gone, no new ones introduced.
|
||||
|
||||
### Step 7.2 — Commit per fix
|
||||
|
||||
```bash
|
||||
git add <files>
|
||||
git commit -m "fix(a11y): <one-line summary>"
|
||||
```
|
||||
|
||||
Atomic commits make rollback safe and history readable. Per Pravila — one logical change → one commit.
|
||||
|
||||
---
|
||||
|
||||
## Task 8 — Update Pa11y baseline doc
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `docs/audit-baseline-pa11y.md` (extended baseline post-rescan)
|
||||
|
||||
### Step 8.1 — Append «Authenticated rescan 2026-05-14» section
|
||||
|
||||
```markdown
|
||||
## Authenticated rescan — 2026-05-14
|
||||
|
||||
> Extension to first baseline (guest pages only). Added 14 authenticated routes
|
||||
> via Pa11y `actions` per-URL login flow. DemoSeeder credentials.
|
||||
|
||||
### URLs scanned (live Vue, authenticated)
|
||||
|
||||
| # | URL | Pa11y exit | Violations | Status |
|
||||
|---|---|---|---|---|
|
||||
| 1 | /dashboard | 0/N errors | M | ✅/⚠️ |
|
||||
| ... |
|
||||
|
||||
### New fixes during rescan
|
||||
|
||||
| URL | Violation | File | Fix commit |
|
||||
|---|---|---|---|
|
||||
| ... |
|
||||
```
|
||||
|
||||
### Step 8.2 — Update «Authenticated pages — out of scope» section
|
||||
|
||||
```markdown
|
||||
~~## Authenticated pages — out of scope для первой baseline~~
|
||||
|
||||
(SUPERSEDED 2026-05-14) — see «Authenticated rescan» section above.
|
||||
Implemented via Pa11y `actions` API per-URL login flow + DemoSeeder
|
||||
credentials.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 9 — Create audit findings document
|
||||
|
||||
**Files:**
|
||||
|
||||
- Create: `docs/superpowers/audits/2026-05-14-a11y-rescan-findings.md`
|
||||
|
||||
### Step 9.1 — Write findings doc following Audit #3 format
|
||||
|
||||
```markdown
|
||||
# A11y Rescan — Live Portal Findings (2026-05-14)
|
||||
|
||||
> Continuation of Audit #3 Phase 7 — closes the out-of-scope clause for
|
||||
> authenticated routes after deferred-fixes sprint (commits 8ba9c55..ae20033).
|
||||
|
||||
## Scope expansion
|
||||
|
||||
- Pre-rescan baseline (after sprint `ae20033`): 7 guest pages, 0 violations
|
||||
- Rescan adds: 14 authenticated routes (Pa11y `actions` API) + axe-core
|
||||
cross-validation via Playwright MCP
|
||||
|
||||
## Findings
|
||||
|
||||
| ID | Severity | Rule | Route | DOM | Status |
|
||||
|---|---|---|---|---|---|
|
||||
| ... |
|
||||
|
||||
## Per-route table
|
||||
|
||||
[Reuse table from Task 8 Step 8.1]
|
||||
|
||||
## Fix tally
|
||||
|
||||
- REAL_PROD fixed inline: N
|
||||
- KNOWN_TEMP (DevIndexBadge) — verified ignored via hideElements: N
|
||||
- STRUCTURAL_VUETIFY (.v-overlay-container) — documented: N
|
||||
- MIGRATED_KNOWN (empty-table-header from `c524227`) — verified closed: N
|
||||
|
||||
## Verdict: 🟢 GREEN / 🟡 YELLOW
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 10 — Final regression sweep (Phase 14-style)
|
||||
|
||||
**Files:**
|
||||
|
||||
- No file changes — verification only.
|
||||
|
||||
### Step 10.1 — Run all gates
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация/app" && ./vendor/bin/pest --parallel
|
||||
```
|
||||
|
||||
Expected: 742/739/3sk/0.
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация/app" && npx vitest run --no-coverage
|
||||
```
|
||||
|
||||
Expected: 91 files / 736 / 3sk / 0.
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация/app" && npx vite build
|
||||
```
|
||||
|
||||
Expected: ≤3s.
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && npm run links
|
||||
```
|
||||
|
||||
Expected: 0 errors.
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && ./bin/gitleaks.exe detect --source . --redact --log-level info
|
||||
```
|
||||
|
||||
Expected: 0 leaks.
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация" && npm run a11y
|
||||
```
|
||||
|
||||
Expected: full pass on all 21+ URLs after Task 7 fixes (or documented exemptions).
|
||||
|
||||
---
|
||||
|
||||
## Task 11 — Final commit + push
|
||||
|
||||
### Step 11.1 — Stage doc-only changes from Tasks 8+9
|
||||
|
||||
```bash
|
||||
cd "/c/моя/проекты/портал crm/Документация"
|
||||
git add pa11y.config.json docs/audit-baseline-pa11y.md docs/superpowers/audits/2026-05-14-a11y-rescan-findings.md docs/superpowers/plans/2026-05-14-a11y-rescan-live-portal.md
|
||||
```
|
||||
|
||||
NB: code-fix commits from Task 7 are already individually committed.
|
||||
|
||||
### Step 11.2 — Commit doc bundle
|
||||
|
||||
```bash
|
||||
git commit -m "$(cat <<'EOF'
|
||||
docs(a11y): extend Pa11y scope to 14 authenticated routes + audit findings
|
||||
|
||||
Closes Audit #3 Phase 7 «authenticated pages out of scope» clause from
|
||||
deferred-fixes sprint Task 1.
|
||||
|
||||
- pa11y.config.json: +14 authenticated URLs via per-URL actions login flow
|
||||
- docs/audit-baseline-pa11y.md: «Authenticated rescan 2026-05-14» section
|
||||
- docs/superpowers/audits/2026-05-14-a11y-rescan-findings.md: full findings
|
||||
|
||||
Final tallies: <N> URLs / <V> violations / <F> fixes inline.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
### Step 11.3 — Push
|
||||
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
Pre-push hooks: gitleaks-full-history + lychee-links must pass.
|
||||
|
||||
---
|
||||
|
||||
## Self-review
|
||||
|
||||
**Spec coverage:**
|
||||
|
||||
- ✅ Re-verify guest baseline (Task 1)
|
||||
- ✅ Login flow discovery (Task 2)
|
||||
- ✅ Pa11y actions config (Task 3)
|
||||
- ✅ Run + tally (Task 4)
|
||||
- ✅ Categorize findings (Task 5)
|
||||
- ✅ axe-core cross-validation (Task 6)
|
||||
- ✅ Fix real prod findings (Task 7)
|
||||
- ✅ Update baseline doc (Task 8)
|
||||
- ✅ Audit findings document (Task 9)
|
||||
- ✅ Final regression (Task 10)
|
||||
- ✅ Commit + push (Task 11)
|
||||
|
||||
**Placeholder scan:**
|
||||
|
||||
- Task 3 references `<SELECTOR_FROM_TASK_2>` etc. — these ARE filled in once Task 2 produces the selectors. Acceptable per workflow.
|
||||
- Task 7 file paths are TBD — fundamentally cannot be filled in upfront because they depend on Task 5 findings. The procedure (identify source → minimal change → verify → commit) is fully specified.
|
||||
- Task 8/9 violation tables are template skeletons — populated as Task 4 produces data.
|
||||
|
||||
**Type consistency:**
|
||||
|
||||
- All Pa11y config blocks share same `defaults` shape — consistent with current `pa11y.config.json`.
|
||||
- All git commands use absolute path pattern — quirk #79 compliant.
|
||||
- All `cd "/c/моя/проекты/портал crm/Документация"` invocations use full absolute path — no double-cd risk.
|
||||
|
||||
---
|
||||
|
||||
## Execution choice
|
||||
|
||||
Plan complete and saved to `docs/superpowers/plans/2026-05-14-a11y-rescan-live-portal.md`. Two execution options:
|
||||
|
||||
1. **Inline Execution (recommended for this task)** — sequential in this session with checkpoints. Task 6 (Playwright MCP) and Task 7 (fix iteration) need orchestrator decisions per-finding — subagent dispatch would fragment context.
|
||||
2. **Subagent-Driven** — alternative for parallelism, but most tasks have inter-task dependencies (Task 2 selectors → Task 3 config → Task 4 run → Task 5 categorize → Task 7 fix per finding). Linear flow fits better.
|
||||
|
||||
**Recommendation:** Inline Execution.
|
||||
Reference in New Issue
Block a user