Skip to content

Converge Newsletter, Calendar, and Mailing Export presentation #222

Description

@alexeygrigorev

Converge Newsletter, Calendar, and Mailing Export presentation

Status: blocked pending final verification — immutable user-authorized checkpoint 65fb9a8392ed76cc55e74a9b783e352914169411 with PM identity amendment approved; final quiescent preflight/full gate and fresh Designer, Tester, and PM gates remain pending; local, unpushed, and unshipped
Tags: enhancement, portal, frontend, testing, design, P1
Parent: #162, Wave A slice 5
Depends on: satisfied for implementation — accepted local commits #218 0c89588df809b2e84af02e796d1910a25eea0165, #219 9d204d208820e3d842a3d3fc83493c230bcadaa5, #220 d334020ca5a582d31a81b371988169cab4e7f6b2, and #221 8c3b110c8aa138d95385a89fe3328749bdf47250; checkpoint 65fb9a8 is based on that exact chain
Blocks: the #162 final integrated design-system audit for these three surfaces
Next owner: Software Engineer — only after the documented host process, port, resource, and retained 30-second network-quiescence prerequisites are demonstrably satisfied, execute the approved final protocol exactly
Resume condition: the host is demonstrably free of other-worktree Playwright/Chromium activity, required ports are free, resource checks pass, and the retained 30-second network observation is empty; then use immutable checkpoint 65fb9a8392ed76cc55e74a9b783e352914169411 without source or evidence drift

Product outcome

Make Newsletter, Calendar, and Mailing Exports read as one chronological planning and recovery workflow without changing their domain contracts.

  • Newsletter is an earliest-first publication plan with stable grouping and a clear next item.
  • Calendar remains an intentional desktop month/week calendar and becomes a true one-column date agenda on mobile.
  • Newsletter overlays and source outages remain explicit without hiding successful Calendar or Newsletter data.
  • Mailing Export cards name the existing safe next action precisely: wait/check status, retry, fix authorization before retrying, repair another named prerequisite, or download the completed private ZIP.

This is a presentation and evidence slice over the existing TypeScript frontend. It must preserve the accepted #108 Mailing Export product and #134 Europe/Berlin operator-day contract. It does not authorize provider execution, an API/data expansion, or a redesign of unrelated surfaces.

Frozen baseline and dependency reconciliation

The PM inventory was performed read-only at clean baseline 78e91223203aa54376a318fd1a3214ce0242e0c3.

That baseline already contains and this slice must preserve:

#218 is not disjoint. It owns shared page-header, section, action-row, form, semantic-status, honest-state, responsive, and evidence convergence in:

  • frontend/src/styles.css
  • frontend/src/surfaces/planning.js
  • frontend/src/surfaces/finance/mailing.js
  • frontend/test/planning-surface.test.mjs
  • frontend/test/finance-surface.test.mjs
  • canonical capability/browser paths and synthetic screenshots

Therefore #222 implementation starts after #218's accepted exact commit. If another accepted branch is integrated first, reconstruct from the reviewed containing SHA, repeat the pre-edit criterion inventory, retain only still-unmet gaps, and send the reconstructed fingerprint through Designer, Tester, and PM. Do not resolve overlap by reverting, absorbing, or silently restyling dependency-owned behavior.

Criterion-to-current-source inventory at 78e9122

