Skip to content

fix(review): reap markerless orphaned review slot + unwedge the dialog-blocked poller - #579

Merged
jlong merged 1 commit into
mainfrom
jlong/review-slot-left-orphaned-with-stale-status-yaml-after-accept-merge-dialog-block-wedges-poller
Aug 18, 2026
Merged

fix(review): reap markerless orphaned review slot + unwedge the dialog-blocked poller#579
jlong merged 1 commit into
mainfrom
jlong/review-slot-left-orphaned-with-stale-status-yaml-after-accept-merge-dialog-block-wedges-poller

Conversation

@jlong

@jlong jlong commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Task

After a review-routed task is accepted (moved to done) and merged, the review workspace can be left as an orphaned session with a stale status.yaml instead of being cleanly torn down and returned to idle. Observed live on 2026-08-17.

Current Behavior

Timeline for workspace review on task provisioning-never-destroy-user-claude-skills-files-mount-shelbi-s-without-committing:

  • 19:02:41 — review slot auto-loads the branch (status=review-load detail=auto-loading_branch_onto_idle_review_slot), boots server, serving.
  • 19:03:09 — working -> blocked reason=dialog:question. This is the last status line the review workspace ever emits.
  • Its ~/.shelbi/workspaces/review/status.yaml freezes at state: working, last_seen: 2026-08-17T19:03:03Z.
  • 19:16:16 — the task is merged (merge ... status=ok detail=pr:577:...) and moves review → done. The review server pane is NOT cleanly torn down.
  • Hours later, shelbi workspace list shows review hub - conventional orphaned session, and shelbi workspace status review still reports state: working, last_seen 5h ago with (idle) task.

So two coupled defects:

  1. The review workspace's status poller stops after a dialog:question block and never recovers — status.yaml goes stale (frozen at working).
  2. On task acceptance/merge, the review slot's server pane is not fully torn down, leaving an orphaned session rather than a clean idle slot.

Meanwhile the hub heartbeat still counts idle_workspaces=6 (including this slot), so it would route the next review-routed task onto a slot that is actually in an orphaned/stale state — risking a failed or confused review-load.

Expected Behavior

  • When a review-routed task leaves the review status (accepted → done, or bounced → ready), the review workspace's server pane is fully torn down and the slot returns to a clean idle with a fresh status.yaml (not orphaned session, not frozen working).
  • A dialog:question (or any) block on a review workspace must not permanently wedge its status poller — status reporting should resume (or the pane should be recovered by the supervisor) rather than going silent for hours.
  • status.yaml should not remain frozen at a stale working/last_seen once the task is gone; it should reflect the real current state (idle) or be cleared.
  • The heartbeat's idle_workspaces count should not include a slot that is actually orphaned/wedged, or the orphan should be reaped so the count is honest.

Acceptance Criteria

  • After accepting (→ done) a review-routed task, shelbi workspace list shows the review slot as idle, not orphaned session.
  • After acceptance, shelbi workspace status <review> shows a fresh, current status.yaml reflecting idle (not a stale working frozen at the dialog-block timestamp).
  • A dialog:question block on a review workspace does not permanently stop its status poller; status updates resume (or the supervisor recovers the pane).
  • The review slot is cleanly usable for the next review-routed task with no manual workspace stop/recovery.
  • idle_workspaces in the heartbeat reflects genuinely available slots (an orphaned/wedged review slot is either reaped or not counted).
  • cargo build --workspace, cargo test --workspace, and cargo clippy --workspace --all-targets -- -D warnings pass.

Context

Discovered while orchestrating on 2026-08-17: after merging PR #577 (the .claude provisioning fix) via review → done, the review slot was left orphaned with a status.yaml frozen at the earlier dialog:question block (19:03), 5h stale. Not currently blocking (no queued review tasks) but leaves the slot in a dirty state and makes the heartbeat idle count dishonest. Likely lives in the review-load / review-window teardown and the workspace status poller (see shelbi-orchestrator review/poller code and the review-window auto-recover path). The unrelated project=contextstore ... supervision=gave-up reason=review-load-crash-loop line at 18:32 is a different project and out of scope for this task, though it may hint the review-load path is fragile under blocks.


Auto-opened by Shelbi — review at: /Users/jlong/.shelbi/projects/shelbi/tasks/review-slot-left-orphaned-with-stale-status-yaml-after-accept-merge-dialog-block-wedges-poller.md

…g-blocked poller

Two coupled defects left a review slot orphaned with a stale status.yaml
after a review-routed task was accepted and merged (observed live 2026-08-17,
PR #577).

1. Dialog-block wedged the status poller. When a Claude pane parks on a
   blocking modal (`dialog:question`, trust, permission), neither the busy
   footer nor the ready input box is drawn and Claude commonly clobbers the
   `shelbi:` pane-title marker with the modal's chrome. `poll_one` then found
   no live state AND no title marker and `return`ed early *before*
   `save_workspace_status`, so status.yaml froze at the pre-dialog state
   (`working`) and `last_seen` stopped advancing for the life of the modal —
   hours, in the incident. Fix: `maybe_emit_dialog_event` now returns the
   detected dialog kind, and `poll_one` folds it into the persisted state —
   a detected modal records `Blocked` (keeping `last_seen` fresh and honest),
   which clears on the next live busy/ready sample once the human answers.

2. Orphaned review pane was never reaped without a serving marker.
   `maybe_reap_orphaned_review_slot` gated the reap on the
   `.claude/shelbi-review-loaded` marker. A slot that was dispatched a review
   task but blocked on a dialog before its branch server came up never got
   that marker written, so when the task was accepted (review → done) nothing
   tore the pane down — and the dev-orphan reaper deliberately skips `review`
   slots, so the pane lingered as an `orphaned session`, keeping the heartbeat
   `idle_workspaces` count dishonest. Fix: drop the marker gate; the
   liveness/user-shell probe is the real guard, so a live non-user-shell agent
   pane with no assigned review task is reaped regardless of marker. A user
   shell / dead / unreachable slot is still left alone.

Also: on any reap (review + dev orphan) and on the TUI accept teardown
(`close_review_window`), clear the freed slot's status.yaml via the new
`shelbi_state::clear_workspace_status`. A killed pane emits no further markers,
so the poller can never refresh the file; left in place it would report the
agent's last state frozen forever. Cleared, the slot reads as idle in both the
board-derived `workspace list` and `workspace status`.

Decisions made without asking:
- Persist `Blocked` (not a new Idle variant) for a detected modal — it's the
  honest state and rides the existing decide()/dedupe machinery.
- Clear (delete) status.yaml on reap rather than write a synthetic idle state:
  there is no agent to describe, and the whole system already derives idle-ness
  from the board + live probe, not a persisted "idle" marker.
- Reap is left to the poller (covers CLI `task move`, hand board moves, and
  eviction uniformly); the CLI accept path is not given its own teardown call.

cargo build/test/clippy --workspace all pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shelbi Ready Ready Preview Aug 18, 2026 3:02am

Request Review

@jlong
jlong merged commit 41f18e4 into main Aug 18, 2026
3 checks passed
@jlong
jlong deleted the jlong/review-slot-left-orphaned-with-stale-status-yaml-after-accept-merge-dialog-block-wedges-poller branch August 18, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant