You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Converge Wave A surfaces on bounded shared UI primitives
Status: accepted and committed locally — exact accepted commit 0c89588df809b2e84af02e796d1910a25eea0165; not merged, pushed, deployed, shipped, or closed
Tags: enhancement, portal, frontend, testing, design, P1
Parent: #162, Wave A slice 1
Depends on: satisfied — accepted #180 increments e684162 and b045739 plus the accepted #161 foundation are present in parent baseline 78e9122
Blocks: implementation of #162 Wave A slices 2–5 on overlapping frontend presentation paths
Next owner: Orchestrator — when coordinated publication resumes, merge the accepted local Wave A chain in order, push main, then hand off to On-Call; no implementation or review rerun is pending for #218
Resume condition: local main is clean and the Orchestrator is ready to publish the accepted Wave A chain; #218 requires no rerun unless commit 0c89588df809b2e84af02e796d1910a25eea0165 changes
Product outcome
Give the dependency-independent Wave A surfaces one small, explicit presentation vocabulary for page headers, section framing, action rows, fields/form footers, semantic status labels, and honest loading/empty/partial/error states.
An operator moving among Templates, Recurring, Process Docs/search, Bookkeeping, Sponsors, Newsletter, Calendar, and Mailing exports should see the same hierarchy and state language without changing any route, API, mutation, authorization, lifecycle, or domain behavior.
This is gap-only convergence. It is not a redesign of those surfaces and not a repository-wide CSS cleanup.
PM scope amendment after review
Screenshot files 09 and 10 prove only the Newsletter READY presentation state for the shared page/header/action/form/status primitives. They do not require or authorize validation copy, error-focus ownership, conflict recovery, Calendar keyboard behavior, or any other Newsletter/Calendar behavior change.
Generic validation, announcement, and useful-focus criteria in Converge Wave A surfaces on bounded shared UI primitives #218 may be proven by another already-in-scope dialog/state; Newsletter and Calendar are not required evidence vehicles for those criteria.
The prior frozen candidate and review verdicts are superseded only for this scope correction. The authorized path is: remove the behavior changes and verifier change, regenerate exactly the amended 12 screenshots, freeze new fingerprints, then repeat Designer, independent Tester, and PM reviews.
Frozen baseline and dependency reconciliation
The PM inventory was performed read-only at clean local SHA 78e91223203aa54376a318fd1a3214ce0242e0c3.
#218 must preserve those behaviors. It does not reopen #180 or #161.
Accepted but separately held #158 and #164 work is not part of 78e9122 and is not scope for this issue. Those branches overlap shared files including frontend/src/styles.css, frontend/src/surfaces/knowledge/search.js, frontend/src/surfaces/planning.js, task tests, the capability catalog, and canonical browser specs. The Orchestrator must serialize writers. If #158 or #164 is integrated before #218 freezes, the engineer must first re-run this issue's gap/overlap inventory on the reviewed containing SHA, retain only still-unmet #218 gaps, and send the reconstructed fingerprint through Designer, Tester, and PM again. Do not resolve overlap by reverting, absorbing, or silently rewriting dependency-owned behavior.
Current-source inventory
Already compliant — preserve, do not rebuild
frontend/src/styles.css already owns the canonical light/dark tokens, spacing/density tokens, 6px shared radius, focus ring, 34px desktop and 44px mobile density concepts, content width, and overlay shadow.
Existing shared primitives already include .primary-button, .danger-button, .surface-dialog, .section-header, .section-kicker, .surface-actions, .surface-status, .status-label, and .honest-state.
Wave A routes already use native headings, labels, status/alert regions, dialogs, semantic status text, public-safe synthetic browser fixtures, canonical URLs, and real local backend calls.
The capability catalog already has durable runtime states for Templates, Recurring, Process Docs, Bookkeeping, Sponsors, Newsletter, Calendar, and Mailing exports. No new capability identity is needed merely for visual convergence.
The 11,695-line stylesheet contains later route-specific layers that restate the same shared presentation contract:
Page header duplication..bookkeeping-header, .crm-header, .mailing-exports-surface > header, .planner-header, and .ops-surface-header independently repeat title, description, divider, spacing, and trailing-action behavior.
Action-row duplication..surface-actions, .row-actions, .finance-actions, .mailing-export-actions, .planner-form-actions, .ops-template-actions, and .recurring-row-actions repeat wrapping, spacing, alignment, footer borders, and mobile target rules.
Form duplication..dialog-fields, .planner-form-grid, and .ops-field repeat stacked labels, control dimensions, helper/error placement, and responsive one-column behavior.
Status-label duplication..status-label, .finance-status, .evidence-state, .mailing-export-status, .planner-status, and Recurring status presentation repeat compact semantic pills and success/warning/danger/info variants.
Honest-state duplication..ops-runtime-state, .ops-docs-state, .ops-empty, .ops-inline-error, .surface-status, .planner-load-state, and route-scoped .honest-state rules express overlapping loading, empty, partial, failure, and recovery presentation.
Responsive duplication. Several late media blocks independently restore 44px controls and one-column form/action behavior, leaving equivalent Wave A controls visually inconsistent and making later slices likely to add more local overrides.
Converge those five primitive families and their responsive rules. Route-specific classes may remain only where they carry a real route layout, behavior hook, or test locator; they must not retain a duplicate shared visual declaration.
Allowed test/evidence paths are the corresponding focused frontend tests, one dedicated backend/e2e/issue-218-shared-primitives.spec.js, and existing capability journey files only where needed to emit already-defined durable state IDs. Do not add new capability IDs for style-only states or alter #159's schema/reporting machinery.
A newly required production path needs a PM amendment before editing. Do not create a shared JavaScript component abstraction merely to rename CSS classes.
Acceptance criteria
Bounded convergence
The engineer posts a fresh criterion-to-source/test inventory before editing, using the exact starting SHA and classifying every item as already compliant, concrete gap, dependency-owned, or out of scope.
One canonical CSS contract owns page header, section framing, action row, field/form footer, semantic status, and honest-state presentation for all in-scope Wave A surfaces.
In-scope markup consumes that contract. Redundant route-specific declarations are deleted in the same change; retained route classes have a documented route-layout, behavior, or locator purpose.
No new hard-coded color, radius, shadow, spacing scale, or control-height vocabulary is introduced. Both themes use the existing tokens.
There is no compatibility alias, duplicate old/new selector contract, framework, runtime helper, API change, or behavior refactor.
Desktop and mobile
At 1440×900, every in-scope page has one dominant heading, adjacent description, content-width primary action, consistent section frame, and no nested-card or duplicated-status hierarchy introduced by Converge Wave A surfaces on bounded shared UI primitives #218.
At 390×844, header/actions and form footers wrap in reading order; fields become one column; every in-scope interactive control is at least 44×44 CSS pixels; there is no page-level horizontal scroll, clipping, overlap, or unreachable action.
At 390×844, each evidence route shows its first meaningful record, state, or recovery action within the initial viewport after route heading/controls; empty decorative containers do not push the decision below the fold.
Light and dark themes preserve semantic contrast and the same hierarchy. Reduced motion causes no lost state or focus cue.
Accessibility and honest states
Each changed route retains one main, one page h1/owned primary heading contract, correctly nested section headings, native labels, and semantic list/table/dialog structure.
Loading is announced without displaying a false zero; empty states explain what is absent and retain a safe next action; partial failures retain successful records and identify the unavailable source with retry guidance.
In an already-in-scope dialog/state other than Newsletter or Calendar, generic validation and conflict presentation retains entered values and useful focus; blocking errors use role="alert", non-blocking progress uses role="status"/appropriate live state, and success names the durable result. Newsletter/Calendar domain copy, focus, route, recovery, and keyboard behavior remain unchanged for Converge Newsletter, Calendar, and Mailing Export presentation #222.
Status meaning is expressed in text and programmatically, never by color alone. Repeated status pills are not added where status does not affect the next decision.
Keyboard operation, visible focus, dialog focus containment/restoration, and zoom remain intact; automated scans report zero critical or serious WCAG A/AA findings on every captured changed state.
Behavior and parity
All existing route, API, mutation, concurrency, authorization, focus, history, and close/return behavior remains unchanged.
A real-server Playwright journey exercises each in-scope family through existing durable capability states, without request interception, fixed sleeps, source-string assertions, incidental copy pins, broad 404 swallowing, test-order dependence, or screenshot assertions.
The successful full browser run emits passing evidence for every existing capability state and role; no state is covered by screenshots, source inspection, or parity alone.
Source, backend/dist, and packaged SAM frontend assets are identical for every changed asset, and the normal source/SAM parity run passes with all evidence records accounted for.
Synthetic evidence contains no operational knowledge, real person/contact/provider data, credentials, private links, or production identifiers.
Test scenarios
Shared hierarchy across Wave A
Given an authenticated synthetic operator/admin and populated local fixtures
When Templates, Recurring, Process Docs, Bookkeeping, Sponsors, Newsletter, Calendar, and Mailing exports are opened directly and through their existing routes
Then each retains its domain behavior while page header, sections, actions, fields, semantic status, and honest-state hierarchy use the one shared contract
Honest partial and failure state
Given successful synthetic records plus one deterministic local source failure
When the affected Process Docs/search, finance, planning, or export surface settles
Then successful data remains visible, unavailable data is named, zero/success is not fabricated, and a safe retry or return action is reachable and focused appropriately
Generic validation without data loss
Given an already-in-scope dialog or editor other than Newsletter or Calendar with public-safe entered values
When local validation, conflict, or save failure occurs
Then the dialog remains open, values remain, the first useful field/error owns focus, the error is announced, and a retry produces at most one intended mutation
Responsive action hierarchy
Given the same ready and critical fixtures at 1440×900 and 390×844
When the operator traverses headings, fields, action rows, statuses, and dialogs by keyboard
Then reading/focus order is stable, desktop actions remain content-width, mobile targets are at least 44×44, and no control or recovery path is clipped or off-canvas
Source/SAM identity
Given the frozen source candidate and a clean SAM build
When the same public-safe routes and changed assets are verified from source and packaged targets
Then route behavior and durable capability evidence agree and every changed frontend asset is byte-identical
Synthetic screenshot evidence
Capture exactly these 12 untracked native-size PNGs under .tmp/screenshots/issue-218/; delete stale extras before review:
Use normal local backend behavior and synthetic public-safe records. Files 09 and 10 capture Newsletter READY presentation only and prove shared page/header/action/form/status primitives; they must not depend on validation copy, error focus, conflict recovery, Calendar keyboard behavior, or any Newsletter/Calendar behavior change. Tester and Designer inspect every image at native resolution for hierarchy, copy ownership, visible state, theme/contrast, target sizing, overflow, clipping, overlap, and first-decision visibility. Screenshots are visual evidence only; they are not committed, attached publicly, or used as behavior/parity proof.
Verification
Engineer uses focused tests while iterating. backend/scripts/sam-workspace-isolation.test.mjs is outside #218 and must not be edited; its clean-workspace isolation command is not an #218 acceptance gate. The required SAM/build/parity/make ci list below remains unchanged. Tester runs the complete relevant workflow on one frozen fingerprint and records commands, exit codes, observed counts, capability-state accounting, and evidence paths:
npm run test:frontend:unit
npm run test:frontend:coverage
npm --prefix backend test
npm --prefix backend run typecheck
npm --prefix backend run build
node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact backend/dist
npm --prefix backend run test:e2e
npm --prefix backend run test:e2e:frontend-parity
make sam-validate
make sam-build
node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact .aws-sam/build/BackendFunction
make ci
git diff --check
The dedicated #218 browser spec must be included in the normal full Playwright run. Existing behavior suites remain authoritative for the durable capability states; do not create a parallel screenshot-only or intercepted test harness.
Converge Wave A surfaces on bounded shared UI primitives
Status: accepted and committed locally — exact accepted commit 0c89588df809b2e84af02e796d1910a25eea0165; not merged, pushed, deployed, shipped, or closed
Tags:
enhancement,portal,frontend,testing,design,P1Parent: #162, Wave A slice 1
Depends on: satisfied — accepted #180 increments e684162 and b045739 plus the accepted #161 foundation are present in parent baseline 78e9122
Blocks: implementation of #162 Wave A slices 2–5 on overlapping frontend presentation paths
Next owner: Orchestrator — when coordinated publication resumes, merge the accepted local Wave A chain in order, push main, then hand off to On-Call; no implementation or review rerun is pending for #218
Resume condition: local main is clean and the Orchestrator is ready to publish the accepted Wave A chain; #218 requires no rerun unless commit 0c89588df809b2e84af02e796d1910a25eea0165 changes
Product outcome
Give the dependency-independent Wave A surfaces one small, explicit presentation vocabulary for page headers, section framing, action rows, fields/form footers, semantic status labels, and honest loading/empty/partial/error states.
An operator moving among Templates, Recurring, Process Docs/search, Bookkeeping, Sponsors, Newsletter, Calendar, and Mailing exports should see the same hierarchy and state language without changing any route, API, mutation, authorization, lifecycle, or domain behavior.
This is gap-only convergence. It is not a redesign of those surfaces and not a repository-wide CSS cleanup.
PM scope amendment after review
backend/scripts/sam-workspace-isolation.test.mjsis outside Converge Wave A surfaces on bounded shared UI primitives #218 write ownership. Its clean-workspace isolation command is not an Converge Wave A surfaces on bounded shared UI primitives #218 acceptance gate. The required SAM/build/parity/make cicommand list in this issue remains unchanged.Frozen baseline and dependency reconciliation
The PM inventory was performed read-only at clean local SHA
78e91223203aa54376a318fd1a3214ce0242e0c3.That baseline already contains:
e684162: accepted focus, refresh, notification, Recurring accessibility, fixture, and browser-race repairs.b045739: accepted behavior-based browser coverage convergence.7d77632and closed by64476d2.#218 must preserve those behaviors. It does not reopen #180 or #161.
Accepted but separately held #158 and #164 work is not part of
78e9122and is not scope for this issue. Those branches overlap shared files includingfrontend/src/styles.css,frontend/src/surfaces/knowledge/search.js,frontend/src/surfaces/planning.js, task tests, the capability catalog, and canonical browser specs. The Orchestrator must serialize writers. If #158 or #164 is integrated before #218 freezes, the engineer must first re-run this issue's gap/overlap inventory on the reviewed containing SHA, retain only still-unmet #218 gaps, and send the reconstructed fingerprint through Designer, Tester, and PM again. Do not resolve overlap by reverting, absorbing, or silently rewriting dependency-owned behavior.Current-source inventory
Already compliant — preserve, do not rebuild
frontend/src/styles.cssalready owns the canonical light/dark tokens, spacing/density tokens, 6px shared radius, focus ring, 34px desktop and 44px mobile density concepts, content width, and overlay shadow..primary-button,.danger-button,.surface-dialog,.section-header,.section-kicker,.surface-actions,.surface-status,.status-label, and.honest-state.Concrete gaps owned by #218
The 11,695-line stylesheet contains later route-specific layers that restate the same shared presentation contract:
.bookkeeping-header,.crm-header,.mailing-exports-surface > header,.planner-header, and.ops-surface-headerindependently repeat title, description, divider, spacing, and trailing-action behavior..surface-actions,.row-actions,.finance-actions,.mailing-export-actions,.planner-form-actions,.ops-template-actions, and.recurring-row-actionsrepeat wrapping, spacing, alignment, footer borders, and mobile target rules..dialog-fields,.planner-form-grid, and.ops-fieldrepeat stacked labels, control dimensions, helper/error placement, and responsive one-column behavior..status-label,.finance-status,.evidence-state,.mailing-export-status,.planner-status, and Recurring status presentation repeat compact semantic pills and success/warning/danger/info variants..ops-runtime-state,.ops-docs-state,.ops-empty,.ops-inline-error,.surface-status,.planner-load-state, and route-scoped.honest-staterules express overlapping loading, empty, partial, failure, and recovery presentation.Converge those five primitive families and their responsive rules. Route-specific classes may remain only where they carry a real route layout, behavior hook, or test locator; they must not retain a duplicate shared visual declaration.
Dependency-owned — preserve exactly
Out of scope
Write ownership
The implementation may edit only these production paths, and only for class/presentation convergence:
frontend/src/styles.cssfrontend/src/surfaces/tasks/templates.jsfrontend/src/surfaces/tasks/recurring.jsfrontend/src/surfaces/knowledge/list.jsfrontend/src/surfaces/knowledge/process-docs.jsfrontend/src/surfaces/knowledge/search.jsfrontend/src/surfaces/knowledge/navigation.jsfrontend/src/surfaces/finance/bookkeeping.jsfrontend/src/surfaces/finance/mailing.jsfrontend/src/surfaces/finance/sponsor-layout.jsfrontend/src/surfaces/finance/sponsor-alerts.jsfrontend/src/surfaces/finance/sponsor-communications.jsfrontend/src/surfaces/finance/sponsor-finance.jsfrontend/src/surfaces/finance/sponsors.jsfrontend/src/surfaces/planning.jsAllowed test/evidence paths are the corresponding focused frontend tests, one dedicated
backend/e2e/issue-218-shared-primitives.spec.js, and existing capability journey files only where needed to emit already-defined durable state IDs. Do not add new capability IDs for style-only states or alter #159's schema/reporting machinery.A newly required production path needs a PM amendment before editing. Do not create a shared JavaScript component abstraction merely to rename CSS classes.
Acceptance criteria
Bounded convergence
Desktop and mobile
Accessibility and honest states
main, one pageh1/owned primary heading contract, correctly nested section headings, native labels, and semantic list/table/dialog structure.role="alert", non-blocking progress usesrole="status"/appropriate live state, and success names the durable result. Newsletter/Calendar domain copy, focus, route, recovery, and keyboard behavior remain unchanged for Converge Newsletter, Calendar, and Mailing Export presentation #222.Behavior and parity
backend/dist, and packaged SAM frontend assets are identical for every changed asset, and the normal source/SAM parity run passes with all evidence records accounted for.Test scenarios
Shared hierarchy across Wave A
Given an authenticated synthetic operator/admin and populated local fixtures
When Templates, Recurring, Process Docs, Bookkeeping, Sponsors, Newsletter, Calendar, and Mailing exports are opened directly and through their existing routes
Then each retains its domain behavior while page header, sections, actions, fields, semantic status, and honest-state hierarchy use the one shared contract
Honest partial and failure state
Given successful synthetic records plus one deterministic local source failure
When the affected Process Docs/search, finance, planning, or export surface settles
Then successful data remains visible, unavailable data is named, zero/success is not fabricated, and a safe retry or return action is reachable and focused appropriately
Generic validation without data loss
Given an already-in-scope dialog or editor other than Newsletter or Calendar with public-safe entered values
When local validation, conflict, or save failure occurs
Then the dialog remains open, values remain, the first useful field/error owns focus, the error is announced, and a retry produces at most one intended mutation
Responsive action hierarchy
Given the same ready and critical fixtures at 1440×900 and 390×844
When the operator traverses headings, fields, action rows, statuses, and dialogs by keyboard
Then reading/focus order is stable, desktop actions remain content-width, mobile targets are at least 44×44, and no control or recovery path is clipped or off-canvas
Source/SAM identity
Given the frozen source candidate and a clean SAM build
When the same public-safe routes and changed assets are verified from source and packaged targets
Then route behavior and durable capability evidence agree and every changed frontend asset is byte-identical
Synthetic screenshot evidence
Capture exactly these 12 untracked native-size PNGs under
.tmp/screenshots/issue-218/; delete stale extras before review:01-templates-ready-desktop-1440x900.png02-templates-ready-mobile-390x844.png03-recurring-referenced-delete-desktop-1440x900.png04-recurring-referenced-delete-mobile-390x844.png05-process-docs-partial-desktop-1440x900.png06-process-docs-partial-mobile-390x844.png07-bookkeeping-ready-desktop-1440x900.png08-bookkeeping-ready-mobile-390x844.png09-newsletter-ready-desktop-1440x900.png10-newsletter-ready-mobile-390x844.png11-mailing-exports-failed-desktop-1440x900.png12-mailing-exports-failed-mobile-390x844.pngUse normal local backend behavior and synthetic public-safe records. Files 09 and 10 capture Newsletter READY presentation only and prove shared page/header/action/form/status primitives; they must not depend on validation copy, error focus, conflict recovery, Calendar keyboard behavior, or any Newsletter/Calendar behavior change. Tester and Designer inspect every image at native resolution for hierarchy, copy ownership, visible state, theme/contrast, target sizing, overflow, clipping, overlap, and first-decision visibility. Screenshots are visual evidence only; they are not committed, attached publicly, or used as behavior/parity proof.
Verification
Engineer uses focused tests while iterating.
backend/scripts/sam-workspace-isolation.test.mjsis outside #218 and must not be edited; its clean-workspace isolation command is not an #218 acceptance gate. The required SAM/build/parity/make cilist below remains unchanged. Tester runs the complete relevant workflow on one frozen fingerprint and records commands, exit codes, observed counts, capability-state accounting, and evidence paths:npm run test:frontend:unit npm run test:frontend:coverage npm --prefix backend test npm --prefix backend run typecheck npm --prefix backend run build node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact backend/dist npm --prefix backend run test:e2e npm --prefix backend run test:e2e:frontend-parity make sam-validate make sam-build node backend/scripts/verify-frontend-artifact.mjs --source frontend --artifact .aws-sam/build/BackendFunction make ci git diff --checkThe dedicated #218 browser spec must be included in the normal full Playwright run. Existing behavior suites remain authoritative for the durable capability states; do not create a parallel screenshot-only or intercepted test harness.
Lifecycle gates
78e9122Closes #218No HUMAN gate is required for this local, synthetic, provider-free slice.