FE-1115: Refine Pi TUI component DX: preview harness, component refinements, and new components#301
Conversation
f299553 to
0e5820f
Compare
0e5820f to
7a30b1f
Compare
PR SummaryMedium Risk Overview Production input: All Live session chrome: Working indicator becomes a single static frame on Themes: Reworked dark/light palettes (fuchsia accent, Docs-only on branch: PLAN/SPEC updates and the exchange-ask-refinement scope card (D116-L / FE-1164); removal of the completed orchestrator-tool-port card file; trivial Reviewed by Cursor Bugbot for commit fcbd45b. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
This PR refines Brunch’s Pi TUI developer experience and production keyboard handling by making the component preview harness a live theme-iteration loop (toggle + hot reload + testbed), standardizing key handling via matchesKey to fix kitty-protocol regressions, and improving long-session UX with a scrollback-safe working indicator plus terminal progress.
Changes:
- Add a switchable component-preview theme with live
ctrl+ttoggle, OSC 10/11 painting + SGR fallback, andfs.watchhot reload ofsrc/.pi/themes/*.json. - Sweep
.pi/componentshandleInputimplementations to usematchesKey/Key(with regression tests) to avoid kitty keyboard protocol freezes. - Make working indication scrollback-safe (static glyph) and enable OSC 9;4 terminal-native progress by default.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/dev/TOPOLOGY.md | Updates dev harness topology docs for switchable theme, hot reload, and testbed entry |
| src/dev/component-preview/theme.ts | Implements switchable preview theme, OSC painting, SGR fallback terminal wrapper, and theme JSON watcher |
| src/dev/component-preview/theme-testbed.ts | Adds markdown/syntax/contrast “theme testbed” component for preview harness iteration |
| src/dev/component-preview/registry.ts | Registers the new theme-testbed preview entry |
| src/dev/component-preview/gallery-component.ts | Switches gallery input handling to matchesKey and displays current theme variant hint |
| src/dev/component-preview/tests/theme.test.ts | Adds tests for switchable theme, toggle consumption, and SGR fallback painting |
| src/dev/component-preview/tests/theme-testbed.test.ts | Adds tests for theme testbed rendering and delegated theme updates |
| src/dev/component-preview.ts | Wires preview harness to use switchable theme + terminal painting + hot reload + toggle registration/disposal |
| src/app/pi-settings.ts | Enables terminal-native progress by default in the sealed settings policy |
| src/app/tests/brunch-tui.test.ts | Updates expectations for showTerminalProgress default and hostile-settings override |
| src/.pi/themes/brunch-light.json | Reworks light theme tokens/vars (accent, ink/text convention, syntax tokens, page bg) |
| src/.pi/themes/brunch-dark.json | Reworks dark theme tokens/vars (accent, ink/text convention, syntax tokens, page bg) |
| src/.pi/extensions/chrome/index.ts | Sets a static ≤1-frame working indicator on session_start to avoid scroll-snapping |
| src/.pi/extensions/tests/chrome.test.ts | Adds/updates tests asserting the scrollback-safe working indicator call occurs |
| src/.pi/components/workspace-dialog/component.ts | Migrates ctrl+c handling to matchesKey(Key.ctrl('c')) |
| src/.pi/components/tui-lab/style-lab-component.ts | Migrates navigation/escape handling to matchesKey |
| src/.pi/components/TOPOLOGY.md | Documents the matchesKey convention for all component input handling |
| src/.pi/components/runtime-posture/axis-picker.ts | Migrates picker key handling to matchesKey/Key |
| src/.pi/components/multi-choice-picker.ts | Migrates picker key handling to matchesKey/Key |
| src/.pi/components/exchange-decision-picker.ts | Migrates picker key handling to matchesKey/Key |
| src/.pi/components/exchange-answer-editor.ts | Migrates escape/ctrl+c/ctrl+g handling to matchesKey/Key |
| src/.pi/components/tests/runtime-posture-axis-picker.test.ts | Adds kitty-protocol regression coverage for navigation/commit |
| src/.pi/components/tests/exchange-decision-picker.test.ts | Adds kitty-protocol regression coverage for decision + multi-choice pickers |
| package-lock.json | Adjusts a bin path entry for pi-ai |
| memory/SPEC.md | Adds/extends decision and lexicon entries around the follow-on “ask” refinement lane (D116-L / A39-L) |
| memory/PLAN.md | Updates plan/frontier definitions and adds the exchange-ask refinement lane notes |
| memory/cards/orchestrator-tool-port--executor-surface-reconciliation.md | Deletes a completed scope card file |
| memory/cards/exchange-ask-refinement--ask-terminal.md | Adds a new active scope card describing the ask-refinement slice plan |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7a30b1f to
a9b403d
Compare
SwitchableComponentPreviewTheme (a real Theme subclass delegating all color reads to the active variant) plus a consuming ctrl+t TUI input listener let the gallery and any open entry reskin in place — no retheme contract on components. BRUNCH_PREVIEW_THEME still picks the initial variant. Co-authored-by: Cursor <cursoragent@cursor.com>
Theme colors only style glyphs, so toggling to light left the terminal's dark background behind them. The toggle (and registration) now sets the terminal background via OSC 11 to the variant's export.pageBg from the theme JSON, and the dispose path restores the terminal default via OSC 111 before the TUI stops. Co-authored-by: Cursor <cursoragent@cursor.com>
ProcessTerminal negotiates the kitty keyboard protocol where supported (Ghostty), and keys then arrive as CSI-u sequences that raw byte equality misses — the gallery could not move its selection and ctrl+t never matched. Gallery navigation and the theme toggle now go through pi-tui's matchesKey, with an explicit key-release guard on the toggle listener (input listeners run before the TUI's release filter). OSC 11 terminal-support limit (Zed) recorded as a ceiling. Co-authored-by: Cursor <cursoragent@cursor.com>
The kitty keyboard protocol (negotiated by ProcessTerminal in Ghostty and kitty) encodes key presses as CSI-u sequences, so every handleInput doing raw byte comparison froze there: axis-picker left/right, decision-picker and multi-choice up/down, answer-editor esc/ctrl+c, workspace-dialog ctrl+c, and the tui-lab reference component. All now match through pi-tui's matchesKey/Key, with Ghostty-regression tests per navigation family and the convention recorded in the components TOPOLOGY. Co-authored-by: Cursor <cursoragent@cursor.com>
…ntax testbed watchComponentPreviewTheme rebuilds the variant palettes when src/.pi/themes/brunch-*.json change on disk (debounced, last-good palette across mid-edit invalid JSON), so theme values iterate against the live harness. The new theme-testbed gallery entry renders one fixture through both live markdown surfaces — pi's assistant theme with real highlight.js syntax-token colors (via pi's registered global theme symbol and a bound facade over the delegating preview theme) and brunch's exchange theme — plus a fg/bg contrast strip for the gray-ramp work. Co-authored-by: Cursor <cursoragent@cursor.com>
Unstyled component text — markdown body, picker labels, anything not wrapped in theme.fg(...) — was falling through to the terminal's own default foreground, so the text token appeared to do nothing outside the gallery menu. The harness now paints OSC 10 with the active variant's text hex alongside the OSC 11 page background on registration, toggle, and hot reload, and restores both defaults (OSC 110/111) on exit. Co-authored-by: Cursor <cursoragent@cursor.com>
…d it from export.pageFg createThemePaintingTerminal wraps the harness Terminal for emulators that ignore OSC 10/11 (Zed): frame writes are prefixed with the reference page fg/bg and default-reset codes are rewritten to that base, so erases and resets stay on the theme's page. The reference colors now come from a Brunch-only export.pageFg extension (plus export.pageBg) instead of the text token, because pi's format defines text as default text with the canonical value "" (terminal default) — the JSONs adopt that convention and keep concrete ink only for themed-surface slots. Co-authored-by: Cursor <cursoragent@cursor.com>
…d derivatives PLAN now reflects the re-activated component-dx TUI-refinement lane (Cards 1-3 done, Card 4 theme values in flight), the FE-1107 residue carried forward from the retired 2026-07-06 handoff (KA conversation + owed post-KA ln-plan pass), and the retained-unconfirmed FE-1154 plan-projection card. Deleted the exhausted FE-1107 executor-surface-reconciliation scope file and the reconciled HANDOFF.md. Co-authored-by: Cursor <cursoragent@cursor.com>
Pi's default working spinner re-renders every 80ms, and each write snaps scroll-on-output terminals back to the bottom — worst during long silent stretches when the spinner is the only writer. The chrome extension now sets a single static frame at session_start (Loader starts no animation interval for <=1 frame, so zero periodic writes), and liveness moves to the terminal-native OSC 9;4 progress channel via showTerminalProgress in the sealed settings policy (hostile fixture flipped to keep seal leakage detectable). Also: the harness reference environment fg now defaults in code, since pi's theme schema strips the unknown export.pageFg key. Co-authored-by: Cursor <cursoragent@cursor.com>
…ge refinement Co-authored-by: Cursor <cursoragent@cursor.com>
…d, manual checks recorded Co-authored-by: Cursor <cursoragent@cursor.com>
…refinement, retire consumed handoff Co-authored-by: Cursor <cursoragent@cursor.com>
…tover, declared continuations) Co-authored-by: Cursor <cursoragent@cursor.com>
… isolate the pi theme global in tests, fix OSC 10 prose drift Semantic #RRGGBB validation in parseBrunchThemePalette (post-vars-resolution, so dangling var references fail too) makes reload's throw-based last-good fallback fire on valid-JSON bad-value saves instead of emitting malformed OSC/SGR. The theme-testbed test now saves/restores pi's registered theme global around each test. TOPOLOGY.md and the theme test comment describe OSC 10 as painting export.pageFg, matching the implementation. Co-authored-by: Cursor <cursoragent@cursor.com>
… noted Co-authored-by: Cursor <cursoragent@cursor.com>
ed755a8 to
fcbd45b
Compare
Merge activity
|

Summary
The TUI-refinement lane of FE-1115: makes the component preview harness a real theme-iteration loop, fixes kitty-protocol input handling across production components, and lands the reworked Brunch theme pair.
ctrl+t) indev:components, including while an entry is open — a delegatingSwitchableComponentPreviewTheme, with OSC 10/11 page fg/bg painting (OSC 110/111 restore) and an SGR-level fallback terminal wrapper for OSC-ignoring terminals (Zed)fs.watch, last-good palette on invalid JSON) plus atheme-testbedentry rendering pi's assistant markdown surface, brunch's exchange markdown surface, and a fg/bg contrast stripmatchesKeysweep: allhandleInputraw-byte comparisons insrc/.pi/components/(and the harness) now match through pi-tui'smatchesKey, fixing frozen pickers under the kitty keyboard protocol (Ghostty); regression tests added, convention recorded in the components TOPOLOGY● Working…glyph (no spinner interval, no scroll-snap) with liveness moved to OSC 9;4 terminal progresstext: ""terminal-default convention with concrete ink moved to theinkvar, neutral reference page anchors (export.pageBg/pageFg), and a final contrast pass — all fg text tokens ≥ 4.5:1 against their reference page (faint-by-designborderMuted/thinkingOffexcepted)Also carried on this branch: planning for the follow-on FE-1164 (SPEC D116-L one-shot ask terminal, PLAN admission, scope card) — implementation stacks on the child branch.
Verification
npm run verifygreen at tip (1517 passed / 2 skipped)