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:
Mika Kuns
2026-07-27 15:02:51 +02:00
parent fde9615b34
commit 3a648b7d77
19 changed files with 168 additions and 11 deletions
@@ -47,7 +47,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
if (row is null || Dialogs is null || _services is null) return;
var rawId = row.Id.StartsWith("user:", StringComparison.Ordinal) ? row.Id["user:".Length..] : row.Id;
var vm = _services.GetRequiredService<ListSettingsModalViewModel>();
await vm.LoadAsync(rawId, row.Name, row.WorkingDir, row.DefaultCommitType);
await vm.LoadAsync(rawId, row.Name, row.WorkingDir, row.DefaultCommitType, row.IsManual);
await Dialogs.ShowListSettingsAsync(vm);
if (vm.Deleted) await LoadAsync();
else await RefreshRowAsync(row.Id);
@@ -243,6 +243,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
DotColorKey = dotColors[idx % dotColors.Length],
WorkingDir = l.WorkingDir,
DefaultCommitType = l.DefaultCommitType,
IsManual = l.IsManual,
};
Items.Add(item);
UserLists.Add(item);
@@ -317,7 +318,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
if (Dialogs is not null && _services is not null)
{
var vm = _services.GetRequiredService<ListSettingsModalViewModel>();
await vm.LoadAsync(entity.Id, entity.Name, entity.WorkingDir, entity.DefaultCommitType);
await vm.LoadAsync(entity.Id, entity.Name, entity.WorkingDir, entity.DefaultCommitType, entity.IsManual);
await Dialogs.ShowListSettingsAsync(vm);
if (vm.Deleted) await LoadAsync();
else await RefreshRowAsync(item.Id);
@@ -397,6 +398,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
row.Name = entity.Name;
row.WorkingDir = entity.WorkingDir;
row.DefaultCommitType = entity.DefaultCommitType;
row.IsManual = entity.IsManual;
}
catch { /* best-effort refresh */ }
}