Skip to content

Part of the approved Iteration 2 design pack. Read together with design-decision.md, which records binding corrections and the O1–O5 dispositions.

Study management — decision log (Waves 3–5 handoff)

Grounded in source-truth.md (camaradesuk/syrf@main, cc271f478d03, read 2026-09-01). Status: Locked = build as specified · Wave 3 = specified, needs implementation decision detail · Open = needs product owner.

Structure and navigation

  • D1 · Three linked routes (Library / Searches / Processing) under one "Study management" sidenav group; below the wide breakpoint the three destinations use merged PR #2994's adaptive primitive (persistent rail ↔ sticky route-aware compact selector, content-driven breakpoint) — not a bespoke segmented-tabs variant (binding correction 3 in design-decision.md). Spine from Iteration 1 option A. Locked
  • D2 · Processing is read-only history. Commands stay with the owning page (upload/retry on Searches, bulk update on Library). Only Bulk PDF exposes cancel — the only family with a cancel/retry API. No cancel/retry is ever rendered for the other three families even in error states. Locked
  • D3 · Contextual summaries + deep links. Library and Searches show each relevant operation as a status strip with "View in Processing"; the deep link reveals the operation on Processing even when terminal and outside the default filter, with an info notice ("Showing the linked operation…") and a Clear action. Locked
  • D4 · Default filter = Active + Needs attention; "All operations" paginates completed history 25 rows at a time with an honest remaining count. Locked

Status language (shared StatusView contract)

  • D5 · One shared status-chip component across all four families, adopting the shipped Bulk PDF StatusView contract (kind: ok/stopped/warn/muted/info; honest bar modes; ariaValueText). Replaces Iteration 1's raw-hex dot/triangle chips. Locked
  • D6 · Deployed labels are reused verbatim where a deployed map exists (Search Import statusText, RoB statusMap, Bulk PDF status-presentation). Bulk Study Update has no deployed map outside the dialog → sentence-cased enum ("Validating on server") with raw enum + value in row detail. Locked
  • D7 · Unknown status values render "Unknown status (17)" with the raw value in detail — a deliberate divergence from Bulk PDF's "Status unavailable" fallback because the numeric value is diagnostic. Unknown never maps to Running. Reconcile in Wave 4 with the Bulk PDF owner (the fallback lives in Wave 4's project-admin/bulk-pdf-upload/** ledger).
  • D8 · Honest progress only. Determinate bars require a real numerator/denominator (e.g. verifiedPartCount/partCount); otherwise indeterminate with "progress not yet measurable" and aria "Working — no estimate available". Completion reports StudyUpdateParseResult matched/modified, never parsed-row counts; a 0-changed run says so explicitly. Locked
  • D9 · Missing data is named, not faked. Timestamps/initiators absent from DTOs (Search Import has LastModified only; RoB has no initiator; initiator can vanish for non-public members) render "Not available". Locked — the Bulk Study Update lastModified convention-mapping bug (year-one risk) is a Wave 1A backend fix (landed in PR #3052), not Wave 3 frontend work.

Processing table mechanics

  • D10 · Grouping: Needs attention (pinned, warning-tinted) → Active → Completed and other outcomes. Group headings carry counts. Locked
  • D11 · Fixed column grid at desktop: Type 118 / Operation flex / Status 170 / Progress 210 / Updated 128 / Started by 118 / link 96, with a labelled column header row; chips constrained to the 170px cell so variable label lengths cannot drift columns. Groups sit in contained, labelled horizontal scrollers (min-width 1060px) — the only 2-D scroll region (WCAG 1.4.10 table exception). Locked
  • D12 · Live updates: 4s poll/push cadence simulated; re-sorting is deferred while a row is expanded ("Order updates paused…" status) so open rows never jump. Reconnecting keeps rows visible and marks them stale. Locked
  • D13 · Bounded error lists: first 10 of N with honest head ("first 10 of 150, bounded"), scrollable, "Show all N" toggle. Parse-error kind (e.g. MalformedRecord) carries specifics; the family status stays the deployed "Error". Locked
  • D14 · Row detail exposes raw enum + numeric value, full UTC timestamps, initiator, job ID with Copy. Locked

Permissions and states

  • D15 · Server-filtered aggregate (ProjectDetails) with one loading boundary; the empty state means "none visible to you" and links to the owning pages. Load failure states "Your operations are unaffected" + Retry. Permission gates per family: ViewSearches/ImportSearch/RemoveSearch, BulkUpdateStudies, BulkPdfUpload, ViewStudies. Locked

Accessibility (see A11y Spec Board)

  • D16 · Contract implemented: polite live region per page, role=status notices, progressbar aria-valuetext per StatusView, aria-expanded rows, labelled focusable scroll regions, reduced-motion static indeterminate track. Locked
  • D17 · UI-wave additions: forced-colors CSS block, ≥44px touch targets below 600px, and deep-link focus ride Wave 3; the app-shell skip link rides Wave 5 (the sole route/navigation writer owns the shell touch). Wave ⅗

Open questions (Wave 4–5)

  • O1 · Should Expired Bulk PDF jobs (not terminal — cleanup pending) surface in Active or Needs attention? Prototype: Needs attention. Needs product confirmation.
  • O2 · Retry affordance for Risk of Bias timeouts — no API today; the note copy points users to launch a new calculation. Candidate Wave 4 API.
  • O3 · "Started by" column for families whose DTOs lack initiator — hide the column per family vs. "Not available"? Prototype shows "Not available" for consistency.
  • O4 · RoB "hide completed default on" behaviour from the existing table — subsumed by D4's default filter; confirm no user relies on the old per-table toggle.
  • O5 · Unknown-status fallback (D7) — align Bulk PDF's "Status unavailable" to "Unknown status (n)" or keep per-family? One rule should win in Wave 3.

Deliverables index

  • StudyManagement.dc.html — interactive prototype (routes, widths, scenarios, live simulation)
  • Artboards.dc.html — static frames: 3 routes × 1440/768/320 + Processing states (embeds the prototype; cannot drift)
  • A11y Spec Board.dc.html — reflow / forced-colours / screen-reader / keyboard spec
  • token-mapping.md — DS token → Angular M3 mapping
  • source-truth.md — status vocabularies and DTO truth per family