Skip to content

v0.6.4

Choose a tag to compare

@hueyexe hueyexe released this 27 Mar 04:04
· 81 commits to main since this release

Fix: Plugin init deadlock causing lead to hang during teammate spawning

When spawning a teammate, OpenCode creates a new instance for the worktree directory and loads all plugins — including ours. Our plugin's init ran recovery routines that called session.abort back to the server. The server couldn't process the abort because it was still handling the session.create that triggered the plugin load. This deadlock caused a 120-second timeout, after which the lead's prompt loop died silently.

The root cause was identified through structured logging added to the plugin. The [ensemble] log lines traced the exact sequence: spawn:session:start → server bootstraps instance → plugin loads → recovery calls session.abort → deadlock.

  • Skip recovery for worktree instances — isWorktreeInstance() detects teammate directories and bypasses recoverStaleMembers, recoverUndeliveredMessages, and recoverOrphanedWorktrees during init
  • Deliver lead-bound messages via system prompt transform instead of promptAsync content injection — messages are stored in the DB and included inline in the lead's system prompt on its next turn
  • Wake the lead from team_message with a minimal promptAsync notification ([System: New team message from X]) — the system prompt transform delivers the actual content
  • Fire-and-forget all promptAsync calls with error logging instead of silent swallowing
  • Clean up withTimeout timer on success to prevent unhandled rejections
  • Remove dead flushPendingMessages code and skip lead-bound messages in recovery

Also in this release

  • Structured logging via SDK app.log() for all critical paths (spawn lifecycle, message delivery, recovery, wake-ups)
  • Biome lint step added to CI workflow
  • 14 integration tests covering full team lifecycle, parallel spawn races, deadlock prevention, spawn rollback with lead notification, message delivery pipeline, concurrent messaging, and edge cases
  • 332 total tests (up from 302)

Full Changelog: v0.6.3...v0.6.4