Commit Graph
12 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 eedeaec05a persist last-opened project and wire welcome open dialog
ProjectManager.open() now saves app.lastProject to user settings.
Boot calls openLast() instead of opening cwd — first launch shows
the welcome screen, subsequent launches restore the last project
directly into Claude. The welcome "Open project" button shows a
modal path-entry dialog that validates against git and activates
the Claude tab on success. Removed the dead "New Claude session"
button since secondary sessions are spawned via command palette.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 23:29:40 +02:00
jpmschweitzerandClaude Opus 4.6 43901bc387 implement editor-above-Claude split in workspace
Editor opens above Claude via Ctrl+E with a draggable divider at
35% height (clamped 15-70%). Ctrl+W or Escape closes it. The
workspace no longer renders a tab bar — Claude is the always-visible
primary surface per D-047/D-048; the editor is a split overlay
per D-049, not a tab. The _WorkspaceSlot separates editor from
primary content tabs and renders them as a vertical split when the
editor is open.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 23:01:02 +02:00
jpmschweitzerandClaude Opus 4.6 11eb91effe implement collapse spine, focus mode, keyboard shortcuts, context rail
Collapsed side panels render as a 12px vertical spine with rotated
label, hover highlight, and badge dot (D-051). Focus mode snapshots
and restores the full layout arrangement (D-052). Fourteen new
commands in the default-layout extension: collapse toggles
(Ctrl+Shift+1/3), panel focus (Ctrl+1/2/3), focus mode (Ctrl+.),
sidebar section switching (Alt+1-5), Escape dismiss (D-054). Right
panel gets a bottom icon rail matching the sidebar pattern (D-047).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 22:47:45 +02:00
jpmschweitzerandClaude ce8529e424 add tree-sitter syntax highlighting via dart:ffi
Vendor libtree-sitter.so (v0.26.8, wasmtime 44.0 statically linked)
and call its C API through dart:ffi. Grammar WASM files are loaded by
tree-sitter's embedded wasmtime engine via ts_wasm_store_load_language.

48 grammars compiled with tree-sitter build --wasm, 48 highlight
queries (42 from upstream repos, 6 written in-house for comment,
erlang, gdscript, gitignore, hcl, hlsl, swift). SQLite grammar
replaces full SQL (974K-line parser exhausted RAM at compile time).

Removes wasm_run and wasm_run_flutter — they downloaded a 22 MB
binary from GitHub at first launch, violating the no-network-on-
default-launch-path policy.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 22:08:00 +02:00
jpmschweitzerandClaude 4f5d97ebc5 define core frame vs shipped extension boundary (D-046)
Core frame builtins are infrastructure the shell can't function
without. Content extensions (editor, claude, canvas, etc.) are
bundled but architecturally removable — users swap the surface,
not the data.

Removes builtin.jira stub: Jira belongs as a third-party
extension, not a frame builtin. Git is a split component —
daemon-side process stays in frame, UI surfaces are extensions.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 22:07:04 +02:00
jpmschweitzerandClaude 8b5615426a wire design palette through resolver with fallback chains
Surface map now tries palette keys (bgSunken, surfaceHi, textHi,
etc.) first, falling back to semantic refs for legacy themes.
Sidebar/panel bg differentiates from workspace bg. Buttons use
accent colour with onAccent text. Four-level text gradient flows
to widgets.

WCAG-AA contrast fixes: clide textDim lightened, midnight
onAccent darkened, paper textDim darkened. Contrast test updated
to cover all four themes. Resolver tests updated for the new
palette shape. Goldens regenerated.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:54:11 +02:00
jpmschweitzerandClaude 5869697297 add four design themes + syntax tokens to theme pipeline
test / unit + widget + golden + a11y (push) Failing after 39s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
SurfaceTokens gains seven syntax-role fields (keyword, type,
string, number, comment, method, punct). Theme loader parses
the syntax: YAML block and injects values into the surface
override layer. Resolver defaults map syntax roles to semantic
colours so themes without explicit syntax blocks still compile.

Four new theme YAMLs (clide, midnight, paper, terminal) replace
summer-night. Palette keys mapped to the existing semantic layer;
syntax values pass through directly. Goldens regenerated for the
14→font-size change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:29:41 +02:00
jpmschweitzerandClaude 681ce3b447 wire builtin.editor to the active buffer + open files from the tree
test / unit + widget + golden + a11y (push) Failing after 38s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
EditorController mirrors the daemon's active buffer into the Flutter
UI. Hydrates on mount (editor.active → editor.read), subscribes to
editor.opened / active-changed / edited / saved / closed, and pushes
local edits back via editor.set-content. A one-shot echo-suppression
flag keeps the daemon's authoritative edit echo from clobbering the
caret the user just moved.

Text surface is EditableText directly — no TextField / Material
import, so D-007's "bare WidgetsApp" guardrail carries into the
editor tab. JetBrainsMono via the shared mono-family constants;
cursor + selection colours come from the theme tokens.

