Commit Graph
102 Commits
Author SHA1 Message Date
Jeroen SchweitzerandClaude Opus 4.6 a028eb7ad3 pass -x/-y to tmux new-session for correct initial size
test / unit + widget + golden + a11y (push) Failing after 27s
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
tmux running inside a PTY without a traditional terminal client
defaults to a huge window size (2000+ cols, 10000 rows). Pass
explicit -x and -y flags matching the TerminalView dimensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 13:03:51 +02:00
Jeroen SchweitzerandClaude Opus 4.6 0b3c6bc1f8 restore tmux session in Claude pane
test / unit + widget + golden + a11y (push) Failing after 34s
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
Reverts the bare-shell diagnostic. Spawns tmux new-session -A -s
<sessionName> for persistence. Claude command will be added back
after tmux + resize are stable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 12:20:03 +02:00
Jeroen SchweitzerandClaude Opus 4.6 29fe6795b3 rename CLIDE_WORKSPACE to CLIDE_PROJECT
test / unit + widget + golden + a11y (push) Failing after 28s
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
Missed in the workspace → project rename. Consistent with the
project.open / project.validate / ProjectOpened naming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 12:11:15 +02:00
Jeroen SchweitzerandClaude Opus 4.6 2921adc9cb add TERMINFO env for top/ncurses, tighten output flush
test / unit + widget + golden + a11y (push) Failing after 28s
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
top fails with "Error opening terminal: xterm-256color" because the
PTY child can't find terminfo. Set TERMINFO=/usr/share/terminfo
explicitly in the pane environment.

Output flush changed from 16ms Timer to Duration.zero (next event
loop turn) for tighter batching of escape sequences.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 12:08:01 +02:00
Jeroen SchweitzerandClaude Opus 4.6 3e6c0279ef batch terminal output at 60fps, increase read buffer to 64KB
test / unit + widget + golden + a11y (push) Failing after 29s
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
Split escape sequences caused rendering artifacts (visible % prompt
mark, garbled lines between commands). Two fixes from the legacy
Python implementation:

1. Read buffer increased from 4096 to 65536 bytes. Larger reads mean
   fewer chunk boundaries that can split multi-byte escape sequences.

2. Output writes throttled to ~60fps via a 16ms Timer. Multiple PTY
   reads within one frame window are batched into a single
   terminal.write() call, so the xterm parser sees complete sequences
   instead of fragments that render as garbage between frames.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 12:01:22 +02:00
Jeroen SchweitzerandClaude Opus 4.6 0485a36091 stagger initial scheduler ticks to avoid rebuild storm
test / unit + widget + golden + a11y (push) Failing after 33s
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
Firing all tier ticks simultaneously on project open causes multiple
IPC calls (pql, git, files) to run in parallel, their responses
triggering rapid setState rebuilds that beachball the merged thread.
Stagger 500ms apart so each panel refreshes sequentially.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 11:41:42 +02:00
Jeroen SchweitzerandClaude Opus 4.6 2f7435f271 debounce terminal resize, add SIGWINCH, remove padding
test / unit + widget + golden + a11y (push) Failing after 28s
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
Rapid resize during window drag sends many SIGWINCH signals causing
the shell to redraw repeatedly, corrupting xterm's render. Debounce
to 150ms so only the final size is sent.

NativePty.resize now explicitly sends SIGWINCH (signal 28) after
TIOCSWINSZ, matching the legacy Python implementation.

Removed 8px padding from ClidePtyView to eliminate potential
dimension mismatch between widget size and PTY cols/rows.

