control-room-recover lands work on cr/ branches but NEVER merges to master
KEYSTONE BUG (4+ instances 2026-06-02/03). The control-room-recover path recovers a finished direct worker's DONE, sets the ticket to in_review, and references its cr/<slug> bra...
StateDoneNext ActionClosedOwnerLuciRuntimeClosedAge9d ago
Ticket is done; runtime is closed.·cwd /home/lucienne/workspace/state/control-room-worktrees/mc-4681-control-room-recover-lands-work-on-cr-br-1ed563 · uptime 9d 11h · last activity 9d 10h ago
Description
MC-4681
KEYSTONE BUG (4+ instances 2026-06-02/03). The control-room-recover path recovers a finished direct worker's DONE, sets the ticket to in_review, and references its cr/<slug> branch — but it NEVER merges that branch to master. So the work is committed + tested but NOT LIVE. Every such ticket reads 'done/in_review' while master is unchanged.
Confirmed unmerged cr/ branches with real, test-passing work stranded:
- MC-4634 0b71b90d (background-task permanent-auth alerting)
- MC-4655 5ed940a6 (shell-safe --description-file/--body-file for ticket creation)
- MC-4640 fcaa1f00+9884e2d8 (MC↔Hermes Kanban bridge, 21 tests pass)
- MC-4629 7d577a7e landed but its TEST commit 36be9b3b stranded on cr branch → master pickup suite RED
Compounds with: workers also report DONE without merging slot-pool branches (MC-4601 fee1babd), so 'done' systematically != 'on master'.
Fix direction (council):
- On control-room-recover of a DONE worker: fast-forward/merge the cr/<slug> branch to master (after the ticket's own tests pass), OR explicitly mark recovered-but-unmerged and surface a controller merge action — do NOT set in_review/done as if shipped.
- Add a board invariant: a ticket cannot reach 'done' unless its referenced commit(s) are ancestors of origin/master. (This single guard would have caught every false-done this week.)
- Regression: recover a worker whose branch is N commits ahead; assert the branch is merged (or ticket blocked) before done.
This is the 4th keystone in the dispatch-hardening cluster: MC-4534 (prompt-echo false DONE/REVIEW), MC-4668 (reviewer reviews wrong commit), MC-4631 (pickup loop only alerts), and THIS (recover never merges). Together they make 'done' on the board untrustworthy — this session every 'done' needed git ground-truth verification. Sequence these four before trusting auto-dispatch/recover again.
Activity
done
INTERACTIVE
Luci is working...
Details —
Done
· High
· Luci
▼
SState
Done
Closed
PPeople
TTiming / Details▼
api (human)
Mission Control
9d ago
9d ago
Advanced / Operator evidence
RRouting owner
ROperator console
Ticket is done; runtime is closed.direct_worker_done_recoveredcwd /home/lucienne/workspace/state/control-room-worktrees/mc-4681-control-room-recover-lands-work-on-cr-br-1ed563 · uptime 9d 11h · last activity 9d 10h agoMC is visibility-only. Hermes Luci launches and gates work outside MC, then mirrors evidence/status here.Raw console: luci-controller · claude-code
WWorkflow
Start Dev Review + QA ▾
Select phases to include:
Agents
Review Gates
Decision
WAT routing: choose an agent, review gate, or decision. Buttons use the live runtime when one is attached.
[follow-up] 12 min past expected check-in (2026-06-03T20:17:32.378091+00:00 UTC).
luci-controller9d ago
[control-room-promote] Promoted MC-4681 from inbox to todo (priority high) so the Control Room pickup loop can dispatch it. Deterministic triage — no worker fired yet.
luci-controller9d ago
[control-room-dispatch] Control Room dispatched MC-4681 to a Claude Code worker.
Worktree: /home/lucienne/workspace/state/control-room-worktrees/mc-4681-control-room-recover-lands-work-on-cr-br-1ed563
Branch: cr/mc-4681-control-room-recover-lands-work-on-cr-br-1ed563
tmux: cr-MC-4681
Expected check-in: 2026-06-03T20:17:32.378091+00:00
luci-controller9d ago
[control-room-recover] MC-4681: recovered DONE from a finished direct worker whose tmux was gone. Ticket → in_review. Summary: MC-4681 — branch `cr/mc-4681-recover-merge-invariant` @ `efb341f` (conrelma/mission-control, pushed; live checkout left on master `754683a` for controller merge+restart). Adds `done` board invariant (`models.unmerged_work_gate_block_reason` wired into `_apply_workflow_action`+`api_update_ticket`) + recover-surfaces-unmerged + safe `--merge-recovered` (ff-only, isolated worktree) in `scripts/contro
api9d ago
Controller deploy + sign-off: LANDED + verified live. Merged feat/mc-4681-merge-invariant-landed (8244af2) to master, restarted MC, smoke-tested the done-gate on the live board:
- merged-work ticket to done: ALLOWED (this very ticket closed).
- unmerged cr/ branch ticket (MC-4655) to done: BLOCKED with unmerged_worker_branch 422 and a clear merge instruction.
- commit-less operational tickets: still allowed (no false block).
203 tests green across the suites. The board now enforces: no done unless the work is an ancestor of origin/master. This is the structural guard for the whole false-done class. Stranded cr/ branches (MC-4655/4640/4634/4629) are now correctly blocked from done until merged via control_room_pickup.py --merge-recovered. Closing.