fix(drop-stage): land the drop on intent main so haiku next doesn't hang - #377
Conversation
…t hang
The keep-or-drop offer parks the checkout on the optional stage's own
branch (the cursor's post-action branch switch). haiku_drop_stage committed
the intent.stages edit to whatever branch was checked out — i.e. that
doomed stage branch. But every future stage branch forks from intent main
(git branch <stage> <main>) and the per-tick sync only flows main -> stage,
and a dropped stage never completes (so it never merges up). Intent main
therefore never saw the drop: the next stage forked from a main that still
listed the dropped stage, findCurrentStage flip-flopped dropped <-> next
every tick, and the deadlock detector halted the loop — the "haiku next
hangs after a drop" report.
Fix: switch back to intent main, land the drop there, and reap the orphan
stage branch so it can't reassert the stale plan through a downstream sync.
Guard 3 already proves the stage never started, so its branch holds no work
to preserve. No-op in filesystem mode.
Statusline: render the optional stage's pending keep-or-drop offer as
"keep / drop?" (gated) instead of a generic "elaborate", so the strip shows
the engine is waiting on a decision. After a drop the dropped stage simply
falls out of the pipeline (resolveIntentStages) — no tombstone.
Adds drop-stage-lands-on-main.test.mjs: red against the old behavior
("drop must leave the checkout on intent main"), green with the fix —
asserts the drop lands on main, the branch is reaped, and the cursor
advances instead of flipping back to the dropped stage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @jwaldrip's task in 2m 11s —— View job PR Review
|
- biome check packages/haiku/src now clean (import ordering on the new
git-worktree import block fixed the failing Biome Lint job)
- statusline: drop the redundant `as { optional_offer?: boolean }` cast —
the switch-case already narrows `action` to the elaborate_loop variant,
which declares optional_offer (cursor.ts:166)
- format the regression test to biome style
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed the review in f35e809:
|
|
Claude finished @jwaldrip's task in 1m 45s —— View job Claude finished reviewing PR #377 — re-review after f35e809
Re-review after f35e809Both issues from the first pass are resolved. The PR is clean. Redundant cast — removed. Biome import ordering — fixed. The Core fix — still correct. Tracing the full path: Test — tight regression proof. The three assertions directly mirror the three failure modes described in the PR: (1) checkout lands on intent main after the drop, (2) the drop appears in main's No new findings. Ready to merge. |

What
haiku nexthangs after an optional stage is dropped. Root cause is a branch-location bug, and the second half fixes how the statusline reads during/after a drop.Why it hung
The keep-or-drop offer parks the checkout on the optional stage's own branch (the cursor's post-action branch switch in
haiku_run_next).haiku_drop_stagecommitted theintent.stagesedit to whatever branch was checked out — that doomed stage branch.But every future stage branch forks from intent main (
git branch <stage> <main>,git-worktree.ts), and the per-tick sync only flows main → stage. A dropped stage never completes, so it never merges up. Intent main never saw the drop:intent.stagestherefindCurrentStageelaborate_loop(dropped)⇆elaborate_loop(next), A/B/A/B forever. The inter-tick deadlock detector caught the churn and swapped inloop_halted— that halt is the "hang."The fix
haiku_drop_stagenow switches back to intent main, lands the drop there (the fork source for every future stage branch), and reaps the orphan stage branch so it can't reassert the stale plan through a downstream sync. Guard 3 already proves the stage never started, so its branch holds no work to preserve. No-op in filesystem mode.Statusline
keep / drop?(gated) instead of a genericelaborate, so the strip shows the engine is waiting on a decision rather than working.resolveIntentStages) — no tombstone. This was also broken before the fix, for the same root cause (the statusline read the same stale mainintent.stages).Tests
drop-stage-lands-on-main.test.mjs— red against the old behavior (drop must leave the checkout on intent main), green with the fix. Asserts the drop lands on main, the branch is reaped, and the cursor advances to the next stage instead of flipping back to the dropped one.🤖 Generated with Claude Code