Repository navigation
feat(web): the Fleet page and the sidebar's spawned-children expander - #149
Conversation
146de83 to
9ca78c7
Compare
9ca78c7 to
74750ea
Compare
bb7539f to
261ebbb
Compare
Jacksondr5
left a comment
There was a problem hiding this comment.
The Fleet page and the per-Crew expander groups are the right surfaces, the cross-environment scoping is correct, retired agents are handled as the definition says, and childless rows really do avoid the shell subscription. The grouping logic is stable and its tests are pure logic.
Requesting changes on the performance claim. The body says memberships and children are read incrementally so the reads stop scaling with the thread list. That holds for the shells-change path only. The 30s poll (inline on fleetClient.ts) re-pends every requested thread id via refreshRequested in packages/client-runtime/src/j5/threadHomes.ts L135, and the sidebar requests every thread, so each tick re-reads memberships and children for the whole list in batches of 200 per environment and swaps the store map so every row re-renders. Empty results also delete their keys rather than marking the row loaded, so a reorder of the requested set refetches ordinary rows too. With the inbox count and the proposals poll from 148 that is three foreground polls. AGENTS.md: performance regressions are usually too much data over the wire. Fix inside this PR: poll only rows that already have memberships or children, and cache negative results; the longer fix is a J5 change stream, which I will file separately.
Minor:
- SidebarChrome.tsx L85 changes the upstream wrapper's classes rather than appending (FORK.md: do not refactor surrounding upstream code).
- Expansion keys omit the environment; two environments with the same thread id share state. Negligible today, but FORK.md case 34 scopes identities for this reason.
- Hit every surface: the Fleet page is reachable only from the rail icon (no palette entry), and a hidden agent-spawned peer can be re-shown only by pinning from the chat view. Fine if deferred; say so in the body.
Reviewed by Claude Fable 5.1 in Claude Code, with an independent pass by GPT-6-Astra in Codex.
261ebbb to
a453d8a
Compare
|
The poll is bounded in a453d8a7f: it re-reads only the rows the roster names as involved, negatives stay loaded, and an unchanged batch keeps its snapshot. The gap sits on the J5 rail entry, expansion keys carry the environment, and the body now says what is deferred. |
a453d8a to
eac8427
Compare
|
From your #152 screenshots, in eac842764: the Captain badge is an anchor mark with the commanded Crews in its tooltip, on the thread card and the Fleet row; seat rows mirror the parent card (time on the top line, provider icon on the bottom); and the seat badge shows only when the thread was renamed, since a seat thread is now titled by its seat (#148) and the badge repeated it. |
eac8427 to
2285134
Compare
Jacksondr5
left a comment
There was a problem hiding this comment.
Round three. The poll now reads only involved rows and the negative cache is correct across environments and request-set changes; expansion keys are scoped; the deferrals are stated; the anchor mark, tooltip, and seat-row layout are J5-owned files with no continuous animation.
Retraction: my note on SidebarChrome.tsx L85 was wrong. That wrapper was added by the fork under FORK.md case 6, so editing it was never an upstream refactor. Sorry for the noise.
Requesting changes on one regression the narrowed poll introduced (inline on fleet.logic.ts). One line.
Minor: useFleetRefresh's .then has no .catch; if the sources refresh rejects, the involved re-read is skipped and the rejection is unhandled.
Reviewed by Claude Fable 5.1 in Claude Code, with an independent pass by GPT-6-Astra in Codex.
2285134 to
0542443
Compare
|
05424434e restores the invalidation: every Crew's Captain is involved on the poll, retired Crews included, and the refresh has a catch. Thanks for the SidebarChrome retraction; I closed that thread with the change standing. |
1b17525 to
7978a19
Compare
Jacksondr5
left a comment
There was a problem hiding this comment.
Round five. The failed state on the Fleet row and expander is right (driven by the latest run's status, cleared by a later run), and the held-row refresh clears a retired Crew's Captain mark on the next tick. One residual on that fix, inline.
Reviewed by Claude Fable 5.1 in Claude Code, with an independent pass by GPT-6-Astra in Codex.
7978a19 to
5c864ce
Compare
5c864ce to
4f0a8b9
Compare
Jacksondr5
left a comment
There was a problem hiding this comment.
Archived instances are now omitted from a Captain's commanded Crews on the server, so a retired Captain leaves the client's held set and the poll cost follows involvement. Approving.
Two cleanups for whenever: the crew reference's archived flag is now always false on the wire, so the client's archived filter is dead weight; and the test covering the archived Captain is the projection function, not the HTTP route, which is fine but narrower than the reply says.
Reviewed by Claude Fable 5.1 in Claude Code, with an independent pass by GPT-6-Astra in Codex.
4f0a8b9 to
95346f7
Compare
|
Both cleanups are in 95346f75c: |
The Fleet page lists every agent in every Squadron across connected environments as the placement tree, with each Crew as a collapsible unit under its Captain and a seat-state summary from measured facts; a rail badge counts agents owing a reply. Agent-spawned Peer Agents leave the flat sidebar unless pinned, and the row that spawned them expands into its placed children so the work stays one click away. Retired agents drop from the Fleet read except as placeholders above active descendants, and retired children leave the expander. Crew memberships and children are read incrementally in batches under the route cap and re-read on the Fleet poll, so the reads stop scaling with the thread list; rows without children never subscribe to the shell list. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A Captain may command several Crews at once, so its sidebar row no longer folds every placed child into one "N crew" toggle. The children are grouped by Crew, newest activity first, and each group is its own collapsible header carrying the Crew's name and a state summary from its seats' measured facts; solo Peer Agents the row spawned outside any Crew form one more group. Expansion is remembered per group under its parent instead of per parent. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The 30-second Fleet poll re-pended every thread id the sidebar had requested, so each tick re-read Crew memberships and children for the whole list in batches and swapped the store map so every row re-rendered. The poll now re-reads only the rows the roster response names as involved (seats, their Captains, spawners with placed children), an empty answer stays loaded so a reordered row set never re-reads it, and a batch that changes nothing keeps the previous snapshot so rows skip their render. A Captain that gained a Crew on another device is named by the roster on the next poll and gets its chip that way. The rail entry carries its own gap so the upstream header wrapper keeps its spacing classes, and expander state is keyed by environment as well as parent and group. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rent card From Jackson's screenshot on PR 152: the sidebar card was out of room, so the Captain badge is now an anchor mark with the commanded Crews in its tooltip, on the thread card and the Fleet row alike. Seat rows in the expander mirror the parent card (time on the top line, provider icon on the bottom) and show the seat badge only when the thread was renamed, since seat threads are now titled by seat. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The narrowed poll built its involved set from live seats and placement parents only, so once a Crew retired its Captain fell out of the set and the cached anchor mark stayed until reload. Every Crew the read returns, retired included, now names its Captain for the re-read, and a failed roster refresh is logged instead of left as an unhandled rejection. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…a retired Crew's Captain clears The badge poll reads the live roster only, and the server filters retired Crews out of it before the response leaves, so the involved-refs helper never saw a retired Crew on that read; only the Fleet page's detail read did. The stale Captain mark survived the last Crew retiring until reload. Rather than paying for retired rosters on every tick, the store's poll re-read now also names every requested row that currently holds a value: a Captain whose last Crew retired is not named by the live roster, but its row still shows a chip, so it is re-read once more and clears. The cost still follows involvement, since a row holds a value only while it was involved. The helper goes back to naming live involvement only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ow and the expander The seat states were running, needs-you, settled, idle, archived, and unknown, so a seat that died on its first turn fell through to idle, the quiet default, and the Fleet row and the Captain's expander showed nothing (Jackson's dogfood, 2026-09-17). A failed last run is now its own state, counted and said in the summary ahead of what the seat may still owe the person. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
95346f7 to
d41da36
Compare
Once agents spawn agents the flat sidebar stops telling the truth about what is running. This PR adds the two surfaces that carry it.
The Fleet page lists every agent in every Squadron across connected environments as the placement tree, with each Crew as a collapsible unit under its Captain and a seat-state summary from measured facts; a rail badge beside the inbox bell counts agents owing a reply. Agent-spawned Peer Agents leave the flat sidebar unless pinned, and the row that spawned them expands into its placed children so the work stays one click away, one named collapsible group per Crew it commands plus one for solo peers, since a Captain may run several Crews at once. Retired agents drop from the Fleet read except as placeholders above active descendants, and retired children leave the expander.
Two performance points I'd draw attention to. Crew memberships and children are read incrementally in batches under the route cap; an empty answer stays loaded, and the Fleet poll re-reads only the rows the roster names as involved (seats, their Captains, spawners with placed children), so the per-thread reads follow Crew activity rather than the length of the thread list, and an unchanged batch keeps its snapshot so rows skip their render. Rows without children never subscribe to the shell list. Deferred on purpose: the Fleet page is reachable from the rail icon only (no command palette entry yet), and a hidden agent-spawned peer can be re-shown only by pinning it from the chat view.
Built with Claude Fable 5.1 in Claude Code.
Evidence
New surfaces, so after-only. Before shots of the old text badge and the doubled seat names are in Jackson's #152 comment.
Sidebar: Captain anchor mark, the per-Crew expander, seat rows mirroring the parent card (time on top, provider below).
The anchor's tooltip names the commanded Crews.
Fleet page with two Captains, three live Crews and a retired one.
🤖 Generated with Claude Code
Closes #205.