Product criterion Classification Current source/test evidence Bounded #222 responsibility
One canonical frontend, routes, shell, focus/history, tokens, and shared state presentation Already compliant / dependency-owned #180/#161 are in the baseline; frontend/src/styles.css contains the accepted token, focus, theme, density, and overlay vocabulary. #218 now owns primitive convergence. Consume #218's accepted primitives. Do not alter shell IA, routing, account/team scope, or reintroduce route-local primitive duplication.
One Europe/Berlin operator day Already compliant; preserve exactly planning.js receives todayIsoDate; Calendar cursor/Today, Newsletter default bounds, and mailing.js absent-run key use it. work-model, Planning, Finance, and canonical browser tests cover the boundary. #134 is closed. No new date resolver, timezone rule, backend timestamp change, or date library. Keep all current #134 tests green.
Newsletter chronological plan Substantially compliant with one concrete determinism/evidence gap planning.js groups by month or ISO week and sorts by publicationDate; rows use semantic <time>, human booking labels, status text, filters, alerts, native dialog, validation/conflict retention, and safe campaign links. Unit and browser suites cover grouping, mutation, conflict, empty/failure, mobile overflow, themes, and Axe. Current tests do not prove out-of-order same-date input produces a stable operator order or that the earliest actionable slot remains first across grouping/filter changes. Define one earliest-first presentation order independent of API order: publication date, then stable human campaign label, then stable record identity only as a non-visible tie-breaker. Preserve grouping, filters, mutation contracts, booking labels, statuses, links, and #134 bounds. Add behavior evidence for shuffled records and filter/group changes.
Newsletter refresh failure after useful data Concrete honest-state gap load() replaces the schedule with Newsletter schedule unavailable and says to reopen; there is no in-surface Retry control. Existing tests prove initial failure and recovery via changing a filter, not preservation of a previously useful schedule. On a later GET failure, keep the last confirmed schedule visible as stale/read-only context, identify Newsletter as unavailable, and provide one connected Retry newsletter schedule control that repeats the current query. On initial failure show no synthetic rows. Do not retain failed mutation as success; dialog values/conflict behavior remain unchanged.
Desktop Calendar month/week planning Already compliant; preserve planning.js renders deterministic Monday–Sunday month/week grids, ISO weeks, filters, layer toggles, holidays, activities, overlays, alerts, semantic dates, create/edit/conflict, and Today navigation. Unit, calendar-seams, canonical capability, and design suites cover these contracts. Keep desktop month/week grid, dates, layers, alert dismissal, mutations, and #134 clock behavior unchanged.
Mobile Calendar agenda Concrete gap At <=820px, late CSS renders each week as seven 112px columns with overflow-x:auto; the UI instructs operators to swipe horizontally. planning-surfaces-design.spec.js is titled “one-column agenda” but explicitly asserts the horizontal strip. At 390×844, render the selected period as one chronological vertical agenda of date rows. Each meaningful day exposes its date, activity/holiday/newsletter items, and state in reading order; empty days may be compact but dates and controls remain reachable. No horizontal day strip, hidden off-screen action, or page-level overflow. Desktop remains a grid.
Newsletter overlay success Already compliant; preserve Calendar independently requests /overlays, renders linked Newsletter items, allows the layer to be toggled, and canonical real-server evidence covers calendar.overlays-alerts. Preserve real overlay links, toggle behavior, chronology, and safe labels. Do not duplicate Newsletter records or create a second source.
Overlay unavailable while Calendar succeeds Partially compliant with a concrete recovery/ownership gap Promise.allSettled keeps Calendar items when the overlay request fails and appends terse text to the shared status. The layer remains checked, no source-owned unavailable block or retry action appears, and existing browser behavior does not prove recovery without reloading the whole route. Keep Calendar activities/holidays usable, mark only Newsletter dates unavailable adjacent to the layer/calendar decision, never imply zero overlays, and provide one Retry newsletter dates action that retries the existing overlay request/range. Recovery removes the warning and restores overlays without duplicating Calendar records.
Full Calendar refresh failure Concrete honest-state gap The catch path clears items, holidays, and overlays, replaces the grid, and says Reopen Calendar to retry, although calendar.failure describes preserved successful data. Existing browser recovery uses Today/reload rather than an explicit recovery control. Initial failure shows no invented records. A later failure preserves the last confirmed calendar as stale/read-only context, names Calendar as unavailable, retains the selected period/filter/layers, and offers one connected Retry calendar action. Recovery updates once without duplicate records or mutations.
Mailing Export durable behavior and privacy Already compliant; preserve exactly mailing.js, Finance tests, canonical real-server capability evidence, and accepted #108 behavior cover no-config, empty, pending, failed, completed, history pagination, deterministic run keys, one logical run, sanitized errors, Artifact linkage, and authenticated short-lived download. No provider/service/API/persistence/configuration/security change. No provider call during implementation/review. Preserve no-secret/no-contact/no-storage-identity output and all #108 tests.
Mailing next-action explanation Already present but not precise enough actionCopy distinguishes wait, retry, fix-authorization, fix-storage, fix-task-link, and download. It also prints raw lower-case states/error codes and every non-completed run exposes the same Advance / retry button, obscuring whether the operator should wait, retry, or repair authorization first. Render human state labels and one unambiguous next-action heading/instruction. Map the existing server nextAction to precise visible controls without changing which existing endpoint is invoked or its durable run key. Remove the combined Advance / retry label.
Wait / Retry / Fix authorization / Download language Concrete gap Pending runs say to wait but still show Advance / retry; failed authorization/storage/task-link states share the same button; completed uses Download ZIP while explanatory copy alone mentions privacy/expiry. Required labels/meaning: Check status for wait (same durable run; no claim of a new export), Retry export for retry, Retry after authorization is fixed for fix-authorization, equivalent named repair-first labels for storage/task-link states, and Download private ZIP for download. Completed cards expose no start/advance action. Copy states that the download is authenticated and expires in five minutes; it never implies the browser has already downloaded or that provider work succeeded before authoritative completion.
Mailing history chronology and honest pagination Already compliant; preserve sortedRuns() orders newest request first with stable ID tie-break; pagination retains loaded history on later-page failure and offers retry. Keep ordering, loaded records, continuation, and error behavior. Presentation may consume #218 primitives only.
Durable capability and source/SAM evidence Machinery already compliant; candidate evidence gap frontend-capabilities.json already defines all Newsletter, Calendar, and Mailing Export states. canonical-capability-behavior.spec.js emits real-server evidence; build/SAM parity machinery exists. Intercepted legacy/design specs are useful regression/visual fixtures but are not core behavior proof. Reuse existing IDs; do not change #159 schema or add style-only capability IDs. Extend behavior assertions so the existing states prove current mobile agenda, partial/unavailable recovery, and exact mailing next-action semantics. Prove changed source, backend/dist, and SAM assets are identical.