Default window size increased to 1600x900.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 11:40:12 +02:00
Jeroen SchweitzerandClaude Opus 4.6 6f12c884cd defer PTY spawn until first TerminalView resize
test / unit + widget + golden + a11y (push) Failing after 1m57s
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
The PTY was spawning at 80x24 defaults before TerminalView had laid
out, then the real resize caused visual artifacts (ghost lines, broken
reflow). Now spawn triggers on the first onResize callback when real
dimensions are known — matching the pty-spike's proven pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-01 09:24:10 +02:00
Jeroen SchweitzerandClaude Opus 4.6 6d180a876a resolve bare command names via PATH before execve
test / unit + widget + golden + a11y (push) Failing after 28s
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
execve doesn't search PATH — bare names like 'tmux' or 'claude' fail
silently. Resolve via the environment's PATH in Dart before passing
to the child. This matches ptyc's old execvp behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 22:42:24 +02:00
Jeroen SchweitzerandClaude Opus 4.6 5aa0eb46e4 replace ptyc with forkpty() via Dart FFI
test / unit + widget + golden + a11y (push) Failing after 3m13s
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
NativePty calls forkpty() directly — no helper binary, no socketpair,
no SCM_RIGHTS. The master fd stays in-process. Reader isolate uses
poll() for clean shutdown.

Based on the pty-spike proof-of-concept. Platform-aware: macOS uses
libSystem (DynamicLibrary.process), Linux needs libutil.so.1.
TIOCSWINSZ platform-detected.

PaneRegistry updated to use NativePty. registerPaneCommands no longer
needs a Toolchain parameter. All ptyc references removed from the
daemon layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 20:30:15 +02:00
Jeroen SchweitzerandClaude Opus 4.6 cf2ae48201 use pql decisions read for full body text
test / unit + widget + golden + a11y (push) Failing after 28s
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.4.4+ restores the 'decisions read' subcommand which returns
metadata + body + refs in one call. Reverts the temporary 'show
--with-refs' workaround.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 18:54:40 +02:00
Jeroen SchweitzerandClaude Opus 4.6 1f028b336d clean up decision debug prints, add --with-refs to show
test / unit + widget + golden + a11y (push) Failing after 28s
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
Remove debug print statements. Pass --with-refs to pql decisions show
so cross-references render in the detail view.

The decision body text is not available from pql — it indexes metadata
only. The body section of the D-record lives in the markdown file.
Rendering it requires either a pql --with-context flag or direct file
read + section extraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 09:55:30 +02:00
Jeroen SchweitzerandClaude Opus 4.6 63e15d99cf fix decision detail: pql decisions show, not read
test / unit + widget + golden + a11y (push) Failing after 28s
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
The pql CLI command is 'decisions show', not 'decisions read'.
The client was sending the wrong subcommand.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 08:59:33 +02:00
Jeroen SchweitzerandClaude Opus 4.6 acc7407fa5 show context panel on decision/ticket selection
test / unit + widget + golden + a11y (push) Failing after 28s
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
The context panel was hidden or collapsed when a decision or ticket
was selected. activateTab alone doesn't make the panel visible.
Now both extensions explicitly setVisible + setCollapsed before
activating the detail tab.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 08:23:54 +02:00
Jeroen SchweitzerandClaude Opus 4.6 baf90270d1 share DaemonBus between backend and kernel, fix terminal spawn timing
test / unit + widget + golden + a11y (push) Failing after 28s
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
The IsolateClient and KernelServices now share the same DaemonBus.
Previously, backend events (pane.output, git.changed) went to a
separate bus that widgets couldn't see.

ClaudePane._spawnWhenReady waits for ProjectOpened before sending
pane.spawn, preventing "No project active" errors.

Recents loaded before runApp so the welcome screen shows them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:17:17 +02:00
Jeroen SchweitzerandClaude Opus 4.6 243a92798c fix macOS PTY: cmsghdr layout, signing, sandbox removal
macOS cmsghdr uses socklen_t (4 bytes) for cmsg_len, not size_t
(8 bytes like Linux). The Dart FFI struct was reading at wrong offsets
causing SCM_RIGHTS fd transfer to fail. Added CmsghdrDarwin with
Uint32 cmsg_len alongside the existing Linux layout.

