Skip to content

feat(ui): see and reach the agent's terminal - #44

Closed
Brad (bmethod) wants to merge 1 commit into
mainfrom
issue-24-phase-7
Closed

feat(ui): see and reach the agent's terminal#44
Brad (bmethod) wants to merge 1 commit into
mainfrom
issue-24-phase-7

Conversation

@bmethod

@bmethod Brad (bmethod) commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Phase 7 of #24: see and reach the agent's terminal. Stacked on #43.

The address, not the pane id

TMUX_PANE is a server-global pane id like %9. A tmux session holds windows and a window holds panes, so the pane id alone throws that structure away. On the machine this was built against, %9 resolves to vsys:1.1 and %13 to vsys:2.1 — two agents in the same worktree, separated by the window, not the pane. %17 and %21 are two panes in one window.

src/collect/tmux.ts is the one place that talks to a tmux server. A capability probe decides whether one answers, and the probe is taken as an argument so no test spawns tmux. One tmux list-panes -a per sample resolves every lane; the collector calls it once and hands the map to the lane builder.

The lane keeps the raw %N as the handle every action addresses. The resolved session:window.pane is a column of its own and a field on the detail — identity a name should not carry, beside the process id for the same reason.

The format string uses tabs, not spaces. A tmux session or window may be named with a space, and a space-separated line cannot then be split back into the values it carried. A test covers a session named my work.

laneNameParts listing pane now selects that column. It had no work and could not be dropped: validate rejects an unknown part, so every stored config naming it would stop vsys starting.

Seeing the pane

A Terminal section on the agent detail holds the last lines that pane drew, read only while the section is open and again on each sample. A pane that has gone away says why rather than showing an empty box.

Captured text is treated as hostile. Complete escape sequences are dropped first for legibility, then every remaining control byte is removed. That order is the guarantee: anything the sequence patterns miss still loses its control bytes, so the safety does not rest on a regex being complete. Tested at both levels — on the parsed lines, and on the rendered frame plus the clipboard stream.

Reaching the pane

Go to terminal runs tmux switch-client when vsys is a client of that same server. It moves the reader's view and does not touch the agent's processes, so it does not sit behind writeMode. When vsys is not in that server, the row copies the command through the phase 1 clipboard path and says why it cannot switch.

No terminal emulator is ever launched. $TERMINAL -e … names a program that differs on every desktop and does not exist on macOS, while switch-client behaves the same everywhere tmux runs.

Checked against a live server, not only stubs

19 panes resolved with their window names. A capture returned 52 readable lines with its escapes gone. A missing pane answered can't find pane: %99999, which is the wording the section shows a reader. The unit tests stub tmux, so this is the part they could not tell.

One trade-off, chosen and pinned

At 180 columns beside the side pane, the address column and the trend column cannot both fit under the name floor. The trend goes: the address is identity nothing else on the row carries, and the trend's own number is already in the CPU column beside it. Both widths are pinned by a test, so the priority cannot flip silently.

Proof

376 tests, 0 fail. Ten plants, each reddening its own test.

This line read 362 while the branch sat under #43. Two things moved it. The stack was replayed onto the merged phase-5, which carries four tests the review rounds added there. And 362 was itself one too high: a duplicate test entered during the test-file split, so every suite figure from that commit onward overstated by one until it was found. #43 records how — a by-name body comparison collapses two identical tests to one key and reads as no loss, so only the count carries that evidence.

Also fixed here: three references in docs/architecture/verdict.md naming a test file deleted in the redesign. Each bullet's cited phrase was confirmed present in the successor rather than assumed.

Part of #24.

https://claude.ai/code/session_01B4rKWUEy6WF5MRxtBEwFdB

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@bmethod
Brad (bmethod) force-pushed the issue-24-phase-7 branch 6 times, most recently from 67ad575 to 6f718b9 Compare September 10, 2026 14:35
Base automatically changed from issue-24-phase-5 to main September 10, 2026 14:46
A tmux pane id like `%9` is a server handle: it names no window a reader can
place, and two agents in one worktree are told apart by their window rather
than their pane. One `tmux list-panes` per sample now resolves every lane at
once into `session:window.pane`, however many lanes there are. That address is
a column of its own and a field on the detail; the raw `%N` stays on the lane
as the handle every action addresses, and never enters a name.

`laneNameParts` listing `pane` selects that column. It composed nothing into a
name and could not simply be dropped, because `validate` rejects an unknown
part and every stored config naming it would stop vsys from starting. Giving it
work again settles that without breaking a single stored file.

The agent detail gains a Terminal section holding the last lines its pane drew,
read only while the section is open and again on each sample so it keeps
moving. That text is the agent's own output, so it is treated as hostile:
complete escape sequences are dropped and every remaining control byte is
removed, which is what stops a captured line moving the cursor, repainting the
screen or writing the clipboard.

Go to terminal moves the reader's own tmux view when vsys is a client of the
server holding that pane. Outside it there is no view to move, so the row hands
over `tmux switch-client` through the clipboard and says why. Neither reading a
pane nor moving a view touches a process, so neither waits on write mode, and
no terminal emulator is ever launched: the program that would open one differs
on every desktop and does not exist on macOS.

No tmux, or no server answering, and the column is absent, the section says so
and nothing else on any screen changes.

Also corrects three references in the verdict document to a test file deleted
in abca412, whose cases now live in `src/ui/attention.test.ts`.

Claude-Session: https://claude.ai/code/session_01B4rKWUEy6WF5MRxtBEwFdB
@bmethod

Copy link
Copy Markdown
Collaborator Author

Closing in favour of a fresh pull request on the same branch, with the same head ade7d51 and the same 376 tests.

This pull request was opened against issue-24-phase-5 rather than main, and it never drew a review — not once, across three months of head changes and a close-and-reopen after #43 merged. The automatic reviewer fires on a pull request's original open. Reopening one it has already reviewed re-arms it, which is how #43 got four reviews; reopening one it has never reviewed does not. Requesting it explicitly is not available through the API either: the reviewer is a bot node the request mutations refuse to resolve.

So the review this work needs can only come from a pull request that is new.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant