Skip to content

fix(dag): block restart when stale cancel fails #213

Description

@LeXwDeX

Symptom

Crash recovery treats a pending/queued node with a stale childSessionId as a restart orphan. If cancelling that old child Session fails, recovery swallows the error and immediately makes the node eligible for spawnReady, allowing the old and replacement executions to overlap.

Reproduction

Baseline: dev@3642796de

cd packages/opencode
bun test test/dag/dag-recovery.test.ts --test-name-pattern "aborts recovery when a stale restart-orphan session cannot be cancelled"

Observed deterministic red result: Exit.isFailure(exit) was false; the cancellation error was discarded.

Root cause

The restart-orphan branch in reconcileWorkflow runs cancelSession(...).pipe(Effect.catch(() => Effect.void)) and then continues. Its own comment requires the old child to be cancelled before re-scheduling, but the implementation turns a failed cancellation into successful reconciliation.

recoverWorkflow already catches a reconciliation failure and abandons adoption, so propagating this error prevents spawnReady until a later recovery attempt can establish single execution ownership.

Expected contract

A restart orphan may re-enter scheduling only after the stale child Session cancellation succeeds. A cancellation failure must abort this recovery attempt without inventing a node terminal event.

Acceptance criteria

  • Retain a red test at the reconcileWorkflow seam.
  • Propagate stale-child cancellation failure for pending and queued restart orphans.
  • Preserve best-effort cancellation for already-running ownership-loss nodes, because those nodes are terminalized and cannot be re-spawned.
  • Publish no node event for the aborted restart-orphan recovery.
  • Run the full recovery test file, OpenCode DAG suite, and package typecheck.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingready-for-agentFully specified and ready for an agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions