Skip to content

Claude/browser test gate handoff d5c1db - #2347

Closed
BigSimmo wants to merge 54 commits into
mainfrom
claude/browser-test-gate-handoff-d5c1db
Closed

Claude/browser test gate handoff d5c1db#2347
BigSimmo wants to merge 54 commits into
mainfrom
claude/browser-test-gate-handoff-d5c1db

Conversation

@BigSimmo

@BigSimmoBigSimmo commented Aug 24, 2026

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


Note

Low Risk
Documentation-only: no application, auth, or data-path code. Risk is limited to stale or incorrect process guidance for later implementers.

Overview
Records that Phase 2A is already on main (squash merge e4cbe8d3a / #2279) and retires claude/suicide-contact-mockup-b5aaa0. Handoff, continuation prompt, and PROGRESS-LEDGER.md now tell sessions to work from origin/main. Browser gate and condensed-bar mutation proofs are marked green (2026-08-24).

Adds copy-decisions-recommended.md: owner approved all 13 copy items, with A9 blocked on a real crisis number and A4 as a loud refusal plus deferred wording. Patient-visible freeze is lifted for implementation that cites item numbers.

Starts Phase 2B tracking: phase-2b-build-record.md (Rulings 67+) plus SDD briefs/reports for Tasks 1, 3, and 5 (ListEmptyState, overlay trigger/commit contract, Patients directory). Group 0 is recorded complete; Task 2 cut, Task 4 merged into 5. No product code in this diff.

Reviewed by Cursor Bugbot for commit 0bebd94. Configure here.

BigSimmoand others added 30 commits August 24, 2026 15:32
…browser gate, capture the deferred findings
Phase 2A was squash-merged to main as e4cbe8d (#2279) on 2026-08-23, but the
handoff, the ledger and the continuation prompt all still named the feature
branch as the source of truth and told the next session to build a worktree from
it. Corrected in place rather than deleted, because the reasoning about
durability and about measuring a moving tree still holds -- and holds harder on
main, which far more sessions touch.
- Browser gate re-run on main: 32 passed, exit 0, no ECONNRESET. The test that
failed on 2026-08-23 (the 1440px condensed-bar pin) ran and passed, so the
residual failure was load, not a defect. Also records that :822 was the test's
declaration line, never the failing statement -- the dropped connection was in
the setup POST at line 672, before any pin assertion ran.
- Seven deferred findings captured as immutable issues-inbox requests, so they no
longer survive only in the build record.
- copy-decisions-recommended.md is new: the copy recommendations existed only in
a previous session's conversation and did not survive it. Also corrects the
count -- the records said seven items need the owner, the copy review actually
raises thirteen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cord the mutation proofs
The entry-point handoff said on line 7 that the branch had never been pushed and
in section 4 that it was pushed to origin. Both were true when written and
neither was updated when the other changed; both are now superseded by the merge.
Records mutation proof A for the condensed bar: top-full -> top-0 turns 32/0 into
13 failed / 19 passed, and the 1440px failure is the pin assertion itself at line
877 (barBox.top 64 -> 0) with the two preceding assertions passing first, so the
assertion is reached and discriminating rather than merely present.
Also records the trap that nearly produced a false proof: the first mutation-B
anchor matched two elements, a uniqueness assertion refused the edit, and the
script ran the full gate anyway on an unmutated tree -- reporting 32 passed, exit
0. Read without the abort line that is a real, green, strongest-looking gate run
supporting exactly the wrong conclusion. A mutation proof therefore has two
results, not one: prove the mutation is in the tree before believing the gate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mutation B (dark-mode colour): 1 failed / 31 passed. The single failure is the
scheme-comparison at line 931 and names the injected literal, so it is
attributable by value and not merely by timing; the display guard before it
passed, so the assertion is reached. A blast radius matching the mutation's
intent is itself evidence the assertion measures what it claims.
With mutation A already proven, both closing proofs the final review recorded as
UNRUN are discharged and the condensed bar's fix round is closed.
Adds the Phase 2B implementation plan. It follows the owner's stated order and is
grounded in a measured reading of what Phase 2A actually left: one real route,
thirteen stub destinations, zero of twenty-four overlays wired to a trigger, no
empty-state component, and no read API for patients, schedule or team.
Two gaps the plan surfaces rather than hides: message templates have a full
governance lifecycle but only ONE hard-coded message, so a template library
cannot show per-version content that does not exist; and 'workload and coverage'
has an approved design only at roster-table depth, which is the single most
likely place the plan under-delivers against what the owner means.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…py decisions
The owner answered 'go ahead with your recommendations' to all thirteen items on
2026-08-24. Recorded as the decision of record, with two qualifications that
approval alone does not settle:
A9 (add Lifeline 13 11 14) is approved in principle but BLOCKED. The
recommendation was conditional -- add Lifeline and drop the Fictional Support
Line once a real crisis number is chosen -- because the message sits about nine
characters from its two-segment maximum, so nothing can be added until something
comes out. No real number exists, and the owner was explicitly asked to name what
goes. An implementer must not pick the removal itself.
A4 (the closing message) is approved as a deferral, not as text: the refusal path
is buildable now, the wording waits for a lived-experience representative.
Patient-visible copy is no longer frozen, but every change must cite its item
number and still live only in the sealed domain's message-copy module.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tradicts
The approval banner lifted the copy freeze, but the line directly beneath it still
said wording stays frozen until the owner answers. That is the same
self-contradiction this session just criticised in phase-2a-handoff.md, created
the same way -- a true sentence left in place when the thing it described changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…can, add Task C
The pre-flight scan found one real defect in the plan before any dispatch: the
design-corrections table routed correction #2 to 'Group 3, Task 11', but Task 11
is Group 1's overlay wiring and Group 3 is Tasks 15-16. An implementer would have
received a requirement it had no surface for. Fixed as Ruling 73.
Adds Task C -- the owner's six approved copy changes, batched into one dispatch
per the method's rule about small same-shape work. A9 (add Lifeline) is
deliberately excluded: it is approved in principle but conditional on a real
crisis number existing, and dispatching it would force an implementer to choose
which patient-facing sentence to delete.
Rulings 73-78 recorded, each with what it costs if wrong.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s forced
Ruling 79: the owner's approved 'refuse any message containing Fictional' cannot
be implemented as a prohibited term, because both approved patient messages
contain 'Fictional Support Line' -- every existing message would be invalid and
the check would have to be disabled to ship. Implemented instead as a validator
issue plus an explicit synthetic-acknowledgement flag on each call site, so a
real send path has to opt in deliberately rather than fail silently.
Ruling 80: A3's 'something automatic comes back' fits only in the reply message.
Message A is 252 septets against a two-segment ceiling. Measured with the repo's
own calculateGsm7 rather than estimated -- the proposed reply is 210 septets.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Carries Ruling 81: EmptyState is its own component and does not render
AutomatedState internally. The two have different triggers -- AutomatedState is
for the system acting on its own, an empty list is usually the user's own filter
or simply nothing existing yet -- and AutomatedState's alert icon and state-name
aria-label are both wrong for 'no patients yet'. The filtered variant reuses its
why/what-changes-it wording shape so a clinician learns one pattern.
The brief models the two emptinesses as a discriminated union rather than
optional strings, because an optional reason is a reason that will be omitted,
and a filtered-empty list that says only 'nothing to show' is indistinguishable
from an empty caseload.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tomated reply (A2 + A3)
Owner-approved 2026-08-24. The reply's first sentence claimed replies "had not
been seen by anyone and had not been kept" -- a firm storage claim about a
system with no telephony provider yet, so nobody could currently know if it
was true (A2). It also left a patient who had just been told "no one reads
this" unable to tell a reply was automatic rather than human (A3). Replaces
the sentence with wording that states only what the system can actually know
and names the reply as automatic. Verified 210 septets / 2 segments / GSM-7
valid (was 218). EXACT_PATIENT_VISIBLE_MESSAGE is untouched -- it has no
segment headroom left, so the "reply is automatic" fact lives only here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ail (A1 / Ruling 79)
Both approved patient-visible messages name the reserved fictional crisis
number on purpose, so a bare prohibition on the word "Fictional" would make
every existing message invalid and the check would have to be disabled to
ship -- worse than no check. Instead validateGovernedMessage now always
reports fictional-contact-detail-present when a message contains the marker
(derived from message-rules.ts's crisisSupportContact, not hard-coded a
second time), unless the caller passes the new, explicit
syntheticFictionalContactsAcknowledged: true. Existing tests that build
compliant first/closing messages from the crisis contact are updated to pass
the acknowledgement, since they were never testing this rule.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…thored body (A4)
No closing message has ever been written -- that wording is a clinical
decision deferred to a lived-experience representative, not an
implementation gap. resolveClosingContactMessageBody is the refusal only:
it never returns an empty string, never falls back to another message's
text, and never silently drops the contact when no authored body exists.
No closing-message wording is drafted here.
No existing seam resolved a contact's message body anywhere in this domain
(checked schedule.ts, simulation.ts, repository.ts, model.ts): PlannedContact
carries a messageType but no body content, and nothing supplies one yet. This
function is the mechanism a future sender will call once that seam exists; it
is deliberately not wired into schedule.ts/simulation.ts here, since doing so
would require inventing where an authored closing body comes from -- exactly
the decision this task defers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lowerText.includes("lead") also matched the ordinary English "the incident
lead" and "the clinical programme lead" -- job titles that appear in the
service-stop wording -- so a message using the word correctly would be
rejected. Word-boundary matching alone would not have fixed this (both job
titles contain "lead" as a whole word too), so "lead" is narrowed to a
commercial-specific form instead: a marketing-word modifier ("sales lead",
"a new lead") or companion ("lead generation", "lead conversion").
The narrowing lives as a per-term pattern override in message-rules.ts
(prohibitedTermPatternOverrides), keeping message-policy.ts's mechanism
generic. Every other prohibited term keeps its exact substring behaviour --
one covering test per term proves it, since narrowing one term is precisely
the change most likely to quietly widen what the rest of the list allows.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…vocabulary (B3)
Until now the prohibited-word ban ran only against outgoing messages
(message-policy.ts) and the 24 frozen overlay definition rows
(caring-contacts-overlay-definitions.test.ts) -- nothing checked the words
on a screen, so it was policy held by people rather than software. This
scans every string/template literal under src/components/caring-contacts/
workspace/** and src/app/caring-contacts/** against the existing wider
CARING_CONTACTS_PROHIBITED_LANGUAGE vocabulary.
src/components/caring-contacts/mockups/** is out of scope by construction
(not one of the two scan roots) -- it is frozen design scratch that 404s in
production and knowingly contains one prohibited phrase the owner ruled
(B4) to leave alone.
Extraction uses a small character-by-character scan rather than a regex
over the raw source: a naive quote-matching regex treats JSDoc inline-code
backticks (`` `useSearchParams` ``) as template-literal delimiters, and an
odd count across a comment pairs unrelated spans into one giant fake
literal spanning most of the file. className attribute values are excluded
before extraction -- narrowing which literals reach the scan, not adding a
file to an ignore list -- because they carry CSS custom-property names
(var(--safe-area-bottom)) that contain "safe" as a substring unrelated to
interface prose.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
npm run test's repo-wide test-runner-safety.test.ts requires every recursive
rmSync in a test fixture to pass maxRetries/retryDelay, guarding against
Windows file-lock flakiness on cleanup. The B3 fixture cleanup added in the
previous commit was missing them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tion-proven
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Verified the two full-suite failures myself rather than accepting the report:
both are gate-receipts file-mode tests failing in chmodSync, on a Windows drive
that cannot represent file modes. Environmental, and a third known local failure.
Records the consequential finding: validateGovernedMessage has zero production
callers. The brief assumed callers to update and there are none. The checks are
real but guard a send path that does not exist yet, so 'the validator refuses
this' must not be read as 'the system refuses this'. Captured as a P2 issue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Spec passed. Three Important findings, four Minor. Two lessons recorded that
generalise beyond this task:
An allowlist cannot close an open-ended set. B2 narrowed the 'lead' prohibition
by enumerating commercial phrasings, so everything unenumerated is now permitted
-- 'lead magnet', 'qualify this lead' and others all pass and all previously
failed. Enumerate the safe set, never the dangerous one.
A guard on a chokepoint fires; a guard beside one does not. A1 and A4 both look
'unwired' and have opposite futures: A1 sits inside validateGovernedMessage which
any sender must pass, while A4 is a standalone function nothing obliges anyone to
call. Ruling 83 therefore refuses to record A4 as closed.
Ruling 82 promotes the A1 marker finding from Minor: it matches the label
'Fictional Support Line', not the reserved number, and the number is the artefact
that would actually reach a patient.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…3, comment)
Fix round 1 against Task C, six of seven fixable findings (the seventh, A4's
standalone resolveClosingContactMessageBody, was recorded and reported to
the owner instead of changed -- it rides no chokepoint yet, and inventing
one is out of this task's scope).
Important 1+2 (B2): the first "lead" override was an ALLOWLIST of nine
commercial modifiers/companions, and commercial vocabulary is open-ended, so
anything not enumerated passed silently -- verified newly permitted "lead
nurturing", "lead magnet", "lead source", "leads database", "lead gen",
"qualify this lead", "convert the lead", "this lead is hot", "your lead".
Inverted: COMMERCIAL_LEAD_PATTERN now refuses "lead"/"leads" as a whole word
BY DEFAULT via a negative lookbehind, exempting only the closed set of job
titles this domain's own wording uses -- incident lead, programme lead,
clinical lead, team lead, service lead. The "scoring?" typo (matched "lead
scoring" but not "lead score") disappears with the allowlist it lived in;
confirmed via a dedicated "lead score" test.
Promoted Important (A1): the marker was `crisisSupportContact.split(":")
[0]`, i.e. the LABEL "Fictional Support Line" only -- a message carrying the
bare reserved NUMBER with no label raised nothing, which is the shape that
would actually reach a sender. fictionalContactMarkerPattern is now
`/Fictional/i` plus every reserved number in synthetic-contacts.ts
(escaped), so relabelling, reordering, or dropping the label entirely are
all still caught. One pre-existing rule-6 test (contains-patient-mobile)
used +61 491 570 006 -- itself one of the four reserved numbers -- as its
example patient mobile; its expectation is updated (not loosened) to the
now-correct two-issue result.
Minor 5: pins prohibitedTermPatternOverrides to exactly {"lead"} so a future
override for another term cannot land unnoticed by this regression suite.
Important 3 (B3): the interface-vocabulary scan only saw quoted/template
strings, missing the plain-JSX-text form this tree actually writes copy in
(shell.tsx, loading.tsx). Added a second raw-prose pass (comments and
className values stripped, everything else scanned as-is) and a fixture
test proving it catches a word planted as bare JSX text between tags, not
just inside quotes.
Minor 7 (B3): the real-tree scan now asserts filesScanned > 0, closing the
vacuous-pass hole a root with no matching files would otherwise leave open.
Minor 6: reworded the AUTOMATED_REPLY_RESPONSE comment claiming content "is
discarded... nothing is stored" as a design INTENT/contract rather than
settled fact, so it no longer contradicts the very next paragraph explaining
that no telephony provider exists yet to make that claim true or false.
Every fixable finding mutation-proven: B2 mutated back to the old allowlist
(the CRM test goes red) and to a bare `\bleads?\b` with no exemption (the
job-title test goes red); A1 mutated to drop the number half of the pattern
(the bare-number and four-numbers tests go red); B3's raw-prose pass and
floor assertion each mutated out and confirmed red. All mutations confirmed
present in the tree via direct file inspection before trusting the red
result.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rified independently
Executed the new negative-lookbehind pattern against 18 cases rather than
accepting the report. All ten previously-leaking commercial phrasings are now
refused -- including 'lead score', the case the scoring? typo let through, so
that finding is genuinely moot rather than relocated. All eight job-title and
ordinary-English cases still pass.
Records the rule the inversion confirms: when a check must separate a safe set
from a dangerous one, enumerate whichever set is CLOSED. Five job titles are
closed; commercial vocabulary is not. That test now applies to every allowlist,
ignore list and exemption the rest of this plan adds.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Re-review re-derived every claim by execution rather than reading assertions. Two
mechanism-level checks worth keeping: the A1/patient-mobile double report is
benign because the patient-mobile check is independent of the acknowledgement
flag, so acknowledging silences the noisy code and keeps the safety-critical one;
and the global-regex handling is correct, with the non-global copy used for
.test() and the global copy only with matchAll.
B2's mutation proof is two-directional as requested -- reverting to the allowlist
reddens the refusal test, widening to a bare pattern reddens the exemption test.
Those bracket the behaviour rather than being two views of one assertion.
Six minors deferred to the final whole-branch review, including a new one: the
job-title exemption needs whitespace adjacency but this domain writes 'team-lead'.
Inert today -- outside the scan roots, absent from both messages, and the
validator has no production callers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ed two
Went to write Task 2's brief, read the code it was meant to extract a pattern
from, and found the pattern already there. Two more premises fell the same way.
Ruling 84 cuts Task 2: readHandler already is the list-read pattern, used by
eight routes, four of them sharing the collection objectId convention. One
requirement survives into the first list route -- a contract test pinning that an
empty list is 200 with an empty array, never a 404, since auditedRead maps a null
release to denied and an empty array is neither.
Ruling 85: Task 5 builds no API. GET /api/caring-contacts/plans already lists
team plans. The patientDirectory object type is not an unwired gap -- the
referrals route already uses it, for patients who may not yet have a plan.
Ruling 86: design correction 1 is already in the domain. schedule.ts takes and
validates firstContactDate and the plans schema accepts it; only the screen
control is missing.
All three came from recon reports that were factually correct and whose
implications I carried too far. Before a brief says build this, open the file.
The cost of skipping that is not a wasted task, it is a second implementation of
something that already works, sitting beside the first, both maintained.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…Task 1)
Adds src/components/caring-contacts/workspace/empty-state.tsx, exporting
EmptyState -- the one shared empty-list surface the four Phase 2B list
screens (patients, schedule, templates, team) will use, so each does not
invent its own.
Modelled as a discriminated union on `kind`: "no-data" (nothing exists yet)
and "filtered" (a filter/search is hiding existing records) cannot be
confused with each other, because "filtered" requires its `because` and
`changedBy` at the type level -- there is no shared optional field a caller
could omit. The "filtered" branch reuses AutomatedState's "Why: .../What
changes it: ..." wording shape without rendering AutomatedState itself
(Ruling 81): the two have different triggers, and AutomatedState's
CircleAlert icon and state-name aria-label are wrong for "no patients yet".
A Server Component with no hooks (Ruling 13): the optional `action` slot
takes an already-built ReactNode (a <Link>, a form-submit button, or an
UnavailableDestination) rather than raw onClick/href props, the same way
ServiceStateBanner hosts UnavailableDestination as a child without becoming
a Client Component itself.
The icon started as lucide-react's Inbox and had to change to FolderOpen:
tests/caring-contacts-interface-vocabulary.test.ts's raw-prose scan caught
the bare identifier "Inbox" as the prohibited reply-monitoring/marketing
term "inbox" (CARING_CONTACTS_PROHIBITED_LANGUAGE), even though it was never
in a string literal -- a real catch by that guard, not a false positive.
tests/caring-contacts-empty-state.dom.test.tsx: 9 tests covering both kinds'
required copy, the absence of the other kind's wording, the optional action
(rendered vs. omitted, and genuinely actionable), a type-level compile
check that "filtered" cannot omit because/changedBy, a 320px-container
render, and the forced-colors override class. Mutation-tested: forcing the
"filtered" branch to always render the "no-data" JSX (dropping the reason
and remedy) reddened exactly the two tests that read that content; reverted
and confirmed green again.
docs/design-system/adoption-manifest.json regenerated via
`npm run design-system:adoption:update` -- the only change is the new test
file being recorded against ui-primitives.tsx's testFiles array.
Not wired into any screen (later tasks' job). Does not modify
automated-state.tsx, shell.tsx, or any route.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…out the commit contract
Verified in code before writing the brief. openWorkspaceOverlay already exists,
is exported and is DOM-tested, so Task 3 was never going to build an opening
mechanism. Reading it exposed the thing that matters instead.
WorkspaceOverlays' commit callback closes the overlay and records nothing, with
an honest comment noting this is safe because nothing in the workspace opens an
overlay yet, so no control advertises an action it does not perform. Task 3 is
precisely what would break that clause: the moment a screen can open an overlay,
its confirm button becomes a control that advertises an action the system does
not perform, which is what the button-wiring gate forbids.
So the trigger and the commit contract ship together, and the trigger requires a
commit handler rather than defaulting to a no-op. A screen must be unable to open
an overlay it has not wired, and the compiler is what finds the omissions rather
than a later sweep.
The general shape, worth keeping: a mechanism that is safe only because nothing
reaches it is not safe, it is unreached. Before making something reachable, check
what its arrival makes true.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Carries Ruling 87 into the brief, and tells the implementer plainly that the
overlay opening mechanism already exists so it does not rebuild one. The task is
the small client control plus the type-level requirement that a screen cannot
open an overlay it has not wired.
Leaves one genuinely open design question to the implementer with instructions to
choose deliberately and record what it rejected: WorkspaceOverlays is rendered
once by the shell rather than per screen, so a screen's commit handler has to
reach it somehow, and the obvious answers each carry costs. If the honest answer
is that it needs a decision above its level, it is told to say so rather than
pick silently.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Records the build of src/components/caring-contacts/workspace/empty-state.tsx,
the TDD red/green proof, the mutation proof, the interface-vocabulary catch
(Inbox -> FolderOpen), and the full verification chain (vitest, full test
suite, typecheck, lint -- including the two bounded lock-contention retries
before typecheck acquired the repo's heavy-run lease).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rected the briefs
The implementer paused mid-task on the heavy-run lease with its work uncommitted,
on a machine that has destroyed four working directories mid-session. Resumed
with an explicit ordering -- commit first, then retry the gate, bounded -- which
is now standing for every remaining brief. Machine health was measured rather
than assumed: node --version in 0.083s, so ordinary lease contention.
Records that Task C's interface-vocabulary scan caught a defect in Task 1 one
task after being built: a lucide Inbox icon, rejected because inbox is banned as
reply-monitoring language. It fired on a bare identifier rather than prose, which
is exactly the deferred concern Task C's re-review raised -- so that concern is
real and will recur. Whether it was a false positive is put to the reviewer
rather than settled here, with the note not to narrow the scan merely because it
was inconvenient once.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nent, and my brief caused the collision
The reviewer re-ran both mutations rather than reading the report, and found the
described mutation does not produce the reported numbers: mutating the filtered
branch gives 1 failed, not 2, because with the guard hardcoded true that branch
is dead code. The evidence is real, the account of which branch was mutated is
not. Second time on this programme that re-deriving a self-reported mutation
changed the answer.
Ruling 88 renames to ListEmptyState. ui-primitives.tsx already exports an
EmptyState and the adoption-manifest generator matches tests to components by a
bare name regex with no import awareness, so the caring-contacts test now falsely
counts as coverage for a shared primitive it never imports. False evidence about
test coverage in a governance artifact. My brief mandated the colliding name.
Also settles two open questions: action: ReactNode is correct because an onClick
prop cannot cross a Server-to-Client boundary; and the vocabulary scan will not
be narrowed after firing on an identifier, closing Task C deferred item 2 as
decided rather than deferred.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ble group, mutation-proof correction
Three review findings addressed:
1. Renamed EmptyState -> ListEmptyState (file, exports, test imports/usages).
src/components/ui-primitives.tsx already exports a registered design-system
primitive called EmptyState, used across 43 files.
scripts/generate-design-system-adoption.mjs credits test coverage by
matching \bName\b against raw test-file text with no import-path
awareness, so the bare name in this component's test file was crediting
tests/caring-contacts-empty-state.dom.test.tsx as coverage for the
unrelated ui-primitives EmptyState in the generated adoption manifest --
false evidence in a governance artifact. ListEmptyState does not match
\bEmptyState\b, so it cannot recreate the collision. Manifest
regenerated; the false testFiles line is confirmed gone from the
ui-primitives EmptyState entry (see report for the diff).
2. Wrapped the whole component in role="group" aria-label={props.heading},
reusing automated-state.tsx's accessible grouping (Ruling 81 forbade
rendering AutomatedState, not reusing its structure): a screen reader
that reaches the state enters a named group and finds "Why:"/"What
changes it:" without hunting elsewhere. Applied to both kinds, not only
"filtered", for one consistent grouping pattern. Uses the same
aria-label (not aria-labelledby) technique automated-state.tsx already
proves hook-free. Two new tests assert the group and its name for each
kind.
3. Re-ran the brief's named mutation correctly. The prior report described
mutating the "filtered" branch but had actually hardcoded the ternary's
guard to `true` AND replaced the no-data branch's real content with a
placeholder string -- coarser than specified, and it broke both kinds
equally rather than leaving no-data's real output intact. This round's
mutation touches only the guard (hardcoded true) plus a necessary
type-safe cast, reusing the actual no-data code path rather than a
placeholder: for a genuine no-data instance the cast is a no-op
(identical output); for a genuine filtered instance, reading a field
that does not exist on it renders nothing. Result: exactly 2 of 11
tests reddened, both in the "filtered" describe block; all "no-data"
tests stayed green throughout. Reverted and confirmed 11 passed again.
Report rewritten to describe this accurately.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Task 4 would have created the patients page rendering the empty state before
Task 5 gave it data -- a caseload screen saying 'No patients yet' whether or not
patients exist. That is precisely the defect Task 1's component was built to
prevent, and the orphan-route gate would have forced an inbound link at the same
moment, making the false state reachable rather than merely present.
Its real deliverables travel with the screen that has real data: the href, the
sitemap update, the codebase-index entry and the reachability assertion.
Same shape as Ruling 87: before making something reachable, ask what its arrival
makes true. There it was confirm buttons that do nothing; here a caseload screen
that says empty when it is not. Both invisible while unreachable.
Also records what already exists: caring-contacts-routes.ts declares all fifteen
destinations plus typed helpers for every dynamic route, and shell.tsx's own
comment says lighting one up is exactly adding an href.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
BigSimmoand others added 10 commits August 24, 2026 20:17
…d correct two claims
Corrects the section that argued for the blanket refusal (now OVERRULED, Ruling 90)
and the M-4 length estimate: NO_STAGED_COMMIT_REASON is 126 characters, roughly
4-5 lines at 390px, not 'one extra short paragraph'. Adds the fix-round mutation
table and reports one chained run that short-circuited and never happened.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…heck and lint clean
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… 1 and is owed a re-take
The coordinator's 32-passed result in 9cc7fa5 ran against the pre-fix head. Ruling 90
changed which rows render the refusal and the confirm-sequence fix changed what renders
at commit time, so that evidence does not name this head.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ould not fail
Records two corrections the implementer made to my framing. My suggested remedy
for the flashing refusal -- close before clearing -- would not have worked, since
both are synchronous while the URL change is not. A controller's suggested remedy
is a hypothesis like any other, and this one was falsified by someone reading the
code more carefully than I did.
The valuable part is a gate it caught not running: grep -c chained with && before
the test, where the mutation had stripped the very classes being counted, so grep
exited non-zero on a legitimate no-match and the test never ran. No summary line,
and it reads as 'confirm the mutation landed, then test it'.
Fifth member of a family this repo keeps meeting. The tell that unites them: ask
what the check prints when it fails, and confirm you have seen that output once.
Four of the five produce no output at all in the failing case.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1306c0b
The earlier green was correctly declared stale: Ruling 90 changed which rows
render the refusal paragraph and the confirm-sequence fix changed what renders at
commit time, so neither the input nor the output of the assertion that mattered
was the same thing twice.
Both greens read 32 passed, which is why the rule matters rather than why it does
not. Identical numbers across two different trees are two separate measurements
that happen to agree, and only one describes the code that now exists. Had the fix
broken the viewport assertion, the stale green would have said 32 passed about a
tree nobody was shipping.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All five findings addressed. The re-reviewer checked Ruling 90 against
definitions.ts itself: exactly 8 non-mutating rows, the withholding reads the
frozen flag, and definitions.ts is untouched across the task range, so the flag
was consulted rather than edited.
It corrected one of my claims. I described the fix as a one-shot token; it is two
mechanisms -- the token and a reconciliation effect -- and neither alone closes
the set. A mechanism described as one thing that is actually two is a description
under which a later maintainer can delete half and still believe the comment.
The generated manifest line is a different problem from Ruling 88 despite the
same weak generator: there the attribution was false, here it is true. Same
mechanism, opposite verdicts, which is why 'we saw this before' is not itself an
answer.
Group 0 done: Task 2 cut, Task 4 merged forward, leaving ListEmptyState and the
overlay trigger with its commit contract.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…link that lands with it
The first real screen of Phase 2B. A Server Component that reads the store
directly (Ruling 85), audits both reads with the same access identities the API
routes already record, and never calls getEpisode -- a directory has no reason
to hold a name or a mobile number.
Ruling 89: the shell's Patients href and the screen land in one change, so the
destination is never reachable in a state where it could say 'No patients yet'
without having read anything.
Filtering is server-side -- plan-state links plus an ordinary GET form -- so no
client boundary is added (Ruling 13).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tion and the route census honest
Two guards the new screen tripped:
* caring-contact-route-files forbids production workspace files from naming
mockup code at all, path included. The directory module cited the design
scratch by file path in a comment; it now names the component only.
* design-system-adoption is a census of production page routes. Patients is the
eightieth, and the count is stated rather than loosened.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e question
Full suite 9851 passed with only the two known Windows file-mode failures;
typecheck and lint fresh passes. Twelve mutations, each red on its covering
test.
Raises for the owner: the approved design shows a patient name and this screen
does not, and the design-system surface now claims browser proof for a route
the Playwright spec has never visited.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… names-only read
The implementer was told to stop and report if the approved design needed a
patient name rather than decide for itself, and did exactly that: the design
shows names, it built rows headed by the synthetic identifier and asked.
The tension is real both ways. getEpisode releases the name together with mobile
number, identifiers and cultural identity, so using it for a list pulls all four
into a page showing one. But a caseload a clinician cannot recognise their own
patients in is barely a caseload. The owner chose the narrow projection.
It is its own task, not a fix round: it changes the repository interface, so both
stores and the shared contract suite move together, and a fix round would have
ballooned into a domain change reviewed as a screen change.
Also records concern 2 as a false-evidence claim to fix rather than defer: the
design-system contract now asserts browser proof for a route the spec has never
visited. Same family as Ruling 88.
Browser gate green at this head, 32 passed -- the implementer's warning about
shifted control counts was right to give and did not materialise.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@supabase

supabaseBot commented Aug 24, 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 ↗︎.

@coderabbitai

coderabbitaiBot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 29 minutes.

View limit details

Limit details: You’ve used the included review currently available. Your 101 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

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

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: da56c988-d374-4bdb-9b61-e338b1e66833

📥 Commits

Reviewing files that changed from the base of the PR and between a5935dd and 143a23c.

⛔ Files ignored due to path filters (30)
  • docs/caring-contacts/PROGRESS-LEDGER.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/copy-decisions-recommended.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2a-build-record.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2a-continuation-prompt.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2a-handoff.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-build-record.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-1-brief.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-1-report.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-3-brief.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-3-report.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-5-brief.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-5-report.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-c-brief.md is excluded by !docs/**, !**/*.md
  • docs/caring-contacts/phase-2b-sdd-archive/task-c-report.md is excluded by !docs/**, !**/*.md
  • docs/codebase-index.md is excluded by !docs/**, !**/*.md
  • docs/design-system/ADOPTION.md is excluded by !docs/**, !**/*.md
  • docs/design-system/adoption-contract.json is excluded by !docs/**
  • docs/design-system/adoption-manifest.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/1838b99a-9323-4e3b-84a5-8e52535ecec8.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/18b32d38-540f-4d7c-af35-3f4f067e4998.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/854ca9ba-ba3b-442b-be6d-6f5873ed60ed.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/9da200a8-0ae0-451b-bef8-d1636b9e3cff.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/a0548b2c-2c80-44f9-9440-5b983e169a13.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/a4b0610d-ef92-4d1b-bcc8-3da0eb646d5a.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/ba655ad0-9934-4885-a959-5efd375a9bf1.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/cd97d402-7af1-473e-a2eb-dbac597cd03d.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/d7725691-5968-48f1-9912-bca3a5942731.json is excluded by !docs/**
  • docs/outstanding-issues-inbox/fa126adf-ade8-4027-a029-d59b4bef8967.json is excluded by !docs/**
  • docs/site-map.md is excluded by !docs/**, !**/*.md
  • docs/superpowers/plans/2026-08-24-caring-contact-phase-2b-screens.md is excluded by !docs/**, !**/*.md
📒 Files selected for processing (26)
  • data/outstanding-issues-snapshot.json
  • scripts/generate-site-map.ts
  • src/app/caring-contacts/patients/page.tsx
  • src/components/caring-contacts/workspace/list-empty-state.tsx
  • src/components/caring-contacts/workspace/overlays/overlay-commits.ts
  • src/components/caring-contacts/workspace/overlays/overlay-host.tsx
  • src/components/caring-contacts/workspace/overlays/overlay-trigger.tsx
  • src/components/caring-contacts/workspace/overlays/workspace-overlays.tsx
  • src/components/caring-contacts/workspace/patients-directory.tsx
  • src/components/caring-contacts/workspace/shell.tsx
  • src/lib/caring-contacts/message-copy.ts
  • src/lib/caring-contacts/message-policy.ts
  • src/lib/caring-contacts/message-rules.ts
  • tests/caring-contact-mockups.dom.test.tsx
  • tests/caring-contacts-empty-state.dom.test.tsx
  • tests/caring-contacts-explained-automation.dom.test.tsx
  • tests/caring-contacts-interface-vocabulary.test.ts
  • tests/caring-contacts-message-copy.test.ts
  • tests/caring-contacts-message-policy.test.ts
  • tests/caring-contacts-overlay-host.dom.test.tsx
  • tests/caring-contacts-overlay-trigger.dom.test.tsx
  • tests/caring-contacts-patients-directory.dom.test.tsx
  • tests/caring-contacts-patients-page.dom.test.tsx
  • tests/caring-contacts-workspace-shell.dom.test.tsx
  • tests/design-system-adoption.test.ts
  • tests/route-reachability.test.ts

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

@BigSimmo
BigSimmo enabled auto-merge (squash) August 24, 2026 13:55
cursor[bot]
cursorBot previously approved these changes Aug 24, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale comment

Approved. Cursor Bugbot was not present after the first check poll, so that signal was skipped; no approval policy required human review and this automation had no prior approval. No reviewers were assigned.

Open in WebView Automation

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor
cursorBot dismissed their stale reviewAugust 24, 2026 14:05

Dismissed the prior Approval Agent approval: Cursor Bugbot was present on the first check poll and never reached a terminal state within the 8-minute wait, so that required signal is incomplete. Human review is needed. Reviewer assignment will follow.

@github-actions

github-actionsBot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 2 failed job(s):

  • Static PR checksneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #13693 (success).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

cursor[bot]
cursorBot previously approved these changes Aug 24, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved. Cursor Bugbot was not present after the first check poll, so that signal was skipped; no approval policy required human review and this automation had no current approval. No reviewers were assigned.

Open in WebView Automation

Sent by Cursor Approval Agent: Pull Request Router and Approver

BigSimmoand others added 2 commits August 24, 2026 22:37
Static PR checks failed because data/outstanding-issues-snapshot.json
was behind docs/outstanding-issues.md (pending 128 vs 138) after
syncing this branch with origin/main. Regenerate via
scripts/generate-outstanding-issues-snapshot.mjs.
cursor[bot]
cursorBot approved these changes Aug 24, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved. Cursor Bugbot was not present after the first check poll, so that signal was skipped; no approval policy required human review and this automation had no current approval. No reviewers were assigned.

Open in WebView Automation

Sent by Cursor Approval Agent: Pull Request Router and Approver

@BigSimmo

Copy link
Copy Markdown
OwnerAuthor

Closing at the owner's direction — no work is lost and nothing is deleted. The branch
claude/browser-test-gate-handoff-d5c1db and every commit on it stay on origin, and Phase 2B
continues on it.

Why this was withdrawn rather than merged:

  • Auto-merge was armed on incomplete work. Roughly four of twenty tasks are done. The Patients
    directory is mid-review, and the names-only patient read the owner approved on 2026-08-24 is not
    built yet — so merging would have landed a caseload screen showing synthetic identifiers, which is
    the version he had already decided against.
  • It carried a known false claim. Adding the Patients route forced it into the
    caring-contacts-workspace design-system surface, whose proof is declared passed with
    tests/ui-caring-contacts-workspace.spec.ts as evidence — and that spec has never visited
    /caring-contacts/patients. A governance artifact asserting browser proof for an unvisited route is
    a defect, and it is fixed by adding the visit, not by softening the claim.
  • The description was the unfilled template, so PR policy was correctly failing: the diff
    touches patient-visible clinical wording and needs a completed Clinical Governance Preflight.
  • Seventeen more tasks would each have re-run the full required suite — including Production UI —
    on a proposal nobody intended to accept yet.

Replaced by a smaller, genuinely finished PR covering only the reviewed foundation: the owner's six
approved copy and message-policy changes, ListEmptyState, and the overlay trigger with its commit
contract. The clinician screens follow as their own PRs, group by group, so each stays reviewable.

auto-merge was automatically disabled August 24, 2026 14:42

Pull request was closed

BigSimmo pushed a commit that referenced this pull request Aug 24, 2026
Records the Run-PR-style sweep checks on #2341 (dictionary filter
band, fixed via main sync, unrelated flake confirmed) and #2347
(browser test gate handoff, fixed stale generated file + doc-link
allowlist entries; owner closed the PR mid-sweep for unrelated reasons).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
BigSimmo added a commit that referenced this pull request Aug 24, 2026
* Add branch review record for PR #2342 sweep
Records the Run-PR-style sweep check on PR #2342 (Improve Therapy
best-match visibility): review comments already fixed, branch synced
from main, CI green on completed checks.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* docs(ledger): record Run PR sweep of Dependabot PRs #2296, #2297, #2325, #2326
Immutable review records for the four-PR dependency sweep: CI fix on
#2325, clean main-syncs on #2296/#2297, and diagnosis-only on #2326
(Node 26 Docker bump incompatible with the engine-strict Node 24 pin).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* Add branch review record for PR #2339 sweep
Records the Run-PR-style sweep check on PR #2339 (therapy comparison
mobile design mockups): already fully green, only needed a main sync.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* Add branch review records for PR #2341, #2347 sweep
Records the Run-PR-style sweep checks on #2341 (dictionary filter
band, fixed via main sync, unrelated flake confirmed) and #2347
(browser test gate handoff, fixed stale generated file + doc-link
allowlist entries; owner closed the PR mid-sweep for unrelated reasons).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
---------
Co-authored-by: Claude <noreply@anthropic.com>
BigSimmo added a commit that referenced this pull request Aug 24, 2026
* Add branch review record for PR #2342 sweep
Records the Run-PR-style sweep check on PR #2342 (Improve Therapy
best-match visibility): review comments already fixed, branch synced
from main, CI green on completed checks.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* docs(ledger): record Run PR sweep of Dependabot PRs #2296, #2297, #2325, #2326
Immutable review records for the four-PR dependency sweep: CI fix on
#2325, clean main-syncs on #2296/#2297, and diagnosis-only on #2326
(Node 26 Docker bump incompatible with the engine-strict Node 24 pin).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* Add branch review record for PR #2339 sweep
Records the Run-PR-style sweep check on PR #2339 (therapy comparison
mobile design mockups): already fully green, only needed a main sync.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* Add branch review records for PR #2341, #2347 sweep
Records the Run-PR-style sweep checks on #2341 (dictionary filter
band, fixed via main sync, unrelated flake confirmed) and #2347
(browser test gate handoff, fixed stale generated file + doc-link
allowlist entries; owner closed the PR mid-sweep for unrelated reasons).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
* Add branch review records for PR #2338, #2337, #2333 sweep
Records the Run-PR-style sweep checks: #2337 fixed a design-token
ratchet failure, #2333 fixed a tap-target size regression and
resolved a concurrent-push merge, #2338 was only a main sync. #2333
and #2338 still have an open PR-policy failure (missing Clinical
Governance Preflight section) left for the PR author to fill in.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4RHy24AtgPobEQQwrj7u1
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto 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

@BigSimmo@claude