UX strategy for the integrated review programme¶
1. Purpose and status¶
Temporary planning document; planning only. This page is the end-to-end user-experience strategy for every screen the programme adds or changes, written to resolve the round-2 UX review (UX-01 to UX-22, its §3 strategy and §4 questions) and the UX-relevant findings of the other round-2 reviews (PH-13, PH-19, PH-35; review AC-17, AC-19, AC-27, AC-28, AC-29; SR-25; DD-11's user-facing glossary and Q-D4/Q-D5; V2-22, V2-25; RT-10, RT-14, RT-22; NS-07, NS-10, NS-13). Its changes to the other package documents have been merged into them: acceptance criteria §2 (AC-ALL-06 to AC-ALL-08; the AC-UX metrics in §2.3), §3 (UI-1 to UI-11 and the width matrix) and §5 (PE-05 and the user-testing tasks); contracts C17; open questions §3 (U30–U45 and the revised U6, U13, U16, U27) and §4 (A-24 rewritten, A-37, A-38); the integrated plan (R2a, R3a–R3c and R4a scope, §6.1 and §6.2 gates, §7, §9 and §10); and the UI comparison §2.3, §4 and §5.
Authority. Chris's 3 October decision UI1 (every new and updated screen is consistent, modern
and Material 3 under FEAT-023's contract; decision register §1.11)
is OWNER. The approved AF2 validation and presentation plan
(/home/chris/workspace/syrf/handover/2026-09-13-af2-validation-presentation-plan.md, approved
14 September) and the project-navigation handoff rev 2
(/home/chris/workspace/syrf/main/docs/features/material-3-migration/handoffs/project-navigation-drawer/README.md,
implemented by the navigation plan) are DOC-APPROVED inputs. Everything else here is
PROPOSAL unless it carries a ledger ID. Product choices that need Chris are cited by their
Batch D IDs from the round-2 brief (D1-06, D2-07, D2-08, D2-10, D2-12, D3-01 to D3-08, D3-15,
D3-17, D3-19, D3-20, D3-23, D4-01, D4-13, D4-18, D4-19); no new question IDs are minted here.
D1-06 (the tester panel) was approved as recommended on 3 October
(register §1.13), and Chris
named the panel late that evening (register §1.14;
§9); no external SyRF users are named yet. D4-18 was answered the same night ("independent of
funders"); its recorded reading keeps the independent WCAG 2.1 AA audit at GA and stays PROPOSAL
until Chris confirms it in the G0 dossier.
Code baseline. Current-UI claims were re-checked on main at de3e98c59 (3 October 2026):
| Claim | Evidence (/home/chris/workspace/syrf/main/…) |
|---|---|
No keyboard decision shortcuts exist on the reviewer page; no kbd hint renders |
src/services/web/src/app/stage/stage-review/review-decision-card/review-decision-card.component.spec.ts:391-392 ("No I/E shortcuts exist yet"); no keydown host listener under src/services/web/src/app/stage/ |
| The only onboarding is a one-shot hint with a "GOT IT" button; the public "What's new" is a marketing page | …/stage/stage-review/review-first-run-hint/review-first-run-hint.component.html:19-27; …/info/home/whats-new/ |
| Per-user review preferences and the My studies navigator already exist | …/stage/stage-review/review-preferences-dialog/, …/stage/stage-review/my-studies-navigator/ |
| AF2's action bar already says "Save progress" (compact "Save"), "Complete" and "Edit annotations" | …/shared/annotation/annotation-form-v2/annotation-form-v2.component.html:419, :466, :506 |
| Typed message constants exist for one feature; a help-URL guard spec exists | …/study-presence/session-messages.ts; …/shared/pipes/user-guide-url/no-hardcoded-help-urls.spec.ts |
| Shared shells and primitives exist: page shell and page state, section shell, overlay scroll, row overflow | …/shared/page-shell/, …/shared/side-nav/, …/shared/overlay-scroll/, …/shared/row-overflow/ |
| The e2e stack has no axe dependency and runs every Playwright project on Desktop Chrome | e2e/package.json (no @axe-core); e2e/playwright.config.ts:60-115 |
| The question-tree designer still uses native HTML5 drag events | …/project/project-admin/question-management/design/question-node/question-node.component.html:12 (dragstart); …/design/design.component.html:67-201 (dragover/drop); …/design/annotation-question-tree-drag-drop.feature.ts:125-226 (DragEvent, dataTransfer) |
No .browserslistrc; TypeScript target ES2022; no stylelint configuration |
src/services/web/tsconfig.json:42; absence verified by listing |
check:theme-migration scans M2 APIs, private Material paths and legacy Bootstrap imports only |
src/services/web/scripts/check-theme-migration.mjs:20-55 |
themeToggle defaults off and is on in staging |
src/charts/syrf-common/env-mapping.yaml:1467-1475; /home/chris/workspace/cluster-gitops/syrf/environments/staging/web/values.yaml:62, …/staging/api/values.yaml:91 |
| LogRocket and Google Analytics are configurable; Sentry is bundled | env-mapping.yaml:1563-1572, :2031-2036; src/services/web/package.json:60-62, :77-78 (runtime state per environment UNVERIFIED) |
| Debug panels render on reviewer-reachable routes | …/stage/stage-reconcile/stage-reconcile.component.html:4-17 (app-debugger-group), :18 (gdColumns); …/stage/stage-review/review-completed/review-completed.component.html:28-38 |
| Legacy project navigation keeps "Studies" and "Screening" sections | …/project/project-nav/project-nav.component.ts:438-548 (Screening info group visible: false at :519) |
| The project index has a "Pending Projects" tab and no cross-project work list | …/project-index/project-index.component.html:56-86 |
| The user guide still says "Save" and "Submit" in one place and "Save progress" and "Complete" in another; the screening progress copy says "Unavailable" | user-guide/annotating.md:239-249 vs :375-376; user-guide/stages/screening.md:37; user-guide/getting-started/glossary.md exists |
2. UX principles for SyRF¶
- Reviewer time is the scarce resource. Reviewers screen and extract for hours a week. Every change to the reviewer page is measured against today's time per decision and per form (AC-UX-03, AC-UX-04), and nothing reviewer-visible ships without a keyboard path.
- Independence and blinding are visible, never implied. Candidates never see each other (VS1 default off, BL1 aliases); the UI says when a view would make work "informed" (VS2) before the reviewer sees it; presence shows counts, not names (pending D3-20); decision buttons stay equal-weight so the interface does not nudge a decision (Review Prototype v4 correction 3).
- Honesty about state and versions. The four AF2 facts stay separate (answer progress, readiness, reveal, persistence). Copy never says "saved" for a kept draft, never "Completed" for an answer scope, never shows a count without a real numerator, and always says which version counts (SL3). Freshness is labelled, not assumed.
- Consistency and Material 3 (UI1). One design system of record (§4), one button and type language (D3-04), one copy deck (§5), and the same chrome in legacy and canonical projects (§3.4). A pattern is specified once and reused.
- Accessible by construction. WCAG 2.2 AA is the working standard (audited to 2.1 AA at GA, D4-18); keyboard, screen-reader, forced-colours, reflow and touch requirements are part of every pattern's specification, not a ship-gate afterthought (§8).
- Change is budgeted. Reviewers see at most three bundles of visible change before GA; each bundle ships with a "What changed" panel, a tour and help links (§12).
- Evidence, not opinion. Real reviewers test prototypes before freezes and releases before pilots; UX metrics are acceptance criteria with thresholds (§9, §10).
3. Information architecture¶
3.1 Project IA (C17) with My work¶
C17's navigation stands: Overview, Review, Reconcile, Design, Stages, Members & groups, Data,
Project settings; "Library" stays with Study Management. This strategy adds one surface and two
chrome elements (PROPOSAL, pending D3-07):
| Element | What it is | Release | Window |
|---|---|---|---|
| My work (project level) | The reviewer's and reconciler's landing inside a project: every actionable item by role, with the four feature-owned queues as filters and the inbox as history | R3c (badge, banner, "changes awaiting approval"); R4a (full surface, "assigned reconciliation work", "requested reviews"); R4b adds "my concerns and outcomes" | U30 in W1 |
| Global My work badge | An app-bar badge whose count is computed at read time over the four queues and the admission-based "to review" count, across projects; no notification flag involved | R3c | U30 |
| Cross-project My work tab | A tab beside "Pending Projects" on the project index listing actionable items grouped by project (the #2621 global landing stays post-GA with its own owner) | R4a | U30 |
| Admin banner | On a project overview, "N changes awaiting your approval" for pending LC1 requests, with every notification flag off | R3c | U30 |
| Workflow version badge and panel | A badge in the overview and rail naming the project's workflow version; a panel in Project settings (admitted or classic, read-only containment, who changed it, when) | R0 (panel), R2a (badge, banner) | U32 in W0 |
My work contents (by role). To review (studies available to you by step, with Start or Continue); Needs your attention (Needs updating, Outdated answers with Fix, kept changes whose slot was released); Reconciliation (assigned to you, available, held); Requested reviews; Your queries (concerns and their outcomes); Awaiting your approval (admins: LC1 change requests, a stalled publication). Counts are computed at read time; rows deep-link to the task identity (RE4) and use stage-owned aliases (BL1). An item resolved by someone else leaves the list but stays in history (pending D3-23). Empty states say why ("Nothing to review: this stage is waiting on other reviewers"). The inbox (when enabled) is delivery and history, never the source of truth (A-07).
Where the new PRISMA, deduplication and adoption surfaces live. Data › PRISMA (report views and the reported-counts entry, R5b; per-search external-step records are entered on the search's own page under Study Management › Searches, P1). Study Management › Processing shows deduplication runs as long-running operations (P2), and Study Management › Library gains the duplicate review queue and the merge or split wizard (P2; alias presentation pending D2-12). Adoption (R6) and the admission action (R0) live in Project settings › Workflow version; operator-only surfaces (adoption manifests, dry-runs) stay in the Admin Console.
3.2 Route inventory with an owner per route group¶
Following the M3 programme's "one owner per route group" rule. Paths marked (indicative) are
proposals; verified paths come from project-nav.component.ts.
| Route group | Routes | Mode | Owner | First release |
|---|---|---|---|---|
| Application chrome | app bar, My work badge, inbox button, help menu | both | M3 navigation owner (navigation plan slice 2); L16 for the badge | R3c |
| Project rail and footer checklist | rail sections per mode; setup checklist (readiness-based content from R2a) | both | M3 navigation owner; L16 supplies section models | R2a |
| Overview | project overview, admin banner, workflow version badge | both | L16 | R2a |
| My work | my-work (indicative) |
both (legacy shows the inbox-independent items it has) | L16 with L6 (reconciliation rows) and L4 (admission rows) | R3c, R4a |
| Review | stage review workspace (AF2, Dockview, step strip) | both | AF2 and stage-review programme; L5 lands programme changes in the agreed order | R2a onward |
| Reconcile | reconcile/… per study × form task (indicative) |
canonical | L6 | R4a |
| Design | questions, entity types, concepts & rules, outcome schemas, forms, screening profiles | canonical (legacy keeps the legacy editor) | L2; L9 (C1); L10 (O1) | R1a, R2a, R3b, C1, O1 |
| Stages | per stage: overview, steps & settings, monitor | canonical; legacy keeps today's settings | L4 (designer), L16 (overview DTOs) | R3a |
| Members & groups | members, groups, permissions | both | L8 with the authorization programme | R1b |
| Data | export, history, agreement, PRISMA | both (export); canonical (history, agreement, PRISMA) | L11; L12 (PRISMA) | R2a, R5a, R5c, R5b |
| Study Management | studies, searches, processing (verified) |
both | Study Management owner; L12 adds the dedup queue and merge wizard | P1, P2 |
| Legacy sections | screening/overview, admin/screening-settings (verified) and today's stage settings |
legacy only | unchanged owners; M3 restyle under D3-06 | GA (restyle) |
| Project settings | general settings, workflow version panel | both | L16; L0 (admission action) | R0 |
| Notifications | inbox, preferences | both | notification programme (M3 redesign before R2c, NS-10) | before R2c |
| Setup | guided setup wizard | canonical | L13 | R3d |
3.3 Workflow version badge and panel¶
- Names (
PROPOSAL, confirmed with D3-03): "Classic workflow" for legacy projects and "Versioned workflow" for admitted projects. "Canonical" and "legacy" never appear in the UI (DD-11 glossary). - Badge: in the overview header and as a rail footer line; text plus a shape, never colour alone; tooltip and panel link.
- Panel (Project settings › Workflow version): current version; what it means for this project (two sentences and a help link); admitted by whom and when; read-only containment state ("Reviewing is paused while this project is checked") with who set it and when; the audited admit or remove action for application administrators (R0). The panel is the admission and rollback UI that UX-18 found missing.
- Reviewer banner (read-only containment, U28): "This project is read-only while it is checked. Your changes are kept. Nothing you saved is lost." No edit control is enabled.
3.4 Legacy coexistence and the minimum shared chrome (D3-06)¶
Until adoption, a user who holds both kinds of project must still feel they are in one product:
| Identical in both modes | Differs by mode |
|---|---|
| App bar, My work badge, inbox, help menu; project rail geometry, colours, type and states; Overview layout; Members & groups; Data › Export page; Project settings; the workflow version badge; status chips, page shell, page state, long-running job language; copy deck terms | Rail sections: legacy keeps "Studies" and "Screening" and today's stage settings; versioned projects show Design, Stages, Reconcile and the Data subsections; the question editor's two modes (C17) |
Pending D3-06, legacy screens (chrome and shared pages, no behaviour change) are restyled under FEAT-023 so the atomic cutover covers them. U27 becomes a cross-project consistency check with a tester who holds both kinds of project (U45 extends it to the restyle).
4. Design system of record and pattern inventory¶
4.1 System of record¶
The design system of record is FEAT-023's emitted token contract (--mat-sys-* roles from
mat.theme() and documented --syrf-* brand or domain roles, measured by
src/services/web/scripts/token-contrast-contract.mjs) plus the shared Angular components:
shared/page-shell (page shell and page state), shared/side-nav (section shell), the project
navigation rail (navigation plan decision 2), shared/overlay-scroll, shared/row-overflow,
the StatusView chip contract (Study Management D5; kinds ok, info, warn, stopped, muted) and the
long-running-job visual language (docs/features/material-3-migration/technical-plan.md,
"Long-running-job visual-language contract"). Prototype kits (_ds React bundle, QM v2 HTML,
redesign v7, #2621) are design inputs; their token names are mapped, never copied (v10 README
"Design tokens"). A new shared token goes through FEAT-023's serial theme-contract change.
4.2 Button and type language (D3-04)¶
Pending D3-04: Material 3 sentence case for every label; button shape and radius from the M3
component theme as emitted, no per-feature radius overrides; no ALL-CAPS tracking; type from the
M3 type scale and the --syrf-space-* ladder (Study Management token mapping). The v4 stage-review
spec is re-audited against this before further parity work; items that change:
| v4 spec item | Under D3-04 |
|---|---|
| ALL-CAPS 13px/500 letterspaced buttons (corrections 3, 4, 11; "Design tokens") | Sentence case, M3 button type and shape |
| 4px button and input radii, 8px cards, hex values | M3 shape and colour roles; no literals (UI-1, UI-10) |
| "Unsaved changes" chip; footer "All changes saved" | Save-status indicator and copy deck terms (§6.4) |
| "Remove all annotations…" (destructive) | Versioned clear or "Discard kept changes" wording (AC-R2a-09) |
| Sidenav in-flow at 1200px | lt_lg edge (1239.98px) from break-points.ts |
Equal-weight outlined Include and Exclude with kbd hints |
Kept (deliberate non-nudging); hints render only once shortcuts exist (U33) |
| Anchored What's new tour | Kept as the shared tour component (§12) |
| Content threshold 980px of remaining width | Kept as a content-driven rule; verified at 925px (UI-6) |
4.3 Pattern inventory¶
Each pattern is specified once (states: hover, focus-visible, pressed, selected, disabled, error, loading, empty; tokens; keyboard model; narrow behaviour; copy keys), built once as a shared component, and shown on a spec gallery route behind a flag (E84). Status is per release; every pattern enters U43 before its first consumer builds.
| Pattern | Used by | States and tokens | Keyboard model | Narrow behaviour | Copy keys (deck) | First |
|---|---|---|---|---|---|---|
| Step strip | reviewer page (Q-12, U7) | selected, available, locked, done, skipped, held; --mat-sys-secondary-container selected; status by shape plus text |
[ ] move, Enter opens, roving tabindex |
collapses to a select-like menu below lt_sm |
steps.* |
R3a |
| Save-status indicator | AF2 action bar, reconcile host, setup wizard | Saving, Kept, Retrying, Offline, Failed, Saved, Completed (§6.4) | status is a polite live region; Retry is a button | icon plus short text below lt_sm |
save.* |
R2a |
| Conflict and take-over screens | reviewer and reconciler forms | read-only, take-over, stale base, copy kept (§6.5) | focus moves to the summary; one primary action | full-width card | conflict.* |
R2a |
| Status chips (StatusView kinds extended) | sessions, forms, versions, queues | Needs updating, Outdated answers, Held, In progress (saved), Kept changes, Completed, Unpublished, Current version, Published; each kind maps to an existing StatusView kind | none (chips are not targets) | wraps; never truncates the kind word | status.* |
R2a |
| Version badge | forms, profiles, sessions, stage settings | current, superseded, unpublished | tooltip on focus | text stays | version.* |
R2a |
| History timeline | history panel, gold history (4.4) | current, pinned inputs, policy-derived, withdrawn, inputs changed | list semantics; Enter opens a version | single column | history.* |
R2a, R4a |
| Candidate pills and agreement icon | reconciliation form (4a) | agree, differ, one-sided, N candidates with overflow menu; selector never hides a disagreeing candidate (U1) | arrow keys between pills; Enter copies an answer | selector plus single column | reconcile.* |
R4a |
| Prefill (autofill) marker | reconciliation form | prefilled, edited, accepted (RE2: no per-field confirm) | none; marker is described by the field's accessible description | unchanged | reconcile.prefill |
R4a |
| Impact flow scaffold (stepper) | publication, profile publication, stage settings publish | review, impact, choices, confirm; busy; blocked by stale evidence | stepper roles; Escape asks before discarding | one step per screen | publish.* |
R2c |
| Queue list (My work rows) | My work, pool, queues | actionable, waiting, held, resolved | list with row actions; Enter opens | cards below lt_sm |
mywork.* |
R3c |
| Workflow version badge and panel | overview, rail, settings | classic, versioned, read-only | panel is a page | text | workflow.* |
R0, R2a |
| What changed panel | app bar | unread, read, dismissed per user | dialog trap and return | full-screen sheet below lt_sm |
per-release keys | R2a |
| Anchored tour | reviewer page, reconciler page | step, paused, resumed | Esc pauses; arrows move; focus follows the spotlight | not shown below lt_sm (RP4) |
per-tour keys | R3a |
| Presence count chip | study header, pool | held, released, offline; counts only (D3-20) | none | hidden below lt_sm |
slot.* |
R2b |
| Progress vocabulary strip | reviewer progress, stage overview | your work, available to you, waiting on others, locked by a step, enough reviewers | none | wraps | progress.* |
R2b |
Keyboard hint (kbd) |
decision card, action bar | rendered only when the shortcut is live | n/a | hidden when a touch pointer is primary | keys.* |
R3a |
| Blinded bibliographic placeholder | screening card | hidden authors, journal, year with a reason line (SR-25, PROPOSAL) |
n/a | text | blind.* |
R3b |
Existing shared components are mandatory where they apply: app-page-shell and app-page-state
on every new admin page; the StatusView chip for every status; the long-running-job language for
every operation that can take more than a few seconds (publication phase 2, ASySD matching, as-of
export generation, O2 dry-runs, adoption waves), each with a place in Processing or a
release-owned surface (U40).
4.4 Handoff template¶
Every prototype pack ships with a handoff on this template, modelled on the navigation handoff
(docs/features/material-3-migration/handoffs/project-navigation-drawer/README.md):
- Why it changed (one paragraph; the decisions it serves, by ledger ID).
- Geometry (exact): widths, heights, radii, spacing from
--syrf-space-*. - Type and colour: a table of element → role (
--mat-sys-*or--syrf-*); no literals; a token-mapping table from the prototype's variables. - Data model: the DTO or store shape the pattern renders, including freshness labels.
- Behaviour: states, transitions, keyboard model, pointer and touch, narrow behaviour at the UI-6 widths, reduced motion.
- Copy keys: every string, by deck key, with the glossary term it uses.
- Accessibility: roles, names, live regions, focus order and return, forced colours.
- Acceptance checks: numbered, each tied to a defect found in review.
- Known gaps.
- Deviations log: filled by the implementing agent (file:line), as the navigation plan does.
- Audit against code: DONE, PARTIAL or NOT DONE with file:line, before building.
- Fixture data used: realistic open-licence abstracts and a 200-question form where relevant.
5. Copy deck and glossary¶
5.1 Mechanism (E83, F1c)¶
- One copy deck document in the programme's feature folder under
docs/features/(copy-deck.md,PROPOSALlocation), with one definition per term, its internal name (DD glossary), where it appears, and "never use" alternatives. - Typed message constants per feature (
<feature>-messages.ts,as const), followingsrc/services/web/src/app/study-presence/session-messages.tsand the session copy review. Core verbs and terms live in one shared constants file consumed by every feature. - A guard spec over the programme's folders fails when a template or constant uses a banned
string ("Save draft", "All changes saved", "Submit", "Gold standard" as a bare label, "Outcome"
for a screening result, "Unavailable" for progress, "canonical", "legacy") or hard-codes a core
verb instead of importing it; modelled on
no-hardcoded-help-urls.spec.ts. - User-guide glossary parity: every deck term marked
glossarymust have an entry inuser-guide/getting-started/glossary.md; a docs script checks it in CI. The guide's "Save"/"Submit" wording (annotating.md:239-249) is corrected in the R2a docs PR. - Validation: a terminology card sort in W0 (U42) before the deck freezes at F1c.
5.2 Terms and verbs (D3-03, Q-D4, Q-D5, DD-11)¶
| User-facing term | Meaning | Internal name | Never use | Label |
|---|---|---|---|---|
| Save progress | Create an immutable incomplete version that becomes current | SaveSession |
Save, Save draft | pending D3-03 (already shipped in AF2 and the guide) |
| Complete | Validate and create an immutable completed version that counts | CompleteSession |
Submit, Finish | pending D3-03 |
| Changes kept, not yet saved | The autosaved draft is held on the server; it is not a version | SessionDraft |
Saved, Draft saved, All changes saved | pending D3-03 |
| Needs updating | An answer invalidated by a publication choice; blocks Complete until valid | policy requireReanswer |
Invalid, Stale | pending D3-03 |
| Outdated answers | A session pins a superseded shared revision; a warning that never blocks alone | SF5 flag | Contains outdated annotations (DTO wording only) | pending D3-03 |
| Fix | Create a current incomplete version from an outdated session and open it | FixTransition |
Repair, Reopen | pending D3-03 |
| Update to version N | Move a session to the current form version (Upgrade transition, VA-10) | Upgrade | Migrate, Rebase | PROPOSAL |
| Accepted answers (gold standard) | The reconciler's authoritative answer set; "(gold standard)" in help text on first use | StudyGold, GoldSnapshot |
Gold as a bare label, Reconciled answers as a status | pending D3-03 (Q-D4) |
| Screening result | The collective result for a profile (Pending, Conflict, Included, Excluded) | ScreeningOutcome |
Screening outcome (UI), Outcome | pending D3-03 (Q-D5) |
| Your decision | A reviewer's own Include or Exclude (or Unsure if D4-01) | ScreeningDecision |
Vote | PROPOSAL |
| Outcome measure, outcome data | Measured outcomes and their series | OutcomeMeasure, Observation |
Outcome for screening | DD glossary |
| Query, concern, resolution | A challenge to an accepted answer and its per-raiser result | Concern, ConcernResolution |
Outcome for a query | DD glossary |
| Publish (a form or profile version) | Make a version current with a recorded impact choice | FormVersionIssue, ProfileVersionIssue |
Release, Deploy | DD glossary |
| Unpublished | A form, profile or question version not yet published; editable until first use | draft definition | Draft | PROPOSAL (PH-19) |
| Review (your review of a study) | A reviewer's work on one study and one form, across stages | FormSession |
Session | PROPOSAL |
| Step | One unit of a stage's workflow (screening, form or both) | ReviewStep |
Task, Phase | ledger DP6 |
| Screening profile | Profile-owned eligibility questions and rules | ScreeningProfile |
Rationale, Criteria set | DP4 |
| Primary and secondary study (duplicates) | Merge as alias; records keep their own study | StudyAlias |
Canonical study | DD glossary, pending D2-12 |
| Classic workflow, Versioned workflow | A project's mode before and after admission | CanonicalEnrolment |
Legacy, Canonical, New | PROPOSAL (§3.3) |
| Review slot | The reviewer's right to review a study for a form; held while active | SlotReservation |
Spot, Reservation, Session | shipped (session-messages.ts), RT-22 |
| Enough reviewers | The study has the reviews it needs for that step; no new slot | capacity | Unavailable, Sufficiently screened, At capacity | RT-22, UX-22 |
| Released | The slot is no longer held (idle or offline timers lapsed) | expiry | Expired, Removed | RT-22 |
| Offline | The browser cannot reach SyRF | connection state | Disconnected from the server | RT-22 |
| Informed, independent | Whether a contribution was made after seeing accepted answers (VS2) | ExposureState |
Contaminated | VS2 |
| Held | Reconciliation work waiting on a compatibility decision | task held state | Blocked | v10 §3 |
| Accepted copy, Copy from another tab | A draft kept from a non-holder tab after take-over (§6.5) | conflict copy | Conflict | PROPOSAL |
Distinct terms for each kind of draft (PH-19, ADR-010's five conflated drafts): reviewer autosave = "kept changes"; explicit incomplete version = "progress saved" or "In progress (saved)"; reconciler autosave = "kept changes" (same machine); correction in progress = "Correction in progress" (v10 r5); unpublished definition = "Unpublished"; resumable setup = "Setup in progress"; conflict copy = "Copy from another tab". The word "draft" appears only in the deck's internal-name column.
Readiness vocabulary (approved AF2 four-state model, PH-19; DOC-APPROVED). Answer scopes
(categories, entities, branches, steps) use exactly the four approved states and their
precedence: Needs attention (a revealed applicable issue), Ready (every applicable
completion requirement met), In progress (some meaningful answers, work remaining),
Not started; "No applicable questions" is handled before them, and 0/0 counters are hidden.
"Ready" is for answer scopes; "Completed" is reserved for the persisted review lifecycle. Counts
are named ("1 of 3 required answered"). The programme extends the model with two scope-level
markers that never change a state's meaning: Needs updating (a publication choice invalidated
an answer; shown as Needs attention with its own wording) and Outdated answers (a shared
revision was superseded; a warning that never blocks alone). Status glyphs are shape-distinct
with contextual accessible names, never colour alone.
5.3 Reviewer progress vocabulary (UX-22)¶
| Term | Replaces | Where |
|---|---|---|
| Your work: N in progress, N completed | "Incomplete studies" headings | My work, My studies navigator, stage progress dialog |
| Available to you | "Studies to screen" | progress strip |
| Waiting on others | (none; today shows "Unavailable") | progress strip, My work empty state |
| Locked by a step | (new, R3a) | step strip tooltip, My work |
| Enough reviewers | "Unavailable", "sufficiently screened" (user-guide/stages/screening.md:37) |
progress strip, slot copy |
5.4 Slot and presence copy (RT-22, D2-07, D3-19, D3-20)¶
Pending D2-07's recommended rule (held while active under today's idle and disconnect timers counting draft activity; released when they lapse with the draft kept; Complete still allowed as an extra contribution unless an optional capacity cap applies, D3-17):
| State | Copy (Comfort, Explain, Act) |
|---|---|
| Held | "Your review slot on this study is held while you work. Your changes are kept as you go." (status line only; no banner) |
| Idle warning | "You haven't done anything here for a while. Your slot will be released in [countdown], but your changes are kept." |
| Released, slot still available | "Your review slot was released while you were away. Your changes are kept. Continue to take a slot again." |
| Released, enough reviewers, no cap | "This study now has enough reviewers. Your changes are kept, and you can still complete this review as an extra review." |
| Released, enough reviewers, cap applies | "This study now has enough reviewers, so this review can't be completed. Keep your changes or discard them." [Keep] [Discard…] |
| Dependent step refused at Include (D3-19) | "Your Include is recorded. This study already has enough reviewers for [step]; nothing more is needed from you here." |
| Offline | "You're offline. Changes are kept on this device until you reconnect. Your slot is held for [countdown]." |
| Presence (D3-20) | "N reviewers on this study now" (count only; names only in Monitor for capability holders; never shown in reconciliation) |
| Reconciler editor claim refused (X-RECLAIM) | "Someone else is reconciling this study right now. Choose another study or come back later." |
5.5 Error and recovery copy for typed conflicts (UX-17)¶
Every typed outcome names what moved, what is kept and one primary action. All strings come from the deck; focus moves to the summary; nothing is lost silently.
| Typed outcome (C18) | What the reviewer sees | Options | Preserved |
|---|---|---|---|
| Stale base (Save or Complete on a superseded draft etag or base) | "A newer version of this review was saved, perhaps in another tab. Your changes here are kept as a copy." | Open current version (primary); Compare copies | Both: the current version and the copy |
| Two-tab lease (second tab opens) | "This review is open in another tab or on another device." | Take over editing (primary); View only | The other tab's edits become a copy on take-over |
| Lease lost (this tab was taken over) | "Editing moved to another tab. Changes you made here since [time] are kept as a copy." | Reload; Compare copies | The copy |
| Retryable conflict or outcome unknown | Save-status Retrying; after exhaustion, Failed with Retry | Retry; keep working | Kept changes on this device |
| Locked, fenced, publication in progress (D2-10) | "This form is being updated. Reviewing resumes in about [n]. Your changes are kept." with a progress line | Wait; go to My work | Draft |
| Size limit exceeded (E28) | "This review is too large to keep in one piece. Save progress now to keep what you have." | Save progress (primary) | Draft up to the limit |
| Conflicted legacy answer | "Two earlier answers to this question disagree. Choose which to keep." | Choose; keep both visible in history | Both revisions |
| Held for compatibility (R4a) | "This study is held until an administrator decides whether versions are compatible." | Open another task | Nothing changes |
| Revoked access | "You no longer have access to this project." (inbox: "Related item unavailable") | Go to My work | Drafts retrievable by owners (AC-ALL-18) |
| Admission refused, feature unavailable | "This isn't available in this project yet." | Back | n/a |
| Read-only containment (U28) | §3.3 banner | None; nothing is editable | Everything saved |
| Enough reviewers (AtCapacity) | §5.4 | Keep or discard | Kept changes |
6. Reviewer efficiency¶
6.1 Keyboard screening path (UX-02, PH-35; R3a/R3b scope, E87)¶
Moved into this plan's scope at R3a (default profile without eligibility questions) and R3b (profiles with eligibility questions), because they belong to the screening renderer and step strip that F5 owns, not to the AF2 parity join. Pending D3-05 the same path works on a phone for title and abstract steps.
| Situation | Keys | Actions per decision |
|---|---|---|
| Plain profile (no eligibility questions, reasons off) | I include, E exclude; auto-advance follows the review preference ("open the next study" default) |
1 |
| Reasons required on Exclude (DP5) | E, then a reason by number key or arrows and Enter |
2 |
| Derived decision (DP3, profiles with eligibility questions) | answer questions by number keys or arrows; the derived decision and its reasoning update live but never vote; Enter submits | answers + 1 (the submit is the decision) |
| Unsure (if D4-01 approves) | U as a third decision key where the profile allows it; "Unanswered only" moves to Shift+U |
1 |
| Skip without deciding (RC6) | N |
1 (records nothing) |
| Navigate | J jump to next required, [ ] previous or next step or category |
n/a |
Rules: keys are ignored while a dialog, menu or text field is active; the decision card shows
kbd hints only once the shortcut is live (review-decision-card.component.spec.ts:391-392);
under DP3 the I and E keys are inert and the hint reads "Answer the questions; Enter
records your decision", so one key never contradicts a derived decision (PH-35); every key has a
visible button equivalent; a 390px phone shows the same card with 44px targets and the keyboard
hidden (U33). The ≤2 actions rule counts actions beyond answering eligibility questions.
6.2 Live completeness and jump¶
Every form host (reviewer, reconciler, setup wizard) shows "N required missing · Jump to next"
in its action bar while incomplete (grey pending; error only after a rejected Complete), per
Review Prototype v4 and the approved AF2 plan's summary pattern. Jump opens the right step,
category, branch and entity, waits for the target to mount and focuses the control. The
reconciler's count reads "N to resolve" (v10 §7). Validated in U34.
6.3 Input latency under autosave¶
Autosave never blocks input. Draft serialisation and the write happen off the input path
(debounced; PROPOSAL 2 s per AC-R2a-28); the per-holder write sequence makes duplicates
harmless (brief §1.8). Budget: keystroke-to-paint p95 under 50 ms at 200 and 1,000 questions on
the AF2 perf spec's reference profile (e2e/tests/perf/annotation-form-perf.spec.ts), measured
with autosave on (AC-UX-04).
6.4 Save-status state machine (UX-04)¶
One quiet status in the action bar; one polite live region; no toast per autosave; the dirty navigation guard arms on any kept change that has not reached the server.
| State | Trigger | Copy | Announce | Actions |
|---|---|---|---|---|
| Clean | no change since the last version | "Progress saved [time]" or "Completed" | no | none |
| Saving | a change is being kept | "Keeping changes…" | no | none |
| Kept | the server acknowledged the draft (etag advanced) | "Changes kept, not yet saved" | once per editing session, not per keystroke | Save progress, Complete |
| Retrying | a retryable error or outcome unknown; same write sequence resent with backoff | "Trouble keeping changes. Retrying…" | once | none; input continues |
| Offline kept on this device | navigator.onLine false or health probe failing; changes written to a bounded local copy (IndexedDB) |
"You're offline. Changes kept on this device." | once | none; input continues |
| Failed | retries exhausted or a non-retryable typed outcome | "Changes couldn't be kept on the server. They're still on this device." | once, with focus to the status on an explicit Save or Complete | Retry; Save progress stays available when the server returns |
| Reconnected | connectivity restored; local copy replayed in sequence | "Reconnected. Changes kept." | once | none |
Rules: the local copy replays only while the server draft etag is the one it was based on;
otherwise it becomes a "Copy from another tab" (§6.5) and is never applied silently; Save
progress and Complete present the draft etag and consume the draft atomically; a stale autosave
arriving after a newer explicit version is discarded by the client (brief §1.8). Harvested from
QM v2 §14 (.local/qm-designer-handover/04-versioning-and-publishing/publishing-versioning-ux.md:845-928)
with the states renamed to the deck. Validated in U31; AC-UX-06 covers recovery.
6.5 Conflict screens¶
- Two-tab take-over (RT-10, D2-08): the second tab opens read-only with a banner and "Take over editing"; take-over transfers the lease by stable client tab ID; the displaced tab is told why, keeps a local copy until reload, and its unsaved edits are kept server-side as a bounded conflict copy ("keeps both" is literal). Copies appear in the history panel with timestamps; the reviewer chooses "Use this copy" or "Discard copy" (audited). Works with tracking off.
- Stale base: §5.5 row 1. The screen shows both timestamps, which tab or device made them when known, and a per-question comparison for small forms (a count plus "Compare" for large).
- Enough reviewers after a released slot: §5.4; a draft never holds a slot for days (D2-07).
7. Key flows¶
7.1 Reviewer screening and annotation¶
Study header (title, position, chips: Your decision, Completed, In progress (saved), Kept changes, Needs updating) → step strip (R3a) → one form area for the selected step → decision card (equal-weight Include and Exclude; derived decision with reasoning under DP3; reasons under DP5) → action bar (Revert, N required missing · Jump, Save progress, Complete) → save-status line. Needs updating shows beside each affected question with "Why it changed" and "What to do differently" (VU2); Complete is refused until valid, with the summary focused (approved AF2 plan). Outdated answers show a non-blocking warning with Fix (R2d). Presence shows counts only. The history panel lists versions, kept copies and policy-derived revisions with provenance.
7.2 Fix, Upgrade and Needs updating¶
| Situation | What the reviewer sees | Action | Result |
|---|---|---|---|
| Publication chose requireReanswer | "Needs updating" chip on the session in My work and on the question in the form; blocks Complete | Answer; Complete | A new version pinned to the current form version |
| Publication chose doNothing; session pinned to an older version | Version badge "On form v1 (current is v3)" with "Update to v3" | Update to v3 (Upgrade, VA-10) | A current incomplete version with unchanged answers carried where compatible |
| A shared answer changed elsewhere (SF5) | "Outdated answers" warning on the session; Complete still counts (AC-R2d-05) | Fix | A current incomplete version opens; the outdated answers are marked |
| Fix on a session pinned to a Completed stage (LC1) | "This stage is complete. Your fix will wait for an administrator." | Request the change | A pending request in "changes awaiting approval"; the reviewer sees its state in My work |
7.3 Reconciler end-to-end journey (UX-14)¶
Pool (KPI cards, Start reconciling, assigned-first then random eligible as the next-task rule,
PROPOSAL) → task header (how assigned, "Reviewers blinded", editor claim held) → screening
part first (RX1, R4p: decisions, reasons, must-agree answers) → matching (3a; drag with CDK
pointer events plus a keyboard "Pair with…" path) → form part (4a: pills, agreement icon,
autofill marker, "N to resolve", Complete anyway after the unseen-control warning) → Complete
(gold snapshot) → next task (same rule) or back to pool.
- Narrow layout: below
lt_mda candidate selector plus a single column; disagreeing candidates are never hidden by the selector; the side-by-side view is desktop-only. - VS2 disclosure (U16): before accepted answers are shown to a candidate under VS1 on, a one-time interstitial: "You are about to view accepted answers for this study. Your contribution will be recorded as informed." [View accepted answers] [Not now].
- Release and reacquire (RA3, RA4): copy in the deck; an admin release keeps saved work.
- Validated as U36 (journey) with U1, U4, U16, U20 as its parts.
7.4 Admin publication as a staged flow (UX-10)¶
Replaces "one dialog combining five concerns" with a four-step flow on the impact scaffold:
- Review changes: changed questions grouped by category (FEAT-003 categories, PH-18) with the system-suggested compatibility and the admin's confirmation (D2-02).
- Impact summary: per prior version and per bound stage, the counts of completed, saved-incomplete and draft-only sessions, with freshness labels and the stale-evidence gate.
- Choices with defaults: per changed question, requireReanswer, autoUpdate (within a compatible class only) or doNothing, with within-session conflicts resolved explicitly; a "what reviewers will see" preview renders the form with Needs updating markers for a sample session in each category.
- Confirm: a dry-run summary table (sessions affected per choice, notices to be sent once per recipient, time estimate for phase 2); the preview digest is re-checked and the admin re-confirms if it changed (brief §1.1).
After confirm: a long-running operation row (phase 2 progress with a real numerator) and, where admission pauses (D2-10), the reviewer-facing pause copy. Prototyped on a realistic fixture (10 changed questions, 3 stages, 200 sessions across the three categories); comprehension criterion in AC-UX-02. Validated in U6 (revised).
7.5 Stage designer and step strip¶
The v10 r2 steps editor in a tabbed layout (U12): steps, dependency edges separate from display order, the effective-policy preview backed by the real admission service, cycle rejection, EW1, VS1, BL1 and lifecycle mode; versioned settings publish uses the same impact scaffold. The reviewer sees the result as the step strip (U7, Q-12).
7.6 Lifecycle approvals¶
Changes awaiting approval (R3c) appear in My work and the admin banner; the approve dialog (U10) shows the specific change, its effect on readiness and shared work, and "approved by you" or "decided by [alias]" once another admin acts (pending D3-23).
7.7 Guided setup with an interim checklist (UX-19)¶
R2a replaces the footer checklist's content with readiness-based tasks (profile, form, step, members) while keeping its placement and interaction (21 September decision). R3d's guided route (U11, prototyped in W1) is measured by AC-UX-07: a new admin reaches a screenable stage from templates in 20 minutes or less without help.
7.8 Exports and PRISMA¶
The export page gains a Current, Previous versions, As of date selector with manifest download and per-dataset coverage labels (U22); unmasking follows the disclosure contract (U26). PRISMA views under Data show the diagram, reported external counts marked as reported, coverage and lower bounds for adopted projects (U23).
7.9 Notifications versus work queues (NS-07, NS-10, NS-13)¶
My work is the source of truth; the inbox is delivery and history. The notification stack's
inbox and preferences screens meet UI-1 to UI-11 before testers see them and the conversation,
issue and PDF screens before production (pending D3-01), through a Material 3 inbox redesign PR
before R2c (NS's evidence for the current inbox is in the stack worktree, CODE-PR,
not re-read here). Flood controls before R2c: mark all read; project and kind filters; a context
line from the resolver; "hide unavailable"; an unread count that excludes resolved items (D3-23);
digests grouped by project and kind; jittered refetch with per-request authority memoisation;
older publication notices for the same form marked superseded. Emails name the project only
(pending D3-22).
7.10 Admission and pilot operations¶
The workflow version panel (§3.3) is the admit or remove screen; the read-only containment banner is what reviewers see after a rollback (U28, U32).
8. Accessibility standard and harness¶
8.1 Standard¶
WCAG 2.2 AA is the working standard (PROPOSAL): it adds the criteria this programme needs anyway
(focus not obscured, dragging-movement alternatives, minimum target size, consistent help). The
GA audit is to WCAG 2.1 AA with an independent auditor (D4-18); 2.2-only criteria are reported
separately.
8.2 Harness (E85, L17, W0 and S0)¶
| Element | Implementation | Evidence |
|---|---|---|
| axe in journey specs | @axe-core/playwright added to e2e/; a per-route check with a committed baseline; journey specs call axe at named states (form open, failed Complete, conflict, dialog open) |
zero serious or critical (AC-UX-09) |
| Screen-reader matrix | NVDA with Firefox and Chrome; VoiceOver with Safari (macOS); VoiceOver with iOS Safari for phone screening only (D3-05); run at staging acceptance by a named person on the release's main tasks | checklist signed per release |
| Keyboard-only journeys | the release's main tasks completed by keyboard alone with visible focus; transcript attached | per release |
| Live regions | one polite region per page for save status, conflicts and status; one announcement per outcome; never per keystroke or per tab change; assertive never for autosave | pattern spec |
| Focus management | focus to the validation summary on a failed Complete; dialog trap and return; take-over moves focus to the banner; Jump focuses the control | pattern spec |
| Forced colours | Playwright forcedColors: 'active' screenshots on the five key surfaces; transparent outlines beside box-shadows (navigation plan decision 5) |
tier-1 matrix |
| Reduced motion | every transition honours prefers-reduced-motion; static indeterminate tracks (Study Management D16) |
guard in pattern specs |
| Zoom and reflow | 200% zoom and 400% reflow at 320 CSS px with no page-level horizontal scroll; short-height layouts (1280×600) keep the action bar reachable | UI-6 matrix |
| Touch targets | 44 px or more below 600 px (Study Management D17); 24 px minimum everywhere (WCAG 2.2) | tier-1 check |
| Contrast | pnpm run check:contrast in both layers; status never by colour alone |
per PR |
8.3 Browser and device matrix (PH-13, review AC-19, D3-15)¶
| Browser | Coverage | Lane |
|---|---|---|
| Chromium (Desktop Chrome) | full E2E, perf, axe | existing projects |
| Firefox | smoke journeys: reviewer screening and annotation, reconciler task, publication flow, My work | new Playwright project on the smoke label |
| WebKit | the same smoke journeys plus phone screening at 390 px with touch | new Playwright project |
| Touch (iPad, phone) | pointer-based CDK drag only; native HTML5 drag is banned in programme folders by a guard spec; the question-tree designer moves to CDK before R1a ships (question-node.component.html:12) |
R1a precondition |
| Browser floor | commit a .browserslistrc, lower the TypeScript target and add the needed polyfills (the May analysis's BUILD.F1 to F3) before R1a |
programme-integration item; recorded here as part of E85 |
Pending D3-15 for the Firefox, WebKit and touch acceptance rows.
9. Research plan with real users¶
| Study | When | Who | Method | Measures |
|---|---|---|---|---|
| Baseline of today's screening and annotation | W0, before the R2a build | 6 to 8 reviewers across the reviewer and admin roles (panel per D1-06), at least two external SyRF users (D3-08) | Moderated think-aloud on staging, production-equivalent configuration (AF2 off) and, as a second reference, AF2 and the redesigned shell on; realistic open-licence content | Time per title and abstract decision; time per 30-question form; actions per decision; confusion points; SUS; a review of support requests and the FAQ |
| Formative, per freeze gate | W0 to W3, one pack per gate (F1c: reviewer states, forms, history, export disclosure, My work, slots; F2: publication flow; F3: step strip, stage designer, route messages, Skip; F4: N-candidate workspace, matching, assignment, queries; F5: screening renderer, DP2 correction; F6: as-of export, PRISMA; F-C and F-O: cohort chip, schema authoring; R3d: guided setup) | 5 or more per affected role, at least two external | Prototype pack with handoff; tasks mirror the §5 explain questions | AC-UX-01, AC-UX-02 on the prototype; pass bars in §11 |
| Summative, per release | Before each ship gate | The tier's panel (five for T1, three elsewhere, D1-06) | Staging with the seeded pilot projects plus one realistic-content project | AC-UX-01 to AC-UX-09 |
| Pilot diaries | During each staging and production pilot | Pilot project members | A two-week diary (three questions a day) or weekly 20-minute interviews | Pain points to the backlog; PE evidence |
| Terminology card sort | W0 | 8 to 12 participants across roles | Closed card sort of the deck terms against meanings; "which version counts" vignettes | ≥ 80% agreement per core term; U42 |
| Instrumented timing on pilots | From R2a pilots, if D3-08 approves | Pilot projects, opt-in at admission | Privacy-safe events: study opened to decision; form opened to Complete; actions per decision; no content, no identifiers beyond a per-project hash | AC-UX-03, AC-UX-04 at pilot scale |
The tester panel (D1-06, named by Chris on 3 October 2026; register §1.14). T1 releases: Gillian Currie, Alexandra Bannach Brown, Francesca Tinsdeall, Chris Sena and Nadia Soleman. Other releases: Gillian Currie, Alexandra Bannach Brown and Francesca Tinsdeall. No external SyRF users are named yet; D1-06 asked for at least two "where possible", so the baseline and formative rows' external participants are still to be recruited (D3-08).
Consent and data handling. A short consent text in the session invite and in the pilot
admission step; session notes and derived metrics only; recordings optional, stored on CAMARADES
storage and deleted after 90 days (PROPOSAL); sessions use the open-licence seed project, never
a live review; no clinical, report or participant data in notes or events. LogRocket session
recording and Google Analytics are not used for UX metrics; the LogRocket flag stays off for this
purpose (UX-21).
Realistic content. L17 builds a "Realistic content (open licence)" seed project from openly licensed abstracts and full texts so that screening-speed findings transfer, alongside the seeded pilot projects in acceptance criteria §6.
10. UX metrics and acceptance¶
Thresholds are PROPOSAL until confirmed at the consuming freeze gate; telemetry rows apply only
if D3-08 approves. PE-05 is redefined as AC-UX-01 and AC-UX-02 being met for every user-testing task of the release.
| ID | Criterion | Verified by | Applies to |
|---|---|---|---|
| AC-UX-01 | Task success: at least 80% of testers complete each release task in §5 of the acceptance criteria without help | UT | every user-facing release |
| AC-UX-02 | Comprehension: at least 80% of testers answer each explain question correctly against its model answer (which version counts; why a study is offered or locked; what an accepted answer rests on; what a publication will do) | UT | R2a, R2c, R3a, R3b, R4a, R5a, R5b and every release with an explain task |
| AC-UX-03 | Screening throughput: median time per title and abstract decision and median actions per decision on the realistic-content project are no worse than the baseline study; a keyboard-only path exists with at most two actions per decision beyond answering eligibility questions | UT, E (keyboard), telemetry if D3-08 | R3a, R3b, then every release touching the screening card |
| AC-UX-04 | Annotation: time to complete the baseline 30-question form is at most the baseline plus 10%; keystroke-to-paint p95 under 50 ms with autosave on at 200 and 1,000 questions | UT, B | R2a, then every release touching the form |
| AC-UX-05 | Reconciliation: median time per three-candidate study is at most 1.5× the two-candidate task on the same build | UT | R4a, R4p, R4c |
| AC-UX-06 | Error recovery: every tester recovers from a two-tab take-over, a stale base and a 60-second offline interval without losing an edit made before the event | UT, E (network throttling) | R2a, R4a |
| AC-UX-07 | Setup: a new administrator reaches a screenable stage from templates in 20 minutes or less without help | UT | R3d |
| AC-UX-08 | Satisfaction: SEQ at least 5.5 per task, or SUS at least 70 per role per release | UT | every user-facing release |
| AC-UX-09 | Accessibility: zero serious or critical axe findings on the release's routes; the main tasks complete by keyboard alone; the screen-reader checklist passes; forced colours and 400% reflow pass on the five key surfaces | A, E | every release |
11. U-validation schedule¶
Rule: every U runs in a window at least one before the build that consumes it, and the consuming freeze gate's exit evidence lists it as passed. "Passed" means: the U's tasks meet AC-UX-01, its explain questions meet AC-UX-02, no unresolved severity-1 usability finding (lost work, a wrong decision, a disclosure), the keyboard path and screen-reader meaning are present on the prototype, and every string comes from the deck. Per-U specifics follow. One documented exception: R1a and R1b build in W0 (plan §7) and nothing is prototyped before G0, so U19 and U8's visibility part run first in W0 and the R1a and R1b UI slices build after they pass, within the same window; their later parts (U8 dialog and delegation) keep the one-window rule.
| U | Window | Consuming build (window) | Gate exit | Tasks and explain questions | Pass bar specifics |
|---|---|---|---|---|---|
| U1 | W0 prototype; W2 validation | R4a (W3) | F4 | Reconcile a study with three and four candidates; explain why a candidate is hidden or not | AC-UX-05; no disagreeing candidate hidden in any test |
| U2 | W1 | R3a (W2) | F3 | Skip a step; explain what was recorded | 100% say "nothing" |
| U3 | W0 | C1 (W1) | F-C | Select cohorts without losing place | AC-UX-01 |
| U4 | W1 | R2d (W2), R4a (W3) | F2 (Fix part), F4 | Fix an outdated session; see the unseen-control warning and Complete anyway | AC-UX-01; warning list with jump links used by ≥ 80% |
| U5 | W1 | R2c, R3a (W2) | F2, F3 | Wait through a publication pause; read a route-change message | no tester infers another reviewer's vote |
| U6 (revised) | W1 | R2c (W2) | F2 | Predict a publication's effect on each session category from the staged flow | AC-UX-02 per category |
| U7 | W1 | R3a (W2) | F3 | Use the step strip versus card-per-step | preference and AC-UX-03 |
| U8 | W0 (visibility), W1 (dialog), W2 (delegation) | R1b (W0), R1c, R1d (floating) | R1b, R1c, R1d | Say who can do what and why | AC-UX-02 |
| U9 | W0 (ordinary), W2 (profile) | R2a (W1), R3b (W3) | F1c, F5 | Edit a question and a profile question; explain ownership | no ownership confusion |
| U10 | W1 | R3c (W2) | F3 | Approve a change to a Completed stage, predicting its effect | AC-UX-02 |
| U11 | W1 | R3d (W4) | R3d | Set up from templates; resume a saved setup | AC-UX-07 |
| U12 | W1 | R3a (W2) | F3 | Build a dependency graph; read the effective-policy preview | cycle refused; preview matches admission |
| U13 | W0 | R2a (W1) | F1c | Edit, save and complete; say which version counts | AC-UX-02 ("which version counts") |
| U14 | W0 | R2a (W1) | F1c | Compose a form; bind it | AC-UX-01 |
| U15 | W0 | R2a (W1) | F1c | Read history; find a kept copy | AC-UX-01 |
| U16 | W2 | R4a (W3) | F4 | View accepted answers after the VS2 disclosure; explain "informed" | AC-UX-02 |
| U17 | W2 | R3b (W3) | F5 | Screen with eligibility questions; explain what the decision rests on; keyboard path under DP3 | AC-UX-02, AC-UX-03 |
| U18 | W2 | R3b (W3) | F5 | Correct an own Exclude from history | AC-UX-01 |
| U19 | W0 | R1a (W0) | R1a | Browse and import templates | AC-UX-01 |
| U20 | W2 | R4a (W3) | F4 | Assignment, expiry, release, request an additional review; next-task rule | AC-UX-01 |
| U21 | W2 | R4b (W3) | F4 | Raise a query; find its outcome | AC-UX-01 |
| U22 | W3 | R5a (W4) | F6a | Download an as-of export; explain coverage labels | AC-UX-02 |
| U23 | W3 | R5b (W5) | F6b | Read the PRISMA diagram with reported counts | AC-UX-02 |
| U24 | W0 | O1 (W1) | F-O | Create an outcome measure; choose a schema | AC-UX-01 |
| U25 | one window before each release's kinds | per release | per release | Open an inbox item to its task; see "Related item unavailable" | deep link honours task identity and aliases |
| U26 | W0 | R2a (W1) | F1c | Export with and without unmasking; explain who may unmask | AC-UX-02 |
| U27 | W0 (navigation), W3 (both project kinds) | R2a (W1), GA | F1c, GA | Switch between a classic and a versioned project; explain the badge | AC-UX-02 |
| U28 | W0 | R2a (W1) | F1c | Read the read-only banner; find kept work | AC-UX-01 |
| U29 | W3 | R5c (W4) | R5c | Explain independent versus informed figures | AC-UX-02 |
| U30 (new) | W1 | R3c (W2), R4a (W3) | F3 | From the project index, reach an assignment in an unopened project in one step; as an admin, see a pending request without opening the project; use the four queue filters | AC-UX-01; with every notification flag off |
| U31 (new) | W0 | R2a (W1) | F1c | Work through Saving, Kept, Retrying, Offline, Failed; take over from a second tab; recover a stale base | AC-UX-06 |
| U32 (new) | W0 | R0 (W1 deploy), R2a (W1) | F1c | Read the workflow version badge and panel; admit a project; read the containment banner | AC-UX-02 |
| U33 (new) | W1 | R3a (W2), R3b (W3) | F3, F5 | Screen 20 studies by keyboard on a desktop and 20 on a 390px phone with the keyboard hidden; DP3 and DP5 variants | AC-UX-03; ≤ 2 actions per decision |
| U34 (new) | W0 | R2a (W1), R3a (W2) | F1c, F3 | Use "N required missing · Jump" and Unanswered only on a 200-question form | AC-UX-04; every jump lands on the control |
| U35 (new) | W0 (panel), W1 (tour) | R2a (W1), R3a (W2) | F1c, F3 | Read the "What changed" panel; dismiss it; replay the tour; open a help link | AC-UX-01; help link opens the right guide anchor |
| U36 (new) | W2 | R4a (W3) | F4 | The reconciler journey end to end at 1440px and 925px and in the narrow layout | AC-UX-05; no disagreeing candidate hidden |
| U37 (new) | W1 | R2c (W2) | F2 | Use the redesigned inbox and preferences; mark all read; filter; see "resolved" | AC-UX-01; UI-1 to UI-11 pass on the stack's screens |
| U38 (new) | W0 | R2b (W1), R3a (W2) | F1c, F3 | Read slot and presence states; a released slot with and without the cap; an Include refused for a dependent step | AC-UX-02; no tester reads a name they should not |
| U39 (new) | W0 | R2a (W1) | F1c | Follow the readiness-based checklist to a screenable stage on the interim route | AC-UX-07 on the interim route (PROPOSAL 30 minutes) |
| U40 (new) | W1 | R2c (W2), P2 (W3), R5a (W4), O2 | F2, P2 | Watch a publication phase 2, an ASySD run and an as-of export in Processing; explain the status | job language honoured; no fabricated progress |
| U41 (new) | W2 | P2 (W3) | P2 | Resolve a duplicate pair; merge and split; explain where the secondary's reviews went | AC-UX-02 (pending D2-12) |
| U42 (new) | W0 | F1c copy deck | F1c | Terminology card sort and "which version counts" vignettes | ≥ 80% agreement per core term |
| U43 (new) | W0, then per new pattern | the first consumer of each pattern | F1c and each gate | Pattern gallery review: every pattern's states, keyboard model, narrow behaviour and copy keys | Chris's per-PR acceptance (D3-02); axe clean |
| U44 (new) | W2 | R3b (W3) | F5 | Screen with bibliographic details hidden (SR-25) | AC-UX-03 unchanged; provenance records hidden metadata |
| U45 (new) | W3 | GA | GA | A tester holding both project kinds walks the restyled legacy chrome and shared pages | no behaviour change; AC-UX-02 on the badge |
12. Change management¶
- Three reviewer-visible bundles (
PROPOSAL): (1) "Versioned reviews" with R2a, R2b and R2c's reviewer-facing parts (kept changes, Save progress and Complete versions, history, Needs updating); (2) "Steps and screening" with R3a and R3b (step strip, screening renderer, derived decisions, reasons, keyboard path, My work badge from R3c); (3) "Workspace additions" with R2d, C1 and O1 (Fix, population chip, outcome schema entry) and R4a's VS1 display. Reconcilers get one bundle (R4a, R4p, R4b). Admin configuration changes are not bundled but get the panel. Anything reviewer-visible outside its bundle ships dark until the bundle's enablement. - "What changed" panel from R2a (AC-ALL-06 extended): keyed by bundle, per-user dismissal stored with the review preferences, read at page load (no notification dependency), each item linking to the user guide page drafted under its target marker (brief §1.15).
- Anchored tour component built once at R3a (spotlight, popover, pause and resume as in
Review Prototype v4) and reused by every later bundle; not shown below
lt_sm. - Contextual help on every new screen through the existing
userGuideUrlpipe, enforced byno-hardcoded-help-urls.spec.ts; help links are placed consistently (WCAG 2.2 consistent help). - User-guide parity: pages drafted under target markers and published at enablement; the glossary parity check (§5.1) runs in docs CI.
13. Design QA process¶
13.1 Tier 1, per PR, agent-run (D3-02)¶
| Check | Tool or evidence |
|---|---|
| Theme guards | pnpm run check:theme-migration, pnpm run check:contrast, syrf-theme.spec.ts, the UI-10 guard spec |
| Screenshot matrix | light theme at the UI-6 widths (320, 390, 599, 600, 768, 904, 905, 925, 1239, 1240, 1439, 1440; 200% zoom; 400% reflow; short height), named states per pattern; dark via token checks per PR |
| axe | per-route and journey-state results, zero serious or critical |
| Keyboard journey transcript | the PR's main task by keyboard, with focus order |
| State coverage list | every state in the pattern spec shown |
| Copy-deck compliance | the guard spec plus a manual read of new strings |
| Design-QA checklist against the handoff | DONE, PARTIAL, NOT DONE with file:line; deviations with reasons |
| Second agent review | a fresh-context agent compares the evidence with the handoff and the pattern inventory |
13.2 Tier 2, Chris, per release¶
Chris accepts the release's bundle of screens on staging (dark mode through themeToggle, which
is on there) with the tier-1 evidence, plus spot checks on previews. Per-PR acceptance is
limited to new shared patterns (U43) and five high-risk surfaces: the publication flow, the
reconciliation workspace, the stage designer, Members & groups and guided setup (D3-02).
Assumption A-24 is rewritten accordingly (open questions §4).
13.3 Materially changed¶
A screen is materially changed when any of these holds: a new route; a new or changed shared pattern; a changed primary action or its placement; changed copy for a core verb; a changed layout at any UI-6 width; a changed keyboard model or focus order. Colour-role swaps and copy fixes within the deck are not material.
14. Material 3 sequencing and dark mode (D3-01)¶
- Now: M3 roles over the current components (no component-generation islands), every new
route registered in FEAT-023's route inventory and baselines (UI-9), the UI-10 literal guard,
and
check:theme-migrationon every PR. UI-3 is rewritten so it is checked statically (review AC-17): roles and public APIs only, no M3 component islands, registered routes. Pending D3-01 the FEAT-023 light cutover is sequenced before R2a's reviewer UI where possible (join X-M3), otherwise before GA; new screens are verified on the path the preview renders plus the static checks (A-37). - Dark mode: evidence per PR is the token-contrast contract in both layers; evidence per
release is a dark screenshot set on staging with
themeToggleon; full dark screenshot sets per PR start only when FEAT-023 activates dark mode (Wave 6). V2-22's UI1 reading (production users see M3 roles on M2 components until the cutover) is put to Chris in D3-01. - Notification stack screens: inbox and preferences meet UI-1 to UI-11 before testers see them; conversation, issue and PDF screens before production (NS-10, D3-01).
- Legacy restyle: chrome and shared pages under D3-06, verified by U45.
15. Decisions needed, engineering items, validations and assumptions¶
15.1 Batch D decisions this strategy rests on¶
D1-06 (tester panel; decided 3 October and named that night, with no external SyRF users yet), D2-07 (slot held by a draft), D2-08 (two-tab take-over), D2-10 (scoped pauses copy), D2-12 (alias presentation), D3-01 (UI1 before cutover; stack screens), D3-02 (acceptance cadence), D3-03 (copy deck terms, including the workflow names and Q-D4/Q-D5), D3-04 (button and type language), D3-05 (phone screening), D3-06 (legacy restyle), D3-07 (My work), D3-08 (participants and telemetry), D3-15 (browsers and touch), D3-17 (capacity cap copy), D3-19 (dependent-step claim), D3-20 (presence disclosure), D3-22 (email content), D3-23 (resolved notices), D4-01 (Unsure key), D4-13 (primary reason order in the reason picker), D4-18 (WCAG audit; answered 3 October, with the audit kept under the recorded reading Chris confirms in the G0 dossier), D4-19 (blinding and random serving as core behaviours).
15.2 Engineering items E82 to E87¶
| ID | Item | Lane | Gate |
|---|---|---|---|
| E82 | Save-status state machine, bounded local copy (IndexedDB) with sequence replay, conflict and take-over screens, typed-outcome recovery copy; lease by stable client tab ID with REST heartbeat; works with tracking off | L5 with L1 | F1c (copy), R2a |
| E83 | Copy deck mechanism: deck document, typed message constants per feature, shared core-terms file, banned-string and import guard spec, user-guide glossary parity script in docs CI | L16 | F1c |
| E84 | Pattern inventory as shared components, spec gallery route behind a flag, handoff template, "What changed" panel with per-user dismissal, anchored tour component, contextual help on every new screen | L16 with L5 | F1c, R2a (panel), R3a (tour) |
| E85 | Accessibility and browser harness: @axe-core/playwright with baselines and journey-state checks, screenshot matrix at the UI-6 widths, forced-colours and reduced-motion runs, Firefox and WebKit smoke projects, native-drag guard spec, CDK drag for the question tree before R1a, browser floor (.browserslistrc, target, polyfills) |
L17 | W0 and S0; R1a precondition |
| E86 | My work: read-time counts endpoint over the four queues and admission-based work, project-level surface, global badge, cross-project tab, admin LC1 banner, deep links by task identity and alias; workflow version badge and panel, admission action, containment banner, legacy explainer | L16 with L6, L4, L0 | R0 (panel), R3c, R4a |
| E87 | Reviewer efficiency: keyboard screening path reconciled with DP3 and DP5, live completeness and jump on every host, input-latency budget under autosave, privacy-safe timing events (subject to D3-08) and the baseline measurement protocol | L5 with L3 and L17 | R2a (count, latency), R3a, R3b (keys) |
15.3 UI validations U30 to U45¶
Listed with windows and pass bars in §11; the open-questions rows are in open questions §3.
15.4 Assumptions¶
| ID | Assumption | Basis | Cost if wrong |
|---|---|---|---|
| A-37 | FEAT-023's light cutover does not land before R2a's reviewer UI; new screens are built on M3 roles over the current components and verified on the Material 2 bridge plus the static checks (UI-3, UI-9, UI-10) | FEAT-023 README (Waves 0 to 4 open; Wave 5 unscheduled); D3-01 pending | If the cutover lands earlier, the screenshot matrix is re-run on the M3 path at cutover; no plan change |
| A-38 | The tester panel (D1-06) and at least two external SyRF users are available for the W0 baseline study and monthly sessions | D1-06 (approved 3 October; named that night, with no external SyRF users yet, §9) and the D3-08 recommendation | AC-UX-03 and AC-UX-04 are re-based on R2a's first summative session, which doubles as the baseline; the thresholds stay PROPOSAL until then |
Resolution record¶
| Finding | Category | Where | Note |
|---|---|---|---|
| UX-01 | Adopted | §9, §10; acceptance criteria §2.3 and §5 | Research plan with baseline, formative, summative, diaries, card sort; AC-UX-01..09 carry the metrics and PE-05 is redefined through AC-UX-01 and 02; participants pending D1-06 (shape approved 3 October; names needed for G0) and D3-08, telemetry pending D3-08. Update: the panel was named late on 3 October (§9); external participants remain pending D3-08 |
| UX-02 | Adopted | §6.1 to §6.3, §10, E87; integrated plan R3a/R3b | Keyboard path and live completeness moved into R3a/R3b scope; AC-UX-03/04; AF2 parity exit set named in programme-integration (other drafter) |
| UX-03 | Corrected | §11; integrated plan §6.1 and §7 | Every U placed one window before its build; gate exit evidence lists U's |
| UX-04 | Adopted | §6.4, §6.5, E82, U31 | State machine, local copy, conflict screens; QM v2 §14 harvested; drafts model per brief §1.8 |
| UX-05 | Adopted | §5, E83, U42; contracts C17 | Copy deck at F1c with typed constants, guard spec and glossary parity; terms pending D3-03 |
| UX-06 | Adopted | §8.2, E85 | Accessibility harness in W0; screen-reader matrix; checklist per release |
| UX-07 | Adopted | §4, U43, E84 | Design system of record, pattern inventory, handoff template; button and type language pending D3-04 |
| UX-08 | Adopted | §3.1, E86, U30 | Project-level My work in R3c/R4a plus NS-07's badge, tab and banner; global landing post-GA; pending D3-07 |
| UX-09 | Adopted | §12 | Three bundles; "What changed" panel from R2a (AC-ALL-06 extended); tour at R3a; help links |
| UX-10 | Adopted | §7.4, U6 revised | Staged flow with preview and dry-run; comprehension in AC-UX-02 |
| UX-11 | Adopted | §3.3, §3.4, U32, U45 | Shared chrome, workflow version badge, explainer; legacy restyle pending D3-06 |
| UX-12 | Question | §14, A-37 | D3-01; dark evidence by token checks plus staging themeToggle |
| UX-13 | Adopted | §13 | Two-tier design QA; "materially changed" defined; cadence pending D3-02 |
| UX-14 | Adopted | §7.3, U36, U16 wording | Journey map, narrow layout, VS2 disclosure copy, next-task rule as PROPOSAL |
| UX-15 | Corrected | §8.2; acceptance criteria UI-6 | Widths from break-points.ts edges plus 320, 390, 925; touch targets; phone screening pending D3-05 |
| UX-16 | Adopted | §4.3, U40; acceptance criteria UI-2 | Shells and StatusView mandatory; long-running operations mapped to the job language |
| UX-17 | Adopted | §5.5, U31 | Error and recovery copy per typed outcome; AC-UX-06 |
| UX-18 | Adopted | §3.3, U32 | Workflow version panel and containment banner |
| UX-19 | Adopted | §7.7, U39, U11 moved to W1 | Interim checklist at R2a; AC-UX-07 |
| UX-20 | Adopted | acceptance criteria UI-2 | No debug components on reviewer-reachable routes unless the debug flag is on; review-completed page in R2b's revision |
| UX-21 | Question | §9 | D3-08; LogRocket and GA never used for UX metrics |
| UX-22 | Adopted | §5.3 | Reviewer progress vocabulary in the deck and R2b's progress-list revision |
| UX §3 strategy | Adopted | §3 to §13 | Incorporated with the amendments above |
| UX §4 Q1 to Q9 | Question | §15.1 | Q1 D3-01; Q2 resolved by the staging themeToggle evidence rule (§14); Q3 D3-04; Q4 D3-03; Q5 D3-08; Q6 D3-05; Q7 D3-06; Q8 D3-07; Q9 D3-02 |
| PH-13 | Adopted | §8.3, E85 | Browser and device matrix; CDK drag for the question tree and the browser floor as R1a preconditions |
| PH-19 | Adopted | §5.2 | Four-state vocabulary and "Save progress" reused; a distinct term per kind of draft |
| PH-35 | Adopted | §6.1, U17, U33 | One-key decisions reconciled with DP3 and DP5 |
| review AC-17 | Corrected | §14; acceptance criteria UI-3, UI-9 | UI-3 statically checkable; routes registered; D3-01 |
| review AC-19 | Adopted | §8; acceptance criteria AC-ALL-07 | Live regions, focus, forced colours, 400% reflow, short height, touch targets, screen-reader matrix, Firefox and WebKit; one width list |
| review AC-27 | Adopted | acceptance criteria UI-10 | Literal-colour guard spec over programme folders (no stylelint exists) |
| review AC-28 | Adopted | §4.3, §13.3; acceptance criteria UI-2, UI-5, UI-8 | Pattern checklist, handoff linked, "materially changed" defined |
| review AC-29 | Adopted | §11; acceptance criteria §5.3 and §5.4 | Tasks for every release, explain rubric, pass bar per U |
| SR-25 | Adopted | §4.3, U44 | Bibliographic blinding placeholder as a per-profile option, PROPOSAL, default off; provenance records it |
| DD-11 (glossary) | Adopted | §5.2 | User-facing terms aligned with the DD glossary; internal names unchanged |
| Q-D4, Q-D5 | Question | §5.2 | Covered by D3-03 ("Accepted answers (gold standard)", "Screening result") |
| V2-22 | Corrected | acceptance criteria UI-6, UI-8; §14 | 925px added; A-24 cited and rewritten; UI1 reading put to Chris in D3-01 |
| V2-25 | Corrected | acceptance criteria §5.3 | Tasks for R2b, R2d, R3c, R4b, R4p, R5c, P1, P2 and C2; O2's operations are covered by U40 |
| RT-10 | Adopted | §6.5, E82 | Lease by stable tab ID, take-over UI, works untracked; D2-08 |
| RT-14 | Adopted | §5.4, §4.3 (presence chip) | Counts and own place only; names with the Monitor capability; D3-20 |
| RT-22 | Adopted | §5.4 | Slot vocabulary and the D2-07 rule copy in the deck; slot states in U38 (extends U13) |
| Q-RT6, Q-RT7 | Question | §5.4, §6.5 | D3-20, D2-08 |
| NS-07 | Adopted | §3.1, E86, U30 | Flag-independent badge, cross-project tab and admin banner merged with UX-08 |
| NS-10 | Adopted | §7.9, §14, U37 | Stack screens meet UI1 before testers; M3 inbox redesign before R2c; timing D3-01 |
| NS-13 | Adopted | §7.9, U37 | Flood controls before R2c; resolved items per D3-23 |
| Q-N3, Q-N5 | Question | §7.6, §7.9 | D3-23, D3-01 |