Skip to content

orchestrate: implementer branches fork from a stale worktree base, so merge-mode ff-only integration parks verified work en masse #46

Description

@TBarregren

Context — field experience (kntnt-wp-skills, 2026-07-19, orchestrate 0.13.0)

A 14-issue merge-mode run (two slices, serial single-issue waves) hit a systematic integration failure: in slice 1, 5 of 8 independently-verified-green branches failed git merge --ff-only, and 3 of them were parked despite being fully verified, because the rebase hit content conflicts the integrate agent is forbidden to resolve. Slice 2 repeated the pattern (1 of 5 needed a rebase; one issue parked). All parked branches were later landed by a manual recovery loop (rebase agent → targeted re-verify of the conflict resolution → ff-only land) — every single one was sound.

Root cause

Three compounding gaps in skills/orchestrate/orchestrate.workflow.js:

  1. The implementer's branch base is stale by construction. The implement prompt says "Work on a fresh branch off the current integration base" but never says how. The agent lands in a Workflow worktree whose HEAD is the harness's scaffolding branch worktree-<runId>-<n>, pinned at run start — observed: every scaffolding branch in both runs sat at the run-start commit even while main advanced issue by issue. So "the current base", resolved from inside the worktree, is the run-start commit, and every issue after the first forks from a base missing its predecessors.
  2. The integrate prompt's premise is then false. It asserts "In the serial integrate-immediately design nothing landed between the build and now, so it is already a fast-forward" — untrue once (1) applies; the ff-only refusal it calls "the rare case" becomes the normal case from issue 2 onward.
  3. A genuine rebase conflict parks verified work with no reconcile path. The integrate agent is (rightly) forbidden to resolve content conflicts, but the engine's only response is to park — even though the branch passed independent verification. For a batch of tickets that touch the same shared files (SKILL.md/spec/manpages — common in doc-heavy plugins), conflicts are the norm, so merge mode degrades into a park generator.

Telling detail: the engine already contains the correct pattern — integrationHotfix creates its branch with git checkout -B <branch> <current-default-tip> precisely so it "can never build on an old base". The same instruction is missing from implement (and fix).

Proposed fix

  1. Primary (cheap, prompt-only): the implement prompt mandates, before any work: git checkout -B <feature-branch> <default-branch> pointing at the current default tip — mirroring integrationHotfix's wording and rationale. In the serial integrate-immediately design this restores the ff-only invariant for real; the fix prompt keeps working in the same branch/worktree as today.
  2. Secondary (engine stage): when ff-only is refused AND the rebase hits a genuine content conflict, do not park a verified branch outright — add a bounded reconcile stage: one implementer-grade agent rebases and resolves minimally (keep both sides' concerns), then one targeted re-verify of the conflict resolution only (not the whole panel), then land; park only if the re-verify blocks or a second conflict round hits. This mirrors the manual recovery that landed 5/5 parked branches in the field run.
  3. Docs: correct the integrate prompt's "nothing landed between the build and now" claim (or make it true via fix 1) so the agent's mental model matches reality.

Acceptance criteria

  • In a serial merge-mode run where issue N's landing edits files issue N+1 also touches, issue N+1's branch forks from the post-N default tip and lands with a plain --ff-only (no rebase) — engine-helpers unit-testable via the prompt text (the checkout -B instruction present in implement), plus a workflow-level assertion if feasible.
  • A genuine rebase conflict on a verified branch triggers the reconcile stage and lands after a clear targeted re-verify; parking happens only when the re-verify blocks or the bounded rounds are exhausted.
  • The integrate prompt no longer asserts the false invariant.

🤖 Generated with Claude Code

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

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions