feat(list-handler): hand off to a fresh session after Phase 2
The merge-helper ("Let Claude handle it") system prompt now calls a new
handoff_list_handler MCP tool once every surviving task is enhanced,
instead of continuing into Phases 3-5 in the same session -- avoiding
paying for Phases 0-2's dedupe/rewrite context on every polling round of
the run/review/merge phases.
The tool broadcasts HandoffRequested; Mission Control opens a second
ConPTY tile for the SAME handler task id (no new task, HandlerBaseCommit
untouched) running a fresh handoff brief that starts at Phase 3. The
original tile stays open. Adds PromptKind.MergeHelperHandoff,
InteractiveLaunchSpecService.BuildForMergeHelperHandoffAsync, and the
GetMergeHelperHandoffLaunchSpec hub method.
This commit is contained in:
@@ -26,6 +26,7 @@ public sealed class MergeHelperTaskHubTests : IDisposable
|
||||
private readonly TaskRepository _tasks;
|
||||
private readonly ListRepository _lists;
|
||||
private readonly List<GitRepoFixture> _repos = new();
|
||||
private readonly List<string> _mergeHelperSessionDirs = new();
|
||||
private readonly RecordingClientProxy _proxy = new();
|
||||
|
||||
private static bool GitAvailable => GitRepoFixture.IsGitAvailable();
|
||||
@@ -42,6 +43,8 @@ public sealed class MergeHelperTaskHubTests : IDisposable
|
||||
foreach (var r in _repos) r.Dispose();
|
||||
_ctx.Dispose();
|
||||
_db.Dispose();
|
||||
foreach (var d in _mergeHelperSessionDirs)
|
||||
try { Directory.Delete(d, true); } catch { /* best effort */ }
|
||||
}
|
||||
|
||||
private sealed class FakeSessionSkillRegistry : ISessionSkillRegistry
|
||||
@@ -136,6 +139,37 @@ public sealed class MergeHelperTaskHubTests : IDisposable
|
||||
() => hub.CreateMergeHelperTask(new[] { "t1" }, "no-such-list", "title", "header"));
|
||||
}
|
||||
|
||||
// ── GetMergeHelperHandoffLaunchSpec ──
|
||||
|
||||
[Fact]
|
||||
public async Task GetMergeHelperHandoffLaunchSpec_ReusesHandlerTaskId_NoNewTaskCreated()
|
||||
{
|
||||
var listId = await SeedListAsync(Path.GetTempPath(), name: "Alpha");
|
||||
var handlerTask = await SeedTaskAsync(listId, TaskStatus.Idle, title: "List handler: Alpha");
|
||||
var survivor = await SeedTaskAsync(listId, TaskStatus.WaitingForReview, title: "Survivor task");
|
||||
|
||||
var hub = CreateHub();
|
||||
var spec = await hub.GetMergeHelperHandoffLaunchSpec(handlerTask.Id, new[] { survivor.Id });
|
||||
|
||||
var args = spec.Args.ToList();
|
||||
var sessionDir = args[args.IndexOf("--add-dir") + 1];
|
||||
_mergeHelperSessionDirs.Add(sessionDir);
|
||||
|
||||
Assert.Contains("--allowedTools", args);
|
||||
Assert.Contains("mcp__claudedo__*,Read,Grep,Glob,Edit,Bash,WebFetch,WebSearch,Skill", args);
|
||||
|
||||
var kickoff = args[^1];
|
||||
Assert.Contains(Path.Combine(sessionDir, "handoff.md"), kickoff);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetMergeHelperHandoffLaunchSpec_UnknownHandlerTask_Throws()
|
||||
{
|
||||
var hub = CreateHub();
|
||||
await Assert.ThrowsAsync<HubException>(
|
||||
() => hub.GetMergeHelperHandoffLaunchSpec("no-such-task", new[] { "x" }));
|
||||
}
|
||||
|
||||
// ── SubmitTaskForReview (worktree-less branch) ──
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user