Skip to content

Codex/ward management design - #2289

Open
BigSimmo wants to merge 103 commits into
mainfrom
codex/ward-management-design
Open

Codex/ward management design#2289
BigSimmo wants to merge 103 commits into
mainfrom
codex/ward-management-design

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

Verification

  • npm run verify:pr-local

During development, use npm run verify:cheap as the faster iteration gate before the final PR-local preflight.

  • npm run verify:ui when UI, routing, styling, browser behavior, reduced-motion, or forced-colors behavior changed
  • npm run verify:release before release or handoff confidence claims

For retrieval, ranking, selection, chunking, source/citation rendering, or answer-contract changes, verify:pr-local runs eval:rag:offline automatically. Run the offline command directly during iteration before spending a live eval.

  • npm run eval:retrieval:quality (must stay 36/36) when retrieval, ranking, selection, chunking, or scoring behavior changed — CI cannot run it (needs live keys), so run it locally and paste the summary. A metadata/governance-weighting change once buried correct docs (recall 1.0→0.76) and only this eval caught it.
  • npm run eval:rag -- --limit 15 + npm run eval:quality -- --rag-only when answer generation, the synthesis prompt, or answer post-processing changed (grounded-supported must not drop; citation-failure 0)
  • npm run check:production-readiness when clinical workflow, privacy, environment, Supabase, source governance, or deployment behavior changed
  • npm run check:deployment-readiness when deployment startup, hosting, or rollout behavior changed

Risk and rollout

Complete this section for clinical, data, API, auth/privacy, workflow, dependency, build, or deployment changes.

  • Risk:
  • Rollback:
  • Provider or production effects: None / describe the explicitly authorized effect
  • RAG impact: Required if touching RAG ranking surfaces (src/lib/rag/, retrieval RPCs, golden fixtures, ranking tests; see docs/rag-behaviour/safeguards.md). Must use one of:
    • RAG impact: no retrieval behaviour change — <reason>
    • RAG impact: behaviour change — canary pair <baseline run> -> <post run>
    • (Use RAG impact: none or omit for non-RAG PRs)

Clinical Governance Preflight

Complete this section when the change touches ingestion, answer generation, search/ranking, source rendering, document access, privacy, production env, or clinical output.

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Notes

BigSimmo and others added 30 commits August 18, 2026 15:38
…nd phase 1 plan

Baseline for the Phase 1 model rework. Adds the ward-management surface
(command, constellation, network, queue, capacity, movements, exceptions,
transport, governance, patient workspace), its synthetic fixtures, the
domain glossary and decision records, the metro patient-flow design spec,
and the Phase 1 implementation plan.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The subagent-driven-development ledger lives in git-ignored scratch and does
not survive a session. This records what a later session needs: the rulings
taken during Phase 1 with what each costs if wrong, the module map, the
deferred findings that Phase 4 must not inherit blindly, and the verification
lessons from this run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ules

Fixes every finding from the final whole-branch review: gate icons that
ignored pass/fail (including MHA authorisation), a five-state bed grid
that double-counted held/blocked beds, "open movement" counts that
included arrived/closed records, generated movements whose stage
contradicted their own fields, negative-instant clock formatting,
bed-release blockers that leaked departing-patient detail, a "catchment"
label computed from origin ED rather than patient catchment, an
"exhausted search" blocker the fixture didn't actually support, a
Readiness panel that ticked a breached legal deadline, and an
unconditional "eligible candidate" claim. Also cleans up the smaller
deferred items: cohort/security gate grammar and pass/fail text, an
advertised-but-unrun exception rule, stale glossary prose, and one
leftover "AI" label.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The whole-branch review found defects the eight per-task reviews could not
see, because each looked at one task's diff. One fix wave closed them. This
records what the review caught and why it mattered, the findings parked at
the close with the ruling on each, the verification actually run, and the two
repo traps that make a green result untrustworthy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rief

Phase 2 builds the flow coordinator's screen — pressure strip, priority
queue, flow diagram, explainable shortlist, exceptions drawer, phone form —
and retires Constellation into it. Ten tasks, two of which build the pure
derivations the screen reads: the operational score (rebuilt with no urgency
component) and per-department pressure.

The kickoff brief carries what a cold session needs, including the process
calibration for a screen-heavy phase and the three Phase 1 lessons that
should shape how it is verified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One self-contained file a session can read cold: the problem, the WA clinical
and legal grounding, the ten settled scope decisions, the model with every
export and identifier, the non-negotiable rules, the repo conventions and the
two gates that report success without running, what Phase 1 learned and why it
shapes how Phase 2 is verified, and the decisions taken on the owner's behalf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nd blocker checks

