feat(claude-do): Expose HandoffRoundTracker budget via an MCP tool (e.g. get_
The handoff-budget task (round/remaining/final now surfaced in the handoff.md brief via HandoffRoundTracker.GetStatus, wired through InteractiveLaunchSpecService.BuildForMergeHelperHandoffAsync) only reaches the session at the start of a handoff round. There is no way to query the current round/remaining budget for a handler task mid-session or from outside (e.g. the UI, or a script). Consider add ClaudeDo-Task: 0a185f8e-823d-42fc-9a5b-97c5eb91c616
This commit is contained in:
@@ -220,4 +220,64 @@ public sealed class HandoffMcpToolsTests : IDisposable
|
||||
Assert.False(resultB.Coerced);
|
||||
Assert.Equal("wait", resultB.NextPhase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetHandoffStatus_NeverHandedOff_ReportsZeroRoundFullBudget()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var handlerTask = await SeedTaskAsync(listId);
|
||||
|
||||
var sut = BuildSut();
|
||||
var status = await sut.GetHandoffStatus(handlerTask.Id, CancellationToken.None);
|
||||
|
||||
Assert.Equal(handlerTask.Id, status.TaskId);
|
||||
Assert.Equal(handlerTask.Number, status.Number);
|
||||
Assert.Equal(0, status.Round);
|
||||
Assert.Equal(HandoffRoundTracker.MaxHandoffs, status.Remaining);
|
||||
Assert.False(status.Final);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetHandoffStatus_AfterHandoffs_ReflectsTrackerState()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var handlerTask = await SeedTaskAsync(listId);
|
||||
var survivor = await SeedTaskAsync(listId, TaskStatus.WaitingForReview, title: "Survivor");
|
||||
var tracker = new HandoffRoundTracker();
|
||||
var survivors = new[] { survivor.Id };
|
||||
|
||||
await BuildSut(tracker).HandoffListHandler(handlerTask.Id, survivors, "wait", CancellationToken.None);
|
||||
await BuildSut(tracker).HandoffListHandler(handlerTask.Id, survivors, "merge", CancellationToken.None);
|
||||
|
||||
var status = await BuildSut(tracker).GetHandoffStatus(handlerTask.Id, CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, status.Round);
|
||||
Assert.Equal(HandoffRoundTracker.MaxHandoffs - 2, status.Remaining);
|
||||
Assert.False(status.Final);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetHandoffStatus_AfterMergeFinal_ReportsFinal()
|
||||
{
|
||||
var listId = await SeedListAsync();
|
||||
var handlerTask = await SeedTaskAsync(listId);
|
||||
var survivor = await SeedTaskAsync(listId, TaskStatus.WaitingForReview, title: "Survivor");
|
||||
var tracker = new HandoffRoundTracker();
|
||||
var survivors = new[] { survivor.Id };
|
||||
|
||||
await BuildSut(tracker).HandoffListHandler(handlerTask.Id, survivors, "merge_final", CancellationToken.None);
|
||||
|
||||
var status = await BuildSut(tracker).GetHandoffStatus(handlerTask.Id, CancellationToken.None);
|
||||
|
||||
Assert.True(status.Final);
|
||||
Assert.Equal(1, status.Round);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetHandoffStatus_UnknownTask_Throws()
|
||||
{
|
||||
var sut = BuildSut();
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() =>
|
||||
sut.GetHandoffStatus("missing", CancellationToken.None));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user