Commit Graph
2 Commits
Author SHA1 Message Date
Neil 8ddad49ae5 fix(opencode): retire a subagent's blocker when the root turn ends (#22604)
A descendant's question is stored under its own sourceSessionID but displayed on
the root session it rolls up to. clearAttentionForSession matches only the
source, so the root's own idle could never retire it: the blocker outlived the
turn that raised it and pinned the pane on "needs input" with nothing left to
answer. The lead agent truthfully reports no pending question, because the
blocker belongs to a child it does not know about (#22371).

Add clearAttentionForTurnEnd, matching the source id or the rolled-up root, and
use it only from the idle branch. Scoped to turn end deliberately: a live
blocker must still outrank the root going Busy, since a subagent can be waiting
on the user while the root keeps working — widening the existing clear broke
exactly that test, which is what surfaced the right scope.

Shared with the OpenCode family, so mimo-code gets the same fix; both pinned
plugin digests move.

New test fails without the change: after the root turn ends the last post is
still AskUserQuestion instead of SessionIdle.
2026-09-23 23:45:50 -07:00
Neil b0ae7d18a0 fix(opencode2): resolve subagent session lineage so child work stops taking over the pane (#22444)
OpenCode 2's plugin adapter unwraps a single-property `{ data }` success schema,
so `ctx.session.get` resolves to the bare session record. The shared lineage
lookup only accepts `result?.data?.id === sessionID`, and OpenCode 2 has no
`session.list` fallback, so `resolveRootSessionID` returned null for every
session and `childState` was permanently null.

With unknown lineage `canFailOpen` is true for attention events, so a subagent's
`permission.asked`/`question.asked` fell through and pinned an un-evictable
blocker keyed to the child's own session id — publishing a subagent as if it
were a root. Observed in hook posts: SessionBusy for a child session id whose
`session_v2` row carries a parent.

Envelope the result in the OC2 client shim so the shared lineage module works
unchanged; OpenCode 1 already receives enveloped results and is untouched.

Also adds `opencode2` to the double-Escape interrupt list, extracted into one
shared helper so the server inference and renderer gate cannot drift. A single
Escape was inferring an interrupt, and Escape is how the Subagents dock closes.

7 of 11 new lineage tests fail without the shim.
2026-09-23 20:08:01 -07:00