Skip to content

fix(opencode): spawn hooks via node:child_process for Desktop - #2018

Merged
Soph merged 3 commits into
entireio:mainfrom
sdshah09:fix/2014-opencode-plugin-node-spawn
Aug 20, 2026
Merged

Soph merged 3 commits into
entireio:mainfrom
sdshah09:fix/2014-opencode-plugin-node-spawn

Conversation

@sdshah09

@sdshah09 sdshah09 commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Replace Bun.spawn / Bun.spawnSync in the OpenCode plugin with node:child_process spawn / spawnSync so hooks fire under both Bun (CLI/TUI) and Node (OpenCode Desktop Electron sidecar).
  • Keep the dogfood .opencode/plugins/entire.ts in sync and update the agent guide.
  • Add a Node canary that loads the plugin and asserts both async session-start and sync turn-end actually spawn.

Fixes #2014

Test plan

  • go test ./cmd/entire/cli/agent/opencode/ -run TestPlugin_SpawnsHooksUnderNode -v -count=1
  • go test ./cmd/entire/cli/agent/opencode/ -count=1
  • mise run lint
  • Optional: OpenCode Desktop — enable opencode, prompt+edit+commit, confirm checkpoint / trailer appears

sdshah09 and others added 2 commits August 17, 2026 15:25
OpenCode Desktop runs the server on Node inside Electron, so Bun.spawn
and Bun.spawnSync threw ReferenceError and every hook was swallowed.
Use node:child_process spawn/spawnSync so CLI (Bun) and Desktop (Node)
both fire hooks. Adds a Node canary that loads the plugin and asserts
turn-end actually spawns.

Fixes entireio#2014

Co-authored-by: Cursor <cursoragent@cursor.com>
Also fire session.created so the canary exercises spawn (session-start)
as well as spawnSync (turn-end). Drop the Go pathToFileURL helper and
use Node's instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M08KHX9P54WJ76X843W433DP
@sdshah09

Copy link
Copy Markdown
Contributor Author

Also still open from last week and ready for review when you have a chance: #1929 (fix(import): sync imported checkpoints once logged in, #1773). Would appreciate a look at that one as well.

@Soph
Soph merged commit ed34d4d into entireio:main Aug 20, 2026
11 checks passed
timothybrush pushed a commit to timothybrush/cli-2 that referenced this pull request Aug 21, 2026
… task data

E2E Tests has failed on every push to main since ed9c31c (entireio#2032, "capture
background subagent work durably"). One job, factoryai-droid, two tests, both
at "expected task checkpoint within 30s" — and failing again on gotestsum's
re-run, so deterministic rather than agent nondeterminism. Bisects cleanly:
ed34d4d (entireio#2018) was green and is ed9c31c's only parent.

It is not a bug in entireio#2032. waitForTaskCheckpoint polled the *shadow branches*
for a tasks/ path, which is precisely what entireio#2032 stopped writing: a Worker's
turn now lands as a completed session.TaskRecord on the parent, and the
transcript is materialized into the parent's checkpoint under tasks/<id>/ at
condensation time. entireio#2032 updated its own integration test to the inverse
assertion ("a Worker's turn must write a task record, not shadow data") and
said so in CLAUDE.md ("records never live on the shadow branch"); these two
E2E tests were the only holdout, and they could not object during review
because E2E Tests runs on push-to-main, never on a PR.

So move them onto the shipped contract, in both directions:

- waitForCompletedTaskRecord polls .git/entire-sessions/*.json for a record
  with a non-empty completed_at (omitempty drops the zero value, so presence
  is the completion signal). Same strength as the existence check it replaces.
- assertNoShadowTaskData pins the inverse — no shadow branch carries a
  tasks/ path. Narrowed to task data on purpose: a parent session
  legitimately has shadow branches of its own, since shadow pinning keys on
  StepCount and says nothing about task content.

TestFactoryTaskCheckpointExistsBeforeCommit becomes
TestFactoryTaskRecordExistsBeforeCommit — there is no pre-commit checkpoint
under the new model, but the durability intent the name carries is still
tested: the Worker's work is captured before the user commits. Prompts are
untouched, so Vogon's regexes are unaffected; both tests skip on non-Factory
agents, so the canary is too.

Whether dropping the pre-commit shadow copy weakens durability is entireio#2058's
question, not this test's. These assert what shipped; they do not settle it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 01M0J4CJ6CCGRXYYVWBSB8Q9H1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

OpenCode hooks never fire in the OpenCode Desktop app: plugin uses Bun globals, desktop runs the server on Node

2 participants