Coordinates Waiting -> Queued transitions between sibling subtasks: when a child finishes Done, the next Waiting sibling is promoted to Queued. WorkerHub.QueuePlanningSubtasksAsync exposes this to the UI; TaskRunner advances the chain on completion. Also tightens the planning-session prompt: planner must use MCP tools, not direct edits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire TasksIslandViewModel to TaskUpdated/WorktreeUpdated/TaskMessage worker
events so rows refresh without a full reload; add ForegroundHelper to permit
wt.exe to take foreground on planning launch; misc UI polish on lists, task
rows and settings modal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add PlanningMcpContextAccessor (Option A) to read PlanningMcpContext
from HttpContext.Items set by PlanningTokenAuthMiddleware
- Annotate PlanningMcpService with [McpServerToolType]/[McpServerTool]
and remove PlanningMcpContext ctx parameter from all tool methods
- Broadcast TaskUpdated(parentTaskId) via HubBroadcaster after every
mutation in PlanningMcpService
- Refactor PlanningSessionManager to accept IDbContextFactory for
singleton-safe use in DI; keep direct-repo ctor for tests
- Register PlanningSessionManager (singleton), IPlanningTerminalLauncher,
PlanningMcpContextAccessor, PlanningMcpService, and MCP server in
Program.cs; wire PlanningTokenAuthMiddleware and MapMcp("/mcp")
- Update PlanningMcpServiceTests with fake HttpContext accessor and
no-op HubBroadcaster (avoids Moq dependency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire TaskResetService into DI and add WorkerHub.ResetTask with the
same InvalidOperationException/KeyNotFoundException error-translation
pattern as ContinueTask.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix sort order regression in GetByListIdAsync (was descending, should be ascending)
- Restore WAL mode pragma (was silently dropped in EF migration)
- Add existing-DB compatibility shim in MigrateAndConfigure (baselines InitialCreate
migration for databases created by the old schema.sql)
- Remove dead AddDbContext/AddScoped registrations from Worker (only IDbContextFactory
is used by singleton consumers)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Worker and App Program.cs: replace SqliteConnectionFactory+SchemaInitializer
with AddDbContextFactory<ClaudeDoDbContext> + Database.Migrate(). Repos
changed from AddSingleton to AddScoped.
All singleton services (QueueService, StaleTaskRecovery, WorktreeManager,
TaskRunner) and singleton ViewModels (MainWindowViewModel, TaskDetailViewModel,
TaskListViewModel, TaskEditorViewModel) now take IDbContextFactory<ClaudeDoDbContext>
and create short-lived contexts per operation.
Test infrastructure: DbFixture now uses EF migrations instead of SchemaInitializer;
all test classes create contexts via DbFixture.CreateContext().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Worker:
- Wire UseWindowsService + Microsoft.Extensions.Hosting.WindowsServices so
SCM's Service Control Protocol handshake succeeds. Previously the binary
exited immediately under sc start, leaving the service registered but
never running.
Installer:
- Pin SDK to .NET 9 (global.json) — SDK 10 dropped win-arm from its RID
graph, breaking restore of the WPF project; .NET 9 keeps win-arm AND
understands the .slnx solution format.
- Force SelfContained=true and default RID=win-x64 when PublishSingleFile
is set, so Rider Publish and CLI produce the same bundle.
- Dark theme: set Background/Foreground explicitly on WizardWindow and
SettingsWindow roots (WPF implicit styles don't cascade to derived
Window types). Custom ComboBox template + ComboBoxItem style so
dropdowns honour the dark palette instead of system defaults.
- Throttle download progress to one report per MB and overwrite the same
UI line (\r prefix marker) instead of appending per chunk.
- Register ClaudeDo in HKLM\...\Uninstall so it appears in Apps & Features.
Copy installer into InstallDir\uninstaller\ for the UninstallString, and
schedule a cmd.exe trampoline to handle the self-delete case when
Apps & Features launches the copy from inside the install dir.
- Treat sc.exe stop exit 1062 (ERROR_SERVICE_NOT_ACTIVE) as success.
- Delete the uninstall registry key during UninstallRunner.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per-task checklist backend: subtasks table with CASCADE delete,
SubtaskEntity + SubtaskRepository (connection-per-op, async), DI
registration in App and Worker, TaskRunner composes a '## Sub-Tasks'
markdown block into the Claude prompt when subtasks exist.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GitService (in ClaudeDo.Data so the UI can reuse it) wraps the git CLI:
IsGitRepo, RevParseHead, WorktreeAdd/Remove, HasChanges, AddAll, Commit
(multi-line via -F -), DiffStat, BranchDelete, MergeFfOnly. Throws with
stderr on failure.
WorktreeManager owns the per-task lifecycle: validate working_dir is a
git repo (throws if not, no DB row written), create the worktree at
<repo>/../.claudedo-worktrees/<slug>/<id>/ (or central root per config),
insert the worktrees row. CommitIfChangedAsync skips when there are no
changes, otherwise commits and updates head_commit + diff_stat.
CommitMessageBuilder produces "{type}({list-slug}): {title<=60}" with a
blank-line-separated description (truncated to 400) and a permanent
"ClaudeDo-Task: <id>" trailer. Slug normalises whitespace + strips
non-alphanumerics. Newlines hard-coded to \n so git on Windows doesn't
choke on \r\n.
TaskRunner branches on list.WorkingDir: worktree path runs Claude in the
worktree, commits on success, broadcasts WorktreeUpdated; failure leaves
the worktree row active for inspection. Sandbox path unchanged.
Tests: 38 pass (12 new). GitRepoFixture spins up a real temp repo with a
seed commit; tests skip gracefully if `git` isn't on PATH.
CommitMessageBuilder fully unit-tested. WorktreeManager covers create,
no-change skip, real-commit, and non-repo failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runner stack (non-worktree path): IClaudeProcess + ClaudeProcess spawning the
CLI with --output-format stream-json, prompt via stdin, parses the final
type:"result" line into RunResult. LogWriter appends ndjson to
~/.todo-app/logs/<taskId>.ndjson. TaskRunner orchestrates DB transitions
(MarkRunning -> MarkDone/Failed) and pushes TaskStarted/Message/Finished/
Updated via HubBroadcaster. Worktree-backed lists short-circuit with a
"Slice E" failure message until git support lands.
QueueService (BackgroundService) holds two in-memory slots (_queueSlot +
_overrideSlot) guarded by a lock. Uses PeriodicTimer + SemaphoreSlim wake
signal so WakeQueue() triggers an instant pickup. RunNow throws
InvalidOperationException when override busy; CancelTask cancels the linked
CTS which kills the child process tree.
WorkerHub extended with GetActive, RunNow (translated to HubException
variants), CancelTask, WakeQueue. HubBroadcaster exposes typed push methods.
Tests: 26 pass (12 new). QueueServiceTests cover override-busy,
schedule-filter, FIFO sequentiality, cancellation, plus a FakeClaudeProcess
that blocks on a TCS for deterministic slot-state assertions.
MessageParserTests cover result extraction + malformed/non-result lines.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Data: TagRepository, ListRepository, TaskRepository (incl. queue selection via
effective agent tag + scheduled_for filter), WorktreeRepository. All CRUD via
parameterized SqliteCommand; enums roundtrip as lowercase strings matching the
schema CHECK constraints.
Worker: StaleTaskRecovery IHostedService flips running -> failed on startup and
marks the result column with a [stale] reason. All four repositories registered
as singletons.
Tests: DbFixture with temp-file SQLite + schema bootstrap, covering
TaskRepository (queue pick via list-tag and task-tag, schedule filter,
transitions, stale flip), ListRepository CRUD + junctions, and
StaleTaskRecovery. 14 tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Data layer: Paths helper with ~/%USERPROFILE% expansion, SqliteConnectionFactory
(WAL + foreign keys), SchemaInitializer that applies the embedded schema.sql, and
POCO entities for lists/tasks/tags/worktrees.
Worker: WorkerConfig loader (~/.todo-app/worker.config.json with defaults),
WorkerHub exposing Ping(), and Program.cs wiring Kestrel to 127.0.0.1:<port>,
SignalR at /hub, schema applied on startup.
Pins Microsoft.Data.Sqlite and Microsoft.Extensions.Hosting to 8.x for net8.0
compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create .slnx with five projects, wire references (App->Ui->Data,
Worker->Data, Tests->Worker+Data), install Avalonia/MVVM/SignalR.Client/
Sqlite/Hosting packages, and add schema.sql per docs/plan.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>