Review findings against the real fixture:
- Declines detail rendered a self-contradictory fraction ("5 of 3 parallel
  referrals declined") — declines.length is cumulative history, the cap
  limits simultaneous live referrals, they never shared a denominator.
  State only the count.
- Transport delay fired for movements already en route (WF-006, WF-014,
  WF-306, WF-313, WF-320, WF-327), contradicting their own blocker text.
  Require acceptedAt set and enRouteAt/collectedAt/cancelledAt all unset,
  matching buildActionInbox's existing condition, and drop the truthiness
  reads on Instant fields in favour of explicit === undefined.
- hasActiveBlocker's "starts with None" match was wide enough to hide a
  real blocker like "None of the secure units can take him"; narrowed to
  the exact sentinel or "None" + end-of-string/dash/colon.
- queueOrder's exclusion test only asserted a shorter list, which would
  still pass if queueOrder dropped everything; pinned to the exact
  isOpen-filtered count instead.
- Exported ward-clock's splitDuration (already zero-padding) and reused it
  for the wait-time detail instead of a second, non-padded formatter.
- Removed the redundant .slice() after .filter() in queueOrder.

Six new/tightened tests cover the behavioural findings; watched them fail
against the unfixed code before applying each fix.
Adds edPressure(now), sorted worst-first by breaching then longest wait
then volume. Reuses ward-clock's clockState for the breach definition
instead of re-deriving it inline, and clamps per-movement waits at zero
so a movement with a future openedAt can never render a negative wait.

The sort test's original array-comparison assertion coerced both sides
to strings via `>=`, which would pass a genuinely wrong ordering; it is
replaced with an explicit numeric tuple comparison.
…ble tests

edPressure(now) imported wardMovements directly, so every assertion was
forced to key off the one fixture (every department busy, every wait
positive). That let three tests pass under mutations that should have
failed them: dropping quiet departments, misattributing counts between
departments, and removing the future-openedAt wait clamp.

Change the signature to edPressure(now, movements = wardMovements),
mirroring queueOrder(movements, now) in ward-priority.ts with now kept
first for the existing/planned call sites. Add tests that inject a
built movement list to prove: quiet departments still report zeros
(never drop, never substitute a different EmergencyDepartment), counts
attribute to the correct originEdId rather than a rotated neighbour,
and a future-dated openedAt clamps to zero rather than going negative.
Also cover the clockState "due exactly now" boundary, and correct the
pre-existing longest-wait test's own expectation to mirror the clamp
(it previously proved the clamp only by fixture coincidence). Use
ward-clock's minutesUntil instead of inline subtraction, matching the
existing elapsedLabel pattern.

Each of the three structural findings was verified red against its
named mutation before being accepted.
…ow, labelling

Two Criticals, three Importants, three Minors from the Task 3 review.

Criticals:
- Wire the unused selectedUnitId setter into a real (if currently unreachable)
  "Clear unit selection" control in the diagram region instead of discarding it,
  clearing the npm run lint no-unused-vars failure.
- Repointing /ward-management broke five tests in ui-ward-management.spec.ts that
  still targeted WardManagementConsole. Repaired gotoWardFlow and three specs
  against the coordinator screen, kept the network-diagram spec untouched, and
  removed the two specs with no coordinator-screen equivalent yet — replaced by
  test.fixme placeholders in ui-ward-coordinator.spec.ts naming the tasks that
  will implement them (5/7 and 8).

Importants:
- The coordinator spec's overflow assertion measured document.documentElement,
  which .screen's overflow:hidden makes impossible to fail. Now measures the
  region grid's own scrollWidth/clientWidth via a testid; proved it goes red
  against the pre-fix CSS (836px overflow at 320px) before applying the fix.
- The region grid had no narrow-layout fallback below its shrink breakpoint and
  overflowed at 1100/820/390/320. Stacked the three regions into one column
  below 1440px (min-width: 90rem restores the three-column grid), and separately
  fixed a blank 72px band at <=640px where the hidden rail's grid track was
  still reserved. Verified zero overflow at 1600/1280/1100/820/390/320.
- "N movements" labelled the open-only queue count as a total; now "N open
  movements".

Minors:
- Dropped the inert z-index on the statically-positioned exceptions drawer (its
  position in .main's row order already pins it) and the now-unused
  --co-z-drawer token, plus two other declared-but-unused tokens.
  --co-space-4, --co-space-16.
- Added a visually-hidden <h1> naming the screen.

Also fixed a wrapping regression the open-movements label change introduced in
the 14rem queue column header, caught by re-inspecting the recaptured
screenshot.

RAG impact: no retrieval behaviour change — this only touches the Ward Flow
coordinator screen shell (src/components/ward-management/coordinator/**) and
its tests; no file under src/lib/rag/**, retrieval-selection, ranking-config,
answer-ranking, the eval harness, or the golden fixture was touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…, selection visibility, empty state

- Tests could not detect a wrong card order or the queue filtering to the wrong
  department; both are now pinned by data attributes (data-breaching,
  data-longest-minutes, data-waiting, data-origin-ed) and asserted directly.
- aria-label on each pressure card replaced its whole accessible name, hiding
  every figure from assistive technology; the name is now composed from the
  hospital name plus the visible figures.
- Selected state was invisible on breaching cards (border/background were
  overridden by the danger tint); a card outline now survives that and is
  pinned to Highlight under forced-colors.
- A quiet department rendered "0 waiting · longest 0m"; it now shows an
  explicit "No patients waiting" state, covered by a new dom test.
- Removed the click-retry loop around Playwright interactions in favour of a
  networkidle wait in gotoCoordinator, matching the sibling ward-management
  spec's helper.
- Added the ordering rule to the strip header and cleared the department
  filter automatically if it ever names a department that cannot be resolved.
…roof, now-prop, origin label, ED lookup hoist

Three mutations survived the appended ordering test with the suite green: removing data-tier
still passed (empty-array vacuity), inverting the within-tier tiebreak still passed (no
machine-readable score on the row), and both a constant score and a deleted breach line still
passed. Fixes:

- Add a count floor before the tier-sortedness assertion so absence can't satisfy it.
- Add data-score to each row and assert non-increasing score within a tier (the property, not
  the fixture).
- Assert the visible score text matches the row's own data-score, and that the breach line is
  present on a breached-deadline row and absent on a non-breaching one.

Also: PriorityQueue now takes now: Instant as a prop (was reading NOW_ANCHOR directly, unlike
its now-prop sibling PressureStrip); origin department renders "from JHC" instead of the
unlabelled "JHC", which read as a destination next to the patient's required security level;
and allEmergencyDepartments() is looked up once per render via a Map instead of once per row.
… as a routed destination

Critical 1: eligibleCandidates sorts eligible-first but never filters, so the diagram was
drawing solid accent routes and "N shortlisted units" for candidates that had already
declined the movement or failed a hard gate (e.g. WF-009: zero of its three nearest
candidates were actually eligible). Every shortlisted node now carries data-eligible plus
its own candidateReason() text, ineligible routes render dashed and danger-toned, and the
hub states the true eligible count instead of the shortlist size.

Important 2: destinationUnit() conflated an accepted bed with an outstanding referral into
one badge and only looked at referredUnitIds[0]. Split into distinct Accepted
destination / Outstanding referral badges, checked directly against the movement's own
fields, so every parallel referral is visible.

Important 3/4: the routed-set and route-connector assertions now hold for a second
movement with a different shortlist (WF-009), and route connectors are marked
data-connector-kind so they're provably distinct from demand connectors, closing the gaps
a single-movement proof and an unmarked connector left open.

Important 5: routed state now reaches the accessible name as real text (candidateReason),
not just an outline colour behind an aria-hidden svg.

Minor 6/7: a unit that fails its service-group lookup renders as an explicit anomaly
instead of vanishing; the window resize listener now attaches unconditionally rather than
being gated behind ResizeObserver's own availability check.

Controller finding 8: the region grid's row-sizing squeezed the diagram to 208px of 1080px
content at 1280x900. `.regionGrid` now sizes to its own content (align-self: start) only in
the stacked (<90rem) layout, `.diagramRegion` gets a real min-height floor, and
`.queueRegion` gets a matching cap so it doesn't balloon to all 41 unclamped rows — the
>=90rem three-column layout is untouched (restored to align-self: stretch there), matching
its original, already-working behaviour exactly.
…ates

Task 7: builds ShortlistPanel, the surface Phase 1's whole-branch review found
rendering a green tick beside "is not authorised under the Mental Health Act".
Every gate row now states its own verdict in text ("Met"/"Not met"), all eight
gates render every time (never .slice()'d), the icon reads directly off
gate.pass, and an ineligible candidate is marked with a dashed danger border
(forced-colors safe) and never styled as a recommendation. Confirm/override are
the only way to place a patient — nothing auto-allocates.
BigSimmo and others added 12 commits August 22, 2026 06:03
Task 8: one inpatient unit's own view at /ward-management/ward/[unitId]
(WardScreen) - the ward answering what the coordinator refers, closing
the loop the coordinator screen opens. Five regions derived live from
useWardFlow(): unit identity, the five-state bed grid plus a
CONFIRM_CAPACITY form scoped to the unit's own id, incoming referrals
(accept in principle / hold a bed / decline with one of the seven
DECLINE_REASONS) each carrying restrictionNotice where it applies,
accepted/held/en-route movements, and withdrawn referrals with reason.
An unresolved unitId renders an explicit empty state naming the id,
never a substituted unit. Every accept/decline/hold control mirrors
wardFlowReducer's own preconditions so it can never advertise an
action the reducer would refuse.

Registers tests/ui-ward-roles.spec.ts in both playwright.config.ts
matchers, adds the route/component to the design-system adoption
contract (regenerated ADOPTION.md/adoption-manifest.json), links the
route from ClinicalRail's rail (literal href, route-reachability-safe),
and regenerates docs/site-map.md (was stale without this run).
Task 9: /ward-management/transport/officer shows every transport job not
yet arrived (the model records a provider organisation, never an officer
identity, so filtering to "my jobs" isn't possible). A coordinator-style
queue-plus-pinned-bar pattern lets one job be "active" at a time, its four
actions (accepted, en route, collected, arrived) pinned to the viewport
bottom and each gated by a function that mirrors the reducer's own
preconditions exactly, including the receiving unit's live empty-bed floor
guard on Arrived. Wires the route into ClinicalRail with a literal <Link>
(RailLink's prop-passed href is invisible to route-reachability's AST scan)
and adds ward-sites.ts's edById alongside unitById.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e implies

Six "moving" transport jobs in the ward-movements fixture (WF-006, WF-014,
WF-306, WF-313, WF-320, WF-327) carried no transport.collectedAt, a state
PATIENT_COLLECTED (the only reducer transition producing stage "moving")
could never leave behind, since it always sets collectedAt in the same
update. That made PATIENT_ARRIVED refuse on all six, leaving the transport
officer's phone screen with four dead controls on six of its eight jobs.

Gives each of the two hand-authored records (WF-006, WF-014) its own
plausible collectedAt derived from its own enRouteAt, and fixes the
generator's "moving" case (stageFields in ward-movements.ts) so every
generated in-transit record gets an index-varied, NOW_ANCHOR-clamped
collectedAt instead of omitting it — the root cause behind the other four.

Adds a fixture-coherence describe block to ward-flow-contracts.test.ts that
walks the whole wardMovements array directly (not through the reducer) and
asserts stage/stamp coherence read off ward-flow-reducer.ts: "moving"
implies collectedAt, "arrived" implies arrivedAt where a transport job
exists, transport stamps only fill in the order the reducer allows, and no
stamp exceeds NOW_ANCHOR. Each invariant counts the records it actually
matched, not loop iterations, so a future fixture edit that hollows the
condition out goes red instead of passing vacuously.
Task 10: /ward-management/transport now renders LiveTracker, the coordinator's
view of every vehicle in transit — patient, leg, and how long since its last
recorded stamp. Every row is a movement that carries a real transport job
(re-measured at this branch's head: 8 of 41 open movements); the other 33 are
named explicitly in an on-screen banner rather than rendered as fabricated-leg
rows, mirroring the officer screen's own honesty discipline.

- tracker/tracker-derivations.ts: trackerRowState delegates leg precedence to
  transportLeg (never re-derives it) and maps the leg to its one real stamp;
  stampAgeText renders "<duration> ago" or an explicit no-timestamp sentence
  for the Requested leg, which the model never stamps at all.
- Strengthens the brief's own Playwright assertion (which the task-10 preflight
  flags as unable to distinguish five correctly-rendered legs from two): adds
  a pinned exact-row-count test, plus a node-environment unit suite covering
  all five legs, Cancelled, and the no-transport absence — none of which the
  seed fixture exercises end to end.
- The tracker screen's root also carries data-testid="ward-mode-transport" so
  the existing cross-mode navigation test keeps working now that this route no
  longer mounts WardModeWorkspace.
…lings R54-R62

Verification of every commit from 171adb6 to b2e0a92, measured in this
session rather than read from any implementer report.

The substantive finding is a fixture defect, not a code one. Six movements sat
at stage 'moving' with no collectedAt - a state PATIENT_COLLECTED is the only
producer of and always sets, so the reducer could never have reached it, and a
patient cannot be in a vehicle that never picked them up. The consequence
landed on the transport officer's phone: six of eight jobs had four dead
controls each, because PATIENT_ARRIVED requires both. Fixed at 1349c21 with
a contract invariant derived from the reducer rather than only correcting the
six records. Counted from the live DOM afterwards: 8 of 8 jobs now have at
least one available action, up from 2.

R60 caught the phase's signature defect inside the guard written to prevent
it: the vacuity tripwire counted loop iterations rather than matches, so its
companion arrived-branch assertion ran on zero records and passed regardless.
Corrected to count matches and to assert the honest zero rather than inventing
a fixture record to satisfy a positive one.

R55 records that no Ward Flow browser spec has ever run in CI's Production UI
lane - scripts/playwright-pr-shards.mjs holds its own copy of the spec pattern
and it has no ward alternation at all. Pre-existing on main, surfaced not
fixed: correcting it needs hosted timing measurements this machine cannot take.

R61 is a new environment trap that cost twenty minutes: the dev server is
reaped when the shell that launched it exits, and the symptom is a Playwright
identity guard failing with a Node connection error while curl to the same URL
still succeeds - which reads exactly like an IPv6 mismatch and is not one.
Task 11: /ward-management/ed/[edId] shows one department's own patients,
the department clock (from openedAt) and the legal clock (from formedAt
where earlier), the four-hour departmental access target — labelled and
computed so it can never be mistaken for a legal deadline and never
touches a LegalForm/dueAt — a police-attendance flag, and each movement's
single outstanding item. Adds a raise-referral form (RAISE_REFERRAL) and
a record-examination form (RECORD_EXAMINATION), plus a mark-handover-ready
control (HANDOVER_READY) — the missing control that lets a movement ever
reach the transport officer's screen. Statewide capacity is shown
read-only. Registers the route in the nav rail, the adoption contract,
the codebase index, and the Playwright roles spec.
… that never accepted them

HANDOVER_READY is the only reducer transition that produces stage
"handover_ready", and it always creates the movement's transport job in
the same update; bed_held (its only precondition) is itself only
reachable after ACCEPT_IN_PRINCIPLE sets acceptedUnitId. Five fixture
records claimed "handover_ready" without a transport job, and four of
those five without an accepted unit either.

WF-008 (hand-authored) had an accepted unit but no bedHeldUntil or
transport, so its honest stage is accepted_awaiting_bed. WF-305, WF-312,
WF-319 and WF-326 are generated records: routineMovements() assigns
stage from index % MOVEMENT_STAGES.length with no case in stageFields()
for "handover_ready" (correctly, since equipping one would mean
fabricating the fields), so any index landing there produced an
incoherent record. Fixed structurally by remapping that one stage to
placement_requested at the point of assignment, closing the defect for
every future index the generator can produce, not just today's four.

Extends the existing fixture stage/stamp coherence block in
ward-flow-contracts.test.ts with the reducer's full stage-producing
table and four new invariants derived from it (direct and transitive),
including the accepted-unit persistence chain that the original defect
exploited. Full derivation, gate evidence and mutation-kill proof for
every new assertion in the task report.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The product owner superseded the four-hour departmental access target
figure for this prototype on 2026-08-22, in response to a direct
clinical question: "change the 4 hour limit to 24 for patients in ED."

ED_ACCESS_TARGET_MINUTES moves from 240 to 1440. Every safeguard Task
6A and Task 11 built around this constant is untouched: it is still
counted UP from movement.openedAt, never a legal deadline, never
attached to a LegalForm or dueAt, and never feeds a legal-breach count
or eligibility gate. Updated the constant's doc comment, its pinning
test, the ED screen's banner copy, the single-source guard's
explanatory comment, and the phase 3 spec (with a dated supersession
note so spec and code cannot drift apart again).
…dy has assessed

The clinician, asked whether being examined should confer priority of its own:
'the reality is in ED that a patient needs review before they are referred for
a bed as they may not need a bed.'

operationalScore gains one factor, 'Bed need confirmed', worth 25 points when
a movement carries an examination whose outcome is inpatient_order - the
model's only operational evidence that a bed is genuinely needed rather than
sought before anyone looked. 25 sits deliberately between the statutory-timing
tiers of 20 (critical) and 30 (breached): a stronger signal than an unbreached
legal timer, but not inflated to read like a deadline. Wording is operational
throughout - never severity, acuity or risk, and the score still orders only
within an urgency tier.

Measured effect on the coordinator queue, tier 1:

  before                          after
  WF-303  61  not examined        WF-009  78  inpatient_order
  WF-009  53  inpatient_order     WF-017  66  inpatient_order
  WF-312  50  not examined        WF-303  61  not examined

Examined patients now lead, which is the clinician's rule reaching the surface.
It also retires a separate concern raised earlier in this phase: the demo no
longer opens on WF-303, a generated movement whose breach came from an
index-derived formula rather than from anything anyone authored.

This deliberately does NOT gate REFER_TO_UNITS on examination. Measured: only 2
of 17 open movements at a referable stage carry an inpatient_order examination,
and 23 further open movements already past that stage carry none, so gating
would make most of the fixture unreachable. That larger reading is with the
product owner.

KNOWN GAP, documented in the code rather than papered over: 21 of 41 open
movements are voluntary and carry no legal form, so they never receive a Mental
Health Act examination and can never earn this factor - even though a voluntary
patient is just as much reviewed before a bed is sought. No proxy was invented.
Covering them needs a general notion of review the model does not yet have.
…63-R67

Brings the committed ledger level with the live workspace after an integrity
check prompted by a reported tree deletion. No loss found: all 15 session
commits present and ancestors of HEAD, git fsck clean, node_modules intact at
523, 59 workspace files, 14 phase-3 screenshots.

Substantive content: Task 11's emergency department screen with both clocks;
the clinician's two answers implemented as separate revertible commits (the
access target raised 4h to 24h, and a 'Bed need confirmed' factor so a patient
confirmed to need a bed outranks one nobody has assessed); and R63/R64, a
second and larger instance of the stage-incoherence defect found by looking at
a screenshot rather than by running anything - five patients recorded ready to
hand over, four of them to a ward that never accepted them.
The last task of Phase 3. One patient, WF-315, walked from an emergency
department to an inpatient bed through all four roles in a single browser
window, never reloading the page.

Eleven steps: ED records the examination (outcome inpatient_order); the
coordinator refers to all three eligible wards; RPH Adult Secure accepts in
principle and holds a bed; the ED marks handover ready, which creates the
transport job; the officer marks accepted, en route, collected, arrived; and
the coordinator confirms WF-315 has left the queue entirely.

The journey opens with the examination because the clinician ruled that a
patient is reviewed before a bed is sought (R67). WF-315 carries a Form 1A
awaiting examination, so recording it flips the form to 3B and earns the
'Bed need confirmed' factor - the patient's queue position visibly improves as
a direct consequence of being reviewed.

The switcher infers where you stand from the selected patient only when exactly
one destination is implied, and otherwise offers a picker. After a three-way
parallel referral nothing can be inferred, and silently taking the first
referral would be a ?? array[0] in interaction form (R52). The coordinator is
statewide and has no place; the switcher shows that asymmetry rather than
inventing a location.

A shared focusMovementId in the provider carries the selection across role
switches, since each screen is a route segment that remounts. Reviewing the
journey's own final screenshot caught a real bug in it: restoring the selection
unconditionally re-selected WF-315 after arrival and left the shortlist showing
'Currently at ARM - waiting in the emergency department' for a patient who had
already left. Now gated on isOpen, so the restore cannot invent a selection a
live click could never produce.

Mutation-proved, by the implementer and independently by me: replacing one
click-based role switch with a page.goto() to the identical URL KILLS the test.
The provider re-seeds and ward-incoming-WF-315 never appears. The journey
therefore proves that state survives navigation across four roles, not merely
that eleven screens each work in isolation - which is a different and far
weaker claim under the same name.
…cing record

Every judgement made on the product owner's behalf across three sessions, in
one place, each with what it costs if wrong. The ledger holds the full text;
this is the map.

Organised so a clinician can find what matters: the eleven rulings that changed
what the software says to a clinician, the eight spent on this project's one
recurring defect (a check that claims more than it delivers), the six
unmeasured fixture claims - three of them the controller's own - the process
and environment calls, and the four questions still open with the owner.
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 151 files, which is 1 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to Pro+ to raise the limit.

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6101977c-e536-467e-8496-b661ad8dbe43

📥 Commits

Reviewing files that changed from the base of the PR and between d617473 and 663a9f4.

📒 Files selected for processing (151)
  • design-qa.md
  • docs/branch-review-records/c7b727bab40ad00fb24a30334953c787ddd0d4d7b3d8d78ce589aff3c3a18250.record.md
  • docs/codebase-index.md
  • docs/design-system/ADOPTION.md
  • docs/design-system/adoption-contract.json
  • docs/design-system/adoption-manifest.json
  • docs/site-map.md
  • docs/superpowers/plans/2026-08-14-ward-management-mockups.md
  • docs/superpowers/plans/2026-08-18-ward-flow-model-and-modes.md
  • docs/superpowers/plans/2026-08-18-ward-flow-phase-1-model.md
  • docs/superpowers/plans/2026-08-18-ward-flow-phase-2-coordinator-screen.md
  • docs/superpowers/plans/2026-08-19-ward-flow-phase-3-role-screens.md
  • docs/superpowers/specs/2026-08-14-ward-management-design.md
  • docs/superpowers/specs/2026-08-18-ward-flow-metro-patient-flow-design.md
  • docs/superpowers/specs/2026-08-19-ward-flow-phase-3-role-screens-design.md
  • docs/ward-flow-complete-ledger.md
  • docs/ward-flow-context.md
  • docs/ward-flow-phase-2-kickoff.md
  • docs/ward-flow-phase-3-handover.md
  • docs/ward-flow-phase-3-ledger.md
  • docs/ward-flow-phase-3-rulings.md
  • docs/ward-flow-phase-3-workspace/README.md
  • docs/ward-flow-phase-3-workspace/clinical-changes-report.md
  • docs/ward-flow-phase-3-workspace/concurrent-session-inventory.md
  • docs/ward-flow-phase-3-workspace/flow-diagram-fix-brief.md
  • docs/ward-flow-phase-3-workspace/flow-diagram-fix-report.md
  • docs/ward-flow-phase-3-workspace/handover-stage-coherence-report.md
  • docs/ward-flow-phase-3-workspace/preflight-tasks-9-to-12.md
  • docs/ward-flow-phase-3-workspace/progress.md
  • docs/ward-flow-phase-3-workspace/task-1-brief.md
  • docs/ward-flow-phase-3-workspace/task-1-report.md
  • docs/ward-flow-phase-3-workspace/task-1-review.md
  • docs/ward-flow-phase-3-workspace/task-10-brief.md
  • docs/ward-flow-phase-3-workspace/task-10-report.md
  • docs/ward-flow-phase-3-workspace/task-11-brief.md
  • docs/ward-flow-phase-3-workspace/task-11-report.md
  • docs/ward-flow-phase-3-workspace/task-12-addendum.md
  • docs/ward-flow-phase-3-workspace/task-12-brief.md
  • docs/ward-flow-phase-3-workspace/task-12-journey-design.md
  • docs/ward-flow-phase-3-workspace/task-2-brief.md
  • docs/ward-flow-phase-3-workspace/task-2-report.md
  • docs/ward-flow-phase-3-workspace/task-2-review.md
  • docs/ward-flow-phase-3-workspace/task-3-brief.md
  • docs/ward-flow-phase-3-workspace/task-3-report.md
  • docs/ward-flow-phase-3-workspace/task-3-review.md
  • docs/ward-flow-phase-3-workspace/task-4-brief.md
  • docs/ward-flow-phase-3-workspace/task-4-report.md
  • docs/ward-flow-phase-3-workspace/task-4-review.md
  • docs/ward-flow-phase-3-workspace/task-5-brief.md
  • docs/ward-flow-phase-3-workspace/task-5-report.md
  • docs/ward-flow-phase-3-workspace/task-5-review.md
  • docs/ward-flow-phase-3-workspace/task-6-brief.md
  • docs/ward-flow-phase-3-workspace/task-6-fix-round-3-findings.md
  • docs/ward-flow-phase-3-workspace/task-6-re-review-rounds-3-4.md
  • docs/ward-flow-phase-3-workspace/task-6-report.md
  • docs/ward-flow-phase-3-workspace/task-6-review.md
  • docs/ward-flow-phase-3-workspace/task-6a-brief.md
  • docs/ward-flow-phase-3-workspace/task-6a-re-review.md
  • docs/ward-flow-phase-3-workspace/task-6a-report.md
  • docs/ward-flow-phase-3-workspace/task-6a-review.md
  • docs/ward-flow-phase-3-workspace/task-7-addendum.md
  • docs/ward-flow-phase-3-workspace/task-7-brief.md
  • docs/ward-flow-phase-3-workspace/task-7-report.md
  • docs/ward-flow-phase-3-workspace/task-8-addendum.md
  • docs/ward-flow-phase-3-workspace/task-8-brief.md
  • docs/ward-flow-phase-3-workspace/task-8-report.md
  • docs/ward-flow-phase-3-workspace/task-9-brief.md
  • docs/ward-flow-phase-3-workspace/task-9-report.md
  • docs/ward-flow-phase-3-workspace/transport-leg-helper-report.md
  • docs/ward-flow-phase-3-workspace/transport-stage-coherence-report.md
  • docs/ward-flow-phase-handoff.md
  • docs/ward-management-context.md
  • docs/ward-management-decisions.md
  • docs/ward-management-mode-map.md
  • playwright.config.ts
  • src/app/ward-management/capacity/page.tsx
  • src/app/ward-management/ed/[edId]/page.tsx
  • src/app/ward-management/exceptions/page.tsx
  • src/app/ward-management/governance/page.tsx
  • src/app/ward-management/layout.tsx
  • src/app/ward-management/movements/page.tsx
  • src/app/ward-management/network/page.tsx
  • src/app/ward-management/page.tsx
  • src/app/ward-management/patients/[patientId]/page.tsx
  • src/app/ward-management/queue/page.tsx
  • src/app/ward-management/transport/officer/page.tsx
  • src/app/ward-management/transport/page.tsx
  • src/app/ward-management/ward/[unitId]/page.tsx
  • src/components/applications-launcher-page.tsx
  • src/components/tools-page-mockups/tool-fixtures.ts
  • src/components/tools/tools-search-results-page.tsx
  • src/components/ward-management/coordinator/coordinator-screen.tsx
  • src/components/ward-management/coordinator/coordinator.module.css
  • src/components/ward-management/coordinator/exception-drawer.tsx
  • src/components/ward-management/coordinator/flow-diagram.tsx
  • src/components/ward-management/coordinator/pressure-strip.tsx
  • src/components/ward-management/coordinator/priority-queue.tsx
  • src/components/ward-management/coordinator/shortlist-panel.tsx
  • src/components/ward-management/ed/ed-screen.tsx
  • src/components/ward-management/ed/ed.module.css
  • src/components/ward-management/officer/officer-screen.tsx
  • src/components/ward-management/officer/officer.module.css
  • src/components/ward-management/tracker/live-tracker.module.css
  • src/components/ward-management/tracker/live-tracker.tsx
  • src/components/ward-management/tracker/tracker-derivations.ts
  • src/components/ward-management/ward-clock.ts
  • src/components/ward-management/ward-derivations.ts
  • src/components/ward-management/ward-eligibility.ts
  • src/components/ward-management/ward-flow-events.ts
  • src/components/ward-management/ward-flow-provider.tsx
  • src/components/ward-management/ward-flow-reducer.ts
  • src/components/ward-management/ward-management-console.tsx
  • src/components/ward-management/ward-management-modes.module.css
  • src/components/ward-management/ward-management-modes.tsx
  • src/components/ward-management/ward-management-navigation.tsx
  • src/components/ward-management/ward-management-network.module.css
  • src/components/ward-management/ward-management-network.tsx
  • src/components/ward-management/ward-management.module.css
  • src/components/ward-management/ward-model.ts
  • src/components/ward-management/ward-movements.ts
  • src/components/ward-management/ward-pressure.ts
  • src/components/ward-management/ward-priority.ts
  • src/components/ward-management/ward-role-switcher.module.css
  • src/components/ward-management/ward-role-switcher.tsx
  • src/components/ward-management/ward-sites.ts
  • src/components/ward-management/ward/ward-screen.tsx
  • src/components/ward-management/ward/ward.module.css
  • src/lib/tools-catalog.ts
  • tests/pressure-strip.dom.test.tsx
  • tests/tools-catalog.test.ts
  • tests/tracker-derivations.test.ts
  • tests/ui-ward-coordinator.spec.ts
  • tests/ui-ward-management.spec.ts
  • tests/ui-ward-roles.spec.ts
  • tests/ward-capacity-reconciliation.test.ts
  • tests/ward-clock.test.ts
  • tests/ward-derivations.test.ts
  • tests/ward-eligibility.test.ts
  • tests/ward-flow-clock-consistency.dom.test.tsx
  • tests/ward-flow-contracts.test.ts
  • tests/ward-flow-provider.dom.test.tsx
  • tests/ward-flow-queue-selection.dom.test.tsx
  • tests/ward-flow-reducer.test.ts
  • tests/ward-flow-single-source.test.ts
  • tests/ward-management.test.ts
  • tests/ward-model-phase3.test.ts
  • tests/ward-model.test.ts
  • tests/ward-pressure.test.ts
  • tests/ward-priority.test.ts
  • tests/ward-restriction-notice.test.ts
  • tests/ward-screen.dom.test.tsx

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands.

@supabase

supabase Bot commented Aug 22, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1813124690

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/ward-management/ward-flow-reducer.ts
Comment thread src/components/ward-management/ward-derivations.ts Outdated
Comment thread src/components/ward-management/ward-derivations.ts
@BigSimmo
BigSimmo marked this pull request as draft August 22, 2026 14:12
@BigSimmo
BigSimmo marked this pull request as ready for review August 22, 2026 19:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2c9c56e244

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/ward-management/ward-flow-reducer.ts
Comment thread src/components/ward-management/ward/ward-screen.tsx Outdated
Comment thread src/components/ward-management/ward-clock.ts
claude added 2 commits August 22, 2026 19:28
- ward-flow-reducer.ts: closing an examination as community_order/
  revoked now cancels in-flight transport and releases any bed already
  held at the accepted unit, and every downstream transition (referral,
  acceptance, hold, decline, handover, transport, arrival, escalation)
  now rejects once a movement carries a `closure`. Reproduces and fixes
  the reported defect where TRANSPORT_EN_ROUTE still succeeded on a
  movement already recorded as revoked, with its bed still reserved.

- ward-screen.tsx: resolves the unit from the provider's live `units`
  instead of the frozen `unitById()` fixture, so CONFIRM_CAPACITY/
  HOLD_BED updates are reflected on this screen instead of the seeded
  count.

- ward-flow-provider.tsx: elapsed time is now accumulated across 30s
  checkpoints instead of compared against the original mount instant,
  so a session open past 24h (or any multiple of it) keeps counting
  forward instead of resetting to zero on an exact-24h wall-clock
  reading, which previously moved every deadline/wait/hold on every
  screen backward by up to a day.

Each fix carries a regression test; the provider one is confirmed to
fail against the pre-fix code (702 vs expected 2142).

Addresses the three unresolved P1 review threads on PR #2289 as part
of a Run PR sweep.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants