From a4d0a10a6ebb6e8a2c76913e8d73f03018f23394 Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:30:16 +0800 Subject: [PATCH] docs(cli): `events` had no schema, and promised a pane-exit event nothing sends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `events` is the streaming interface an agent builds on, and it was the one verb whose JSON shape the reference did not give — every other one lists its fields exactly. Now it does: the externally tagged envelope, the four event kinds a listener sees, and the thirteen `layout` delta kinds. The prose also listed "pane exits" as an event type. There is no such event. `ControlEvent::PaneExited` is defined, encodes, and has a line `tty7 events` would print for it — and nothing anywhere constructs one outside the round-trip tests in its own file. `AgentStatus`, `Preempted` and `LayoutResync` have 2, 10 and 6 emitters respectively; this one has none. An agent waiting for a pane-exit line waits for good. What actually happens is checked against a running server: exit the shell in a pane and exactly one event arrives — a `layout` delta carrying `pane_facts` for that pane with `"live": false`, and the pane is gone from `pane ls --all`. The docs now say to watch for that, in a note that says outright there is no pane-exit line whatever the wire protocol's shape suggests. The variant keeps a comment saying the same thing, and that resolving it means either emitting it where the pane is reaped or removing it along with the `event_line` arm — not something to do in passing, since taking a variant out of a wire enum is a dialect change. 2951 tests pass. --- crates/tty7-core/src/daemon/control.rs | 11 +++++++++++ docs/cli/reference.mdx | 27 +++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/crates/tty7-core/src/daemon/control.rs b/crates/tty7-core/src/daemon/control.rs index 48c9c3c0..3506b8ff 100644 --- a/crates/tty7-core/src/daemon/control.rs +++ b/crates/tty7-core/src/daemon/control.rs @@ -529,6 +529,17 @@ pub enum ControlEvent { failed: bool, }, + /// Nothing sends this. The variant, its encoding and the line + /// `tty7 events` would print for it all exist, and no code path anywhere + /// constructs one outside this file's own round-trip tests — so an agent + /// waiting on a pane-exit event waits for good. + /// + /// A pane exiting *is* reported, as `Layout` carrying a `PaneFacts` delta + /// whose pane has `live: false`, which is what the docs now tell readers to + /// watch. Worth resolving one way or the other: either something emits this + /// where the pane is reaped, or it goes, and the `event_line` arm in + /// `tty7-cli` goes with it. Left in place because removing a variant from a + /// wire enum is a dialect change and this is not one to make in passing. PaneExited { pane_id: u64, code: Option, diff --git a/docs/cli/reference.mdx b/docs/cli/reference.mdx index 13f0ec67..d043e9ef 100644 --- a/docs/cli/reference.mdx +++ b/docs/cli/reference.mdx @@ -213,9 +213,30 @@ while you watched. ### `tty7 events` -Streams server events until interrupted, one per line — pane exits, agent status -changes, workspace preemption, layout deltas. `--json` makes it NDJSON. Blocks -forever; run it with a timeout or in the background. +Streams server events until interrupted, one per line — layout changes, agent +status, workspace preemption. `--json` makes it NDJSON. Blocks forever; run it +with a timeout or in the background. + +Each line is one externally tagged object, `{"": {…}}`: + +| Kind | Payload | +|---|---| +| `layout` | `{"workspace","delta"}` — the bulk of the stream | +| `agent_status` | `{"pane_id","json"}` — whatever the agent's hooks reported | +| `preempted` | `{"workspace","by"}` — another client took the workspace | +| `layout_resync` | no payload; the tree moved in a way no delta describes, so re-read it | + +`delta` is externally tagged the same way. The kinds are `workspace_created`, +`workspace_renamed`, `workspace_deleted`, `workspace_touched`, +`active_tab_changed`, `tab_created`, `tab_closed`, `tab_renamed`, `tab_moved`, +`tab_regrouped`, `tab_restructured`, `ratio_changed` and `pane_facts`. + + + **A pane exiting is not its own event.** It arrives as a `layout` delta: + `pane_facts` carrying that pane with `"live": false`. Watch for that rather + than for a pane-exit line — there is no such line, whatever the shape of the + wire protocol suggests. + ### `tty7 status`