# Pathrule Pattern: LLM Streaming UX (1.0.0)
# ::pathrule:package:llm-streaming-ux

### [RULE] Stream typed events with stable identity and order  (path: /app/api/chat)
<!-- scope: folder | priority: high | strict -->

The transport carries message, part, event, sequence, and terminal state instead of unframed text chunks. Raw chunk concatenation cannot represent tool calls, citations, errors, refusal, usage, reconnect position, or duplicate delivery safely. Enforce this boundary in /app/api/chat so invalid work stops before it reaches another subsystem or creates an externally visible side effect.

- Assign the assistant message and each content or tool part a stable server-generated identifier before streaming deltas.
- Use explicit event types for start, delta, tool state, metadata, error, canceled, and completed outcomes.
- Include a monotonic sequence or resumable cursor and make clients ignore already-applied events.
- Emit exactly one terminal outcome and close the stream after durable finalization or explicit failure.

Verification: Duplicate, reorder, delay, and drop events around tool and terminal boundaries; confirm the client converges or reconnects without corrupting content or effects.

---

### [MEMORY] Persistence follows semantic commit points  (path: /src/ai)

A visible delta is not yet a completed message, a confirmed tool result, or a billable product outcome. Persist the message shell and event cursor early for recovery, but mark content and tool parts with explicit in-progress, failed, canceled, and complete states.

Commit tool side effects through their own idempotent transaction before emitting a successful result. Finalize assistant content only after the terminal provider event and server validation. Keep partial output available for diagnostics or user recovery without presenting it as authoritative completion. Keep the decision explicit at /src/ai; moving it into an incidental caller makes behavior depend on which route happened to execute first.

See /app/api/chat for event framing and /src/components/chat for state rendering. That related boundary consumes this decision and carries the evidence that proves it still holds.

---

### [MEMORY] The interface renders state, not transport activity  (path: /src/components/chat)

Chunk arrival rate is noisy and does not map directly to readable motion, focus, or trustworthy completion. Buffer visual text updates to a stable cadence while applying semantic events such as tool start, approval, failure, and completion immediately.

Keep focus under user control and announce meaningful state changes through a restrained live region. Show cancellation as an available action while work is active and a durable outcome after it wins the race. Preserve the message identity and visible partial state across reconnect instead of adding another message. Keep the decision explicit at /src/components/chat; moving it into an incidental caller makes behavior depend on which route happened to execute first.

See /app/api/chat for terminal truth and the streaming UX test skill for degraded networks. That related boundary consumes this decision and carries the evidence that proves it still holds.

---

### [SKILL] implement-streaming-ux  (path: /)

---
name: implement-streaming-ux
description: Implement an LLM streaming flow from typed server events through accessible client state and persistence.
---

# Implement Streaming Ux

Run this procedure whenever the governed surface changes or its operational evidence becomes stale.

1. Define the event union, message and part identifiers, sequence or cursor, terminal outcomes, and serialization tests before building the UI.
2. Implement server production with cancellation propagation, idempotent tool effects, durable cursors, and one terminal transition.
3. Build a client reducer that applies duplicate-safe events, batches text rendering, restores persisted state, and exposes retry or reconnect without new identities.
4. Add accessible busy, tool, approval, error, canceled, and complete states; verify focus, reduced motion, copy, selection, and screen-reader announcements.

Record the decision, failed checks, and follow-up owner with the change. A successful run leaves reproducible evidence that another reviewer can inspect without repeating the investigation from memory.

---

### [SKILL] test-streaming-failures  (path: /tests/ai)

---
name: test-streaming-failures
description: Test partial, duplicated, reordered, disconnected, canceled, and failed LLM streams across server and client boundaries.
---

# Test Streaming Failures

Run this procedure whenever the governed surface changes or its operational evidence becomes stale.

1. Create deterministic event fixtures with text, tool, metadata, refusal, usage, error, canceled, and completed events around every boundary.
2. Inject duplicate, missing, delayed, and out-of-order delivery plus disconnect before and after tool commit and final persistence.
3. Race user cancellation with provider completion and tool completion; confirm exactly one terminal state and no orphaned side effect.
4. Reconnect from every cursor, reload the UI, and verify message identity, rendered content, accessibility state, stored status, and usage remain consistent.

Record the decision, failed checks, and follow-up owner with the change. A successful run leaves reproducible evidence that another reviewer can inspect without repeating the investigation from memory.
