feat(tasks): mark tasks and lists as manual
Reminders written down as todos had no home: every task looked like Claude work. A manual task now shows a MANUAL badge and hides send-to-queue, refine and the planning session; the queue picker, daily prep and the list handler all skip it, with a TaskStateService guard so the MCP surface and hub cannot start one either. Opening a hand-driven ConPTY session stays available on purpose. A list can be marked manual in its settings, which makes tasks created there (UI and MCP add_task) start out manual. Toggle per task from its context menu.
This commit is contained in:
@@ -41,7 +41,8 @@ public sealed class TaskStateServiceTests : IDisposable
|
||||
string? parentId = null,
|
||||
int sortOrder = 0,
|
||||
string? blockedBy = null,
|
||||
PlanningPhase phase = PlanningPhase.None)
|
||||
PlanningPhase phase = PlanningPhase.None,
|
||||
bool isManual = false)
|
||||
{
|
||||
var id = Guid.NewGuid().ToString();
|
||||
await using var ctx = _factory.CreateDbContext();
|
||||
@@ -56,6 +57,7 @@ public sealed class TaskStateServiceTests : IDisposable
|
||||
ParentTaskId = parentId,
|
||||
SortOrder = sortOrder,
|
||||
BlockedByTaskId = blockedBy,
|
||||
IsManual = isManual,
|
||||
});
|
||||
await ctx.SaveChangesAsync();
|
||||
return id;
|
||||
@@ -89,6 +91,30 @@ public sealed class TaskStateServiceTests : IDisposable
|
||||
Assert.Contains(_built.Hub.Proxy.Calls, c => c.Method == "TaskUpdated");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnqueueAsync_ManualTask_Rejected_AndStaysIdle()
|
||||
{
|
||||
var id = await SeedTaskAsync(TaskStatus.Idle, isManual: true);
|
||||
|
||||
var result = await _sut.EnqueueAsync(id, default);
|
||||
|
||||
Assert.False(result.Ok);
|
||||
Assert.Contains("Manual task", result.Reason);
|
||||
Assert.Equal(TaskStatus.Idle, await GetStatusAsync(id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartRunningAsync_ManualTask_Rejected_AndStaysIdle()
|
||||
{
|
||||
var id = await SeedTaskAsync(TaskStatus.Idle, isManual: true);
|
||||
|
||||
var result = await _sut.StartRunningAsync(id, DateTime.UtcNow, default);
|
||||
|
||||
Assert.False(result.Ok);
|
||||
Assert.Contains("Manual task", result.Reason);
|
||||
Assert.Equal(TaskStatus.Idle, await GetStatusAsync(id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnqueueAsync_FromRunning_Rejects_AndDoesNotMutate()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user