Skip to content

feat(chat): open agents' plans, to-dos and edits in a Work panel - #181

Merged
titan-ron merged 1 commit into
mainfrom
titan/side-panel-changes-plans-26aab7
Sep 24, 2026
Merged

titan-ron merged 1 commit into
mainfrom
titan/side-panel-changes-plans-26aab7

Conversation

@titan-ron

Copy link
Copy Markdown
Collaborator

Summary

Agents hand the person things to look at while they work: a plan to approve, a to-do list, edits to files. Until now each of these reached the chat as up to 400 characters of JSON behind a collapsed tool row. The plan gate's Approve the plan card didn't even show the plan.

This change carries them as structured data and opens them in a Work panel beside the conversation:

  • Plan: the proposed plan as a document. Every version is kept (Earlier / Later), and the tab is flagged while the plan waits for approval.
  • To-dos: the agent's list as it stands now. Each step shows as not started, in progress or done, marked by shape plus a word, never colour alone.
  • Edits: every file the agent changed, in first-touched order, with each change shown the way its call described it. An edit whose call failed is listed as didn't apply. A link points to Changes (⌘D) for what is actually on disk.

A tool row that carries one of these is a single button: it shows the plan's title, the list's progress, or the files with their +/− counts, and one click opens the panel at that item. The header's Work key (⌘J) appears once the conversation holds any of them and opens on what matters now. Escape closes the panel and returns focus. The approval card now shows the plan above its two answers.

What each agent contributes

Plan To-dos Edits
Claude Code ExitPlanMode TaskCreate/TaskUpdate (numbered by their results), TodoWrite Edit, MultiEdit, Write
Codex — update_plan, the exec stream's todo_list apply_patch (function, freeform, or as a shell command), the typed FileChange items that code-mode patches complete with, the exec stream's file_change (paths only)
Copilot CLI exit_plan_mode — (kept in its own SQL table, not the log) edit, create, apply_patch
ACP agents — plan updates diff content on the announcing call

How

  • src/main/parsers/artifacts.ts (IO-free) reads each call's input into SessionMessage.artifact / ChatEvent.artifact. It is shared by the three log parsers and by the stream parsers in chat.ts and acp-core.ts. Everything is bounded in main (24 files per call, 400 lines per file, 400 characters per line, 3 lines of context around each change of a before/after pair) because it crosses IPC on every transcript read.
  • A call whose result failed is marked on its own row (failed), matched to its result by tool-use id (Claude) or toolCallId (Copilot). Pairing by adjacency got parallel calls wrong.
  • Codex: current rollouts apply patches inside code-mode exec scripts, so their only record of a change is the FileChange item. Those are now rendered as apply_patch rows, unless the rollout applies patches as calls of their own (then the call is the row, never both). Streamed file_change rows use the same name, so a rejoined turn can match the two.
  • The renderer only folds artifacts (work.ts); it never parses tool JSON. WorkPanel.tsx reuses the card tabs and the review's diff blocks (DiffLines is now exported from InstructionDiff).
  • Layout: under the header the chat is now a row (.chat-deck → .chat-main + panel). Below 720px of deck, a @container rule makes the panel cover the conversation instead, the way Changes does. Changes closes a covering panel first so it never opens unseen behind it.

Screenshots (UI tour fixture world)

Edits, opened from the row (desktop):
edits

To-dos (⌘J) · the plan in its approval card · the plan in the panel:
todos
plan card
plan panel

900×700: the panel covers the conversation:
mid

Testing

  • npm run typecheck and npm test (124 files, 1914 passed) on the branch rebased onto main
  • npm run test:e2e: 46 passed (the minimum-window audit and the a11y walk included; 6 opt-in specs skipped as usual)
  • npm run ui:tour: new chat-work-edits, chat-work-todos, chat-plan and chat-work-plan shots at desktop, 900×700, the 560×420 floor and 200%; the fixture world gained Claude tasks and a plan waiting for approval
  • New tests: tests/artifacts.test.ts (every tool shape, patch and unified-diff parsing, bounds), tests/work.test.ts (the fold), parser tests against real log shapes for all three CLIs, stream and ACP mapping, and tests/component/work-panel.test.tsx

Not covered

  • Copilot's to-dos: it writes them as free-form SQL against its own table, so parsing its log would be fragile. Reading that table directly is the reliable follow-up.
  • An ACP diff that arrives only in a later tool_call_update for a call already on screen is not carried. The session's log still has it.
  • A Codex turn Cockpit is streaming names changed files but not lines; reopening the session reads the lines from the log.

What an agent hands the person to look at - a plan to approve, a to-do
list, an edit - reached the chat as 400 characters of JSON behind a
collapsed tool row. Each tool call's own input is now read in main into a
bounded SessionMessage.artifact, for Claude (ExitPlanMode, TodoWrite,
TaskCreate/TaskUpdate, Edit, MultiEdit, Write), Codex (update_plan,
apply_patch, the FileChange items code-mode patches complete with, the
exec stream's todo_list and file_change) and Copilot (exit_plan_mode,
edit, create, apply_patch), plus ACP plan updates and diff content.

The renderer folds them into a Work panel beside the transcript: Plan
(every version, flagged while it waits for approval), To-dos (where the
list stands now) and Edits (per file, each change as its call described
it, with a link to Changes for what is on disk). A row that carries one
opens the panel at itself in one click; the header's Work key and cmd+J
open it on what matters now. Under 720px of deck the panel covers the
conversation instead. A plan gate's approval card now shows the plan.

A call whose result failed is marked on its own row, matched by tool-use
id, so an edit that never landed reads as one. Codex's streamed
file_change rows are named as their logged FileChange rows are, so a
rejoined turn matches the two.
@github-code-quality

github-code-quality Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/unit

The overall line coverage in commit a751c3b in the titan/side-panel-cha... branch is 80%. The line coverage in commit 06299b0 in the main branch is 79%.

Show a line coverage summary of the most impacted files.
File main 06299b0 titan/side-panel-cha... a751c3b +/-
src/main/chat.ts 75% 75% 0%
src/main/parsers/util.ts 93% 93% 0%
src/main/acp-core.ts 98% 98% 0%
src/main/parsers/copilot.ts 89% 90% +1%
src/main/parsers/codex.ts 88% 90% +2%
src/main/parsers/claude.ts 84% 87% +3%
src/main/parsers/artifacts.ts 0% 97% +97%

TypeScript / code-coverage/component

The overall line coverage in commit a751c3b in the titan/side-panel-cha... branch remains at 88%, unchanged from commit 06299b0 in the main branch.

Show a line coverage summary of the most impacted files.
File main 06299b0 titan/side-panel-cha... a751c3b +/-
src/renderer/src/ChatView.tsx 95% 93% -2%
src/renderer/src/logos.tsx 95% 96% +1%
src/renderer/src/work.ts 0% 66% +66%
src/renderer/src/WorkPanel.tsx 0% 89% +89%

Updated September 24, 2026 20:55 UTC

@titan-ron
titan-ron merged commit 167b09e into main Sep 24, 2026
9 checks passed
@titan-ron
titan-ron deleted the titan/side-panel-changes-plans-26aab7 branch September 24, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant