fix(worker): thread handler task id into list-handler kickoff prompts

Neither the initial nor the handoff kickoff ever told a list-handler
session its own handler task id, so handoff_list_handler(taskId, ...)
was unrenderable -- the handoff chain broke exactly where it was needed
(#200/#201 on 2026-08-21).

Add {handlerTaskId} to both MergeHelperInitialDefault and
MergeHelperHandoffDefault, thread a handlerTaskId parameter through
BuildForMergeHelperAsync (interface, WorkerHub.GetMergeHelperLaunchSpec,
IWorkerClient/WorkerClient, and the MissionControlViewModel call site,
which already had the id from CreateMergeHelperTaskAsync but never
passed it on), and render it in BuildForMergeHelperHandoffAsync from the
taskId parameter it already receives.

RenderTemplate leaves unknown/missing tokens untouched, so a
user-edited override without the new token still renders fine -- no
forced migration for override users.
This commit is contained in:
mika kuns
2026-08-21 18:00:16 +02:00
parent 93be76a144
commit 9c4a63d2c5
12 changed files with 93 additions and 24 deletions
@@ -241,7 +241,7 @@ public sealed class InteractiveLaunchSpecService : IInteractiveLaunchSpecService
private const string MergeHelperAllowedTools =
"mcp__claudedo__*,Read,Grep,Glob,Edit,Bash,WebFetch,WebSearch,Skill,Task";
public async Task<LaunchSpec> BuildForMergeHelperAsync(IReadOnlyList<string> taskIds, string listId, CancellationToken ct)
public async Task<LaunchSpec> BuildForMergeHelperAsync(IReadOnlyList<string> taskIds, string listId, string handlerTaskId, CancellationToken ct)
{
if (taskIds.Count == 0)
throw new InvalidOperationException("No tasks selected for the list handler.");
@@ -278,6 +278,7 @@ public sealed class InteractiveLaunchSpecService : IInteractiveLaunchSpecService
{
["scope"] = $"List: {list.Name}",
["repo"] = repoDir,
["handlerTaskId"] = handlerTaskId,
["tasks"] = string.Join("\n", briefLines),
}), ct);
@@ -371,6 +372,7 @@ public sealed class InteractiveLaunchSpecService : IInteractiveLaunchSpecService
{
["scope"] = $"List: {list.Name}",
["repo"] = repoDir,
["handlerTaskId"] = taskId,
["tasks"] = string.Join("\n", briefLines),
["finalNote"] = finalNote,
}), ct);
@@ -34,9 +34,11 @@ public interface IInteractiveLaunchSpecService
/// given tasks to a merged/Done state via the mcp__claudedo__* tools. Writes a per-session
/// system prompt + task brief under ~/.todo-app/merge-helper-sessions/&lt;guid&gt; and exposes
/// that dir plus the list's repo dir via --add-dir. cwd is the list's working directory.
/// handlerTaskId (the id returned by CreateMergeHelperTaskAsync) is rendered into the brief so
/// the session can call handoff_list_handler/submit_task_for_review on its own handler task.
/// Throws KeyNotFoundException if the list doesn't exist; InvalidOperationException if
/// taskIds is empty or the list has no existing working directory.</summary>
Task<LaunchSpec> BuildForMergeHelperAsync(IReadOnlyList<string> taskIds, string listId, CancellationToken ct);
Task<LaunchSpec> BuildForMergeHelperAsync(IReadOnlyList<string> taskIds, string listId, string handlerTaskId, CancellationToken ct);
/// <summary>Creates the ClaudeDo task that hosts a list-handler run (Mission Control's
/// "Let Claude handle it") and stamps the list repo's current HEAD as the review range's