/** * Canonical state inventory for the chat-style task thread (the default task * view; the classic legacy view sits behind enableClassicTaskInterface). * * This list is the single source of truth for: * - the dev harness state switcher (/dev/task-chat-lab), and * - the finish-line test that asserts every state renders without error. * * Each id traces to a real agent-protocol state (plan Deliverable 1). `tier` * marks whether the state already streams live ("live") or is emitted upstream * but dropped by acpx today ("tier-b", driven by synthetic events in the * harness, live wiring flagged). `surface` says where the state renders. */ export const TASK_CHAT_STATES = [ "session-start", "human-message", "agent-message", "thinking", "responding", "responding-burst", "tool-call", "diff", "working", "running", "completed", "activity-phases", "awaiting-approval", "plan-todo", "interrupted", "refused", "truncated", "live-token-cost", ] as const; export type TaskChatStateId = (typeof TASK_CHAT_STATES)[number]; export type TaskChatStateTier = "live" | "tier-b"; export type TaskChatStateSurface = "thread" | "plan"; export interface TaskChatStateMeta { id: TaskChatStateId; label: string; tier: TaskChatStateTier; surface: TaskChatStateSurface; /** Real protocol source, quoted for the harness inspector. */ protocol: string; } export const TASK_CHAT_STATE_META: Record = { "session-start": { id: "session-start", label: "Session start", tier: "live", surface: "thread", protocol: 'acpx.session → TranscriptEntry kind:"init"', }, "human-message": { id: "human-message", label: "Human message", tier: "live", surface: "thread", protocol: 'IssueComment authorType:"user"', }, "agent-message": { id: "agent-message", label: "Final response", tier: "live", surface: "thread", protocol: 'PRP item.delta kind:"agentMessage" channel:"final"', }, thinking: { id: "thinking", label: "Thinking", tier: "live", surface: "thread", protocol: "text_delta stream:thought (ACP agent_thought_chunk)", }, responding: { id: "responding", label: "Progress update (streaming)", tier: "live", surface: "thread", protocol: 'PRP item.delta kind:"agentMessage" channel:"progress"', }, "responding-burst": { id: "responding-burst", label: "Progress update burst", tier: "live", surface: "thread", protocol: "text_delta stream:output ×N, tool calls between (PAP-368 dwell)", }, "tool-call": { id: "tool-call", label: "Tool call", tier: "live", surface: "thread", protocol: "acpx.tool_call (ACP tool_call / tool_call_update)", }, diff: { id: "diff", label: "Diff", tier: "live", surface: "thread", protocol: 'ToolCallContent type:"diff" → TranscriptEntry kind:"diff"', }, working: { id: "working", label: "Working", tier: "live", surface: "thread", protocol: "heartbeat.run.progress + acpx.status", }, running: { id: "running", label: "Running", tier: "live", surface: "thread", protocol: 'message.status.type === "running"', }, completed: { id: "completed", label: "Completed (collapsed)", tier: "live", surface: "thread", protocol: "acpx.result (StopReason in subtype)", }, "activity-phases": { id: "activity-phases", label: "Long-run activity phases", tier: "live", surface: "thread", protocol: "assistant boundaries + chronological tool calls", }, "awaiting-approval": { id: "awaiting-approval", label: "Awaiting approval", tier: "tier-b", surface: "thread", protocol: "ACP RequestPermissionRequest + PermissionOptionKind", }, "plan-todo": { id: "plan-todo", label: "Plan / todo", tier: "tier-b", surface: "plan", protocol: "ACP Plan { entries: PlanEntry[] }, PlanEntryStatus", }, interrupted: { id: "interrupted", label: "Interrupted", tier: "tier-b", surface: "thread", protocol: 'AcpRuntimeTurnResult.status:"cancelled" / StopReason "cancelled"', }, refused: { id: "refused", label: "Refused", tier: "tier-b", surface: "thread", protocol: 'StopReason "refusal"', }, truncated: { id: "truncated", label: "Truncated", tier: "tier-b", surface: "thread", protocol: 'StopReason "max_tokens" | "max_turn_requests"', }, "live-token-cost": { id: "live-token-cost", label: "Live token / cost", tier: "tier-b", surface: "thread", protocol: "ACP UsageUpdate { used, size, cost }", }, }; export const TASK_CHAT_STATE_LIST: TaskChatStateMeta[] = TASK_CHAT_STATES.map( (id) => TASK_CHAT_STATE_META[id], );