You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Preserve the carry choice across target confirmation
Fresh evidence in the implementation shows that the absent-destination flow still loses its context: this link carries only the destination year, and after confirmation CmeSetupRoute pushes back to /cme/setup, not to the source plan or selected goal. A doctor must manually find the prior year and choose the goal again, so the promised confirm-then-return carry action is not implemented. Include the source year and goal ID in a validated return target and resume that exact carry choice after confirmation.
PR draft ready (2026-10-15) — local branch mavis/3161-cme-goal-carry-choice, not pushed, no PR opened, no label added.
Shape (4 files, 267 +/3 -):
src/lib/cme/return-target.ts (new, 66 lines) — zod-validated { fromYear, goalId? } round-trip via base64url JSON. decodeCmeCarryReturnTarget returns null on any failure rather than throwing — worst case is the pre-fix behaviour, never an unsafe deep-link.
src/components/cme/cme-setup-route.tsx — reads ?returnTo= via useSearchParams, decodes, after confirmation navigates to /cme/plan?year=<fromYear>[&goal=<goalId>]#cme-carry-goals when valid, else falls back to the original /cme/setup?year=<year> (no regression).
src/components/cme/cme-plan-page.tsx:354 — the "Confirm <year+1> targets first" link now appends &returnTo=<encoded> so the carry context survives the round trip.
✅ Related CPD tests (no regressions): cme-setup.dom.test.tsx 10/10, cme-plan-page.dom.test.tsx 14/14, cme-plan-carry.test.ts 10/10, cme-one-tap-routine-log.dom.test.tsx 3/3, cme-catch-up-plan.test.ts 11/11. 48/48 pass.
Open for owner decision:
The goalId field is in the schema but only fromYear is set in cme-plan-page.tsx. A future flow that carries a specific goal could pass goalId too. Currently the link is invoked from the general "Confirm <year+1> targets first" prompt and the doctor re-selects the goal on return. Acceptable, or do you want the specific goal to flow through now?
The cmeCarryReturnTargetHref always appends #cme-carry-goals (the carry section anchor on the plan page). If the doctor came from elsewhere (e.g., the dashboard), this still lands them on the plan page at the carry section. Confirm the landing is right for those flows before they adopt the link.
Diff:/workspace/issue-3161-pr-diff.patch (327 lines including the test). Branch is local at mavis/3161-cme-goal-carry-choice in /workspace/PsychSift, staged, not committed, not pushed. Push + PR + merge is yours.
Rebase + re-verification (2026-10-15, 14:25 local):
Main moved forward 5 commits (a07dec0 → e0c62df) since the PR draft was first staged. Rebased branch mavis/3161-cme-goal-carry-choice onto the new main. The 4 files in the diff are unchanged in shape; no conflicts with the 5 new commits.
No open PR addresses this issue (verified by is:pr is:open search). The 4 currently open PRs on PsychSift (#3555 migrations rule, #3554 search cutoff, #3553#3538 walk-back, #3546 admin ingestion) are unrelated.
Diff at /workspace/issue-3161-pr-diff.patch — 327 lines, 267+/3-, 4 files. Branch is local, not pushed, no PR opened, no label added.
Activity
BigSimmo commentedon Oct 15, 2026
PR draft ready (2026-10-15) — local branch
mavis/3161-cme-goal-carry-choice, not pushed, no PR opened, no label added.Shape (4 files, 267 +/3 -):
src/lib/cme/return-target.ts(new, 66 lines) — zod-validated{ fromYear, goalId? }round-trip via base64url JSON.decodeCmeCarryReturnTargetreturnsnullon any failure rather than throwing — worst case is the pre-fix behaviour, never an unsafe deep-link.src/components/cme/cme-setup-route.tsx— reads?returnTo=viauseSearchParams, decodes, after confirmation navigates to/cme/plan?year=<fromYear>[&goal=<goalId>]#cme-carry-goalswhen valid, else falls back to the original/cme/setup?year=<year>(no regression).src/components/cme/cme-plan-page.tsx:354— the "Confirm <year+1> targets first" link now appends&returnTo=<encoded>so the carry context survives the round trip.tests/cme-setup-route-return-target.dom.test.tsx(new, 178 lines) — 11 cases: round-trip with/without goal, malformed payload, tampered payload (out-of-range year, overlong goalId), missing target, programme-page no-confirm, codec edge cases.Verification (all run on Node 24.22, npm 11.19):
tsc -p tsconfig.changed.json --noEmit(focused on the 4 changed files): 0 errors.tests/cme-setup-route-return-target.dom.test.tsx: 11/11 pass.cme-setup.dom.test.tsx10/10,cme-plan-page.dom.test.tsx14/14,cme-plan-carry.test.ts10/10,cme-one-tap-routine-log.dom.test.tsx3/3,cme-catch-up-plan.test.ts11/11. 48/48 pass.Open for owner decision:
goalIdfield is in the schema but onlyfromYearis set incme-plan-page.tsx. A future flow that carries a specific goal could passgoalIdtoo. Currently the link is invoked from the general "Confirm <year+1> targets first" prompt and the doctor re-selects the goal on return. Acceptable, or do you want the specific goal to flow through now?cmeCarryReturnTargetHrefalways appends#cme-carry-goals(the carry section anchor on the plan page). If the doctor came from elsewhere (e.g., the dashboard), this still lands them on the plan page at the carry section. Confirm the landing is right for those flows before they adopt the link.Diff:
/workspace/issue-3161-pr-diff.patch(327 lines including the test). Branch is local atmavis/3161-cme-goal-carry-choicein/workspace/PsychSift, staged, not committed, not pushed. Push + PR + merge is yours.BigSimmo commentedon Oct 15, 2026
Rebase + re-verification (2026-10-15, 14:25 local):
Main moved forward 5 commits (
a07dec0→e0c62df) since the PR draft was first staged. Rebased branchmavis/3161-cme-goal-carry-choiceonto the new main. The 4 files in the diff are unchanged in shape; no conflicts with the 5 new commits.Re-verification on current main (
e0c62df):tsc -p tsconfig.changed.json --noEmit(4 changed files): 0 errors.tests/cme-setup-route-return-target.dom.test.tsx: 11/11 pass.No open PR addresses this issue (verified by
is:pr is:opensearch). The 4 currently open PRs on PsychSift (#3555 migrations rule, #3554 search cutoff, #3553 #3538 walk-back, #3546 admin ingestion) are unrelated.Diff at
/workspace/issue-3161-pr-diff.patch— 327 lines, 267+/3-, 4 files. Branch is local, not pushed, no PR opened, no label added.fix(cpd): return to the carry choice after confirming next year's tar…