3.9 KiB
3.9 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec | |
|---|---|---|---|---|---|---|---|
| 03-bound-frontend-stream-work | Bound frontend stream work | done | 3 |
|
plan.md | ../../specs/platform/bounded-task-status-delivery.md |
Task 03: Bound Frontend Stream Work
Acceptance
- During one animation frame, hundreds of updates for one message cause one Zustand update with the newest complete payload.
- Different message keys each make progress once per frame; add/delete and turn-settle barriers cannot resurrect or leave stale message state.
- Pending frame work is cleared when the router/client is disposed or replaced.
- Office task detail rerenders with equivalent task/session objects send no subscription changes or snapshot replays; real membership changes apply only the session-ID delta.
- Desktop and mobile share the same store behavior and no new copy/layout is introduced.
TDD sequence
- RED: add message-handler tests with a fake animation-frame scheduler for same-key replacement, multi-key fairness, barriers, and teardown.
- RED: add an Office live-sync rerender test proving equivalent IDs do not unsubscribe/resubscribe and changed membership applies only a delta.
- GREEN: extract the frame-batched replacement helper and route
session.message.updatedthrough it. - GREEN: extract/stabilize Office live sync around a sorted session-ID key and incremental membership reconciliation.
- REFACTOR: keep transport helpers independent of React components and verify shared mobile/desktop state selectors do not need changes.
Files likely touched
apps/web/lib/ws/handlers/messages.ts- new
apps/web/lib/ws/handlers/messages.test.ts apps/web/lib/ws/router.tsor its disposal ownerapps/web/app/office/tasks/[id]/page.tsx- new extracted Office live-sync hook/helper and test
- focused session-slice tests if message merge semantics change
Verification
cd apps/web && pnpm exec vitest run \
lib/ws/handlers/messages.test.ts \
'app/office/tasks/[id]/use-session-live-sync.test.tsx'
cd apps/web && pnpm run typecheck
cd apps/web && pnpm run lint
Dependencies
Task 02 defines replacement and semantic-barrier ordering at the wire boundary.
Parallelism
Sequential. Task 04 needs the complete backend/frontend containment stack.
Inputs
- Existing
registerMessagesHandlers, session sliceupdateMessage, and OfficeuseSessionLiveSyncbehavior. - Mobile parity contract in the parent plan.
Risks
requestAnimationFrameis throttled in hidden tabs; retain only latest full state and reconcile on resume.- A queued update after delete can apply stale state unless deletion cancels the key before store mutation.
- Sorting/memoizing IDs must not hide real membership changes or leak refcounts.
Output contract
Report input versus store-update counts, barrier behavior, subscription call counts across rerenders/membership changes, desktop/mobile shared-state proof, test results, and files changed.
Verification results
pnpm exec vitest run lib/ws/handlers/messages.test.ts 'app/office/tasks/[id]/use-session-live-sync.test.tsx'— passed (7 tests).pnpm run typecheck— passed.pnpm run lint— passed for the web package.session.message.updatedbatching keeps one latest payload per key per animation frame; add/delete and turn-complete events flush as barriers.- Office live sync sorts and deduplicates IDs, reconciles only membership deltas, and clears subscriptions on disconnect/unmount. Desktop and mobile continue to consume the same WebSocket/store path; no layout or copy changed.
Files changed
apps/web/lib/ws/handlers/messages.tsapps/web/lib/ws/handlers/messages.test.tsapps/web/lib/ws/handlers/turns.tsapps/web/lib/ws/router.tsapps/web/lib/ws/use-websocket.tsxapps/web/app/office/tasks/[id]/page.tsxapps/web/app/office/tasks/[id]/use-session-live-sync.tsapps/web/app/office/tasks/[id]/use-session-live-sync.test.tsx