File-tree click now calls ipc.request('editor.open', {path}) instead
of the kernel command registry (which wouldn't have reached the
daemon). The opened file becomes active, the editor tab's controller
sees editor.active-changed, and the text content reconciles.

Linux release bundle still builds; 174 app tests + 74 core tests
stay green.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 10:31:01 +02:00
jpmschweitzerandClaude b9fbcd43a2 implement builtin.claude per D-041
test / unit + widget + golden + a11y (push) Failing after 45s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Tier-0 stub flipped to the real Claude pane. Primary-per-repo
semantics: session name is `clide-claude-<hash>` where <hash> is
FNV-1a over the workspace root path, so reopening clide attaches
to the same `claude` process through `tmux new-session -A`.

Primary has no close button — closing the tab disposes the widget
but deliberately does NOT call pane.close, so the tmux session
survives until the user actually exits claude or clide is shut
down. Secondary sessions (spawned via the claude.new-secondary
command registered here, UI wiring lands next) close normally and
the pane.close cascades into tmux kill-session.

Graceful fallback when tmux isn't on PATH: retries the spawn with
argv=['claude'], surfaces "no-tmux · fresh every launch" in the
header subtitle so the user knows persistence is off.

Session-naming unit tests cover determinism + uniqueness per repo.
Full app suite: 174 tests passing.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:40:30 +02:00
jpmschweitzerandClaude 4ff5556896 implement builtin.files — workspace file tree with live watcher
Flutter sidebar tab that lazy-loads the workspace tree via IPC
files.ls and refreshes subtrees on files.changed events. Click-to-
open routes through a future editor.open command; until Tier 2
registers it, the execute call no-ops gracefully.

Daemon side adds a new files subsystem:
  - files.root returns the resolved workspace root (git root if
    present, otherwise cwd)
  - files.ls lists a directory with ignore filtering applied
  - files.watch starts a recursive Directory.watch and fans
    FileSystemEvents out as files.changed IPC events
  - FilesService owns the watcher + ignore set lifecycle

IgnoreSet + IgnorePattern implement the common gitignore subset:
anchored (/foo), directory-only (foo/), negation (!foo), **
crossing dirs, ** at trailing position. Built-in layer hides clide-
owned dirs (.git, .pql, .clide, .dart_tool, build, node_modules);
.gitignore + .clideignore at the root layer on top per D-004. Full
multi-file ignore_files: layering from .pql/config.yaml is future
work.

11 new ignore-matcher tests + 5 files.* dispatcher tests.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:36:02 +02:00
jpmschweitzerandClaude e1ea52c5e4 implement builtin.terminal — general-purpose shell pane
Flips the Tier-0 stub into a real extension. Contributes a Terminal
tab in the workspace slot that spawns $SHELL -l via IPC pane.spawn,
feeds pane.output events into xterm.dart's Terminal, and routes user
input back through pane.write. Viewport resize propagates via
pane.resize. Surface for disconnected-daemon / exited-shell states so
there's no silent dead tab.

Knows nothing about Claude deliberately — the Claude-specific pane
(primary-per-repo, tmux-backed, D-041) lives under builtin.claude in
the next steps.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:23:44 +02:00
jpmschweitzerandClaude b13483e2d5 scaffold Flutter app — kernel, extensions, widgets, Tier 0 built-ins
First real content under app/. Lays the whole Tier 0 foundation in one
commit because the pieces depend on each other circularly (kernel →
extension → widgets → built-ins all reference types from the layer
below); splitting would leave intermediate commits that don't compile.

Key shapes:

  * bare WidgetsApp root — no Material, no Cupertino, no Scaffold.
    ClideTheme InheritedWidget is the only source of tokens.
  * ClideKernel InheritedWidget aggregates 18 services (settings,
    project, extensions, theme, panels, events, ipc, commands +
    palette + keybindings, clipboard, files, notify, dialog, tray,
    secrets, os, net, focus, log, i18n). ExtensionContext exposes
    them through a stable interface.
  * ClideExtension + sealed ContributionPoint hierarchy (Tab,
    StatusItem, Toolbar, Command, TrayItem, LayoutPreset). One
    manifest ships N contributions into kernel slots.
  * Three-tier theme pipeline: palette (named colors) → semantic
    roles → ~60 surface tokens. Defaults at each layer so legacy
    palette-only themes produce a complete SurfaceTokens.
  * A11y baked in from day one — every interactive primitive wraps
    in Semantics(label:, hint:, button:); ensureSemantics() at boot;
    theme/contrast.dart helper exposes token pairs for the WCAG
    gate in the a11y test suite.
  * i18n ported from fframe's L10n pattern (text-driven, namespaced
    JSON catalogs, caller-supplied placeholders) with a proper
    locale fallback chain (exact → language → default → placeholder)
    fframe lacks.
  * Four Tier-0 built-ins live (default-layout, welcome, ipc-status,
    theme-picker) plus 17 id-reserving stubs so later tiers fill in
    without rename churn.

.gitignore extended to cover app/ sub-package artefacts and the
Playwright harness scratch dirs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:39:41 +02:00