SOL_SOCKET is 0xffff on macOS (was hardcoded to 1 for Linux).
Now platform-detected.

Switched from ad-hoc to Apple Development signing with team ID.
Removed app sandbox from entitlements — proper signing makes it
unnecessary. All SBPL hacks eliminated.

PtySession.spawn() runs recvFd in a child isolate to avoid blocking
the backend isolate's event loop.

Terminal testmode test now passes: pane.spawn via backend isolate
successfully forks and execs the shell.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 17:04:22 +02:00
Jeroen SchweitzerandClaude Opus 4.6 45e8132a41 async recvFd + backend terminal test (sandbox blocks ptyc exec)
test / unit + widget + golden + a11y (push) Failing after 28s
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
PtySession.spawn() now runs recvFd in a child isolate via
Isolate.spawn so the blocking FFI call doesn't stall the backend
isolate's event loop.

Terminal testmode test spawns a real backend isolate, opens a project,
and sends pane.spawn via IPC — the exact same path the full app uses.
Currently fails: ptyc successfully starts but its fork+execvp is
blocked by the macOS sandbox ("Operation not permitted"). The SBPL
allows /bin/zsh exec from the app process, but ptyc's child process
may not inherit the exec permission, or the PTYC_SOCK_FD is not
inherited by the ptyc child (Dart Process.start fd inheritance on
macOS).

IsolateClient.events getter exposed for test access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:55:29 +02:00
Jeroen SchweitzerandClaude Opus 4.6 8f6ab1ac95 add terminal test category, skip on macOS merged thread
test / unit + widget + golden + a11y (push) Failing after 31s
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
PtySession.spawn() uses synchronous FFI calls (socketpair, recvFd via
SCM_RIGHTS) that block the merged UI/platform thread on macOS. The
test correctly identifies this — PTY must move to the backend isolate.

Three tests added (echo, shell, write-to-child) that will run on
Linux where threads are separate. macOS skips with a diagnostic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:26:38 +02:00
Jeroen SchweitzerandClaude Opus 4.6 e9e346cc2d add ptyc spawn test to toolchain category
Sends a valid JSON request to ptyc via stdin, verifies it parses the
request (exit 2 = syscall failed, not exit 1 = bad request). Full PTY
setup needs socketpair/SCM_RIGHTS which only PtySession provides.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 15:07:25 +02:00
Jeroen SchweitzerandClaude Opus 4.6 f8e8ee3992 widen project switcher dropdown, fix labels and shortcuts
test / unit + widget + golden + a11y (push) Failing after 30s
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
Dropdown width 380 → 480 to prevent RenderFlex overflow on recent
project rows. "Close Workspace" → "Close Project". Keyboard shortcuts
show ⌘ on macOS instead of Ctrl.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:16:59 +02:00
Jeroen SchweitzerandClaude Opus 4.6 5515d88407 lazy backend boot and rename workspace to project
Backend isolate now boots in two phases: resolve toolchain on spawn
(binary availability only), initialize services on project.open. The
dispatcher stays empty until a project activates — IPC requests before
that return "No project active".

Scheduler ticker only runs while a project is open. Fires an immediate
first cycle on ProjectOpened so sidebar panels refresh without waiting
for the next interval. Stops on ProjectClosed.

Renamed workspace → project throughout backend messages
(project.validate, project.open, project.ready), callbacks
(onProjectOpen, onValidateProject), and methods
(openProject, validateProject, resolveProject).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 14:16:46 +02:00
Jeroen SchweitzerandClaude Opus 4.6 a89910dc36 move daemon services to backend isolate
The merged UI/platform thread on macOS (Flutter 3.41) freezes on any
synchronous work — file I/O, Process.run, even isolate spawning during
early frames. No timing workaround (Timer, addPostFrameCallback,
Future.delayed) was reliable.

