summaryrefslogtreecommitdiff
path: root/docs/tui-refactor-plan.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tui-refactor-plan.md')
-rw-r--r--docs/tui-refactor-plan.md60
1 files changed, 46 insertions, 14 deletions
diff --git a/docs/tui-refactor-plan.md b/docs/tui-refactor-plan.md
index 15c7e8e..9f18ff0 100644
--- a/docs/tui-refactor-plan.md
+++ b/docs/tui-refactor-plan.md
@@ -357,16 +357,31 @@ is at fault, not the framework. No magic merge.
### 7.4 Timing & lifecycle
-- An event fires **once, at its component-creation boundary**, *before* the
- component first paints — so `setComponent` swaps it before anything renders.
-- For `tool`, that boundary is tool-use **start** (name known). The single
- `tool` event covers the whole call: the chosen component is then **driven by
- panto** with the streaming args/result/status as structured deltas. The
- handler does **not** re-fire per delta; it chooses the component once.
-- All streamable components share this shape: fire once at start, hand over a
- component, drive with deltas (§8).
-- **No "active component" (§6 invariant).** Each `tool`/subagent event yields its
- own component instance keyed by call-id. Parallel calls each get their own.
+- **Streaming LIFECYCLE events (as built).** Rather than a single fire-once
+ boundary, each streaming block emits events across its whole lifecycle, so a
+ handler can act (and re-choose the component) at any meaningful point:
+ - thinking: `thinking` (start) → `thinking_delta` (per chunk) →
+ `thinking_complete`.
+ - assistant text: `assistant_text` → `assistant_text_delta` →
+ `assistant_text_complete`.
+ - tool: `tool` (block-start; name **unknown**, component shows `tool (?)`) →
+ `tool_details` (name resolved) → `tool_delta` (args chunk) →
+ `tool_call_complete` (full args) → `tool_result` (atomic result block).
+ - `user_message` / `session_start` / `compaction` fire once.
+- **Mid-stream swap.** `setComponent` may be called at **any** lifecycle event,
+ not only creation. Swapping replaces the slot's component at the **same key**;
+ the incoming component fully takes over the region (renders from line 0, the
+ predecessor's orphaned lines cleared). The superseded component is released by
+ its owner. This is what makes `tool` honest: it fires at block-start as
+ `tool (?)`, and a handler **claims the call by name at `tool_details`** by
+ swapping in its own component over the default that was already rendering.
+- **panto keeps driving.** Across any swap, panto continues feeding the
+ structured deltas/details/result into the slot's typed default box; the engine
+ renders whatever component currently owns the slot (default, wrapper, or
+ swapped-in). Drive-by-default-box, render-by-current-component.
+- **No "active component" (§6 invariant).** Each `tool`/subagent block yields its
+ own component instance keyed by call-id/block-index. Parallel calls each get
+ their own; a swap replaces the component *at* a key, never a global current.
### 7.5 The skills example (worked)
@@ -450,11 +465,28 @@ the vtable stays C-ABI-friendly so it can be added elsewhere later.
cache_write`, latest from `message_complete`). **No git branch** (panto uses
jj, not git).
-**P3 — Extension components + cursor/IME polish.**
-- Event system (`on`/`emit`, `event.get/setComponent`); built-in events wired at
- component-creation boundaries; public default components.
-- Zig event + component API → Lua bridge.
+**P3 — Extension components + cursor/IME polish. ✅ COMPLETE.**
+- Event system (`on`/`emit`, `event.get/setComponent`); a full **streaming
+ lifecycle** taxonomy wired at the real libpanto boundaries (start / `_delta` /
+ `_complete` for thinking & assistant; `tool` / `tool_details` / `tool_delta` /
+ `tool_call_complete` / `tool_result` for tools; `user_message` /
+ `session_start` / `compaction` once — see §7.4); public default components.
+ **Mid-stream component swaps** are supported: a handler may `setComponent` at
+ any lifecycle event, replacing the slot's component (full-region takeover,
+ superseded component released) while panto keeps driving deltas into the
+ default box. `tool` fires at block-start as `tool (?)`; handlers claim by name
+ at `tool_details` (§7.5).
+- Zig event + component API → Lua bridge. Extension-authoring APIs moved under
+ `panto.ext` (`register_tool`/`register_command`/`on`/`emit`); the bare
+ `panto` namespace is reserved for the future full libpanto API. Lua-defined
+ components bridge the `Component` vtable via **synchronous** `lua_pcallk`
+ render (not the libuv scheduler) with a native cache-derived
+ `firstLineChanged`.
- Virtual cursor compositing + hardware-cursor sync (IME marker positioning).
+ Relative-move positioning inside the sync block; `differential` reconciles
+ from the actual left-on row so repaints stay correct. **IME anchoring is
+ implemented but unverified against a real IME** (the plan's [verify] flag
+ stands).
**Deferred (post-refactor):**
- Markdown + syntax highlighting renderer (hosting components designed for it