docs(interactive): record ConPTY library + binding decision from spike

This commit is contained in:
mika kuns
2026-07-23 16:47:15 +02:00
parent 5f740c05d8
commit d28c63d2df
@@ -65,18 +65,40 @@ chosen directory (no task). These also get MCP config + env set up so the
`claudedo` tools are available, but no per-level session-skills seeding tied to a
task.
### Terminal host control
### Terminal host control — RESOLVED by spike (2026-07-23)
Embed a ConPTY-capable Avalonia terminal control in the UI. Candidates:
**Library: `Iciclecreek.Avalonia.Terminal` 2.0.3** (namespace `Iciclecreek.Terminal`).
It needs Avalonia >= 12.0.2; the repo is on 12.0.4 → compatible, no bump.
`SvcSystems.UI.Terminal` (latest) needs Avalonia 12.1+ → rejected.
- **SvcSystems.UI.Terminal** (IvanJosipovic) — explicit ConPTY, full-screen TUI
render + resize reflow, selection/mouse reporting.
- **Iciclecreek.Avalonia.Terminal** — XTerm.NET + Porta.Pty, clean
`TerminalControl` embed API.
Visual pass (user, 2026-07-23): the real `claude` TUI renders correctly inside
the embedded control — Claude Code opened and was usable.
Selection is resolved by a **spike** (first plan step): the acceptance criterion
is that the real `claude` TUI renders correctly inside the control — colors,
resize/reflow, and a live permission prompt are usable.
**Binding approach — drive Porta.Pty ourselves, reuse Iciclecreek's VT engine.**
The convenience `TerminalControl.LaunchProcess()` spawns the child itself and
never sets `PtyOptions.Environment`, and there is no settable pty/env seam on
`TerminalControl`/`TerminalView` (env-building lives in the non-virtual
`TerminalView.LaunchProcess()` using private fields). But the VT parser/renderer
is the public `XTerm.Terminal` object exposed via `TerminalControl.Terminal`, so
we reuse it without forking:
- `Porta.Pty.PtyProvider.SpawnAsync(new PtyOptions { Name, App, Cwd, CommandLine,
Environment = <fully populated dict> }, ct)` → `IPtyConnection`.
- Do **not** call `TerminalControl.LaunchProcess()` (leaves its `_ptyConnection`
null).
- Get `TerminalControl.Terminal` (public, `XTerm.Terminal`) after template apply.
- Pump `IPtyConnection.ReaderStream` → `Terminal.Write(text)`; subscribe
`Terminal.DataReceived` → `IPtyConnection.WriterStream`; mirror
`Terminal.Resized` ↔ `IPtyConnection.Resize(cols, rows)`.
- Implement our **own** exit-code / kill / wait-for-exit against our
`IPtyConnection` — do NOT touch `TerminalControl.ExitCode`/`Pid`/`Kill()`/
`WaitForExit()`, they NRE on the null `_ptyConnection`.
Note on environment: `Porta.Pty.SpawnAsync` already seeds the child from the
current (ClaudeDo) process environment (PATH/APPDATA/etc.) and merges
`PtyOptions.Environment` on top — so we only need to ADD our custom vars (MCP
config path, `MAX_THINKING_TOKENS`, …), not rebuild the whole environment. (The
earlier spike's "child gets zero env vars" claim was wrong.)
### Command Center layout
@@ -108,10 +130,11 @@ UI:
## Open items (implementation time)
- Whether `LiveSessionRegistry` is referenced outside the interactive path.
- Exact env dictionary handed to the ConPTY control (parity with the autonomous
run environment).
- Session-id availability for a never-run task (no `--resume` → start fresh).
Resolved: env approach (see Terminal host control — add custom vars on top of the
inherited process env via `PtyOptions.Environment`); library + binding seam.
## Non-goals
- No screen-scraping of terminal output back into task status/diff/review.