Scope

  1. Start from Converge Wave A surfaces on bounded shared UI primitives #218's exact accepted commit or reviewed containing SHA and post a refreshed version of the inventory above before editing.
  2. Preserve already-compliant Newsletter, Calendar, Mailing Export, Automate private Mailchimp account exports and attach them to recurring work #108, Reconcile and close one Europe/Berlin business date #134, Restore behavior-based browser coverage and fix canonical UI accessibility races #180, Finalize the canonical scan-first Operations Home #161, and Converge Wave A surfaces on bounded shared UI primitives #218 behavior.
  3. Implement only the concrete presentation/recovery gaps: deterministic Newsletter chronology, retained useful data with explicit retry, desktop Calendar/mobile agenda, overlay-specific unavailable recovery, and precise Mailing Export next-action language.
  4. Add focused production-module tests, one dedicated real-server Converge Newsletter, Calendar, and Mailing Export presentation #222 browser journey, updates to existing regressions whose old mobile/action assumptions are intentionally replaced, and existing durable capability/source-SAM evidence.
  5. Complete Designer → independent Tester → PM acceptance on one frozen fingerprint before commit.

Bounded write set

Production files:

  • frontend/src/surfaces/planning.js
  • frontend/src/surfaces/finance/mailing.js
  • frontend/src/styles.css

Focused tests/evidence:

  • frontend/test/planning-surface.test.mjs
  • frontend/test/finance-surface.test.mjs
  • backend/e2e/issue-222-planning-presentation.spec.js (new)
  • backend/e2e/canonical-capability-behavior.spec.js
  • backend/e2e/planning-surfaces-design.spec.js
  • backend/e2e/calendar-seams.spec.js
  • backend/e2e/newsletter-production-portal.spec.js

A newly required production or test path needs a PM amendment before editing. Do not edit backend/e2e/frontend-capabilities.json, capability reporter/schema machinery, backend routes/services/models, infrastructure, provider adapters, or configuration. Existing intercepted specs remain regression/visual checks only; the dedicated and canonical real-server journeys are the behavior authority.

Acceptance criteria

Newsletter chronology and recovery

  • Newsletter records render earliest publication first regardless of API order, grouped by the selected month/week with a stable same-date tie-break; filter/group changes preserve that chronology.
  • Semantic <time datetime> values, human campaign/booking labels, statuses, alert language, public campaign links, Add/Edit dialog, validation/conflict value retention, and Reconcile and close one Europe/Berlin business date #134 date bounds remain unchanged.
  • Initial Newsletter failure invents no records. A refresh failure after success preserves the last confirmed schedule as visibly stale/read-only context, identifies the unavailable source, retains current filters, and exposes one connected Retry newsletter schedule control.
  • Retry repeats the current query once, removes the stale/unavailable state on success, and neither duplicates rows nor performs a mutation.

