Hidden runs: create OpenCode 2 hidden children unparented (issue 913)
Approved issue: #913
On OpenCode 2.3 every historian and dreamer run starts a turn in the user's session. The hidden child was created with parentID set to the user's session, and OpenCode 2.3 reports every idle of a parented session to its parent and wakes it. Each hidden run therefore lands as a <subagent> completion message in the user's session and prompts the main agent to answer it.
This change creates the hidden child as a root session of the run's directory (childCreateInput already carries that location) and keeps removing it when the run ends. The parent read-back, the dropped-parent notice and the directory refusal only existed for the parented shape, so they go with it.
Evidence
tests/opencode2/hidden-child-native-remove.test.ts now also checks that the user session's message ids are unchanged after a historian and a dreamer run, and asserts parentID === null for both children.
| Host | Plugin | Result |
|---|---|---|
| OpenCode 2.3.0 | master 82b8c13 | fail: user session gains 6 messages; both children have parentID = user session |
| OpenCode 2.3.0 | this branch | pass: no new user-session messages; both children parentID: null, removed after the run |
| OpenCode 2.0.22 (pinned) | master 82b8c13 | fail: parentID = user session |
| OpenCode 2.0.22 (pinned) | this branch | pass |
The 2.3.0 rows used MC_E2E_OPENCODE2_CLI with @opencode/cli@2.3.0 and MC_E2E_OPENCODE2_AI_ROOT with @opencode/ai@2.3.0, plus a local, uncommitted relaxation of schemaGeneration to accept v2.3.x (the e2e schema guard has no 2.3 bundle yet). That relaxation is not part of this PR.
Also run on Linux (WSL Ubuntu 22.04, Bun 1.4.2): bun run typecheck exit 0; bun run lint exit 0 (no findings in changed files); biome format on changed files: no fixes; src/v2/hidden-child-native.test.ts + src/v2/hidden-completion.test.ts: 88 pass / 0 fail.
Not run: the full unit and e2e suites.
Harness coverage (required)
- OpenCode 1: not applicable — surface does not exist there (the OpenCode 1 host does not report a child's idle to its parent; this lifecycle is
src/v2only) - OpenCode 2: covered
- Pi: not applicable — surface does not exist there (no host session parenting for hidden runs)
- OMP: not applicable — surface does not exist there (no host session parenting for hidden runs)
- Rust module: not applicable — surface does not exist there (its
parent_idis a historian invocation id, not a host session)
Summary by cubic
Fixes issue #913: historian and dreamer runs on OpenCode 2.3 no longer inject <subagent> turns into the user's session. Hidden children are now created as root sessions of the run's directory instead of being parented to the user's session, and are still removed when the run ends.
- The parent read-back, dropped-parent notice, and directory refusal only existed for the parented shape, so they were removed.
- Tests now assert the hidden children are unparented and that the user session's messages are unchanged after historian and dreamer runs.