dock Claude's task list above the composer (T-308)

Claude's TodoWrite checklist was invisible. Add a TaskItem/TaskStatus
model + a latest-wins parser (taskListFrom) that reads the most recent
TodoWrite tool call (it replaces the whole list each time), and a compact
display-only ClaudeTaskDock pinned between the conversation and the
composer: collapsed to "N tasks · M done" + the current in-progress item,
expandable to the full checklist with per-item status glyphs + a11y
labels. Hidden when there are no tasks. Parser + widget tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-10 14:31:35 +02:00
co-authored by Claude Opus 4.8
parent 2c8e9f2821
commit 4f632d3cdd
8 changed files with 348 additions and 0 deletions
+8
View File
@@ -9,6 +9,7 @@ import 'claude_banner.dart';
import 'claude_composer.dart';
import 'claude_config.dart';
import 'claude_status.dart';
import 'claude_task_dock.dart';
import 'clipboard_paste.dart';
import 'activity_cluster.dart' show foldLevelFromName, kActivityFoldLevelKey;
import 'conversation_controller.dart';
@@ -21,6 +22,7 @@ import 'session_orchestrator.dart';
import 'session_picker.dart';
import 'slash_commands.dart';
import 'stream_json_session.dart';
import 'task_list.dart';
import 'transcript_reader.dart';
/// The Claude conversation pane. Drives `claude` over the stream-json control
@@ -513,6 +515,12 @@ class _ClaudePaneState extends State<ClaudePane> {
),
),
),
// Claude's task list, docked above the composer (T-308). Rebuilds
// with the conversation; renders nothing when there are no tasks.
ListenableBuilder(
listenable: _conversation!,
builder: (_, __) => ClaudeTaskDock(tasks: taskListFrom(_conversation!.items)),
),
// An open prompt takes the composer's space and hides the text
// input until it's answered, so interaction stays out of the
// conversation stream (D-78).