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,6 +41,9 @@ public sealed class TaskStateService : ITaskStateService
|
||||
if (await IsDraftChildAsync(ctx, taskId, ct))
|
||||
return new TransitionResult(false, "Draft subtask: finalize the plan before queuing it.");
|
||||
|
||||
if (await IsManualAsync(ctx, taskId, ct))
|
||||
return new TransitionResult(false, "Manual task: mark it as a Claude task before queuing it.");
|
||||
|
||||
var affected = await ctx.Tasks
|
||||
.Where(t => t.Id == taskId && t.Status != TaskStatus.Running)
|
||||
.ExecuteUpdateAsync(s => s.SetProperty(t => t.Status, TaskStatus.Queued), ct);
|
||||
@@ -60,6 +63,9 @@ public sealed class TaskStateService : ITaskStateService
|
||||
if (await IsDraftChildAsync(ctx, taskId, ct))
|
||||
return new TransitionResult(false, "Draft subtask: finalize the plan before running it.");
|
||||
|
||||
if (await IsManualAsync(ctx, taskId, ct))
|
||||
return new TransitionResult(false, "Manual task: mark it as a Claude task before running it.");
|
||||
|
||||
var affected = await ctx.Tasks
|
||||
.Where(t => t.Id == taskId && t.Status != TaskStatus.Running)
|
||||
.ExecuteUpdateAsync(s => s
|
||||
@@ -418,6 +424,11 @@ public sealed class TaskStateService : ITaskStateService
|
||||
// A subtask is "draft" only while its planning parent has an open (Active) session.
|
||||
// Improvement children whose parent has PlanningPhase.None are not drafts and may be
|
||||
// queued freely. Standalone tasks (no parent) are never draft.
|
||||
// Server-side backstop for the manual flag: the UI hides the hand-off affordances, but the
|
||||
// MCP surface and hub can still be driven directly.
|
||||
private static Task<bool> IsManualAsync(ClaudeDoDbContext ctx, string taskId, CancellationToken ct)
|
||||
=> ctx.Tasks.AsNoTracking().AnyAsync(t => t.Id == taskId && t.IsManual, ct);
|
||||
|
||||
private static async Task<bool> IsDraftChildAsync(ClaudeDoDbContext ctx, string taskId, CancellationToken ct)
|
||||
{
|
||||
var parentId = await ctx.Tasks.AsNoTracking()
|
||||
|
||||
Reference in New Issue
Block a user