Skip to content

(session-state): subagent activity feeds the same running set and the same rung for every source - #288

Merged
devsuitup merged 3 commits into
mainfrom
fix/284-285-subagent-parity
Sep 13, 2026
Merged

(session-state): subagent activity feeds the same running set and the same rung for every source#288
devsuitup merged 3 commits into
mainfrom
fix/284-285-subagent-parity

Conversation

@devsuitup

@devsuitup devsuitup commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Closes #284, closes #285.

Both come from the parity audit (.work-files/switchboard/parite-sidebar-2026-09-13.md, findings A2 and B1/B2), reproduced through the real renderer under jsdom.

#285 — running dot on remote / local-transcript subagent rows. activeSubagentsByParent was fed only by the local subagent-spawned / subagent-completed IPC pair; the remote watch event and the local-transcript adapter set the parent's agentsBusy and dropped the agentId. noteSubagentActivity(parent, agentId) in public/sidebar.js is now the single write path for the three sources, so the child row gets the same .running dot, slot and TTL. The B2 hypothesis (DOM id mismatch) does not hold: subagent rows are ided from subagentSessionId(parent, agentId) on every layout, and the existing no-rebuild test passes on main. One side effect fixed on the way: reflectSubagentRunningState repainted the parent slot from the local-pty snapshot, which would have blanked a remote or local-transcript parent's icon — it now repaints only when local-pty owns the row.

#284 — remote parent on the animated busy rung while only a subagent runs. A Task-tool invocation writes the parent's own transcript too, so the remote watch channel fired a plain busy that outranked agentsBusy for the 20 s decay. The parent's busy decay is now SUBAGENT_PARENT_DECAY_MS = 3 s instead of PIP_DECAY_MS = 20 s whenever agentsBusy is set: every subagent touch shortens a pending longer decay, busy is never cleared synchronously. A parent that really works keeps writing at the 1 s IPC throttle and stays busy; one merely bookending a Task-tool call lands on agentsBusy — the local row's rung — within seconds. A parent with no subagent keeps the 20 s decay. A first version used a 3 s coincidence window keyed on the spawn edge; review reproduced two failures (genuine output swallowed inside the window; a second spawn has no edge) and it was replaced. Domain PRIORITY untouched. seedRemoteActivity keeps its PIP_DECAY_MS arithmetic (out of scope, noted in the context doc).

Tests: test/dom-sidebar-subagent-running-parity.test.js (remote, local-transcript, decay, local IPC without rebuild, attached remote parent repaints live, unattached remote parent's remote-painted icon untouched); test/remote-session-adapter.test.js with an injected clock (busy holds under 1 s touches while a subagent runs; a coincident touch decays to agentsBusy at 3 s; a second spawn shortens the decay; no-subagent parent keeps 20 s). Rationale in .ai/contexts/session-state.md and .ai/contexts/subagent-observability.md.

… same rung for every source

A remote or local-transcript subagent event now threads its agentId into
activeSubagentsByParent through one write path, so the child row gets the
same running dot, slot and TTL as a local PTY subagent. Closes #285.

On a remote parent, a busy touch that coincides with a fresh subagent spawn
(3 s window, either order) no longer outranks agentsBusy for the 20 s decay:
the Task-tool invocation writes the parent's own transcript too, which put
the remote row on the animated busy rung while the local row sat on the
static agents-busy rung. A busy touch outside the window still wins.
Closes #284.
…ent runs; ownership guard honours attach

Replaces the coincidence window: a remote parent's busy decay is 3 s
instead of 20 s whenever agentsBusy is set, on every subagent touch rather
than the first spawn edge, and busy is never cleared synchronously. A parent
that really works keeps writing at the 1 s throttle and stays busy; one
merely bookending a Task-tool call lands on agentsBusy within seconds.

reflectSubagentRunningState now repaints the parent slot unless the row is
genuinely remote-owned (present and not attached), so an attached remote
row gets the same live repaint as a local one.
…ame short decay while a subagent runs

seedRemoteActivity computed its remaining window from PIP_DECAY_MS, so a
rebuild triggered by the subagent's own writes put a waiting parent back on
the busy rung for up to 20 s after its short decay had fired.
@devsuitup
devsuitup merged commit caacee0 into main Sep 13, 2026
10 checks passed
@devsuitup
devsuitup deleted the fix/284-285-subagent-parity branch September 13, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant