diff --git a/.pql/changelog/ticket_history/2026-06.sql b/.pql/changelog/ticket_history/2026-06.sql index 8e4ba1f7..ac11bca0 100644 --- a/.pql/changelog/ticket_history/2026-06.sql +++ b/.pql/changelog/ticket_history/2026-06.sql @@ -3173,3 +3173,4 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2W4G9K8ZF782W7H2TM5XA8', 'status', 'backlog', 'ready', NULL, '2026-06-10 12:12:30', '2026-06-10 12:12:30', '2026-06-10 12:12:30', NULL, '6b9aaf9bd7ec3ad4ad3b95d1468ff9cf', 2) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB1XDWKQ594ET4GDYEFK5ZJ4', 'status', 'ready', 'done', NULL, '2026-06-10 12:14:00', '2026-06-10 12:14:00', '2026-06-10 12:14:00', NULL, 'd90deec4e27b4298c6f7280338599c01', 2) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB1Q1Y3CYJHD7W5F68VDB6T4', 'status', 'ready', 'done', NULL, '2026-06-10 12:31:23', '2026-06-10 12:31:23', '2026-06-10 12:31:23', NULL, 'dbac53eef0b8d58dbb5f00a2f77ee52f', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB1Q1Y3CYJHD7W5F68VDB6T4', 'status', 'done', 'done', NULL, '2026-06-10 12:32:07', '2026-06-10 12:32:07', '2026-06-10 12:32:07', NULL, 'ea979d683072b321ce6eae3dbbbf6c31', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/tickets/2026-06.sql b/.pql/changelog/tickets/2026-06.sql index 725c072d..a2249a35 100644 --- a/.pql/changelog/tickets/2026-06.sql +++ b/.pql/changelog/tickets/2026-06.sql @@ -2379,3 +2379,21 @@ Acceptance: 5. Tests: transcript_reader parses the task-list event into the model (incl. status transitions + latest-wins); widget renders states + collapse/expand + hidden-when-empty. Refs: conversation card patterns (conversation_card.dart), D-78 (interaction zone), ui-design skill (tokens/icons).', 'done', 'medium', NULL, NULL, NULL, '2026-06-10 09:28:04', '2026-06-10 12:31:23', NULL, 'ddfb6e694a6c5b6e3bc39132cd57318c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB1Q1Y3CYJHD7W5F68VDB6T4', 'story', '06FB0TNQM5TWC00GW0P3X02HZW', 'Surface Claude''s task list docked above the bottom input pane', 'Claude maintains a task/todo list during a session (the TodoWrite / TaskCreate checklist), but clide never shows it — it is completely invisible to the user. The transcript reader (lib/builtin/claude/src/transcript_reader.dart:205-212) skips the relevant event types and there is no model class for task items; the conversation view (conversation_view.dart) renders none. So the user has no view of what Claude is tracking or how far along a multi-step task is. + +Surface it as a compact, always-current task list DOCKED to the bottom input pane of the Claude conversation view. Per the Explore: the pane is a Column in claude_pane.dart (_ClaudePaneState.build, ~line 474-542) with ConversationView (Expanded) on top and the ToolPromptCard/ClaudeComposer at the bottom (~line 519-525); the task list should sit between them — directly above the composer (claude_composer.dart), non-expanded — so it stays pinned and visible as Claude works. + +Scope: +- PARSE: model Claude''s task list from the transcript. Find the event type carrying the todo/task items (currently among the skipped types in transcript_reader.dart) and add a TaskList model + items (text + status: pending/in_progress/completed). Latest-write-wins — the list reflects the most recent todo state, not an append log. +- RENDER: a docked task-list widget above the composer. Compact: collapsed/summary by default (e.g. ''N tasks · M done'' + current in_progress item), expandable to the full checklist. Per-item status glyph (pending/in-progress/done) using existing tokens + Phosphor icons (ui-design skill). Hide entirely when there are no tasks. +- Keep it display-only and de-emphasised so it never competes with the composer for attention; honour D-78 (interaction zone) — this is a display surface, not an interactive control. +- a11y: list semantics, status announced per item. + +Acceptance: +1. When Claude has an active task list, it shows docked directly above the input pane and updates live as items change state. +2. Empty/no-task sessions show nothing (no empty chrome). +3. Collapsed by default with a one-line summary; expandable to the full list. +4. Display-only; the composer keeps full function and focus behaviour. +5. Tests: transcript_reader parses the task-list event into the model (incl. status transitions + latest-wins); widget renders states + collapse/expand + hidden-when-empty. + +Refs: conversation card patterns (conversation_card.dart), D-78 (interaction zone), ui-design skill (tokens/icons).', 'done', 'medium', NULL, NULL, NULL, '2026-06-10 09:28:04', '2026-06-10 12:32:07', NULL, '9ed7b932a0448a813e89c462e383b88a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); diff --git a/CHANGELOG.md b/CHANGELOG.md index 467262df..6eab9a8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit. - **The activity-card run-status spinner is now legible.** At 12px the spinning logo mark read as a static speck; the run-status indicator on collapsible - cards is bumped to a `clideIconHero` (24) so the running state is clear at a + cards is bumped to a `clideIconHero` (26) so the running state is clear at a glance. The check / cross share the size, so the card doesn't jump on settle. (T-304) diff --git a/lib/widgets/src/spacing.dart b/lib/widgets/src/spacing.dart index 20f6f457..c6cb4c46 100644 --- a/lib/widgets/src/spacing.dart +++ b/lib/widgets/src/spacing.dart @@ -88,7 +88,7 @@ const double clideIconEmphatic = 18; /// Hero icon — large enough to read at a glance, e.g. the activity-card run /// status where the spinner must be legible as motion, not a static speck /// (T-304). Success/error glyphs share it so the card doesn't jump on settle. -const double clideIconHero = 24; +const double clideIconHero = 26; /// Standard control height (tab, button, list row). const double clideControlHeight = 28; diff --git a/test/goldens/goldens/linux/collapser_card.png b/test/goldens/goldens/linux/collapser_card.png index 6462aeb9..b95606b7 100644 Binary files a/test/goldens/goldens/linux/collapser_card.png and b/test/goldens/goldens/linux/collapser_card.png differ diff --git a/test/goldens/goldens/linux/tool_collapser.png b/test/goldens/goldens/linux/tool_collapser.png index 7a461dfa..2f555fba 100644 Binary files a/test/goldens/goldens/linux/tool_collapser.png and b/test/goldens/goldens/linux/tool_collapser.png differ