Skip to content

Babysitter-enabled team dispatch can still wedge: #spawnAgent clobbers published phase mid-babysitter-attach #455

Description

@khaliqgant

Follow-up to #443 / PR #454

PR #454 fixed two gaps that left a team-dispatch (multi-implementer) work unit wedged in a slot-occupying phase forever when a dispatch-lifecycle save failed on the publish path:

  1. The agent-exit handler's fallback-publish branch didn't re-arm the retry on a save failure.
  2. #driveDispatchLifecycle's retry loop for an incomplete published team-dispatch row was gated on !babysitter.enabled, so babysitter-enabled team dispatch had the identical wedge. Fixed by removing that guard, and by only advancing the row to running from #ensureBabysitter once every implementer has a completion PR.

Remaining gap

Verified via targeted instrumentation while testing the babysitter-enabled fix: #ensureBabysitter calls #spawnAgent to place the babysitter agent itself, and #spawnAgent unconditionally saves dispatch-lifecycle phase dispatching as part of normal spawn plumbing — before #ensureBabysitter's new completeness guard ever runs. So even with #454's fix, spawning ONE implementer's babysitter can still durably move a still-incomplete team-dispatch row off published (to dispatching), which #driveDispatchLifecycle handles via #resumeDurableDispatch — a code path built for resuming a stalled/interrupted dispatch, not for retrying a sibling implementer's publish. A sibling implementer that hasn't published yet can still end up without a working retry path in this specific case.

Reproduction

Team dispatch (2 implementers), babysitter enabled. One implementer (pear) fails to publish; the other (hoopsheet) succeeds and its own exit handler calls #ensureBabysitter for its receipt. pear keeps failing until hoopsheet has already published (pins the ordering). Durable phase moves publishing → (hoopsheet's babysitter spawn) → dispatching, and pear's retries never land a receipt. A test exercising exactly this (retries a sibling implementer's publish after another has already reached published, with babysitting enabled) was written and removed from #454's branch before merge because it could not be made to pass without this deeper fix.

Suggested fix

Defer the babysitter spawn itself (not just the running phase-advance already fixed in #454) until #allImplementersHaveCompletionPr(record) is true, for a multi-implementer dispatch. #ensureBabysitter has ~10 call sites; the safest form is likely a single guard near the top of #ensureBabysitter itself (a no-op for single-repo dispatches, where #allImplementersHaveCompletionPr trivially returns true) rather than gating each caller individually. Needs care and its own test coverage given how widely #spawnAgent/#ensureBabysitter are used.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Er8WLsn6HU3C3HHUiX6Uh8

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions