From 7ecb1fa0b58c39e3ab3ab4030967268d2863a70c Mon Sep 17 00:00:00 2001 From: Mika Kuns Date: Wed, 16 Sep 2026 11:20:33 +0200 Subject: [PATCH] Fix: some Reactive stuff --- src/ClaudeDo.Worker/Hub/WorkerHub.cs | 1 + .../InteractiveReviewSubmissionService.cs | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ClaudeDo.Worker/Hub/WorkerHub.cs b/src/ClaudeDo.Worker/Hub/WorkerHub.cs index 01a41be6..1c176a90 100644 --- a/src/ClaudeDo.Worker/Hub/WorkerHub.cs +++ b/src/ClaudeDo.Worker/Hub/WorkerHub.cs @@ -774,6 +774,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub { if (_interactiveLaunchSpec is null) throw new InvalidOperationException("Interactive launch spec service is not configured."); + _broadcaster.WorktreeUpdated(taskId); return _interactiveLaunchSpec.BuildForTaskAsync(taskId, Context.ConnectionAborted); }); diff --git a/src/ClaudeDo.Worker/Lifecycle/InteractiveReviewSubmissionService.cs b/src/ClaudeDo.Worker/Lifecycle/InteractiveReviewSubmissionService.cs index b41c4315..ef2c8173 100644 --- a/src/ClaudeDo.Worker/Lifecycle/InteractiveReviewSubmissionService.cs +++ b/src/ClaudeDo.Worker/Lifecycle/InteractiveReviewSubmissionService.cs @@ -2,6 +2,7 @@ using ClaudeDo.Data; using ClaudeDo.Data.Git; using ClaudeDo.Data.Models; using ClaudeDo.Data.Repositories; +using ClaudeDo.Worker.Hub; using ClaudeDo.Worker.Runner; using ClaudeDo.Worker.State; using Microsoft.EntityFrameworkCore; @@ -20,17 +21,20 @@ public sealed class InteractiveReviewSubmissionService private readonly GitService _git; private readonly ITaskStateService _state; private readonly WorktreeManager? _worktreeManager; + private readonly HubBroadcaster? _broadcaster; public InteractiveReviewSubmissionService( IDbContextFactory dbFactory, GitService git, ITaskStateService state, - WorktreeManager? worktreeManager = null) + WorktreeManager? worktreeManager = null, + HubBroadcaster? broadcaster = null) { _dbFactory = dbFactory; _git = git; _state = state; _worktreeManager = worktreeManager; + _broadcaster = broadcaster; } public async Task SubmitAsync(string taskId, CancellationToken ct) @@ -86,5 +90,14 @@ public sealed class InteractiveReviewSubmissionService var result = await _state.SubmitInteractiveForReviewAsync(taskId, DateTime.UtcNow, ct); if (!result.Ok) throw new InvalidOperationException(result.Reason ?? "Could not submit for review."); + + // The transition itself only broadcasts TaskUpdated, and the detail pane answers that by + // refreshing the task row alone -- its whole REVIEW/MERGE block (Open diff, branch picker, + // change summary) is gated on the worktree it last read, refreshed only on WorktreeUpdated. + // An interactive session creates its worktree at launch and gets it committed HERE, both + // outside the autonomous pipeline that would normally announce it, so without this the task + // arrives in WaitingForReview with the diff button missing until it is re-selected. + if (_broadcaster is not null) + await _broadcaster.WorktreeUpdated(taskId); } }