Merge branch 'claudedo/b346a534f0fc4635bd7614a00ab2a20e'

This commit is contained in:
mika kuns
2026-09-02 20:55:43 +02:00
18 changed files with 840 additions and 10 deletions
@@ -44,6 +44,7 @@ public sealed class InteractiveLaunchSpecService
private readonly GitService _git;
private readonly string _claudePath;
private readonly HandoffRoundTracker _handoffRounds;
private readonly HandlerRoundState _roundState;
// Local wall clock, injectable so the PowerUse time window is testable without sleeping.
private readonly Func<DateTime> _now;
@@ -56,6 +57,7 @@ public sealed class InteractiveLaunchSpecService
GitService git,
WorkerConfig cfg,
HandoffRoundTracker handoffRounds,
HandlerRoundState roundState,
Func<DateTime>? now = null)
{
_now = now ?? (() => DateTime.Now);
@@ -66,6 +68,7 @@ public sealed class InteractiveLaunchSpecService
_git = git;
_claudePath = cfg.ClaudeBin;
_handoffRounds = handoffRounds;
_roundState = roundState;
}
/// <summary>Builds a LaunchSpec for opening an interactive session in a task's worktree.
@@ -347,9 +350,20 @@ public sealed class InteractiveLaunchSpecService
["MCP_TOOL_TIMEOUT"] = McpToolTimeoutMs,
};
// The opening round. Recorded so anything watching a handler run knows which round is live
// (the deferred-handoff follow-up needs that), but marked "triage" rather than a
// MergeHelperPhase value on purpose: there is no handoff spec for this phase, so
// HandlerRestartCoordinator will not reopen it.
_roundState.Save(new HandlerRound(handlerTaskId, TriagePhase, taskIds, DateTime.UtcNow));
return new LaunchSpec(repoDir, resolvedClaude, args, env);
}
/// <summary>The <see cref="HandlerRound.Phase"/> marker for the initial (dedupe/enhance) handler
/// session. Deliberately not a <see cref="MergeHelperPhase"/> value — that set is exactly the
/// phases <see cref="BuildForMergeHelperHandoffAsync"/> can rebuild.</summary>
public const string TriagePhase = "triage";
// Builds the LaunchSpec for the fresh session a merge-helper run hands off to for the given
// phase -- SAME handler task id as the run that called handoff_list_handler, so
// HandlerBaseCommit/HandlerHeadCommit and the review range stay untouched; this never creates
@@ -454,6 +468,11 @@ public sealed class InteractiveLaunchSpecService
["MCP_TOOL_TIMEOUT"] = McpToolTimeoutMs,
};
// Persist the round that is about to start. Phase + task set only exist in the transient
// HandoffRequested broadcast otherwise, so without this a dead tile cannot be reopened at
// the same phase with the same set (see HandlerRestartCoordinator).
_roundState.Save(new HandlerRound(taskId, nextPhase, survivingTaskIds, DateTime.UtcNow));
return new LaunchSpec(repoDir, resolvedClaude, args, env);
}