diff options
| author | Adam Malczewski <[email protected]> | 2026-06-30 01:30:06 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-30 01:30:06 +0900 |
| commit | bf74aeab143a49005c380706ae9847cf064fd2f2 (patch) | |
| tree | c9e93dc0ebe818e7c0d0aafeba8387afd161da3f /frontend-conversation-lifecycle-handoff.md | |
| parent | 6dd9ea9b935e5011c16faed6c869c976cf5ff172 (diff) | |
| download | dispatch-main.tar.gz dispatch-main.zip | |
Removed 40+ markdown files that were cluttering the repo root:
- frontend-*-handoff.md (28 files) — historical API contract handoffs, features all implemented
- backend-to-fe-handoff.md, backend-to-fe-handoff-2.md — old handoff docs
- broken-chat-repair-handoff.md — old repair handoff
- PLAN-mcp.md, PLAN-per-edit-diagnostics.md — old planning docs
- ai-review-report.md, crash-review-report.md — one-time review reports
- tasks.md, HANDOFF.md — outdated status docs (git log is the source of truth)
Kept: AGENTS.md, GLOSSARY.md, ORCHESTRATOR.md, README.md
Also: gitignored ai-review-report.md so future Gemini reviews don't commit it
Diffstat (limited to 'frontend-conversation-lifecycle-handoff.md')
| -rw-r--r-- | frontend-conversation-lifecycle-handoff.md | 102 |
1 files changed, 0 insertions, 102 deletions
diff --git a/frontend-conversation-lifecycle-handoff.md b/frontend-conversation-lifecycle-handoff.md deleted file mode 100644 index ca6de57..0000000 --- a/frontend-conversation-lifecycle-handoff.md +++ /dev/null @@ -1,102 +0,0 @@ -# FE handoff — conversation lifecycle (tab persistence across devices) - -Courier this to `../frontend`. All changes are ADDITIVE — nothing existing breaks. - -## What shipped (backend) - -Conversations now have a lifecycle **status** field: `active`, `idle`, or `closed`. -This enables tab persistence: when a new browser connects, it fetches all -`active` + `idle` conversations and restores the tab bar. - -- **`active`** — an agent is currently generating (a turn is in-flight). -- **`idle`** — conversation exists, not generating. User can send a message to resume. -- **`closed`** — user dismissed the tab (hidden from the tab bar, not deleted). - -Status transitions are driven by the backend: -- `idle → active` when a turn starts. -- `active → idle` when a turn settles (done/error). -- `→ closed` when `POST /conversations/:id/close` is called. - -## Bump pinned deps -- `@dispatch/wire` → `0.10.0` -- `@dispatch/transport-contract` → `0.14.0` - -## New types (`@dispatch/wire` + `@dispatch/transport-contract`) - -```ts -export type ConversationStatus = "active" | "idle" | "closed"; - -// ConversationMeta now has a status field: -export interface ConversationMeta { - readonly id: string; - readonly createdAt: number; - readonly lastActivityAt: number; - readonly title: string; - readonly status: ConversationStatus; -} - -// New WS message (server → client): -export interface ConversationStatusChangedMessage { - readonly type: "conversation.statusChanged"; - readonly conversationId: string; - readonly status: ConversationStatus; -} -``` - -`ConversationStatusChangedMessage` is added to the `WsServerMessage` union. - -## `GET /conversations?status=active,idle` — filter by status - -The existing `GET /conversations` endpoint now accepts an optional `?status=` -query param: a comma-separated list of statuses to filter by. - -- **Default (no param):** returns ALL conversations (all statuses). -- `?status=active,idle` → only active + idle (what the FE tab bar wants). -- `?status=closed` → only closed conversations (for a history view). -- Invalid values are silently dropped. If all values are invalid, no filter - is applied (returns all). - -## `POST /conversations/:id/close` — marks as closed - -The existing close endpoint now also sets the conversation's status to `closed` -in the store. This persists across server restarts. The response is unchanged -(`{ conversationId, abortedTurn }`). - -## `conversation.statusChanged` WS message - -Broadcast to ALL connected WS clients whenever a conversation's status changes. -The backend emits this synchronously alongside the existing `turnStarted` / -`turnSettled` / `conversationClosed` hooks. - -```ts -{ type: "conversation.statusChanged", conversationId: "conv-1", status: "active" } -``` - -## What the FE needs to do - -1. **On connect:** call `GET /conversations?status=active,idle` to fetch - conversations for the tab bar. Render tabs for each. - -2. **`active` tabs:** subscribe to the conversation's live stream - (`chat.subscribe` WS op) to receive in-flight events. - -3. **`idle` tabs:** load history via `GET /conversations/:id`. No live - subscription needed until the user sends a message. - -4. **Tab close button:** call `POST /conversations/:id/close` to mark the - conversation as `closed`. Remove it from the tab bar. - -5. **Handle `conversation.statusChanged` WS messages:** update the tab's - status indicator. When a conversation goes `idle → active`, show a - loading/generating indicator. When it goes `active → idle`, remove the - indicator. When it goes `closed`, remove the tab. - -6. **Closed conversations:** accessible from a history view - (`GET /conversations?status=closed`). Can be reopened by sending a message - (which transitions `closed → active`). - -## CLI - -`dispatch list` now defaults to `active,idle` (excludes closed). New flags: -- `--status <active|idle|closed>` — filter by a single status. -- `--all` — include closed (show all statuses). |
