4.2 KiB
id, title, status, wave, depends_on, plan, requirements, acceptance_criteria, system_design
| id | title | status | wave | depends_on | plan | requirements | acceptance_criteria | system_design | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-batch-message-frame-mutations | Batch message frame mutations | completed | 2 |
|
plan.md |
|
|
|
Task 02: Batch Message Frame Mutations
Summary
Apply all accepted replacement messages from one animation frame in one Zustand and Immer transaction. Preserve message merge and barrier behavior.
Failing regression first
Add a scheduler test named applies different message keys with one bulk store action. Enqueue two message keys, flush one frame, and prove that the store
receives one ordered array instead of two updateMessage calls.
Add a real-store test named notifies subscribers once for one replacement frame. Seed two messages, subscribe to the session message array, apply the
bulk action, and prove that both messages change after one notification.
In scope
- Add
updateMessages(messages)to the session slice type and implementation. - Share partial-field merge logic with
updateMessage(message). - Convert, settle, and stale-filter frame payloads before one store action.
- Preserve first-key insertion order from the scheduler map.
- Preserve add, delete, and turn-settle barriers.
- Keep unaffected session arrays and message objects stable.
- Extend scheduler and slice tests for multi-session frames.
Out of scope
- Backend lifecycle or gateway coalescing changes.
- Protocol payload or timestamp changes.
- Incremental transcript grouping or virtualization.
- A replacement for Zustand or Immer.
Acceptance
- Several accepted message keys in one frame cause one bulk store call.
- A real store emits at most one subscriber notification for that frame.
- Final message fields match the current single-update behavior.
- Stale payloads remain rejected.
- Add and delete events cannot be reordered around pending replacements.
Verification
cd apps && pnpm --filter @kandev/web test -- lib/ws/handlers/messages.test.ts lib/state/slices/session/session-slice.update-messages.test.ts lib/state/slices/session/session-slice.merge-messages.test.ts
cd apps && pnpm --filter @kandev/web run typecheck
cd apps/web && pnpm exec eslint lib/ws/handlers/messages.ts lib/ws/handlers/messages.test.ts lib/state/slices/session/types.ts lib/state/slices/session/session-slice.ts lib/state/slices/session/session-slice.update-messages.test.ts
Files likely touched
apps/web/lib/ws/handlers/messages.tsapps/web/lib/ws/handlers/messages.test.tsapps/web/lib/state/slices/session/types.tsapps/web/lib/state/slices/session/session-slice.tsapps/web/lib/state/slices/session/session-slice.update-messages.test.ts
Dependencies
- Task 01 completes first so the later comparison trace can attribute logger and store work separately.
Risks
- Payload conversion inside the mutation can observe different turn state.
- A multi-session frame can accidentally replace an unaffected session array.
- Partial updates can clear known fields if undefined values are merged.
- Barrier tests can pass with mocks while real subscriber count still grows.
Parallelism
sequential
Inputs
- Bounded task status delivery acceptance criteria 7 and 9.
- The accepted replaceable session stream decision.
- Existing message scheduler and session slice tests.
Results
Implemented the bulk replacement action and scheduler batching. Accepted
replacement payloads are converted and settled before one updateMessages
transaction, while add, delete, and turn-settle events remain ordered barriers.
The shared merge helper preserves partial-field behavior and unaffected session
state remains stable. The stale-snapshot regression now asserts that neither the
legacy single-update action nor the production bulk action is called.
Targeted verification passed:
lib/ws/handlers/messages.test.tslib/state/slices/session/session-slice.update-messages.test.ts
The broader work-order verification remains in the package-level check.