D-106 supports opening a worktree under <repo>/.worktrees/ as its own
workspace; the dir itself is sibling checkouts, not tree content — so
the builtin ignore set hides it and the project-init scaffold
gitignores it alongside .clide/.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
Implements D-106. The T-439 login-shell probe is a global heuristic
with a known hole — login-but-non-interactive shells skip ~/.bashrc,
so interactive-only additions (brew shellenv) never reach the agent's
Bash tool or terminal panes on a desktop launch. The preset is the
explicit per-repo layer on top: user-scope storage keyed by repo
identity (a linked worktree resolves through its gitdir pointer to the
main repo, so worktrees share the preset), prepended at spawn via the
PaneRegistry pathForSpawn hook and agentEnvDelta prependDirs — which
now exports PATH even when clide is already resolvable, closing the
gap where the hosted session inherited the sparse GUI PATH untouched.
CLI half: `clide env path list|set|add|remove|clear|capture` over an
injected Flutter-free store port; capture diffs the login-shell PATH
against the process PATH to suggest the dirs a desktop launch dropped.
Binary resolution (toolchain, supporter pins, bundled pql/git) stays
preset-blind per the D-92/T-98 fence.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Decides FR-1: a machine-local, user-scope list of dirs prepended to the
PATH of every spawned shell, keyed by repo identity so linked worktrees
(.worktrees/) share their main repo's preset. Prepend-over-login-shell
semantics, D-6 CLI parity (env path verbs), and a security fence: the
preset never feeds clide's own binary resolution (T-98 lesson).
Also corrects D-104's cross-references: the bundled-pql decision is
D-92, not D-58 (D-58 is format engines) — the anchor was dead.
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>
builtin.canvas graduated from a Tier-0 stub to a real extension with an
activate/deactivate lifecycle, so the real-boot harness should exercise
it like its siblings. 26/26 pass.
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>
Batch selection via /whats-next confirmed finishing T-322 as the next
work. Refinement pass resolved the open integration questions:
workspace slot + real MultitabPane tabs (user-confirmed), file-open
routing via the openWorkspaceFile() .md-branch mirror plus a ui_command
_readers entry for D-6 CLI parity (fileGlobs confirmed dead — not
wired), and a stale SVG-lowering doc header in json_canvas.dart to fix
alongside the pane-shell work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The .canvas rendering + interaction foundation is built and tested (parser,
CustomPaint renderer, interactive CanvasView — 21 tests). Records the
remaining reachable-integration phase: pane shell, CanvasExtension
registration, and .canvas file-open routing (TabContribution.fileGlobs is
declared but unconsumed, so routing must be built).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds hitTestCanvasNode (topmost node under a point, cards over the group
frames behind them, via the same viewport the painter draws with) and the
CanvasView widget: scroll-zoom, drag-pan, and click-to-select with a focus
ring. Node drag/resize and edit affordances follow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Records that the model/effort trust problem spans more than the
local-command-stdout render defect: control state reflection, point-of-
interaction acknowledgement, and active-value drift are all in scope.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-509 (child of the UI/UX epic T-276): investigate + improve the model
switch and effort toggle so a change is unmistakably confirmed. T-322
(canvas pane) moved to in_progress with its parser + renderer foundations
recorded.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-509 (child of the UI/UX epic T-276): investigate + improve the model
switch and effort toggle so a change is unmistakably confirmed. T-322
(canvas pane) moved to in_progress with its parser + renderer foundations
recorded.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Paints a CanvasDoc — group frames behind, edges with arrowheads, then
node cards (text / file / link) — fitted by a shared pan/zoom CanvasViewport
so a later hit-test lands on what's drawn. Node colours come from the file
(Obsidian presets 1..6 or hex), not clide tokens, since a .canvas is
arbitrary content; only the chrome is themed. Read-only for now; selection,
drag, and edit affordances follow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Parses the Obsidian .canvas format into a typed CanvasDoc — text / file /
link / group nodes and edges (sides, end caps, colour, label) — and
serialises back with round-trip fidelity. Unknown node types and entries
missing required fields are skipped rather than fatal; end caps omit their
spec defaults on write. Pure Dart, no I/O; runs under dart test. The
foundation for the interactive canvas pane.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Tier-5 graph pane is fully delivered: force-directed layout, hover
highlight, click-to-open, pan/zoom, and path-glob / tag / depth filters.
Real-boot verified via testmode; 56 graph tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <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>
Adds the pure filtering primitives the graph pane composes: VaultGraph
nodesWithin (depth-bounded BFS over undirected edges = the local graph
around a note) and subgraph (retain a node set + the edges between them),
plus GraphFilter, which combines depth-from-active with tag include/exclude
over a caller-supplied tag map. Flutter-free; runs under dart test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds PqlExtension + GraphExtension to the extensions-category boot test so
the graph view's dependency-ordered activation and real i18n-catalog load
are validated in a full app boot, not just the widget fixture.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Folds a user zoom (scroll wheel, clamped) and pan (drag) transform into
GraphViewport so the painter and hit-testing move in lockstep — hover and
click keep landing on what's drawn. Zoom scales about the canvas centre; a
fresh graph re-fits and drops the transform.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 2026-07-02 skill review found the repo bundling skills that don't
belong to it: d2-diagram and frame0-wireframe are repo-agnostic and
carried settled-reach game content verbatim (agent personas, palette,
templates) presented as clide conventions; skill-create was a
byte-identical copy of a generic skill; clean-house was double-installed
(the pql-managed user-scope copy is canonical); the generic commit skill
collided with git-commit on its trigger word while contradicting three
repo safety rules; penpot-login was fully broken and published personal
infrastructure in a public repo.
d2-diagram, frame0-wireframe, and skill-create now live de-contaminated
at user scope (~/.claude/skills/). The commit/penpot-login/clean-house/
skill-create deletions landed with the previous commit (pre-staged by
git rm); this one removes the centralized pair and rewrites the README
index to the five clide-specific skills that remain.
Co-Authored-By: Claude <noreply@anthropic.com>
The 2026-07-02 skill review (adversarially verified) found the bundled
skills teaching pre-refactor reality: whats-next pointed refinement
agents at the pre-governance/ decision paths, claimed gh doesn't exist,
and taught the hand-staged .pql/changelog flow the pre-commit hook
replaced; git-commit mandated the heredoc-in-substitution commit form
the repo moved away from and referenced sidecar-era paths; the clide
skill omitted the dock slot (D-87); testmode omitted the terminal
category; ui-design's glyph table taught the static-const icon API
removed in T-314, and its generator scanned for a pattern that no
longer matches anything.
All fixed against current repo state. The glyph table is regenerated
3-column (name-keyed, byName-first); tool/gen_phosphor_glyphs.dart
round-trips it byte-identically. git-commit also gains the
session-vs-pre-existing triage step (backported from the settled-reach
variant) since this worktree hosts concurrent Claude sessions.
Co-Authored-By: Claude <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>
Wraps GraphController + GraphView into the panel widget: loads the vault
graph on mount, shows a spinner / empty / error state until it is ready,
then draws the graph and opens a note on node click via editor.open. A
debounced refresh keeps the current graph on screen instead of flashing
back to the spinner.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lists every markdown note (nodes) and fetches each one's outlinks
(edges) via the pql.files / pql.outlinks IPC commands, assembling the
file->outlinks map that VaultGraph consumes. Coalesces file-change
bursts into one debounced reload. 1+N calls, since pql exposes no
bulk-outlinks query; acceptable for a spinner-backed, explicitly-opened
view.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GraphView lays a VaultGraph out with the force solver, paints it, and wires
hover (light the hovered node's neighbourhood, dim the rest) + click (onOpen
with the node's vault path). A shared GraphViewport keeps hit-testing aligned
with paint. Solver + model + painter + interactive view now stand; the pql
link-data wiring, filter, and MultitabPane/slot registration are the
remaining "integrate into the app" work.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GraphPainter draws a solver-positioned VaultGraph — edges as lines, nodes as
labelled dots — fitting the layout space into the canvas (aspect-preserving,
centered), with a hovered node's neighbourhood lit and the rest dimmed.
Paints through SurfaceTokens (the graph is IDE chrome here, D-7).
Pixel-tested. Solver + model + painter now stand; the interactive pane (pql
wiring, hover/click, filter, tab/slot) is next.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
VaultGraph.fromOutlinks builds the graph from pql's per-file outlinks: every
file a node (labelled by basename), each outlink to a known file an edge;
self/dangling links dropped, parallels de-duped. neighborhood() drives the
hover-highlight; edgePairs feeds the ForceLayout solver. Pure Dart,
dart-tested (6 cases). The graph pane's data layer, on top of the solver.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The three worst-covered files were genuinely untested, not edge cases:
os.dart 27%→~85% (inject the process runner so openURL/reveal don't spawn a
real browser), clide_code_block 39%→~90% (expose the byte→char span mapper
as a top-level fn + render tests), deeplink 29%→~75% (the confirm-opens and
not-activated paths). Buys buffer above the 95% floor so a feature batch
doesn't immediately trip the gate. 95.01% → 95.22%.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The drawing-card feature batch (icon/image/compare/graph/d2 cards, --stdin,
tool resolution) added widget + wiring code that dipped total coverage under
the 95% floor — surfaced by `make release` (push-check skips coverage). Cover
the gaps: ProblemsController.refresh, every SVG shape-type bbox + the style
vocabulary, _spawnD2 via a real /bin/cat, the icon-show bus path + error
branches, and quad/arc/close marker paths.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
draw is single-token (no verb), so `clide draw --file x` mis-parsed as cmd
"draw.--file" — the dispatcher registered draw but the argv parser never
learned it was umbrella (unlike icon/image which use subsystem.verb). Found
driving the live install; the handler unit tests bypassed the argv path so
they missed it. Added draw to _umbrellaCommands + a parse regression test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fruchterman-Reingold (clide-owned, no layout package): nodes repel, edges
attract, cooled over iterations into a readable layout. Deterministic — a
fixed circular seed, no RNG — so the graph view is stable across rebuilds
and the solver is unit-tested (6 cases). Flutter-free; the interactive graph
pane (render, pan/zoom, hover, filter, pql wiring) builds on this.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
graphTemplateHandler lowers a {nodes,edges} payload to SVG: a deterministic
circular layout of labelled <circle> nodes with <line> edges, self-contained
(own light backdrop + content colors, like a d2 card) and painted by the
shared renderer. Display-only (D-78); decoupled from the interactive graph
pane (T-323) since a static card only needs a layout->SVG. Honest error on
a duplicate id or an edge to an unknown node.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The C client slurps stdin when it sees --stdin, strips the flag, and ships
the payload alongside the argv; the Dart unwrap folds it into the request
as a `stdin` arg (undeclared keys pass the schema untouched). icon.show and
image.show now read that payload as the peer of --file (stdin wins). Bounded
slurp + the envelope's existing size guard keep a huge payload from
corrupting the wire. C client builds clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The drawing card now loads any <image> hrefs its SVG references into
ui.Images before painting (loadDrawingImages, decoder injectable for
tests) — the renderer and the lightbox both paint through the resolver, so
a compare card shows real images and zooms. main registers the `compare`
template with a workspace path resolver. A drawing with no images is
unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
compareTemplateHandler lowers an `images` array to an SVG of side-by-side
<image> cells, each with the per-object data-label/description caption and
data-lightbox; paths resolve to absolute up front (injected, honest error
on a miss). _paintImage now aspect-fits (contain, centered) so cells of
differing-shape images don't distort. Flutter-free handler + painter pixel
tests. Card image-loading + registration next.
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>
icon.show resolves Phosphor glyphs by name (injected resolver) or a 0xNNNN
codepoint, reads a --file JSON array of {icon,label,description,color}
entries, validates colors via parseSvgColor (hex or CSS name), and
publishes on the `icon` bus channel. Honest userError on an unknown glyph,
a bad color, or a malformed payload. A trailing stringList positional is
now variadic so `icon show gear folder gauge` collects every token.
Flutter-free, dart-tested. Card widget + wiring next.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`clide image show --file meta.json` reads a {path,label,description,caption}
payload so an image can carry a title and a longer description, not just a
one-line caption. ImageMessage + the image card render the richer metadata;
the bare `image show <path> [--caption]` form is unchanged. Honest userError
on a malformed/missing payload. Text annotation only (option a) — visual
marker overlays stay a follow-up.
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>
The d2 drawing template compiles a diagram's source to SVG through the d2
binary (resolved via the D-104 path layer), then paints it with the same
renderer the svg card uses. `clide draw --file x.d2` infers the type from
the extension; `.svg` files render directly. Template handlers now return
a DrawResult so a compile failure or an unresolved d2 surface as an honest
userError with an install hint, not a generic "no SVG". Real d2 0.7.1
verified end to end.
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>
Store each tool's override under its own key (app.tools.<name>) instead of
one map, so the settings panel can bind a plain text field per tool.
loadSupporterBinaries reads the per-tool keys plus a first-run marker and
keeps an explicit path; redetectSupporterBinaries backs the Re-detect
action. The resolver itself is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Problems panel flags a configured tool path (app.tools) that no longer
points at a file — a real misconfig, echoing D-58's soft floor. A merely-
unfound optional tool isn't flagged (its use-time userError covers that).
Extracted to a pure supporterToolProblems(), flutter-tested (3 cases).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
main resolves the override map (and first-run auto-detects, using the
primed login-shell PATH) right after bootSettings.load(), exposing the
process-wide activeSupporterBinaries that tool consumers read — the d2
template (T-494) will resolve its binary through it. Analyze clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>