diff --git a/SPEC.md b/SPEC.md index 462e11e..1a5256b 100644 --- a/SPEC.md +++ b/SPEC.md @@ -104,15 +104,17 @@ Scratchpads and command-preset trust grants persist across runs. Sessions and ch └───────────────────────────────────────────────────────────────────────────┘ ``` -- **Top tab bar:** one per top-level session. `+` opens the palette pre-filtered to "Spawn…" entries. -- **Main area:** the focused pane's PTY, rendered identically to viewing it in a regular terminal. The focused pane is either the orchestrator (root of the active session's tree) or one of its children, whichever the user last selected from the sidebar. -- **Right rail, top half — session tree:** the active session's process hierarchy, drawn as an indented tree with box-drawing connectors (`├─`, `└─`). The orchestrator is the root (`▶`); each child appears one level deeper with a status glyph (`◉` running, `✓` exited cleanly, `✗` errored). Selecting an entry (palette, arrow keys, or click) makes it the focused pane. v1 only has two levels because of the §8 two-level-tree rule, but the renderer should be tree-shaped from day one so a future depth bump doesn't require UI surgery. +- **Top tab bar:** one per running top-level session. Exited top-level sessions disappear from the tab bar; historical output is still available through the underlying process state / logs where supported, but dead panes do not stay in the navigation chrome. `+` opens the palette pre-filtered to "Spawn…" entries. +- **Main area:** the focused pane's PTY, rendered inside patterm's main viewport. The viewport starts below the tab bar and excludes the right rail and bottom status line. The focused pane is either the orchestrator (root of the active session's tree) or one of its running children, whichever the user last selected from the sidebar. +- **Right rail, top half — session tree:** the active tab's running process hierarchy, drawn as an indented tree with box-drawing connectors (`├─`, `└─`). The active top-level session is the root (`▶` when focused); direct children appear one level deeper with a running glyph (`◉`). Exited / killed processes are removed from the visible tree. Selecting an entry (palette, arrow keys, or click) makes it the focused pane. v1 only has two levels because of the §8 two-level-tree rule, but the renderer should be tree-shaped from day one so a future depth bump doesn't require UI surgery. - **Right rail, bottom half:** scratchpad list and a preview of the selected scratchpad. - **Status line:** input-ownership toast ("orchestrator driving" / "you have control") on the left, palette hint on the right. -**Empty state:** Until the user spawns their first preset, the top tab bar, main area, and sidebar all sit empty with a centred hint ("Press Ctrl-K to spawn an agent or process"). No "default session" is created. +**Empty state:** Until the user spawns their first preset, the top tab bar, main area, and sidebar all sit empty with a hint ("Press Ctrl-K to spawn an agent or process") centred in the main viewport, not the full host terminal. No "default session" is created. -**Switching:** Clicking a top tab (or selecting one via the palette) switches the active session — the sidebar tree swaps to that session's hierarchy. Clicking a sidebar entry switches the focused pane within the current session. +**Switching:** Clicking a top tab (or selecting one via the palette) switches the active session — the sidebar tree swaps to that tab's hierarchy only. Clicking a sidebar entry switches the focused pane within the current session. If the focused pane exits, focus falls back to another running top-level session if one exists; otherwise the UI returns to the empty state. + +**Viewport and chrome ownership:** patterm owns the tab bar, right rail, status line, and any empty-state text. Child PTYs own only the main viewport. This is a hard UI boundary: child terminal output must not be allowed to clear, wrap into, or position the cursor inside patterm chrome. When rendering live child output, patterm may rewrite or clip destructive terminal sequences (for example clear-line / clear-screen / cursor-positioning sequences) and must redraw chrome after focused child output so the outer frame wins any rendering conflict. The goal is that agent TUIs behave as if their terminal size is exactly the main viewport, even though patterm is drawing additional UI around them. **Command palette (v1 input model):** @@ -148,7 +150,7 @@ One PTY per session orchestrator and one per child. For each PTY the tool mainta **Terminal emulator:** Go has limited options. Start with `vt10x` or a maintained fork. Budget real time — this is the load-bearing component for grid mode `read_output`. The emulator must handle: SGR colours (then strip them on read), cursor movement, alt-screen entry/exit, scroll regions, basic mouse passthrough where needed. -**Resize:** On startup and on SIGWINCH, the tool reads its own terminal dimensions, computes per-pane winsize (accounting for tab bar, sidebar, status line), and `ioctl(TIOCSWINSZ)` each PTY. Children get SIGWINCH automatically. One process, one viewport — no multi-client resize negotiation. +**Resize:** On startup and on SIGWINCH, the tool reads its own terminal dimensions, computes the main viewport winsize (accounting for tab bar, sidebar, and status line), and `ioctl(TIOCSWINSZ)` each PTY to that viewport size — never the full host terminal size. The headless emulator for each child is resized to the same grid. Children get SIGWINCH automatically. One process, one viewport — no multi-client resize negotiation. ---