diff --git a/.pql/changelog/ticket_deps/2026-06.sql b/.pql/changelog/ticket_deps/2026-06.sql index 75a74863..e4f13006 100644 --- a/.pql/changelog/ticket_deps/2026-06.sql +++ b/.pql/changelog/ticket_deps/2026-06.sql @@ -15,3 +15,5 @@ INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updat INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2ERREMEEF26KKHGNZBWW64', '06FB2ETJQP0CT6X7W3CWZ6NS9G', '2026-06-10 11:12:20', '2026-06-10 11:12:20', NULL, 'cb20764a77d2a15290ed61a186542095', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash); INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2ERREMEEF26KKHGNZBWW64', '06FB2EV29HSK6EJ5VF50R87VC4', '2026-06-10 11:12:25', '2026-06-10 11:12:25', NULL, 'dd9434426790edcaa556221f74c431ba', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash); INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2ERREMEEF26KKHGNZBWW64', '06FB2G1WD1839Z90AQ5C0BHNV4', '2026-06-10 11:17:25', '2026-06-10 11:17:25', NULL, '5535e3d16bee2a2cdfcbeb84ea3fca99', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash); +INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM5TWC00GW0P3X02HZW', '06FB2TY91VHK7TPKPMZ11EG3TM', '2026-06-10 12:04:53', '2026-06-10 12:04:53', NULL, 'ed3717d8f6467c0a77236eda670efce5', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash); +INSERT INTO ticket_deps (blocker_record_id, blocked_record_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM5TWC00GW0P3X02HZW', '06FB2TY91VHK7TPKPMZ11EG3TM', '2026-06-10 12:04:53', '2026-06-10 12:05:01', '2026-06-10 12:05:01', '137cd047c9eaec01cac955b49fedd839', 2) ON CONFLICT(blocker_record_id, blocked_record_id) DO UPDATE SET updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_deps.updated_at OR (excluded.updated_at = ticket_deps.updated_at AND excluded.hash > ticket_deps.hash); diff --git a/.pql/changelog/ticket_history/2026-06.sql b/.pql/changelog/ticket_history/2026-06.sql index 79f09c35..7ecc98da 100644 --- a/.pql/changelog/ticket_history/2026-06.sql +++ b/.pql/changelog/ticket_history/2026-06.sql @@ -3125,3 +3125,34 @@ 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 ('06FB1Q1Y3CYJHD7W5F68VDB6T4', 'status', 'backlog', 'ready', NULL, '2026-06-10 11:33:26', '2026-06-10 11:33:26', '2026-06-10 11:33:26', NULL, 'f280d9b2793130900d5e470c4cb6c088', 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 ('06FB0TNQM4KS233FGZE9H7ABWR', 'status', 'backlog', 'ready', NULL, '2026-06-10 11:33:35', '2026-06-10 11:33:35', '2026-06-10 11:33:35', NULL, 'bb110c716ec26f37ed4ece36b582d4d5', 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 ('06FB2J2HWD66QAFDDRRWS5NM48', 'status', 'ready', 'done', NULL, '2026-06-10 11:36:35', '2026-06-10 11:36:35', '2026-06-10 11:36:35', NULL, '376bbab713452158f399f02429870546', 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 ('06FB0TNQM4KS233FGZE9H7ABWR', 'description', 'The logo-mark spinner shown on in-progress activity/holder cards in the Claude conversation is too small to read as a spinner — it reads as a static speck. Enlarge it so the running state is legible at a glance. + +**Where** +- `ClideSpinner` (lib/widgets/src/clide_spinner.dart) — defaults to size 14; renders the logo SVG at width/height = size. +- `ClideStatusIndicator` (lib/widgets/src/clide_status_indicator.dart) — default size 14; maps running→ClideSpinner, success→check, error→cross at the same size. +- Call sites: holder_card.dart:117 and :199 pass `size: 12` — the small value the user is seeing. + +**Direction (settle in review)** +- Bump the spinner size on the activity cards (the `size: 12` call sites, and/or the indicator default) to something clearly legible — pull a concrete value from the ui-design control-geometry tokens rather than a magic number. +- Keep the running spinner, success check, and error cross visually balanced at the new size (they share `size`), so the card doesn''t jump when the state settles. +- Check the other ClideSpinner/StatusIndicator consumers (status surfaces) so the bump doesn''t bloat unrelated spots — may warrant sizing the cards explicitly rather than changing the shared default. + +**Acceptance** +- The in-progress spinner on conversation activity cards is comfortably distinguishable as a spinning indicator; success/error glyphs stay aligned at the same footprint.', 'The logo-mark spinner shown on in-progress activity/holder cards in the Claude conversation is too small to read as a spinner — it reads as a static speck. Enlarge it so the running state is legible at a glance. + +**Where** +- `ClideSpinner` (lib/widgets/src/clide_spinner.dart) — defaults to size 14; renders the logo SVG at width/height = size. +- `ClideStatusIndicator` (lib/widgets/src/clide_status_indicator.dart) — default size 14; maps running→ClideSpinner, success→check, error→cross at the same size. +- Call sites: holder_card.dart:117 and :199 pass `size: 12` — the small value the user is seeing. + +**Direction (settle in review)** +- Bump the spinner size on the activity cards (the `size: 12` call sites, and/or the indicator default) to something clearly legible — pull a concrete value from the ui-design control-geometry tokens rather than a magic number. +- Keep the running spinner, success check, and error cross visually balanced at the new size (they share `size`), so the card doesn''t jump when the state settles. +- Check the other ClideSpinner/StatusIndicator consumers (status surfaces) so the bump doesn''t bloat unrelated spots — may warrant sizing the cards explicitly rather than changing the shared default. + +**Acceptance** +- The in-progress spinner on conversation activity cards is comfortably distinguishable as a spinning indicator; success/error glyphs stay aligned at the same footprint. + +**Initial trial** +- For the first cut, double the current size: the `size: 12` activity-card call sites go to `size: 24`. Trial that footprint, then settle the final value in review against the control-geometry tokens.', NULL, '2026-06-10 11:55:15', '2026-06-10 11:55:15', '2026-06-10 11:55:15', NULL, '3be7c3ff633afbc67c91dd3f97c27e6f', 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 ('06FB0TNQM4KS233FGZE9H7ABWR', 'status', 'ready', 'done', NULL, '2026-06-10 12:05:17', '2026-06-10 12:05:17', '2026-06-10 12:05:17', NULL, 'a19ce81190caca50c2628a98835d41a3', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/ticket_idmap/2026-06.sql b/.pql/changelog/ticket_idmap/2026-06.sql index 5e915007..19a3d0bf 100644 --- a/.pql/changelog/ticket_idmap/2026-06.sql +++ b/.pql/changelog/ticket_idmap/2026-06.sql @@ -149,3 +149,5 @@ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2G1WD1839Z90AQ5C0BHNV4', 'T-322', '2026-06-10 11:17:17', '2026-06-10 11:17:17', NULL, 'f33b1db4b67a0521f02c5c49fcfa8e6f', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2G2KHKT5CJYR0TK1WQGMD0', 'T-323', '2026-06-10 11:17:23', '2026-06-10 11:17:23', NULL, '0738a8da475a6d8d49132d1e4e753775', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2J2HWD66QAFDDRRWS5NM48', 'T-324', '2026-06-10 11:26:07', '2026-06-10 11:26:07', NULL, 'd8aa9ae4522d97b70331c42b8ab7a365', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2T11GCV1EV07DYD5BZENTM', 'T-325', '2026-06-10 12:00:52', '2026-06-10 12:00:52', NULL, '47b8f31d9337c5bbc6476d62c7f6ed4d', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB2TY91VHK7TPKPMZ11EG3TM', 'T-326', '2026-06-10 12:04:51', '2026-06-10 12:04:51', NULL, '348dee79d9d3fe0a8b260c1f9c47a289', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); diff --git a/.pql/changelog/tickets/2026-06.sql b/.pql/changelog/tickets/2026-06.sql index b1b5ab08..5312fdb8 100644 --- a/.pql/changelog/tickets/2026-06.sql +++ b/.pql/changelog/tickets/2026-06.sql @@ -2194,3 +2194,67 @@ The tab strip is ClideTabBar (lib/widgets/src/clide_tab_bar.dart) — a Containe Keep it a hairline (1px) so it relieves the cramping without shifting the layout noticeably. Watch the tabBarBackground vs the surface behind it so the 1px gap shows the intended color, not a seam. Acceptance: the tab strip has 1px of space above it; tabs no longer butt against the chrome edge; checked across the surfaces that use ClideTabBar.', 'done', 'low', NULL, NULL, NULL, '2026-06-10 11:26:07', '2026-06-10 11:36:35', NULL, '06aaa8609442446ebb98cd83cf241450', 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 ('06FB0TNQM4KS233FGZE9H7ABWR', 'bug', '06FB0TNQM5TWC00GW0P3X02HZW', 'Activity-card spinner too small to make out — enlarge it', 'The logo-mark spinner shown on in-progress activity/holder cards in the Claude conversation is too small to read as a spinner — it reads as a static speck. Enlarge it so the running state is legible at a glance. + +**Where** +- `ClideSpinner` (lib/widgets/src/clide_spinner.dart) — defaults to size 14; renders the logo SVG at width/height = size. +- `ClideStatusIndicator` (lib/widgets/src/clide_status_indicator.dart) — default size 14; maps running→ClideSpinner, success→check, error→cross at the same size. +- Call sites: holder_card.dart:117 and :199 pass `size: 12` — the small value the user is seeing. + +**Direction (settle in review)** +- Bump the spinner size on the activity cards (the `size: 12` call sites, and/or the indicator default) to something clearly legible — pull a concrete value from the ui-design control-geometry tokens rather than a magic number. +- Keep the running spinner, success check, and error cross visually balanced at the new size (they share `size`), so the card doesn''t jump when the state settles. +- Check the other ClideSpinner/StatusIndicator consumers (status surfaces) so the bump doesn''t bloat unrelated spots — may warrant sizing the cards explicitly rather than changing the shared default. + +**Acceptance** +- The in-progress spinner on conversation activity cards is comfortably distinguishable as a spinning indicator; success/error glyphs stay aligned at the same footprint. + +**Initial trial** +- For the first cut, double the current size: the `size: 12` activity-card call sites go to `size: 24`. Trial that footprint, then settle the final value in review against the control-geometry tokens.', 'ready', 'medium', NULL, NULL, NULL, '2026-06-09 21:22:28', '2026-06-10 11:55:15', NULL, 'f1b11537f6c416bae19a6da5447a384e', 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 ('06FB2T11GCV1EV07DYD5BZENTM', 'story', '06FB0TNQM5TWC00GW0P3X02HZW', 'Live tail sub-card inside expanded Bash activity cards', 'Expanded Bash activity cards should be able to show a live, scrolling tail of a file-backed source the command is following, so the user can watch the same output Claude is tailing — connected lazily, only while the card is expanded. + +**Motivation** +Long-running / tailing Bash steps render only a final result block once the command finishes (see screenshot in T-304 thread). The user can''t follow progress. We want an embedded scrolling terminal sub-card inside the expanded activity card for visibility. + +**Hard constraint (feasibility, established by investigation)** +Claude Code CLI executes every Bash tool itself; clide only ingests stream-json events (stream_json_session.dart -> parseTranscriptChunk). A tool_result arrives as ONE complete block — clide never sees in-flight tool output, and the controller''s in-place upsert path is hardcoded for `partial-` prose deltas, not tool results (controller.dart). We cannot tap Claude''s subprocess fd. So a fully-general "mirror the running command''s stdout" is NOT possible. + +**Viable scope: independent file-tail on expand** +- On card expand, parse the Bash command string (AssistantToolUse.input["command"], transcript_reader.dart) for a file-backed source: `tail -f X`, `tail -n N X`, `cat X`, `less X`, known log paths, or a background task writing to a file. +- If found, clide opens its OWN read-only follower — a NativePty running `tail -f X` (native_pty.dart already exposes Stream) or a Dart file-watcher — and renders it in an embedded scrolling terminal sub-card, reusing TerminalView. +- Lazy lifecycle: connect on expand, disconnect/dispose on collapse. No connection until expanded. +- Read-only & safe: clide observes the same file; it never re-runs or intercepts Claude''s command. +- Graceful when there is no file-backed source (e.g. `git push ... | tail -25`, a pipe inside Claude''s process): show a muted "no independent source to follow" note rather than faking output. + +**Where** +- Card body: conversation_card.dart / conversation_view.dart (_toolUseCollapser, the Bash tool card). Add an optional live-tail segment below the RESULT segment. +- Key the live connection on AssistantToolUse.toolUseId. +- Embedded terminal: reuse lib/src/terminal TerminalView + lib/src/pty NativePty. + +**Open questions (settle in review / may need a Q-record)** +- Command-parsing surface: which commands/forms count as "tailable"? Keep it a small, explicit allowlist to avoid mis-following. +- Security: only follow paths inside the workspace? How to handle absolute paths outside the repo. +- Lifecycle when the underlying command has already finished (file static) vs still running. + +**Acceptance** +- Expanding a Bash card whose command tails a file shows a live scrolling terminal sub-card that updates as the file grows; collapsing it tears the follower down. +- A Bash card with no file-backed source shows a clear "nothing to follow" affordance, never a broken/empty terminal. +- No follower process is spawned until the card is expanded.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 12:00:52', '2026-06-10 12:00:52', NULL, '96c66c13b16a312fa2ae625817269bb0', 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 ('06FB2TY91VHK7TPKPMZ11EG3TM', 'bug', NULL, 'ClideStatusIndicator: duplicate ''running'' key crashes AnimatedSwitcher on rapid status flips', NULL, 'backlog', 'medium', NULL, NULL, NULL, '2026-06-10 12:04:51', '2026-06-10 12:04:51', NULL, '6543e76a19006cfc6cd6ff85cd2c2d6e', 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 ('06FB0TNQM4KS233FGZE9H7ABWR', 'bug', '06FB0TNQM5TWC00GW0P3X02HZW', 'Activity-card spinner too small to make out — enlarge it', 'The logo-mark spinner shown on in-progress activity/holder cards in the Claude conversation is too small to read as a spinner — it reads as a static speck. Enlarge it so the running state is legible at a glance. + +**Where** +- `ClideSpinner` (lib/widgets/src/clide_spinner.dart) — defaults to size 14; renders the logo SVG at width/height = size. +- `ClideStatusIndicator` (lib/widgets/src/clide_status_indicator.dart) — default size 14; maps running→ClideSpinner, success→check, error→cross at the same size. +- Call sites: holder_card.dart:117 and :199 pass `size: 12` — the small value the user is seeing. + +**Direction (settle in review)** +- Bump the spinner size on the activity cards (the `size: 12` call sites, and/or the indicator default) to something clearly legible — pull a concrete value from the ui-design control-geometry tokens rather than a magic number. +- Keep the running spinner, success check, and error cross visually balanced at the new size (they share `size`), so the card doesn''t jump when the state settles. +- Check the other ClideSpinner/StatusIndicator consumers (status surfaces) so the bump doesn''t bloat unrelated spots — may warrant sizing the cards explicitly rather than changing the shared default. + +**Acceptance** +- The in-progress spinner on conversation activity cards is comfortably distinguishable as a spinning indicator; success/error glyphs stay aligned at the same footprint. + +**Initial trial** +- For the first cut, double the current size: the `size: 12` activity-card call sites go to `size: 24`. Trial that footprint, then settle the final value in review against the control-geometry tokens.', 'done', 'medium', NULL, NULL, NULL, '2026-06-09 21:22:28', '2026-06-10 12:05:17', NULL, '1266a6e25abae600315c65aefd7d8f93', 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 9baf460c..f179f2ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,14 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit. ## [Unreleased] +### Fixed + +- **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 + glance. The check / cross share the size, so the card doesn't jump on settle. + (T-304) + ## [2.2.0] — 2026-06-10 ### Added diff --git a/assets/licenses.yaml b/assets/licenses.yaml index 2c6b1fd2..0ab6fe77 100644 --- a/assets/licenses.yaml +++ b/assets/licenses.yaml @@ -39,7 +39,7 @@ self: # Auto-synced from pubspec.yaml `version:` by `make gen-build-info` # (runs implicitly on every build/run/test). Don't hand-edit; bump # pubspec instead. - version: "2.1.0" + version: "2.2.0" homepage: https://github.com/postmeridiem/clide license: MIT license_file: assets/LICENSE diff --git a/lib/widgets/src/clide_collapser_card.dart b/lib/widgets/src/clide_collapser_card.dart index 9ffdc6b0..8fc768e1 100644 --- a/lib/widgets/src/clide_collapser_card.dart +++ b/lib/widgets/src/clide_collapser_card.dart @@ -31,6 +31,7 @@ import 'package:clide/widgets/src/clide_status_indicator.dart'; import 'package:clide/widgets/src/clide_tappable.dart'; import 'package:clide/widgets/src/clide_text.dart'; import 'package:clide/widgets/src/icons/chevron.dart'; +import 'package:clide/widgets/src/spacing.dart'; import 'package:clide/widgets/src/typography.dart'; import 'package:flutter/widgets.dart'; @@ -139,7 +140,7 @@ class _ClideCollapserCardState extends State { // Status — the icon hard against the right edge. if (widget.status != null) ...[ const SizedBox(width: 8), - ClideStatusIndicator(status: widget.status!, size: 12), + ClideStatusIndicator(status: widget.status!, size: clideIconHero), ], ], ); diff --git a/lib/widgets/src/spacing.dart b/lib/widgets/src/spacing.dart index 306735d6..20f6f457 100644 --- a/lib/widgets/src/spacing.dart +++ b/lib/widgets/src/spacing.dart @@ -85,5 +85,10 @@ const double clideIconHitTarget = 16; /// Emphatic icon (standalone affordances, primary action glyphs). 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; + /// 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 b15b6629..6462aeb9 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 035d075a..7a461dfa 100644 Binary files a/test/goldens/goldens/linux/tool_collapser.png and b/test/goldens/goldens/linux/tool_collapser.png differ