feat(ports): surface listening ports per session in the fleet view - #104
Merged
Conversation
The captain runs many worktrees with make local PORT=xxxx e2e servers and loses track of which port belongs to which session. Surface the observed listening TCP ports on each loop, per pivot.md §11: - claude.ListeningPortsByCwd: two bounded lsof probes (system-wide TCP listeners, then those pids' cwds), same procTimeout discipline and p/n record parsing as LiveClaudeCwds - claude.applyPorts: enrich after applyLiveness, attaching ports only to CwdVerified loops by exact real-path match — probe failure attaches nothing, ambiguity attaches nothing, State/Stall never touched - probe is gated: skipped entirely when no loop has a verified cwd - FLEET row: optional dim 🌐:3000 tag column (accountTag pattern, shown only when >=1 visible loop has ports; drops before ACCOUNT in the width cascade); DETAIL panel: PORTS row under CWD with every port - demo fleet: flaky-tests carries an observed port so --demo shows it Pure observation, display-only: no actuation, no health claims — a port present means exactly "a listening socket was observed in this loop's verified cwd", nothing more. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: jitokim <pigberger70@gmail.com>
jitokim
marked this pull request as ready for review
July 31, 2026 00:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review
Review complete. I read the full diff (7 files, +742/−27), pivot.md §11, and ran
go vet+ the three affected packages' tests (all green). Verdict: solid — no blocking issues. Minor notes only:Loop.Ports []int(nil = nothing observed),ListeningPortsByCwd()as twoprocTimeout-bounded lsof probes,applyPortsright afterapplyLiveness, the CwdVerified-only gate, exact-match-only v1, the gated probe (recommended option), dim🌐:3000FLEET tag + DETAIL PORTS row, and all four honesty rules. The deviation: §11 specified the cwd→loop join asencodeCwd(serverCwd) == Loop.ProjectDir, but the code compares real lsof paths (portsByCwd[loops[i].Cwd]) instead. That's strictly more honest —encodeCwdis many-to-one and could attach one dir's server to another dir's loop — and theapplyPortsdoc comment explains exactly why. Improvement, not drift.open, no spawn/write/backend coupling;State/Stallnever touched (pinned byTestApplyPorts_StateNeverTouched); probe failure attaches nothing. The §11 "open :3000" actuation was correctly left out of v1.procs.gonow has three sibling p/n record walkers (parseLsofCwds,parseLsofListenPorts,parseLsofPidCwds) with near-identical loop skeletons. §11 anticipated this ("isomorphic to parseLsofCwds"), and each has a real reason to differ (count vs pid-keyed vs port-parsing), so it's acceptable — but a sharedp/nrecord iterator is an easy follow-up if a fourth walker ever appears. TUI side reuses the ACCOUNT-column pattern faithfully (caller-requested, presence-gated, byte-identical rows when absent).applyPorts/anyCwdVerifiedon injected maps; the width cascade, tag truncation (+Nsuffix drops, digits never sheared), demo fixture, and both DETAIL presence/absence cases are covered, including failure cases (probe failure, unverified cwd, subdirectory listener, bad pid lines). OnlyListeningPortsByCwditself is untested — consistent withLiveClaudeCwds, which has the same exec-boundary exemption.pline orphans thenlines under it, never credited to the previous pid," but a barepline (length 1) is skipped by thelen(line) < 2guard before the switch, leavingpidat its previous value — so itsnlines would be credited to the prior pid. Purely theoretical (lsof never emits a barep; the testedpNOPEcase is handled correctly), but if you want the comment to be literally true, resetpid = -1for short lines starting withp, or soften the comment.wPort = 10claim about survivingrenderWide's capped panel holds — at inner width 70 with ACCOUNT + PORT requested, the cascade sheds ORACLE and CYCLE and lands NAME exactly atnameGoodWidth(20), so PORT survives; at 12 it would drop. The🌐:65535fit claim (8 cols ≤ wPort−1) is also correct.🤖 Generated with Claude Code