Calendar desktop, mobile agenda, and source honesty

  • At 1440×900, Calendar retains the intentional seven-column month/week grid, Monday–Sunday/ISO-week semantics, activity filter, layer controls, holiday/activity/Newsletter distinctions, alert dismissal, and create/edit dialog.
  • At 390×844, the selected month/week is a one-column chronological agenda—not a horizontally scrolling seven-day strip. Dates, relevant items, status, and links follow DOM reading order; there is no hidden horizontal day content or page overflow.
  • The first meaningful current/next agenda date and its first item or honest empty decision are visible in the initial viewport after the page heading and compact controls. All controls and linked/actionable agenda items are at least 44×44 CSS pixels.
  • Overlay failure preserves successful Calendar activities/holidays, clearly labels only Newsletter dates unavailable, never presents zero as authoritative, and provides Retry newsletter dates for the same range.
  • Initial Calendar failure invents no records. A later Calendar refresh failure retains the last confirmed period as visibly stale/read-only context with selected view/filter/layers and a connected Retry calendar action.
  • Successful retries replace state once, remove the associated warning, restore overlays/calendar data without duplicates, and preserve Today/previous/next/week/month behavior under the Reconcile and close one Europe/Berlin business date #134 Berlin day.
  • Existing Calendar/Newsletter mutation, validation, conflict, dialog, route, focus, and history contracts remain unchanged.

Mailing Export next-action language

  • The existing server status and nextAction remain authoritative; no browser-only lifecycle or guessed provider success is introduced.
  • Human state labels and action instructions never expose raw enum/reason-code/storage/provider/credential identity as routine operator copy.
  • wait shows that the same durable run is still pending and labels its existing safe action Check status; it never claims a new export was requested.
  • retry labels the existing action Retry export and retains the same durable run key.
  • fix-authorization says authorization must be repaired through the approved external mechanism and labels the existing action Retry after authorization is fixed. Storage and Task-link repairs receive equally precise repair-first labels; no portal control claims to repair credentials, storage, or Task configuration itself.
  • download appears only for an authoritative completed run with an Artifact and is labeled Download private ZIP; nearby copy states that the authenticated link expires in five minutes. The UI claims preparation/success only after the existing download API succeeds.
  • Completed cards have no start/check/retry control; empty cards retain Start daily export; no-config remains non-actionable; later-page failures retain loaded history and precise retry.
  • All Automate private Mailchimp account exports and attach them to recurring work #108 privacy, idempotency, provider-limit, Artifact/Task relationship, controlled-download, and safe-failure tests remain green. No test or review calls an external provider.

Responsive, visual, and accessibility

  • At 1440×900 each surface has one dominant heading, adjacent description, content-width action hierarchy, and its first chronological decision visible without duplicated status/card chrome.
  • At 390×844 filters/actions/forms wrap in DOM order, dialogs remain within the viewport, controls meet 44×44, and there is no clipping, overlap, inaccessible off-canvas content, or page-level horizontal scrolling.
  • One owned page-heading contract, correctly nested period/date/history headings, semantic list/article/time/status/alert/dialog structure, native labels, and meaningful accessible names are retained.
  • Loading/progress uses role=status; blocking unavailable/mutation failure is announced; partial failure keeps successful content and names only the failed source. Status and next action are not conveyed by color alone.
  • Keyboard operation, visible focus, dialog containment/restoration, retry focus, 200% zoom, light/dark token hierarchy, and reduced-motion behavior remain intact.
  • Automated scans report zero critical/serious WCAG A/AA findings for every captured changed state.

Behavior, privacy, and parity

  • The engineer freezes HEAD plus binary diff, status, and candidate-content fingerprints before review; Designer, Tester, and PM use the same fingerprint.
  • A real local TypeScript server journey creates only synthetic records through normal authenticated APIs and exercises Newsletter chronology/recovery, Calendar desktop/mobile/overlay/full-failure recovery, and all Mailing next-action states without request interception for core behavior.
  • Deterministic local fault/provider-simulator controls may produce unavailable/run states, but there are no external provider calls, fixed sleeps, test-order dependencies, broad 404 swallowing, source-string assertions, incidental copy/whitespace pins, screenshot assertions, or screenshot goldens.
  • The normal full Playwright run emits passing evidence for every existing Newsletter, Calendar, and Mailing Export capability state and role; responsive-only assertions complement rather than replace durable state evidence.
  • Source, backend/dist, and packaged SAM frontend assets are identical for every changed asset; the normal source/SAM parity run accounts for all existing capability evidence and screenshots.
  • Fixtures, logs, screenshots, and comments contain only synthetic public-safe data: no provider execution, contact/audience data, production/private records, credentials, signed URLs, storage identity, private links, or operational artifacts.

Test scenarios

Shuffled Newsletter chronology

Given shuffled synthetic slots spanning month/week boundaries, including same-date records
When Newsletter loads and the operator switches grouping and filters
Then each visible group and row remains earliest-first with the documented stable tie-break, semantic dates and status stay correct, and the first actionable slot is not displaced by response order

Newsletter refresh outage and recovery

Given a confirmed visible schedule and current filters
When the next list request fails through the deterministic local fault seam
Then the prior schedule remains visibly stale/read-only, Newsletter alone is named unavailable, no false empty state appears, and Retry newsletter schedule repeats the same query once
When the fault clears
Then fresh rows replace the stale state once without duplication

Desktop Calendar and mobile agenda

Given synthetic activities, holidays, alerts, and linked Newsletter overlays across several dates
When Calendar opens at 1440×900 and then 390×844
Then desktop uses the existing month/week grid while mobile uses one chronological agenda in DOM order, the first meaningful date/item is visible, and there is no horizontal day strip or page overflow

Independent overlay outage

Given Calendar data succeeds and Newsletter overlays fail
When the period settles
Then activities and holidays remain usable, the overlay layer says Newsletter dates are unavailable rather than empty, and Retry newsletter dates restores links for the same range without re-creating Calendar records

Calendar refresh outage

Given a successful populated period and selected view/filter/layers
When a later Calendar request fails
Then the last confirmed period remains visibly stale and read-only with an announced Retry calendar action
When retry succeeds
Then the current period refreshes once, retained controls remain selected, and no record or mutation is duplicated

Exact Mailing next actions

Given synthetic no-config, empty, waiting, retryable failure, authorization failure, storage failure, Task-link failure, and completed runs returned by the normal local server/provider simulator
When the operator scans each card and invokes the available safe action
Then visible labels distinguish Start, Check status, Retry export, repair-first retries, and Download private ZIP; each existing action uses the same durable run key/endpoint, completed has no run action, and no secret/provider/storage identity appears

Source/SAM identity

Given the frozen accepted source candidate and a clean SAM build
When the same routes and existing durable states run from source and packaged targets
Then behavior evidence agrees, changed assets are byte-identical, and every expected source/SAM record is accounted for

Synthetic screenshot inventory

Capture exactly these 12 untracked native-size PNGs under .tmp/screenshots/issue-222/; delete stale extras before review:

  • 01-newsletter-chronological-ready-desktop-1440x900.png
  • 02-newsletter-chronological-ready-mobile-390x844.png
  • 03-newsletter-retained-unavailable-desktop-1440x900.png
  • 04-newsletter-retained-unavailable-mobile-390x844.png
  • 05-calendar-overlay-ready-desktop-1440x900.png
  • 06-calendar-overlay-ready-agenda-mobile-390x844.png
  • 07-calendar-overlay-unavailable-desktop-1440x900.png
  • 08-calendar-overlay-unavailable-agenda-mobile-390x844.png
  • 09-mailing-wait-retry-fix-auth-desktop-1440x900.png
  • 10-mailing-wait-retry-fix-auth-mobile-390x844.png
  • 11-mailing-completed-download-desktop-1440x900.png
  • 12-mailing-completed-download-mobile-390x844.png

Use the normal local server, deterministic local faults/provider simulator, and synthetic public-safe records. Tester and Designer inspect every image at native resolution for chronology, first-decision visibility, grid-versus-agenda behavior, state/action ownership, exact safe language, focus cues, target sizing, theme/contrast, overflow, clipping, overlap, and private-data leakage. Screenshots are visual evidence only: do not commit or publicly attach them, and do not use them as behavior/parity proof.

Required verification

Engineer may use focused commands while iterating. Independent Tester runs the complete relevant workflow on one frozen candidate and records commands, exit codes, observed counts, behavior titles, capability-state accounting, artifact/evidence paths, and every intentional skip:

node --test frontend/test/planning-surface.test.mjs frontend/test/finance-surface.test.mjs
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 -- e2e/issue-222-planning-presentation.spec.js e2e/canonical-capability-behavior.spec.js e2e/planning-surfaces-design.spec.js e2e/calendar-seams.spec.js e2e/newsletter-production-portal.spec.js --retries=0
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 #222 spec must be part of the normal full Playwright run. Existing canonical capability evidence remains authoritative for durable state IDs. Intercepted Calendar/Newsletter regression/design specs do not substitute for the real-server journey.

Lifecycle gates

No HUMAN gate is required for this local, synthetic, provider-free presentation slice. #108's separate real-provider HUMAN gates remain untouched and do not block local #222 implementation/review after #218.

Out of scope

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1ImportantdesignDesign and UXenhancementNew or improved functionalityfrontendFrontend UIportalShared portal shell and UXtestingTests and QA

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions