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>
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>
Four layers under app/test/:
* kernel/, extension/ — unit tests for every kernel service and
the extension contract. i18n fallback chain gets the full
matrix (exact/lang/default/placeholder, namespace isolation,
unknown namespace, interpolation). Theme resolver and
extension-manager topo sort covered.
* widgets/, builtin/ — widget tests for every primitive and each
Tier 0 built-in. Assertions reach into the Semantics node so
a missing label fails structurally, not visually.
* goldens/ — Alchemist + Ahem font for cross-platform pixel
stability; primitives only (button, tab bar, icon set). No
goldens for compositions — they'd churn through every tier.
* a11y/ — contract-level gate: semantic coverage walks the
built-in catalogue, contrast walks every token pair in every
bundled theme against WCAG-AA thresholds (catches real
regressions: the first run caught `tab.inactive_text` at 2.81
in summer-night), i18n coverage asserts every referenced key
exists in its catalog (exists-in-map, not "key == value" — too
ambiguous for keys that happen to equal their translation).
Helpers under helpers/: `KernelFixture.create()` boots a
KernelServices with in-memory stores + a FakeDaemonClient (no
socket, drivable connected-state), `widget_harness` wraps a
widget in the minimum tree that resolves theme + i18n.
Co-Authored-By: Claude <noreply@anthropic.com>