Commit Graph
13 Commits
Author SHA1 Message Date
jpmschweitzerandClaude 4f8840ccd2 add type scale constants; remove scattered font size overrides
Sidebar and panel text was too small — dozens of bare fontSize:
10/11/12 values fighting the ambient DefaultTextStyle. Root font
bumped from 13 to 14. Three semantic constants replace the magic
numbers: clideFontBody (14), clideFontCaption (12), clideFontMono
(13). Widgets that render body text now inherit instead of
overriding.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 15:18:30 +02:00
jpmschweitzerandClaude e290ae6dbd wire builtin.pql + builtin.problems panels
test / unit + widget + golden + a11y (push) Failing after 40s
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
PqlExtension contributes a sidebar tab (files, query, decisions,
tickets views) and a context-panel tab (backlinks + outlinks for
the active file, auto-refreshing on editor.active-changed).

ProblemsExtension contributes a sidebar tab aggregating pql.doctor
and decisions.sync diagnostics with actionable hints.

Both upgraded from stubs to 0.1.0.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 14:03:32 +02:00
jpmschweitzerandClaude e43438d369 remove Python stopgap; rewire to pql 1.0
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
pql 1.0 ships full feature parity for decisions and tickets.
Sunset condition from D-040 met; deletion per R-011.

Removed: tools/scripts/plan entrypoint, tools/scripts/planning/
Python modules, tools/scripts/README.md, .gitignore pycache
entries.

Rewired: make decisions-validate now calls pql decisions validate.
CLAUDE.md decision discipline guardrail points at pql. Extension
stub comments updated. decisions/README.md examples use pql.
D-040 amended as superseded.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 13:39:28 +02:00
jpmschweitzerandClaude 6bce2621b7 wire builtin.git sidebar panel + builtin.diff workspace tab
test / unit + widget + golden + a11y (push) Failing after 37s
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
GitController hydrates from git.status IPC and auto-refreshes on
git.changed events. Panel shows staged/unstaged/untracked/conflict
groups with per-file actions and an inline commit field.

DiffController renders unified diffs with line numbers, addition/
removal colouring, and a staged/unstaged toggle. Both extensions
upgraded from stubs to 0.1.0.

ClideText gains an optional fontFamily parameter so diff lines can
render in JetBrainsMono without breaking golden tests (font still
inherits from ambient DefaultTextStyle by default).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 11:09:48 +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 50d9e00ea5 add shared pane widgets + Q-023 ssh-remote question
ClidePtyView is a theme-bound wrapper around xterm.dart's TerminalView
— token-derived TerminalTheme, JetBrainsMono as the face, Semantics
live-region label so screen readers + Playwright both hear it. The
consumer (terminal / Claude extensions) owns the `Terminal` model and
wires IPC pane.write / pane.output → terminal.write() themselves; the
widget deliberately has no IPC dependency so it stays trivially
testable.

ClidePaneChrome is the shared pane header — title + subtitle + leading
icon + trailing widgets + optional close button. The close button is
null-conditional so primary Claude panes (D-041, landing in step 7)
can render without one.

xterm 4.0.0 added as a justified runtime dep + logged in
licenses.yaml per D-042. 3 new widget tests cover header rendering,
close-button presence, and the close-tap round-trip.

Q-023 records the SSH-remote-development question so the daemon + IPC
seams don't accrete local-only assumptions during Tier 1-5.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:19:24 +02:00
jpmschweitzerandClaude c1ad33f1b0 bundle Josefin Sans as the default UI face at weight 300
Vendor the JosefinSans variable font (upright + italic, weight range
100-700), OFL licensed. _AppRoot installs it as the ambient
DefaultTextStyle at weight w300 (Light); ClideText inherits rather
than re-specifying the family, so Alchemist's Ahem injection keeps
goldens deterministic per D-024 while production renders the
intended face.

typography.dart gains clideUiFamily + clideUiFamilyFallback
alongside the existing mono constants; .gitignore learns about
Alchemist's failures/ diff output dir so local re-runs don't leak
into `git status`.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 08:18:15 +02:00
jpmschweitzerandClaude 7bdeb9ab24 bundle JetBrains Mono for terminal panes
Vendor the 4 core weights (Regular, Italic, Bold, BoldItalic) of
JetBrains Mono v2.304 under app/assets/fonts/jetbrains_mono/, ~1 MB
total. OFL license checked in alongside. Declared as the
JetBrainsMono family in pubspec so Flutter bundles it automatically.

app/lib/widgets/src/typography.dart exposes clideMonoFamily plus a
platform-ordered fallback chain (SF Mono / Menlo / Monaco →
JetBrains Mono system install / Fira Code / Hack / DejaVu / Liberation →
Cascadia / Consolas → monospace) for web builds and test harnesses
that don't load asset fonts. Terminal widgets pick both up via a
single import.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 08:02:10 +02:00
jpmschweitzerandClaude e2b3f7cff1 update CLAUDE.md and reserve decision/ticket/claude-control slots
test / unit + widget + golden + a11y (push) Successful in 4m34s
test / integration_test (xvfb) (push) Failing after 1m4s
test / bundle smoke (xvfb 5s) (push) Failing after 58s
test / daemon subprocess + web WASM smoke (push) Successful in 2m27s
CLAUDE.md gains a "Decision discipline" guardrail pointing at
decisions/<domain>.md, rewrites every inline ADR link to the new
anchor-link style (ADR 0001 → D-001, etc.), collapses the bottom
"Open questions" section to a one-line pointer, and updates the
parent-project note to reference decisions/architecture.md instead
of the deleted docs/ADRs/.

Three extension slots are reserved with id-only stubs, registered
alongside the existing 21 built-ins in main.dart:
  - builtin.decisions — future sidebar for D/Q/R records
  - builtin.tickets — future sidebar + kanban workspace
  - builtin.claude-control — future .claude/ first-class surface
    (Settings / Skills / Agents / Hooks / MCP). Distinct from the
    existing builtin.claude PTY-pane stub.

`flutter analyze` clean; builtin + a11y test suites still pass.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:32:06 +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