At size 12 the rotating logo-mark spinner on in-progress collapser cards
read as a static speck. Add a clideIconHero (24) control-geometry token
and use it for ClideStatusIndicator on the collapser — the spinner now
reads as motion at a glance; the success check / error cross share the
size so the card doesn't jump when the run settles. Only call site is the
collapser, so other status surfaces are untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The tab strips — Claude session tabs (MultitabPane._TabStrip) and the
slot tab bar (ClideTabBar) — sat flush against the chrome above, reading
as cramped. Add a 1px top margin to both Containers so the pane surface
behind shows as a hairline gap, separating the tabBarBackground strip
from the chrome edge. Both are single-use widgets, so the margin applies
once per surface (no double-apply).
Regenerated the linux clide_tab_bar golden. (The macOS variant is now 1px
stale but is dormant on the linux gate; regenerate on macOS.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Filed under UI epic T-276. The ClideTabBar
(lib/widgets/src/clide_tab_bar.dart) sits flush against the
chrome above it; add a 1px hairline of breathing room, applied
where it won't double up across the surfaces that embed a tab
bar. Changelog only — leaves concurrent lib/ work untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Image cards, thumbnails, the lightbox, and `clide image show` rendered
via Image.file, whose FileImage keys Flutter's imageCache by (path,
scale) only — so overwriting a file at the same path handed back the
previously decoded frame (hit live re-exporting a wireframe PNG). Add
ClideFileImage, a FileImage that folds mtime + size into ==/hashCode so an
in-place change is a fresh cache key (miss → re-decode), and route the
five Image.file sites through it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Records the T-7 -> T-317 merge on D-91's Relationship bullet (the
former Tier-5 canvas+graph epic folds into the unified canvas
epic; canvas pane T-322 + graph view T-323 consume the shared
renderer) and the D-91 index line. Plus the changelog for this
turn's board restructure: epic T-317, core engine T-318,
templates T-319/320/321, re-parented T-313/315/316, T-7 cancelled
as superseded, T-41 moved to T-276.
Governance + .pql/changelog only — leaves concurrent lib/ work
and CHANGELOG.md to the other worker on this branch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The injected context block and the thinking / agent-prompt blocks
rendered as frameless `bare` cards, reading as unfinished `> context …`
rows next to the framed tool cards. Switch them to the bordered variant —
same panel border + left chevron + label as the surrounding cards — while
keeping the D-78 de-emphasis (muted accent, collapsed by default,
first-line summary; thinking gains a summary for parity). Adds a
conversation_card_meta golden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-315 (task): add a client-side stdin path to the clide CLI so
commands can take a piped JSON payload (`… | clide icon show
--stdin`), the ergonomic peer of --file. Generic infra slurped in
lib/src/cli/ before the IpcRequest is sent; commands opt in via
CommandSchema. Unblocks the piped variants of T-313/T-316.
T-316 (task): give `clide image show` the same metadata plumbing
as the icon card — a JSON payload (--file, or --stdin once T-315
lands) carrying label/description/captions so images can be
annotated, extending ImageMessage + the image card. Starts with
text metadata; visual marker overlays flagged as a follow-up.
Existing `image show <path> --caption` form stays unchanged.
Both under UI epic T-276; cross-linked from T-313.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The CLI section was partly aspirational. Tie it to the real
plumbing: register icon.show on DaemonDispatcher with a
CommandSchema (clide icon show); bare previews as variadic
stringList positionals; labelled/described entries via a
--file <json> flag — NOT --stdin (clide's argv parser
lib/src/cli/argv_to_request.dart has no stdin path). Render path
mirrors image.show: Flutter-free handler, injected resolver,
publish on an 'icon' MessageBus channel captured in main.dart,
injected by the Claude extension. Acceptance updated to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the 49 hand-maintained named consts with one generated
label→codepoint map (phosphor_glyphs.g.dart, 1512 glyphs from the glyph
table via tool/gen_phosphor_glyphs.dart). Feature code now references
glyphs by their exact kebab-case name — PhosphorIcons.byName('folder') —
with no raw codepoints; this also lets a Lua extension name an icon
without crossing the FFI boundary with a codepoint.
byName is total: an unknown name degrades to the `placeholder` box so the
bug is visible (it's a real error), while phosphor_glyphs_test asserts
every byName('...') literal in lib/ resolves — recovering the typo check a
const gave. Migrated the 89 call sites. Adds EmptyIconPainter for an
intentional blank that still reserves the icon box; ClideFilterBox gains
showIcon to keep the slot aligned when blank.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the proposed new 48px constant; the hero glyph reuses the
existing clideFontWelcomeBanner (52) token instead — no new
typography token needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Broadens the Phosphor glyph card from a single-glyph preview to a
list of entries, each glyph + optional label + optional
description, driven by `clide icon show` (terse positional for
bare previews, JSON payload for labelled/described entries).
- Multi-size: each icon renders at a 48px hero (new named
constant) plus a sample at every inline type token (badge 11 ->
body 15) so legibility at real UI sizes is visible.
- Selection model (decided): display card stays display-only
(D-78); selection happens in the interaction zone via a
Claude-offered choice list whose options reuse the card's
per-icon labels — labels are the bridge for the show-then-pick
flow.
- Notes name->codepoint resolution already exists
(phosphor_glyphs.g.dart, PhosphorIcons.byName), retiring the
old 'generate the full set' caveat.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Frame0 wireframe for the app settings UI (design step under T-8). A
centered modal with a left sidebar of sections (Claude is one), inline
per-field scope (no header toggle): each field shows its EFFECTIVE value
+ a source tag, edits default to Project, and a field's tag promotes it
to Always (global, all clide) or resets. Editor category fully rendered
(number/select/toggle/external-file + override shadow).
Scope tag becomes an icon: folder (project) / globe (always) /
circle-dashed (default), recorded on T-302. Filed T-313 (native Phosphor
glyph preview card — the vehicle to pick icons in-pane) and T-312 (image
card caches by path).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The prompt card's number-key shortcuts matched only digit1..digit9
(the number row); numpad 1-9 fell through to ignored. Add a
parallel _numpadKeys list and check it in _onKey so the keypad
maps to the same 1-9 selection for Allow/Deny and question
options. numpadEnter was already handled. The hasPrimaryFocus
guard still lets digits type into a focused note field.
Adds four widget tests (numpad Allow/Deny, question option,
focused-note swallow). Closes T-310 (under UI epic T-276).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Filed under UI epic T-276. Adds a fourth permission-card option:
a deny carrying a preformatted note asking Claude to retry the
action in a simpler format, with an explicit clause not to add a
memory or rewrite permission config (avoids continuous fiddling
with the permission surface). Working label 'Deny & simplify',
tooltip via ClideButton's existing tooltip param. Captures the
escalation-in-context design note. Persisting the changelog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Core Workflow ran straight through and tended to fan out a
whole set of screens unprompted. Reframe it as a design
conversation: author one screen, show it, then STOP for explicit
user approval before building the next (loop back to step 2 per
screen). Multi-screen requests become a one-at-a-time queue.
Closes T-307 (under UI epic T-276).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Capture the three card categories (dialog / simple / collapsible), the
ClideCollapserCard rules, and the shared card-spacing constants so future
conversation-panel work follows the settled model. Closes T-305.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Filed under UI epic T-276. Prompt-card number shortcuts only
match the top number row (_digitKeys = digit1..digit9); numpad
1-9 fall through. numpadEnter is already handled, so numpad
parity is partial. Persisting the ticket changelog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Filed under UI epic T-276. Clicking the dimmed area beside a
smaller-than-94% image doesn't close the lightbox today — the
host backdrop only reaches the 6% margin. Persisting the ticket
changelog (no code change to piggyback on).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude's TodoWrite/TaskCreate task list is currently neither parsed
(transcript_reader skips the event) nor rendered — invisible to the user.
Ticket covers modelling it from the transcript and docking a compact,
collapsible, display-only list directly above the composer in the Claude
conversation view. Filed under the UI epic T-276.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bookkeeping only — these all had DONE/FIXED completion notes (and landed
commits) but were never transitioned off in_progress/ready:
T-29 editor respects .editorconfig (d5da614)
T-292 pty session_test flake — serial pty pass (0231cb4)
T-236 pasted-image @path thumbnails (7fb1a10)
T-254 pasted-image inline render — closed with T-236 (7fb1a10)
T-241 ultrawide widget-test coverage (1411e19)
T-253 clickable conversation links (1e8e37c)
T-293 per-repo theme persistence (e7cbdcd)
Review queue is now empty; no open work left in active/ready.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First slice of the conversation-panel card unification. Adds the
category-3 collapser primitive (lib/widgets/): a list of 1..N inner item
cards, collapsed ticker <-> expanded framed inner canvas, with the agreed
chrome — color drives the border + chevron/label tint, a fixed-width
counter slot, the status icon hard against the right edge, chevron hard
against the left edge, background + caret toggle (D-78 tail-follow). The
aggregate status/count/echoed-title are caller-computed, so the widget
stays free of conversation semantics; inner items keep their own per-item
status.
Also adds clide_card_metrics.dart — shared spacing constants (gap, radius,
header padding, counter slot width) for all three card categories.
Not yet wired into the stream (no user-visible change); migration of the
group/tool cards follows. Widget test + golden included.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-306: card the injected "context" conversation block to match the
collapser-card frame the rest of the tool/group cards use, keeping the
D-78 muted/collapsed de-emphasis.
T-307: gate the frame0-wireframe skill on user approval after each shown
screen — wireframing is a design dialogue, not a batch generation run.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two collapser-card families (ClideHolderCard group container, T-266; the
ConversationCard merged tool card, T-262) attach collapse differently and
render inconsistent header chrome — status mark placement, no fixed
counter slot, color knob on one but not the other. File T-305 (under the
T-276 UI tracker) to extract one ClideCollapserCard primitive both grab:
a `color` for border/text fidelity, a fixed-width counter slot, and the
status icon hard against the card edge.
Adds the Frame0 wireframe (collapsed color variants + expanded nested
cards) at docs/design/wireframes/cards/collapser-card.{json,png}.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrites the committed .pql/changelog/ from the old T-NNN-keyed format to
the record_id identity model (pql 1.10.0, D-26): tickets keyed by a ULID
record_id, the friendly T-NNN in ticket_idmap, references and hashes
recomputed. Produced by the one-off cmd/migrate-ids in the pql repo.
Other clones: install pql >= 1.10.0, then rm .pql/pql.db && pql plan
rebuild to regenerate the local DB from this changelog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "Open Folder on a non-repo path" widget test wedged the runner ~10
minutes on a _RawReceivePort teardown hang. Root cause: project
validation shelled out to `git rev-parse` via Process.run, whose exit
ReceivePort leaks under the fake-async widget-test harness.
The KernelFixture now injects a pure-Dart `.git`-walk validator
(synchronous existsSync/typeSync, no native port), so the open-folder
flow is subprocess-free. Un-skipped the test and scoped the switcher
tap to the hat-bar ClideTappable to disambiguate it from the welcome
overlay's "clide" wordmark.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The composer (and any bottom-most pane content) ran flush into the
window's bottom resize-drag strip when the status bar was hidden, since
the bar normally covers that edge. Reserve ClideResizeBorder.edgeThickness
as a bottom inset in RootLayout whenever the status bar is not visible, so
the interaction zone bottom-anchors consistently either way.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause (confirmed by standalone reproducer): the Open Workspace
folder picker. GTK's GtkPlacesSidebar enumeration inside
gtk_file_chooser_dialog_new(SELECT_FOLDER) builds GFileInfo objects
without standard::size, then calls g_file_info_get_size() — a
GTK-internal bug that emits a GLib-GIO-CRITICAL pair on every pick.
Ruled out the T-138 clipboard channel.
Two-part fix:
- Switch pickDirectory to GtkFileChooserNative (portal-backed; runs
out-of-process and silently in sandboxed/Flatpak builds).
- Install a narrowly-scoped GLib-GIO log handler that drops only the
"g_file_info_get_size / without standard::size" message and forwards
every other GLib-GIO critical untouched — the universal fix for the
non-sandbox fallback path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
clide://open?path=&line= translates (in parseArgv) to editor.open, so an OS
scheme invocation routes through the existing CLI→IPC path into the running
window — single-instance for free, no new code path. Registered the scheme:
linux/clide.desktop MimeType x-scheme-handler/clide (Exec already passes %U) and
macOS Info.plist CFBundleURLTypes. Parser validates the action/path/line.
Linux works end to end (the OS passes the URL as argv). macOS URL DELIVERY (the
AppDelegate openURLs callback → forward into this path) is a follow-up — the
scheme is registered, but the native hook needs a real macOS machine to verify,
so it's not shipped blind. Also drops a stray import in clide_markdown_test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add setSurfaceSize(tester, width) to the widget harness — the reusable way to
test width-sensitive layout at an ultrawide surface (a wide SizedBox under the
default 800px surface is clamped, so the view's physicalSize must be set), the
foundation T-241 asked for.
Ultrawide cases on the surfaces most prone to width-proportional bugs (the T-239
class): ClideMarquee stays static when a line fits a 3440 slot (it was only
tested narrow); the quick-open palette stays width-capped, not stretched edge to
edge. The status bar already covers 600+3440 (T-239).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
In a ToolPromptCard, number keys pick the matching button/option (labels are
prefixed 1./2./3.…) and Enter confirms the primary action — matching the Claude
CLI. Permission: 1=Allow, 2=Allow&remember (when offered) else Deny, 3=Deny.
AskUserQuestion: 1..N select/toggle the current question's options + Other.
The card autofocuses and the key handler self-guards on hasPrimaryFocus, so once
the user clicks into a note field the digits type normally and never fire a
button. Shared the permission/option actions between the buttons and the keys.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both under the UI tracker epic T-276. T-300: linkify file-path
references in the conversation so they open in the editor via
`clide editor open`. T-301: show in-repo paths relative to the repo
root — design open, needs discussion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-235: app-scoped kActivityFoldLevelKey + a claude.activity.fold-level command
that cycles none→tools→thinking→everything; ClaudePane + team_panel_host read it
and re-fold live via the settings notifier. Unit tests for the helpers.
T-132 cleanup: the one blocked item (account/team token budget) is detached
(T-158), reframed as Q-34 'how + when to surface the budget given upstream
doesn't expose it', with T-158 as its backlog resolver. T-132 closed — all
doable work delivered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two fixes to the just-shipped collapse toggles:
- They lived inside the centre StatusbarHost, so they shifted when a pane
collapsed and the bar resized. Move them to the OUTER status-bar row ends
(screen edges) so they stay put. StatusbarHost reverts to its prior layout.
- The toggle was a const widget that read isCollapsed in its own build; Flutter
skips identical const children on rebuild, so the chevron never flipped. Pass
collapsed/visible in from the parent's arrangement listener so it rebuilds and
the chevron tracks the action direction. A 'flips live' test now guards it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Salvage the report's only actionable content — automate Dart osv-scanner
and native SHA256 verification in CI — into T-299, then drop the stray
root-level analysis doc (the rest was praise + an exploration trace;
recoverable from history at bf4b6be).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Composer/prompt box alignment depends on the status bar being present;
with it hidden the box sits weird. Should bottom-anchor independently.
Filed under T-276.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
set() doesn't await its file write, so a write in flight when the store is
disposed (app shutdown, or a closing test) would assert on a disposed
ChangeNotifier. Skip the post-write notify once disposed via a _disposed guard +
_safeNotify. Surfaced by the T-293 theme-persistence test flaking under the
loaded parallel run; also the correct behaviour for graceful shutdown.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the interaction zone (D-78) grows for a permission / AskUserQuestion
prompt, the conversation viewport shrinks but the scroll offset isn't
adjusted, so tail content hides behind the box. Filed under T-276.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bundle subsequent edits to the same file into a single ClideHolderCard
(reusing the T-230/T-266 folding), labelled "# edits" instead of
"# steps", with every per-edit report preserved on expand. Under T-276.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revise the mock — toggles no longer float on the pane edges; they live in
the bottom status bar, pinned to the center pane's left/right edge so each
slides to the far end when its pane collapses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>