Parent epic: #326 · Depends on: V1–V9 (verticals must be implementable end-to-end for the flows to run) · Stories: All 22 MVP stories (validation only — no new feature stories)
Problem
Unit and component tests cover each component in isolation, but the MVP's value emerges from cross-component lifecycles (proposal → merged PR, multi-issue nav with state preservation, task → agent chat, activity-feed navigation, PR merge gate). A11y is also a non-functional MVP requirement that we have not validated end-to-end.
Solution
A. Five Storybook + Playwright E2E flows
Under tests/e2e/:
ProposalLifecycleFlow.e2e.ts — agent creates 3 proposals on issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 → user accepts 1, rejects 1, accepts the last → section header reads "✓ All reviewed" → accepted proposals appear in Related Files → reload plugin → state preserved (validates X1 too).
PRMergeGateFlow.e2e.ts — open PR with reviewStatus='review-required' → Merge button hidden → Approve → Merge unlocks (because CI is passing) → Merge → 800ms transition → PR row pill in sidebar → purple ✓ → breadcrumb back-nav to parent issue works.
MultiIssueNavigationFlow.e2e.ts — open issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 (right=tasks) → click PR docs: define Specorator product vision #45 from Related Files → main=pr, right=pr → back to issue → right=tasks preserved → navigate to issue feat(plugin-shell): MCP server — workflow tools (6 tools) #192 via sidebar → no feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 state leakage. Validates the sidebar active-row sync (Handoff's explicit warning).
TaskAgentChatFlow.e2e.ts — open issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 → click in-progress task → main=task, right=agents → click agent → right=agent, messages stream in → user types message + Enter → optimistic append → back to agents list → unsubscribed cleanly.
ActivityFeedNavigationFlow.e2e.ts — open Activity Feed → click "Agent X completed task on issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 " → main=issue with active sidebar row → click "PR docs: define Specorator product vision #45 merged" event → main=pr, right=pr → each event-type→destination mapping validated.
Each flow uses tests/__fixtures__/specorator-mvp/ from F4. No real GitHub or agent runtime — Mock adapters from F3.
B. A11y audit + remediation
Storybook a11y addon enabled with WCAG 2.1 AA ruleset; all atoms + components must pass with zero violations
Manual keyboard-only walkthrough of each critical flow above; document any escapes in docs/a11y-checklist.md
Required fixes:
Focus traps on all modals + LIFO Esc (validated by V9 but tested end-to-end here)
role="list" + role="listitem" + aria-selected on sidebar
aria-current="page" on terminal breadcrumb crumb
role="log" + aria-live="polite" on AgentChat message container
aria-label on every icon-only badge / button (status dots, draft/merged glyphs)
Reduced-motion respect for the breakdown-card delay, merge transition, typing indicator
Color-contrast verification for the token map (F4): every --sp-* token meets WCAG AA against its expected background
C. Performance smoke tests
Sidebar with 200 issues: paint < 100ms in Chromium headless
Activity feed with 500 events: append-new without scroll-reset, scroll jank < 16ms / frame
Agent chat with 200 messages: append-new at 60fps
Defer large-scale virtualization to X3; X2 sets the smoke baseline.
Acceptance criteria
Out of scope
Browser matrix beyond Chromium (Obsidian's runtime)
Production-adapter tests (those are X3)
Visual regression beyond a11y + smoke (out-of-band Percy snapshots are nice-to-have, not required)
Affected files
File
Action
tests/e2e/ProposalLifecycleFlow.e2e.ts
New
tests/e2e/PRMergeGateFlow.e2e.ts
New
tests/e2e/MultiIssueNavigationFlow.e2e.ts
New
tests/e2e/TaskAgentChatFlow.e2e.ts
New
tests/e2e/ActivityFeedNavigationFlow.e2e.ts
New
tests/performance/*.test.ts
New (3 smoke tests)
docs/a11y-checklist.md
New
scripts/check-token-contrast.ts
New
V-issue component files
Apply ARIA / keyboard fixes
References
inputs/specorator-mvp-design-2026-05/SYNTHESIS.md §"Cross-cutting concerns" — a11y items
QA review §"Cross-Component / E2E Flows" (the five flows above are directly from there)
ADR-009 testing conventions
Parent epic: #326 · Depends on: V1–V9 (verticals must be implementable end-to-end for the flows to run) · Stories: All 22 MVP stories (validation only — no new feature stories)
Problem
Unit and component tests cover each component in isolation, but the MVP's value emerges from cross-component lifecycles (proposal → merged PR, multi-issue nav with state preservation, task → agent chat, activity-feed navigation, PR merge gate). A11y is also a non-functional MVP requirement that we have not validated end-to-end.
Solution
A. Five Storybook + Playwright E2E flows
Under
tests/e2e/:ProposalLifecycleFlow.e2e.ts— agent creates 3 proposals on issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 → user accepts 1, rejects 1, accepts the last → section header reads "✓ All reviewed" → accepted proposals appear in Related Files → reload plugin → state preserved (validates X1 too).PRMergeGateFlow.e2e.ts— open PR withreviewStatus='review-required'→ Merge button hidden → Approve → Merge unlocks (because CI is passing) → Merge → 800ms transition → PR row pill in sidebar → purple ✓ → breadcrumb back-nav to parent issue works.MultiIssueNavigationFlow.e2e.ts— open issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 (right=tasks) → click PR docs: define Specorator product vision #45 from Related Files → main=pr, right=pr → back to issue → right=tasks preserved → navigate to issue feat(plugin-shell): MCP server — workflow tools (6 tools) #192 via sidebar → no feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 state leakage. Validates the sidebar active-row sync (Handoff's explicit warning).TaskAgentChatFlow.e2e.ts— open issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191 → click in-progress task → main=task, right=agents → click agent → right=agent, messages stream in → user types message + Enter → optimistic append → back to agents list → unsubscribed cleanly.ActivityFeedNavigationFlow.e2e.ts— open Activity Feed → click "Agent X completed task on issue feat(plugin-shell): MCP server — write proposal queue (PendingProposal mechanism) #191" → main=issue with active sidebar row → click "PR docs: define Specorator product vision #45 merged" event → main=pr, right=pr → each event-type→destination mapping validated.Each flow uses
tests/__fixtures__/specorator-mvp/from F4. No real GitHub or agent runtime — Mock adapters from F3.B. A11y audit + remediation
docs/a11y-checklist.mdrole="list"+role="listitem"+aria-selectedon sidebararia-current="page"on terminal breadcrumb crumbrole="log"+aria-live="polite"on AgentChat message containeraria-labelon every icon-only badge / button (status dots, draft/merged glyphs)--sp-*token meets WCAG AA against its expected backgroundC. Performance smoke tests
Defer large-scale virtualization to X3; X2 sets the smoke baseline.
Acceptance criteria
tests/e2e/and pass via Playwrightnpm run test:storybookruns the a11y addon with zero violations on every storydocs/a11y-checklist.mdwith a screenshot per flowaria-labelfixes applied in the V-issue components--sp-*tokens against expected backgroundsnpm run typecheck,npm run lint,npm run test,npm run test:storybookpassOut of scope
Affected files
tests/e2e/ProposalLifecycleFlow.e2e.tstests/e2e/PRMergeGateFlow.e2e.tstests/e2e/MultiIssueNavigationFlow.e2e.tstests/e2e/TaskAgentChatFlow.e2e.tstests/e2e/ActivityFeedNavigationFlow.e2e.tstests/performance/*.test.tsdocs/a11y-checklist.mdscripts/check-token-contrast.tsReferences
inputs/specorator-mvp-design-2026-05/SYNTHESIS.md§"Cross-cutting concerns" — a11y items