summaryrefslogtreecommitdiffhomepage
path: root/frontend-todo-handoff.md
diff options
context:
space:
mode:
Diffstat (limited to 'frontend-todo-handoff.md')
-rw-r--r--frontend-todo-handoff.md91
1 files changed, 0 insertions, 91 deletions
diff --git a/frontend-todo-handoff.md b/frontend-todo-handoff.md
deleted file mode 100644
index 4a81296..0000000
--- a/frontend-todo-handoff.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# FE handoff — todo task list surface
-
-Courier this to `../frontend` (cross-repo contract change; `lsp references` does
-not span repos — ORCHESTRATOR §7). All changes are ADDITIVE — nothing existing breaks.
-
-## What shipped (backend)
-
-A per-conversation **task list** the AI model maintains via a `todo_write` tool. The
-list is exposed to the frontend as a per-conversation **surface** (read-only). The
-model creates/updates the list during a turn; the surface updates live so the FE can
-render the current state.
-
-- **`todo_write` tool** — the model passes the FULL list each call (replaces the
- existing list). Returns the list as JSON. The tool description guides the model on
- when to use it (3+ step tasks, planning, etc.).
-- **State** — in-memory, per-conversation. No persistence (the list lives for the
- process lifetime of the conversation).
-- **No new wire types, no version bumps.** The todo surface uses the existing
- `custom` surface field kind (`ui-contract` unchanged). The `TodoItem` type is
- defined by the `todo` extension and carried in the surface payload — it is NOT
- in `@dispatch/wire` or `@dispatch/transport-contract`.
-
-## The surface
-
-The `todo` extension contributes a per-conversation surface:
-
-- **Surface id:** `"todo"`
-- **Scope:** `"conversation"` (subscribe with the `conversationId`)
-- **Region:** `"side"`
-- **Title:** `"Tasks"`
-- **One `custom` field**, `rendererId: "todo"`, `payload: TodoPayload`
-
-```ts
-interface TodoPayload {
- todos: readonly TodoItem[];
-}
-
-interface TodoItem {
- content: string;
- status: "pending" | "in_progress" | "completed" | "cancelled";
-}
-```
-
-- **Read-only** — no `invoke` actions. The model mutates the list via the
- `todo_write` tool; the FE only renders.
-- **Updates** on every `todo_write` call (subscriber-notify → full new spec with the
- updated `todos` array).
-- **Empty list** — an idle conversation (no todo list created yet, or the model
- cleared it with an empty array) renders `todos: []`. Hide the panel when empty.
-
-## What the FE needs to do
-
-1. **Subscribe** to the `todo` surface per conversation (same pattern as
- `message-queue` and `cache-warming` — `scope: "conversation"`, pass
- `conversationId` on subscribe).
-
-2. **Custom renderer** for `rendererId: "todo"` — render the `payload.todos` array
- as a task list. Suggested UI:
- - Each item shows `content` with a status indicator:
- - `pending` — empty circle / checkbox
- - `in_progress` — spinner / filled circle (highlight)
- - `completed` — checkmark (strikethrough or dim the content)
- - `cancelled` — X / dash (dim/strikethrough)
- - Order is significant — items are in the order the model provided them (array
- index = identity).
- - Only one item should be `in_progress` at a time (the tool description enforces
- this via guidance, not validation — but the model should comply).
-
-3. **Live updates** — the surface pushes a new spec on every `todo_write` call. No
- polling needed. Just re-render from the new `payload.todos`.
-
-4. **Empty state** — when `todos` is `[]`, hide the panel (the model hasn't created
- a list yet, or cleared it).
-
-## No other integration points
-
-- No new WS ops (no `chat.queue` equivalent — the model is the only writer).
-- No new HTTP endpoints (the list is tool-driven, not API-driven).
-- No new `AgentEvent` types (the list is not on the chat stream).
-- No version bumps in `@dispatch/wire` or `@dispatch/transport-contract`.
-
-## Notes
-
-- **In-memory only** — the todo list does NOT persist across server restarts. If
- the server restarts, the list is cleared. The model recreates it on the next
- `todo_write` call. This mirrors the message-queue behavior.
-- **Per-conversation** — each conversation has its own list. Switching conversations
- means subscribing to a different `conversationId` and rendering that conversation's
- list.
-- **Model-driven** — the FE has no control over the list (read-only surface). The
- model creates, updates, and clears items. The FE just displays the current state.