The UI half of D-106 (D-6 parity with `clide env path`): an ordered
preset editor — add/remove/reorder, a missing-dir warning, a worktree
note naming the shared main repo, and capture-from-login-shell
suggestions adopted with one click. Writes land on the same user-scope
key the CLI verbs use and publish on the same channel, so both
surfaces stay live off the store notifier.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restores the original intent that T-226's refinement wording lost: the
shift modifier is the explicit opt-in for bypassPermissions, not a
separate confirm flow. Plain Ctrl/Cmd+M keeps cycling the safe trio;
Ctrl/Cmd+Shift+M cycles the full list. The composer menu's bypass row
was permanently disabled, deferring to "the cockpit's confirmed path" —
but that roster is ghost-fed (T-396), so bypass was unreachable from
the primary session's UI entirely. The row now no-ops on a plain click
(menu stays open) and selects on shift-click, with a hint naming the
gesture. Roster badge and /permissions paths unchanged.
lib/test_app.dart is a format-only follow-up to the previous commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Makes the canvas foundation (parser/renderer/view) reachable. The
extension owns an app-scoped MultitabController (the diff/T-233
pattern) so open documents survive the pane being rebuilt; each
document is a real sub-tab per the refinement decision, kept alive
across switches. Routing goes through the existing seams instead of
the dead TabContribution.fileGlobs field: openWorkspaceFile gains a
.canvas branch mirroring .md, and ui.open gains a canvas reader for
D-6 parity (clide ui open canvas <path>). Also corrects the
json_canvas doc header that claimed SVG-lowering — the interactive
pane paints the model directly (D-103 live-widget exception).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Switches the controller from pql.outlinks to pql.meta (outlinks + tags in
one call per file) and strips #heading fragments from link targets, so a
heading link now connects the two notes. Adds a filter bar above the graph:
a path glob that re-queries pql on submit, a depth-from-active selector for
the local graph around the open note, and tri-state tag pills
(neutral / include / exclude). The pane draws the filtered visibleGraph.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wires GraphPanel into GraphExtension as the graph.view context-panel tab
(its icon-rail entry and tab id were already scaffolded) and ships the
builtin.graph i18n catalogs. The graph is now reachable: notes as nodes,
wikilinks as edges, hover-highlight and click-to-open. It activates after
its pql dependency, which supplies the link data.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The icon card renders each glyph at a hero size plus a continuous sample
strip (10–48px) so legibility is judged at the sizes the app uses, with the
entry's optional label + description and a per-entry or card-level color.
Wired end to end: icon.show publishes on the `icon` bus, the Claude
extension injects an IconMessage, and conversation_view paints the card
(display-only, D-78). en+nl catalogs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The rendered diagram leads; the d2 source carries through the draw bus and
folds into a collapsed ClideCollapserCard beneath the card (D-78 display-
only). en+nl catalogs. Also switches the d2 test to a null-aware element.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ToolsSettingsExtension adds a Tools settings category — a path field per
tool (app.tools.<name>) plus a Re-detect action (tools.detect) — and keeps
the live resolver in sync as paths are edited (supporterBinariesFrom). en
+ nl catalogs. Completes the D-104 UI surface.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The last wire: a DrawingMessage conversation item + the Claude-extension
subscriber on the `draw` channel (buildSvgDocument → inject), the
conversation renderer (DrawingCard), the fold/summary switches, the i18n
`drawing` label, and registering `clide draw` at boot (empty template
registry for now — primitive SVG works; d2/icon/compare/image handlers
plug in as they land). `clide draw --file doc.json` now renders a card in
the conversation. Render widget-tested; analyze + format clean across the
repo. Templates + per-object overlay remain; the CHANGELOG entry lands
with the user-complete feature.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Help → About gains a "Check for updates" button that fetches the latest GitHub
release, semver-compares it to clideVersion, and shows the result inline:
up-to-date, available (with a tappable link to the release notes), or a clear
error. clide's first and only outbound HTTP call — a plain GET with no user
data, run ONLY on this explicit tap, never on a launch path or a timer. So it's
D-64-clean with no amendment; a background/periodic poll stays deferred (would
need the narrow opt-in amendment first).
The fetch is injectable so no test touches the network. compareSemver handles
2.3.10 > 2.3.9 and ranks pre-releases below their release. Closes T-492 (P1);
the release-channel CI for downloadable signed packages is T-491, and download/
apply (P2/P3) depend on it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes the new-project story (T-486). The dead-end "not a git repo" dialog now
offers to initialize the folder: project.init runs git init + a non-clobbering
scaffold, then opens + announces on projectCreatedChannel so the account
roadblock fires — the same path a brand-new project takes. Adds initExistingProject
+ the `clide project init [--dir]` verb (default: the current workspace).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The UI half of the new-project flow (story T-486). A "New project…" welcome
action opens a dialog (location + name) that dispatches project.new (T-487),
opens the result, and announces it on projectCreatedChannel. The Claude
extension consumes that and shows the account roadblock — the embedded
per-workspace picker + accounts list, so a fresh project gets bound to an
account (or Default) right at birth.
The two halves stay decoupled: the welcome builtin only publishes the event
(no claude import); the claude builtin owns the account dialog. Only freshly-
created projects announce, so existing opens are never prompted.
Closes T-488. The non-repo "initialize as a project" path (T-489) is next.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes the account settings surface with the global Accounts list under the
Claude category: each registered account shows a sign-in dot, name, and config
dir, with re-login and remove affordances plus an inline add-account field.
- Sign-in status: accountIsSignedIn, a read-only probe (a .credentials.json, or
an oauthAccount marker in .claude.json; under-reports on macOS keychain).
- Add: registers ~/.claude-<name> and publishes a login action (T-485 opens the
pane).
- Remove: registry-remove, guarded while a workspace is bound — matching the CLI
`account remove`. --purge dir deletion stays on the CLI flag.
All management routes through the AccountRegistry + accountActionChannel, and
the list rebuilds live off the settings notifier. en/nl strings + widget/probe
tests added. Closes T-482.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A custom settings control under the Claude category: a dropdown of the
registered accounts plus Default. Picking one binds (or unbinds) this
workspace via the AccountRegistry and publishes set/unset on
accountActionChannel — the same channel the CLI verbs use, so the session
respawns onto the account (T-480) and the IDE lock re-syncs (T-479). It reads
live off the shared settings notifier, so a CLI `account set` updates the
dropdown too. Empty states cover no-workspace and no-accounts, each pointing at
the CLI.
Registry writes set the in-memory binding synchronously then flush, so the
control publishes the bus event before the disk write completes.
Part 2 (the global Accounts registry CRUD list + sign-in probe) is still open
on T-482. en/nl strings added; widget test covers the states + bind/unbind.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After live review: the shared account /usage budget read as redundant on
both the Activity and Team tabs. Usage is per-account and can't be split per
member, so one place is enough — it lives only on the Activity tab, next to
the refresh control that fetches it (T-415). Removes the Team-tab account
card, its usage prop wiring, the team.section.usage/team.usage.shared i18n
keys, and the now-obsolete team_tab test. The three-tab card facelift stays.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements T-158 option A: the forwarded /usage budget (already parsed for
the Activity tab, T-415) now also renders in the Team tab as a single
ACCOUNT card, captioned "shared across the team". Usage is per-account —
every team session shares one ~/.claude login — so it's shown once, not
split per member (which would just repeat identical numbers).
Facelift: the Activity, Team, and Config tabs now render their sections as
elevated cards (panelHeader fill, dividerColor hairline, 6px radius) under
small-caps mono headers, matching the settings overlay's card design
(settings_category_view). Shared helpers — metaSectionHeader / metaCard /
metaCardRow — live in meta_sidebar/models.dart; the SESSION control strip
and the pinned Config SETTINGS block adopt the same card. The shared
ClideAccordion (also used by decisions/tickets) is left untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes i18n coverage of the conversation surface — the strings the
T-464 migration left as "decorative" English:
- running-indicator verbs (Pondering/Conjuring/… → catalog, Dutch added)
- pane chrome title (primary / secondary N) and banner role
- tool-card titles (Edit → Bewerken) via a tool.name.* key set, with
command/proper-name tools (Bash, Grep, Glob, LS) falling back to the
raw name
- collapser step/edit/agent counters
- the folded-activity ticker (result/error/thinking/image + tool name)
English degrades to the placeholder where a key is absent, so untranslated
or MCP tool names render unchanged. en_us and nl_nl stay at key parity.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The i18n epic (T-462): every user-facing label — panels, dialogs, command
palette, menus, settings, framework chrome — now resolves through the i18n
catalog instead of a hardcoded string. Catalogs are bundled per locale under
assets/i18n/<locale>/<namespace>.json. Adds a live UI-language selector
(Settings → Appearance → Language) and a full Dutch (nl-NL) pack; English
stays the default. Architecture in D-102.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A full nl_NL catalog set under assets/i18n/nl_nl/ — all 26 namespaces, key-for-
key parity with en_us. Proper nouns (clide, Claude, Git, font names) and the
Vim mode names stay as-is; everything else is translated. Selectable via
Settings → Appearance → Language. The a11y i18n gate now also asserts the
Dutch pack covers every Tier-0 key, so a locale switch never falls back to
English for a built-in label.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the localization usable: an app.locale select (English / Nederlands) in
the Appearance category, applied live by root_shell — it parses app.locale and
calls i18n.setLocale on boot + on settings change (setLocale is a no-op when
unchanged). nl_NL registered in availableLocales. The ui-design skill now
documents the locale-dir config and the rule to design for string-length
variation (translations run ~20% longer; never hard-size to the English label).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the catalogs out of lib/kernel/src/i18n/catalog/ into assets/i18n/, and
switch the layout from a `{namespace}_{locale}.json` filename to a per-locale
DIRECTORY: assets/i18n/en_us/{namespace}.json. Adding a language is now just a
new folder (assets/i18n/nl_nl/, nl_be, en_eu, …) of the same namespace files —
no renames — which is cleaner to maintain and mirrors how an external
extension ships its own catalog. AssetCatalogLoader/FileCatalogLoader resolve
`<root>/<locale>/<namespace>.json`; pubspec bundles the locale folder.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Patch on 2.7.0: Josefin Sans is the default UI font again (Inter stays
selectable), and Claude's markdown-rendered prose + links now honour the
live UI-font setting instead of pinning the bundled default (T-475).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reverts the Inter default introduced in 2.7.0 — Josefin Sans (Light, w300) is
the default UI face again. Inter stays bundled and selectable in Settings →
Appearance; JetBrains Mono remains the default monospace with Fira Mono
selectable. Flips clideUiFamily/default weight, the picker's default + option
order, and the licenses.yaml purpose notes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Settings panel epic: schema-driven settings engine (modal shell, category
rail, per-field scope tags, cross-category search) with Activity, Keymap,
Appearance, Extensions, and Claude categories; Inter as the default UI font
plus live UI + monospace font pickers (Inter, Fira Mono bundled). Backed by
the ClideSettings facade (D-101) unifying theme, i18n, and fonts behind one
widget-facing read entry, with consumer reads migrated onto it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Settings → Appearance gains a Monospace font select (JetBrains Mono / Fira
Mono) on the schema engine, writing app.mono.font. It applies live: root_shell
resolves the family into the ClideSettingsScope (D-101) and rebuilds on the
settings change, so the ~93 migrated mono sites — terminal, diffs, code, IDs —
re-read the new family at once.
Vendor Fira Mono (Regular + Bold, OFL) under assets/fonts/fira_mono/ with the
pubspec font family + licenses.yaml entry per D-42; JetBrains Mono stays the
default.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Vendor Inter (variable + italic, OFL) under assets/fonts/inter/ and make it
the default application UI face, replacing Josefin Sans (which stays bundled
as a selectable option). pubspec font family + licenses.yaml entry per D-42.
Settings → Appearance gains a UI-font select (Inter / Josefin Sans). The root
DefaultTextStyle reads app.ui.font (kUiFontSettingKey) over the default and
re-applies live on settings change, so a pick takes effect immediately. Bump
the default UI weight to w400 — Inter reads better at Regular than Josefin's
Light.
The monospace picker is deferred to T-471: clideMonoFamily is a const at ~38
call sites (not inherited), so a live mono picker needs the family routed
through context first.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
self.version is auto-synced from pubspec by make gen-build-info; pubspec
is already at 2.6.0 but the generated value had lagged at 2.5.0. Commit
the regenerated file so the working tree matches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes out the T-403 cross-pane vim layer. gt/gT bind to the existing
workspace.tab.next/previous commands (also on ctrl+pagedown/up for every
preset), resolved by the focused editor's matcher or a pane's PaneKeyNav —
bare-g sequences stay editor/pane-local (T-404's global matcher only engages
on modified-chord prefixes), so no global-matcher surgery.
- vim.yaml: g t -> command:workspace.tab.next, g shift+t -> .previous
(vim.normal); shares the `g` prefix with `g g` (docStart / nav.top),
distinguished by the final chord.
- PaneKeyNav now EXECUTES non-editor.vim.* command intents (e.g.
workspace.tab.*) instead of swallowing all command intents, so gt/gT work
from a focused pane; editor.vim.* buffer edits stay blocked in panes.
Tests: vim-preset resolution (gt/gT bind, gg intact), PaneKeyNav executes
the command from a pane, and editor.vim.* is never run from a pane. make
test green; analyze + format clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Under the Vim preset, `:` opens a transient one-line ex overlay running a
fixed v1 table; ZZ runs :wq directly. Completes the last built child of the
T-403 cross-pane vim layer (T-405 part 2 gt/gT still open).
- ExLineController + parseExCommand grammar + editor-targeted executors
(lib/kernel/src/ex_line.dart); the overlay (lib/widgets/src/ex_line_overlay
.dart) reuses the quick-open chrome, mounts in the root_shell Stack, and
publishes the exline.open scope flag. Unknown commands flash + stay open;
with no active buffer every command no-ops (2026-06-13 decision).
- :q closes the active tab via editor.close on its id — the registry promotes
the next buffer and the split self-collapses on the last (2026-06-12
decision); :w/:wq/:x/ZZ save (+close) the active buffer.
- :e <path> seeds quick-open (new QuickOpenController.open(seed:)); :N adds the
editor.goto-line IPC/CLI verb (reuses _offsetForLine). Goto needs caret sync:
EditorController now handles editor.selection-changed and the editor view
moves the caret on a selection-only change.
- `:` and ZZ are typed intents; the editor matcher and PaneKeyNav now bubble
unhandled typed intents to the app-root Actions, so they fire from any focus.
vim.yaml binds `:`, ZZ (shift+z shift+z), and Esc-dismiss.
Tests: parser/controller/executors, editor.goto-line daemon tests,
selection-changed (controller + view), full overlay widget test. make test
green; analyze + format clean.
Also files T-441 (drop bold from the ticket-id card label) and T-442
(sub-agent renders as 3 cards instead of one bundle) under the T-276 UI epic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gen-build-info auto-syncs assets/licenses.yaml `self.version` from pubspec on
every build/run/test; this is the generated catch-up to the 2.5.0 cut (it ran
during the coverage build). Also persists the T-432 done status.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The structural piece: a global SequenceMatcher in root_shell, at the
HardwareKeyboard level so a focused editor/pane can't swallow the second
chord. It only STARTS on a modified chord that prefixes a sequence (ctrl+w),
so bare-key sequences (gg, dd) stay editor/pane-local and single-chord presets
are untouched; bare ctrl+w still fires editor.close after the D-82 timeout.
vim.yaml binds the window family under vim.normal||vim.visual: ctrl+w h/l →
panel.focus.left/right, j → dock.toggle, w / ctrl+w → focus.nextPanel,
shift+w → focus.previousPanel, o → panel.focusMode, q/c → editor.close.
Tests: ctrl+w sequence resolution at the keymap layer, plus app-level
integration (ctrl+w o toggles focus mode; bare ctrl+w closes the editor after
the timeout; a bare g is not grabbed globally).
This is the global matcher T-405 part 2 (gt/gT) was waiting on — though bare-g
sequences need more thought (g is editor-local), noted for that follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The structural T-403 child: make vim normal mode mean navigation in panes
that were mouse-only. The passive global key path can't run multi-chord
sequences (D-82), so each pane hosts its own SequenceMatcher — factored into
a reusable PaneKeyNav that resolves the live keymap and dispatches nav.*
intents while a pane holds focus under the vim preset.
- nav.* intents (down/up/pageDown/pageUp/top/bottom/expandOrRight/
collapseOrLeft/activate) — preset-neutral; vim.yaml binds j/k/ctrl+d/ctrl+u/
gg/G/l/h/[o,enter] under `vim.normal && !editor.focused`.
- The editor publishes an `editor.focused` scope flag from its focus node, so
the same keys stay buffer motions while the editor is focused and become nav
when a pane is — resolved by file order + the guard (no change to the editor
motion bindings).
- File tree: a flattened visible-index selection cursor in FileTreeController
(j/k move, h collapse-or-out, l expand-or-into, o/enter open), with a focus
ring + scroll-into-view.
- Conversation: j/k line-scroll, ctrl+d/u half-page, gg top, G bottom — G
re-arms follow-tail.
Foundation for T-404/T-405/T-407, which build on the per-pane matcher and the
editor.focused guard. Git panel + ticket board list nav deferred to a
follow-up (the ticket says lists can trail). Tests: keymap resolution under
both scopes, PaneKeyNav dispatch, the controller selection model, and
end-to-end key-driven nav in both panes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Patch release: double-Shift quick-open (new in 2.4.0) no longer fires
on chorded Shift, so Shift+; types a colon again in the editor and the
Claude composer (T-409).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Minor release. Adds live tail inside expanded Bash activity cards
(T-325) and double-tap-modifier shortcuts with double-Shift quick-open
across all keymap presets (T-341); each spawned subagent now gets its
own activity card (T-342). Carries a large stability sweep — PTY fd
and process leaks, IPC framing, settings durability, UTF-8 decoding
across chunk boundaries, transactional extension lifecycle — plus two
security fixes: the MCP HTTP server now requires a per-start auth
token (T-362) and editor.open/save are workspace-confined (T-363).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mocktail was pinned and documented as the IO-mocking strategy, but
after the T-91 coverage drive it had zero imports — every IO seam
ended up with an injected hand-rolled fake instead. D-25 is amended
to record that the hand-rolled-fakes rule covers IO seams too;
licenses.yaml and the lockfile follow. The ptyc binary removal noted
in this sweep landed with the git-API commit (it was already staged).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The chord matcher couldn't represent a bare or double-tapped modifier:
KeyChord.parse required a base key, so `shift shift` failed, and JetBrains
"Search Everywhere" (double-Shift) was unbindable.
Design decision: search-everywhere aliases clide's existing quick-open
finder (not a new overlay) — bound across all four presets per the user.
Changes:
- KeyChord: a bare modifier name (`shift`, `ctrl`, `cmd`, …) parses as a
modifier-free chord on that modifier's logical key, so parseSequence(
'shift shift') yields a two-chord double-tap. Adds KeyChord.bareModifier
and modifierForLogicalKey.
- ModifierTapTracker: headless, clock-injected double-tap detector. A bare
modifier never forms a single chord; an intervening key breaks the gesture.
- app.dart global handler feeds bare-modifier KeyDowns to the tracker and,
on a double-tap, resolves the 2-chord sequence via the new
KeymapService.resolveSequence. The existing single-chord path is untouched
(zero behavioural risk to normal keys).
- Presets: default/vim/vscode/jetbrains add `shift shift` → quickOpen.open.
jetbrains header updated (the gesture is now expressible).
Tests: bare-modifier parse/equality/round-trip; tracker window/reset/
different-modifier/consume; each shipped preset resolves double-Shift to
QuickOpenIntent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Patch release: the daemon boots its pql/git/files workspace at the last
opened project instead of the launch directory (HOME) on a desktop
launch, so the ticket/decision sidebars load on first open instead of
erroring against a stale ~/.pql/pql.db (T-352). Also raises the toolchain
floor to Flutter 3.35 / Dart 3.9 and refreshes dependencies after a clean
CVE audit (T-353).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Now that the SDK floor is Dart 3.9 (markdown 7.3.1 requires ^3.9.0), take
the bump. 7.3.0/7.3.1 are bug-fixes + perf with no breaking AST/Node
changes (we walk the parsed tree in our own renderer); only API-level
deprecations (LinkContext, BlockParser.standardBlockSyntaxes) we don't
use. licenses.yaml updated in the same commit; markdown goldens green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewed every direct and transitive dependency against the GitHub
Advisory Database / OSV (Pub ecosystem). No advisory affects any
dependency at its current pin or upgrade target — the "N packages have
newer versions" noise is freshness, not security. (Consistent with
`dart pub get` printing no advisory warnings.)
Bumped the safe pins + their licenses.yaml entries in the same commit:
- ffi 2.1.3 -> 2.2.0
- jovial_svg 1.1.26 -> 1.1.30 (pulls jovial_misc 0.10.0 + xml 7.0.1)
- mocktail 1.0.4 -> 1.0.5
Held, with the reason recorded inline in pubspec.yaml:
- markdown 7.2.2: 7.3.1 requires Dart ^3.9.0 — defer to an SDK-floor bump
- alchemist 0.12.1: 0.13.0 disabled text anti-aliasing -> golden churn
- test 1.31.0: flutter_test SDK-locks the resolvable ceiling
make test green (incl. SVG/xml goldens — the xml 6->7 major didn't churn
rendering).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Patch release: the real fix for the ticket/decision sidebars failing on
first load — IPC-server swaps are now serialized so the repo workspace
bind always wins over the boot launch-CWD bind (T-352). Supersedes the
partial 2.3.1 re-fetch-on-open, which is kept for mid-session switches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Patch release: ticket/decision sidebars load on first open (T-352), plus
the KWin frameless-chrome map fix (T-351) and the transient pql-failure
retry (T-350) that landed since 2.3.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cut the accumulated Unreleased entries under a dated 2.3.0 heading and
bump pubspec + licenses self.version. Minor bump: the batch adds features
(file references, task dock, deny-simplify, ticket pick-up, type-filter
chips, VS Code/JetBrains keymaps) alongside the fixes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- test: 1.30.0 → 1.31.0 (matches pubspec dev_dependencies)
- tree-sitter purpose: stale app/native/ path → native/linux-x64/
Surfaced by the T-25 audit and the 2026-05-14 security review. The
"phantom lints entry" that review also flagged is already gone.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
A custom in-window menu bar in the hat (no native menu, D-7), built from
the command registry so it stays in sync and satisfies D-6 parity.
- Menu model + hybrid resolver (menu_model.dart): a curated File/View/Help
tree where a MenuAutoFill node sweeps in unplaced view.* commands; titles
+ keybindings come from the registry/keymap; unregistered or
enabledWhen-false items render disabled (greyed), never hidden.
- Widgets: MenuBar row in the hat (chrome tokens), anchored MenuDropdown
overlay (dropdown tokens), two-column MenuItemRow with inline keybinding.
- Full keyboard: Alt+mnemonic opens (hook in _RootShell._onKey), arrows
navigate, Enter activates, Esc closes, Left/Right switch menus.
- Commands: file.openFolder / file.newWindow / file.closeWorkspace /
help.about, registered by MenuBarExtension(services:). File logic lifted
out of the project switcher into FileActions (one source of truth; the
switcher now dispatches the commands). Ctrl+O / Ctrl+Shift+N are now real
keybindings in default.yaml.
- Help → About: version/commit/date/repo from build-info + the bundled
dependency licenses parsed from assets/licenses.yaml.
Edit/Selection menus are deferred to T-271/T-272 (need focused-surface
command routing).
Tests: resolver + controller + licenses parse (pure); menu-bar widget
(open/close/execute/disabled/Esc/arrow/Enter/Left-Right); FileActions +
Open dialog; app-level Alt+F, non-repo dialog, and closeWorkspace.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ships catppuccin-mocha (faithful to the official Catppuccin Mocha
palette) and catppuccin-mocha-hc (high-contrast sibling per D-69 — the
faithful palette is never retuned to pass the gate). Both bundled and
gated: mocha clears baseline AA, mocha-hc clears the strict extended
set. Catppuccin MIT palette recorded in licenses.yaml.
Closes T-82 (Mocha + hc meets every acceptance bullet; faithful Latte
deferred — it can't clear baseline AA without retuning, a separate call).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>