Adds Number alongside every task id in External/'s DTOs -- the two
central mappers (ToDto/ToRefDto -> TaskDto/TaskRefDto) plus every
DTO that carries a bare task id and bypasses them (batch results,
queue state, wait-for-change, config, attachments, handoff,
lifecycle, merge-preview-set, worktree list). Input resolution
(#123 as an argument) stays for slice 3.
A task selected before its run started kept LatestRunSessionId null, so the
roadblock reply box and Continue stayed dead until it was re-selected.
The handoff left the Phase 1-2 tile open so its last message could be read, but
its process is gone by then and the terminal renders empty -- a dead
placeholder. It is closed on handoff now.
Also drops the WARN flood from worktree cleanup (already-unregistered worktree
and already-deleted branch are normal outcomes, not failures) and replaces the
fixed sleep in UsageGate_TransitionLogging_FiresOncePerChange with the polling
helper that already sits three lines below it in the same file.
Add Merge entry to the worktrees overview context menu wiring the existing
MergeModalViewModel, replace fire-and-forget list selection with a
collection-change-aware JumpToTaskHelper, and propagate list renames to
visible task rows via a new ListUpdated event.
Harden worktree state changes: WorkerHub.SetWorktreeState now rejects
invalid transitions, WorktreeMaintenanceService only drops the DB row when
the on-disk worktree was actually removed, and Cleanup/Reset broadcast
WorktreeUpdated for affected tasks. SetWorktreeStateAsync returns the hub
error message so the modal can surface it.
Also: de-duplicate the worktrees overview modal opener, hook
OnParentTaskIdChanged to refresh IsDraft, fix MergeModal CanExecute
notifications, and add WorktreeStateHubTests for the transition rules.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Slice 5 of the worker state consolidation refactor.
OverrideSlotService (new in Worker/Queue/) owns RunNow, ContinueTask,
and the override-slot piece of CancelTask. QueueService keeps the
queue-slot guard for "task is already running" rejection and delegates
to OverrideSlotService for execution; CancelTask tries the override
slot first, then the queue slot. QueueSlotState is extracted to its own
file.
Folder reorg (via git mv to preserve history):
- Worker/Queue/ QueueService, OverrideSlotService, QueueSlotState
(alongside existing waker/picker)
- Worker/Lifecycle/ StaleTaskRecovery, TaskResetService, TaskMergeService
- Worker/Worktrees/ WorktreeMaintenanceService
- Worker/Agents/ AgentFileService, DefaultAgentSeeder
Worker/Services/ folder removed. All consumers updated to the new
namespaces (Program.cs, WorkerHub, ExternalMcpService,
PlanningMergeOrchestrator, all Worker tests).
OverrideSlotService is registered as a DI singleton in both the main
worker app and the external MCP app.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>