fix: resolve critical bugs and improve reliability across worker, data, UI

- Fix worker using wrong DB by defaulting to CurrentUser service account
  and expanding ~ to absolute paths at install time
- Fix DbContext disposed before fire-and-forget by passing taskId instead
  of TaskEntity into RunInSlotAsync, which creates its own context
- Fix ActiveTaskDto property casing mismatch between hub and client
- Move WAL mode PRAGMA before migrations to prevent concurrent lock issues
- Replace FirstAsync with FirstOrDefaultAsync + null guards in tag operations
- Add delete confirmation flow for lists
- Log fire-and-forget exceptions instead of swallowing them
- Broadcast RunCreated event from WorkerHub.RunNow
- Add IDisposable to MainWindowViewModel for event handler cleanup
- Preserve subtask CreatedAt on updates instead of overwriting
- Replace bare catch blocks with Debug.WriteLine logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-16 13:12:59 +02:00
parent fca2bdb596
commit 3423919655
11 changed files with 154 additions and 61 deletions

View File

@@ -5,6 +5,8 @@ using Microsoft.AspNetCore.SignalR;
namespace ClaudeDo.Worker.Hub;
public record ActiveTaskDto(string Slot, string TaskId, DateTime StartedAt);
public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
{
private static readonly string Version =
@@ -12,19 +14,21 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
private readonly QueueService _queue;
private readonly AgentFileService _agentService;
private readonly HubBroadcaster _broadcaster;
public WorkerHub(QueueService queue, AgentFileService agentService)
public WorkerHub(QueueService queue, AgentFileService agentService, HubBroadcaster broadcaster)
{
_queue = queue;
_agentService = agentService;
_broadcaster = broadcaster;
}
public string Ping() => $"pong v{Version}";
public IReadOnlyList<object> GetActive()
public IReadOnlyList<ActiveTaskDto> GetActive()
{
return _queue.GetActive()
.Select(a => (object)new { slot = a.slot, taskId = a.taskId, startedAt = a.startedAt })
.Select(a => new ActiveTaskDto(a.slot, a.taskId, a.startedAt))
.ToList();
}
@@ -33,6 +37,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
try
{
await _queue.RunNow(taskId);
await _broadcaster.RunCreated(taskId, 1, false);
}
catch (InvalidOperationException)
{