Fix: spawn a backend isolate that owns the DaemonDispatcher, GitClient,
PqlClient, FilesService, EditorRegistry, and Toolchain resolution. The
main isolate stays free for rendering. Communication uses SendPort with
the existing IPC message protocol (IpcRequest/IpcResponse/IpcEvent) —
zero new serialization.

New files:
  backend.dart       — spawns isolate, manages SendPort/ReceivePort
  backend_entry.dart — isolate entry point, boots all services
  isolate_client.dart — replaces InProcessClient for production

Toolchain now exposes resolveToolchainPaths() as a top-level function
with self-contained PATH expansion (no module-level state that would
prevent isolate message passing).

ClideTestApp gains boot-sequence tests: compute(), Isolate.run(),
sequential Process.run, and the full resolve+exec chain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 13:53:33 +02:00
jpmschweitzerandClaude 9e340197d7 expand ClideTestApp with IPC, extension, and theme tests
Six improvements to the testmode harness:

1. Shell passthrough tests use the resolved shell instead of
   hardcoded /bin/zsh.
2. Exit code reflects test results (non-zero on any failure).
3. JSON summary line for machine-readable parsing.
4. IPC round-trip smoke (ping, version, unknown-cmd, encode/decode).
5. Extension lifecycle smoke (register + activate files, diff,
   git, terminal; theme loading for all four bundled themes).
6. Test categories via CLIDE_TESTMODE dart-define (toolchain, ipc,
   extensions, all). Makefile exposes TESTMODE_CATEGORY variable.

Also switches main.dart from bool.fromEnvironment to
String.fromEnvironment so category values other than "true" work.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-26 13:45:43 +02:00
Jeroen SchweitzerandClaude Opus 4.6 d3fc9bc48a add native picker and error dialog to project switcher
test / unit + widget + golden + a11y (push) Failing after 29s
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
The project switcher dropdown's "Open Local Project" action now uses
the native directory picker (same as the welcome screen). Shows "No
git repo found" dialog when the selected directory is not a git
repository.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 13:18:39 +02:00
Jeroen SchweitzerandClaude Opus 4.6 770048fbd2 add ClideTestApp for platform integration testing
Standalone test harness activated via CLIDE_TESTMODE=true dart-define.
Runs a table of existence checks and exec tests against all external
binaries (git, pql, tmux, ptyc, zsh), including zsh-passthrough and
env variants. Results printed to stdout and shown in a minimal UI.
Auto-exits after 15 seconds.

make run-testmode launches it with a 60-second kill timer and pipes
output to /tmp/clide-testmode.log.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 13:18:39 +02:00
Jeroen SchweitzerandClaude Opus 4.6 73e80a55a6 add Toolchain, GitClient, native directory picker
Toolchain centralizes binary resolution — replaces five ad-hoc
mechanisms (expandedPath, _resolveGit, _resolve, _resolvePtyc,
_existsOnPath). Resolves via Future.delayed after runApp to avoid
blocking the merged UI/platform thread on macOS.

GitClient wraps all git operations with a typed API. Every subprocess
call goes through _run() using toolchain.git + toolchain.gitEnv.
Replaces free functions in operations.dart.

Native directory picker: NSOpenPanel on macOS (method channel in
AppDelegate), GtkFileChooserDialog on Linux. Falls back to text-input
dialog on web or MissingPluginException. Shows "No git repo found"
dialog when the selected directory is not a git repository.

PqlClient and pane commands updated to use Toolchain. ToolCheck
replaced by Toolchain.missing/allOk. All IPC handlers now catch
GitException to prevent unhandled exceptions on the merged thread.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 13:18:39 +02:00
Jeroen SchweitzerandClaude Opus 4.6 8edcc78bfe add macOS desktop target with sandbox entitlements
OS-detecting Makefile (make run works on macOS/Linux/Windows), 1280x720
default window in MainMenu.xib, squared app icons, sandbox with scoped
SBPL exceptions for subprocess execution, _DARWIN_C_SOURCE for ptyc
compilation, expanded PATH merging Homebrew and ~/.local/bin for GUI
apps, native traffic dots skipped on macOS (titlebar owns them).

DebugProfile.entitlements is gitignored (machine-specific SBPL paths);
a template with __HOMEDIR__/__PROJECTS__/__SHELL__ placeholders is
committed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 13:18:39 +02:00
jpmschweitzerandClaude 054808c634 drop withChildren flag — folded into --with-context by pql
test / unit + widget + golden + a11y (push) Failing after 36s
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
Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-24 10:59:34 +02:00
jpmschweitzerandClaude b8c8826b9e use pql --with-context for ticket detail loading
test / unit + widget + golden + a11y (push) Failing after 26s
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
Replaces the N+1 parent-chain walk (one IPC call per ancestor, one
per decision ref) with a single pql ticket show --with-context call.
pql now returns ancestors and decisions arrays inline.

Updates PqlClient.ticketShow to accept withContext/withChildren flags,
removes the obsolete withDecision flag.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-24 10:54:17 +02:00
jpmschweitzerandClaude ad1261fdc2 auto-refresh sidebar panels, pin/focus accordion logic
Decisions: file-change subscription for decisions/*.md plus 1-minute
scheduler tick. Tickets: 1-minute scheduler tick plus changed-event
subscription from status button clicks. PQL markdown tab: file-change
subscription for *.md files. All panels get a manual refresh button.

Accordion sections use pin/focus logic: manually toggled sections are
pinned and stay open; the focused item's section auto-opens; unpinned
sections without focus auto-collapse. Both decisions and tickets views
use ClideAccordion with this pattern.

Ticket sidebar split into six status sections (IN PROGRESS, REVIEW,
READY, BACKLOG, DONE, CANCELLED) matching pql's actual statuses.
Status changes scroll the ticket into its new section.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-24 10:50:25 +02:00
jpmschweitzerandClaude 8a0ca92a1f wire ticket status buttons to pql ticket status
Status buttons in the detail view now call pql.tickets.status IPC,
publish a changed event to refresh the sidebar list, and reload the
detail. Disabled for the current status. IPC handler accepts ids as
a list for batch transitions. PqlClient.ticketSetStatus takes
List<String> and joins with comma per pql CLI contract.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-24 10:50:05 +02:00
jpmschweitzerandClaude cf9a510e6c extract ClideAccordion widget, add arrowClockwise icon and codepoint CSV
ClideAccordion — shared accordion section with optional leading widget,
replaces private _AccordionSection in tickets and decisions views.

Phosphor arrowClockwise icon (0xe036) for refresh buttons. Full
codepoint reference CSV (1512 glyphs) at assets/fonts/phosphor/ for
icon lookup without external tools.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-24 10:49:52 +02:00
jpmschweitzerandClaude 2d08c421ae add kernel scheduler service on background isolate
Tiered Timer.periodic instances (1min, 10min, 15min, 1hr, midnight)
running on a dedicated Dart isolate. Tick messages sent back to the
main isolate via SendPort and emitted as SchedulerTick events on the
DaemonBus. Extensions subscribe with events.on<SchedulerTick>() and
filter by tier.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-24 10:49:31 +02:00
jpmschweitzerandClaude 226520cfce add ranked search to pql sidebar with DSL toggle
test / unit + widget + golden + a11y (push) Failing after 33s
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
Search tab defaults to ranked text search via pql search — debounced
300ms, scored results with visual score bar.  DSL toggle switches to
raw PQL query mode for SQL-like queries.  Clicking a search result
opens it in the markdown context viewer.

Adds pql.search IPC command and PqlClient.search method.  Controller
gains SearchMode enum and search() method alongside existing runQuery.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 22:22:16 +02:00
jpmschweitzerandClaude bfd304a3f9 restructure pql sidebar: Search default, Markdown tab with viewer
Search (PQL DSL query) is now the default left tab; Markdown (filtered
to .md files) on the right.  Clicking a markdown file publishes on
the message bus; the markdown extension activates the context panel
viewer and re-publishes on a load channel after the frame so the
viewer is guaranteed to be mounted.  Viewer subscribes to load channel
and editor buffer events, publishes focus for sidebar highlighting.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 21:25:52 +02:00
jpmschweitzerandClaude 47c2def656 add files.read IPC, fix pane chrome layout, raise context panel max
Register files.read command for reading file content by relative path.
Remove top padding on context panel container and mainAxisSize.min
from ClidePaneChrome so the header sits flush and the pane fills
available height.  Context panel max raised from 420px to 1000px.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 21:25:36 +02:00
jpmschweitzerandClaude b236ec439f make TreeSitterService a shared singleton
Each ClideCodeBlock and EditorView created its own TreeSitterService,
each allocating a WASM engine, store, parser, and cursor via FFI.
When widgets were disposed, multiple instances freeing the same
underlying native resources caused double-free corruption on startup.

Single shared instance for the app lifetime.  Also fixes overlapping
tree-sitter spans that caused duplicated text in code blocks — spans
are now clipped to avoid re-emitting already-rendered characters.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 21:25:22 +02:00
jpmschweitzerandClaude 04d133f4ed sidebar focus indicators, bus navigation, font constants
All sidebar and detail panes use clideFontSmall/clideFontBadge/
clideFontCaption instead of hardcoded sizes — single place to tune.

Decision detail view subscribes to the message bus for selection
events (same pattern as ticket controller) and publishes focus after
loading.  Both decisions and tickets sidebar views subscribe to the
focus channel, expand the accordion section, highlight the active
card, and scroll it into view.

Clickable DQRT links wired in decision detail, ticket detail, and
markdown viewer via onRecordTap.  Ticket descriptions now render
through ClideMarkdown instead of plain text.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 18:53:53 +02:00
jpmschweitzerandClaude 81cc062409 add text zoom, fix context panel drag, widen default panels
Ctrl+Plus/Minus/0 text zoom (5% steps, 60%–200%) via MediaQuery
textScaler.  App-wide clideLineHeight (1.25) applied in DefaultTextStyle.

Context panel drag resize was inverted — dragging left shrank the
panel instead of growing it.  Negate delta for right-anchored slots.

Default sidebar widened from 240px to 400px, context panel from 280px
to 420px (both at their previous maximums).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 18:53:35 +02:00
jpmschweitzerandClaude fbcfee20b7 overhaul ClideMarkdown renderer
Inline grouping collapses consecutive inline nodes (strong, em, code,
a, del) into a single RichText widget instead of rendering each as a
separate block — fixes tight list items like `builtin.git` appearing
on its own line.  HTML entity unescaping moved from pre-parse (useless)
to post-AST extraction where the markdown package actually introduces
the entities.  Explicit Josefin Sans Light font family and 1.25 line
height on all RichText spans.  Body text bumped to 16px; inline code
uses clideFontMono for visual weight parity.

Adds onRecordTap callback — markdown links matching [DQRT]-\d+ render
as tappable WidgetSpans with hover underline.  New typography constants
clideFontSmall (12), clideFontBadge (11), clideLineHeight (1.25).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-23 18:53:18 +02:00
jpmschweitzerandClaude Opus 4.6 8b93ccd6d6 fix markdown spacing and HTML entity escaping
More vertical breathing room between paragraphs (8→12), list
items (2→6), headings (increased top/bottom). Tighter horizontal
indent on lists (16→8) and blockquotes (12→8). Added HTML entity
unescaping (quot, amp, lt, gt, apos) before parsing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 17:40:03 +02:00
jpmschweitzerandClaude Opus 4.6 227d787bc6 add ClideMarkdown, ClideCodeBlock, ClideSvgView primitives
Three reusable rendering widgets in lib/widgets/:

- ClideMarkdown: walks markdown AST (GFM tables, task lists,
  fenced code), renders headings, lists, blockquotes, tables,
  inline bold/italic/code/links. Delegates code blocks to
  ClideCodeBlock.

- ClideCodeBlock: syntax-highlighted code via TreeSitterService.
  Async highlight, byte-to-char offset mapping, theme-aware
  colors from SurfaceTokens.

- ClideSvgView: wraps jovial_svg with asset/string constructors
  and optional sizing.

Retrofitted: decision detail body renders as markdown instead of
raw text. Markdown viewer uses ClideMarkdown. Welcome logo uses
ClideSvgView.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 17:36:40 +02:00
jpmschweitzerandClaude Opus 4.6 5fd31247da re-contribute detail tabs with initialId on each selection
Both tickets and decisions extensions now uncontribute and
re-contribute the detail tab on every selection, passing the
selected ID via initialId. This guarantees the view loads
immediately — no first-click miss from the widget not being
built when the message fires.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 17:23:08 +02:00
jpmschweitzerandClaude Opus 4.6 2345125172 decision detail shows full markdown body via pql decisions read
New pql.decisions.read IPC verb returns the full markdown section
body. Decision detail view now shows: title card, full decision
text (rationale, cost, cross-references), and clickable ref cards
for cross-reference navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 17:19:15 +02:00
jpmschweitzerandClaude Opus 4.6 dad2d0ad52 make parent tickets and decision refs clickable throughlinks
Clicking a parent ticket in the tree publishes
builtin.tickets/selection — loads that ticket in the detail view.
Clicking a decision ref publishes builtin.decisions/selection —
switches context panel to the decision detail. Both show hover
highlight. Enables full cross-reference navigation without
leaving the context panel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 17:02:18 +02:00
jpmschweitzerandClaude Opus 4.6 de321bfe92 bidirectional focus: detail broadcasts, list highlights
Detail controller publishes builtin.tickets/focus with the loaded
ticket ID after every load. Ticket list subscribes and highlights
the matching card with selected background and accent border.
Works regardless of what triggered the detail load — sidebar
click, parent tree navigation, or future command palette.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 16:59:21 +02:00
jpmschweitzerandClaude Opus 4.6 1108ffd85c wrap parent tree card titles instead of ellipsis
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 16:45:36 +02:00
jpmschweitzerandClaude Opus 4.6 a1ff41d981 fix tab switching on selection, tickets first in sidebar
Extension listens to its own selection channel and activates the
detail tab in the context panel — fixes the chicken-and-egg where
the controller only subscribes after the widget builds. Registration
order in main.dart now determines sidebar icon rail order: tickets
first, then decisions, files, git, pql, problems.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 16:42:29 +02:00
jpmschweitzerandClaude Opus 4.6 6dcb24144e icons from extensions, settings-based tab ordering, static context tabs
Icons now declared on TabContribution via the icon field — the
hardcoded switch in _BottomRail is a fallback only. All sidebar
and context extensions set their Phosphor icon explicitly.

PanelRegistry supports setTabOrder(slot, List<String>) — tabs
render in the order specified by project.layout.sidebar.order /
context.order in settings.yaml. Falls back to registration order.
Priority field removed from all contributions.

Context tabs are static again — persist with their last content,
selection just loads new data and switches focus. No spawn/despawn.

Tickets sidebar priority set to -200 (leftmost, default open).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 16:37:32 +02:00
jpmschweitzerandClaude Opus 4.6 bd00990e1d fix detail pane: load on first click, despawn on navigate away
Two flow fixes:
1. First click now works — extension passes initialId to the
   detail view constructor, which loads immediately in
   didChangeDependencies. No second click needed.
2. Tab despawns when user navigates away — extension listens to
   PanelRegistry changes, despawns detail tab when it's no longer
   the active context panel tab.

Each selection re-creates the tab with a fresh initialId so the
view always matches the selection. Applied to both tickets and
decisions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 16:23:09 +02:00