#22399 admitted an OpenCode 2 form.created as a pane blocker only when
metadata.kind === "question". On v2.0.15 that is an allow-list on a field
with no contract: packages/schema/src/form.ts declares Metadata as an open
Schema.Record and metadata itself as optional, and the public
POST /api/session/:sessionID/form endpoint lets any client raise a real
blocking form on a real session with no metadata. Orca dropped those, so
the pane painted no blocker while OpenCode waited forever.
Invert the default. Every form whose owner is a real session blocks;
only a form owned by the "global" MCP-elicitation sentinel is dropped,
because that owner is not a session and never goes idle, so its blocker
could not be retired. That also restores websearch.provider as a blocker:
it carries the real context.sessionID, session idle retires it, and while
it is pending the agent is genuinely stalled on the user.
Resolution is unchanged: clearAttentionForResolution keys on the exact
form id plus source session, so a resolution for a dropped form matches
nothing and cannot retire a live blocker.
* fix(opencode2): only treat the question tool's form as a pane blocker
OpenCode 2 has one form primitive and several producers, and Orca's setup
bridge mapped every `form.created` to `question.asked` — the un-evictable
"the pane owner must answer this" blocker. Against opencode v2.0.12 only
`metadata.kind === "question"` is the agent's question tool; `websearch.provider`
is a provider picker and `mcp-elicitation` is an MCP server prompt raised on
sessionID "global", which is not a session and so can never be retired by that
session going idle.
Admit only the question kind, remember the admitted form ids, and drop
`form.replied`/`form.cancelled` for forms that were never admitted so an
ignored form's resolution cannot retire a live blocker.
Evidence (live v2.0.12 capture, real TUI in a PTY against `opencode serve`)
in docs/bug-reproductions/opencode2-form-created-kinds. That capture also
shows the reported Subagents/Shell/Terminals dock and the agent picker emit
no server event at all, so they were never the `form.created` source.
Refs #22371
* refactor(opencode2): drop the unreachable form-resolution guard
Review was right that the admitted-form-id set defended against nothing.
`clearAttentionForResolution` builds the exact key
[factoryID, "AskUserQuestion", form.id, sourceSessionID] and returns null on a
miss, with no session-wide fallback, and form ids are unique — so a resolution
for a form Orca ignored already matches no live blocker. The guard's comment
claimed a collision the key structure rules out, which is worse than no comment.
Removes the set, its FIFO eviction helper, and the claim; the kind check on
form.created is the whole fix. The end-to-end test stays: it pins the behavior
that an MCP form raised and cancelled leaves a live question blocker standing,
which is the property worth holding regardless of how it is achieved.