summaryrefslogtreecommitdiff
path: root/9player/src/nine.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-21 16:49:20 -0300
committerGabriel Schneider <[email protected]>2026-09-21 16:49:20 -0300
commitdddd556accea6b6ea7802cd3f622f8b3cf8eb43f (patch)
tree64a1cc34d44f9be6ec266d852fdef6f5b842d004 /9player/src/nine.zig
parentb4db588dd5b92d647b661c2dc17b40925af92348 (diff)
downloadcloud9-dddd556accea6b6ea7802cd3f622f8b3cf8eb43f.tar.gz
cloud9-dddd556accea6b6ea7802cd3f622f8b3cf8eb43f.zip
9harness: /active, and zmxify as a write to a file
The mirror answers what files exist. /active answers what is running: one directory per live agent, normalized across harnesses, fields as small text files, synthesized per request. /active/claude/345104/{pid,cwd,session,via,name,status,title, model,started,zmx,transcript,agents/} This is /proc's shape, and deliberately: a directory per object named by pid under a directory per harness, rather than a compound `claude-345104` that would make you parse a name to recover a field that is already the directory above it. There is no `updated` file — that is the mtime of `transcript`, which stat already carries. Each harness is asked in its own terms, and the route is reported in `via` so a wrong guess is visible rather than silent. Claude Code publishes sessions/<pid>.json itself, with procStart as a pid-reuse guard, so nothing there is guessed. omp and dsh are found by the transcript they hold open, omp falling back to the store named after its cwd. codex's rollout file carries the session id in its *name*, so its sqlite is never opened. hermes is the one gap and needs none: its sessions live only in sqlite, and the only hermes processes that run are the gateway and the dashboard, which are not sessions. Liveness is /proc/<pid> plus a matching start time: a pid alone is not an identity. The daemon never lists its own ancestry, so it cannot show or act on the tree serving the request. The write path, and why it is a file and not a ctl: writing a zmx session name into an agent's `zmx` moves it there. The file means which zmx session this agent lives in, and writing makes that true. A ctl taking verbs is the ordinary Plan 9 spelling, and an executable script served in the tree is the spelling zmx's own `attach` uses, but a script that shells out to a local binary lies over a remote mount — it would run against a session that is not on the client's machine. A write is served where the authority is. Every refusal comes before anything is destroyed: the name must be zmx's label charset, unused by a live session, and the agent's session must have resolved, because nothing is killed that has nowhere to come back to. The command is fixed per harness and no client byte reaches exec. It is off unless --allow-move: this is the one place the tree is not read-only, and anything that can mount it could otherwise kill an agent. 9harness/zmxify replaces the 307-line rc script. It parses no /proc, opens no fd table and queries no database; it lists /active, offers the rows to fzf and writes the chosen name. It no longer excludes the caller's own session, which the old one had to: that script did the killing itself, so killing its own parent lost the session it was rescuing. The daemon completes the kill and the re-exec whether or not the client is still connected — verified by hanging up immediately after sending the write — so zmxifying the terminal you are sitting in now works, which is the common case. --proc DIR is the fixture seam: the scan, the liveness guard, the exclusions and the ancestry rule are unit-tested against a fake process tree, never the live one. Suites: 87/87 root, 48/48 9ns, 26/26 9harness (+5 for the view), 60/60 9proc, 144/144 programs-test, 51+88 9ns integration, 44/0 9harness end-to-end (+16, including a real move against a fake harness and a fake zmx), 29/0 9proc debug, 213/0 9ns adversarial, freestanding green.
Diffstat (limited to '9player/src/nine.zig')
0 files changed, 0 insertions, 0 deletions