From 49046310ef8d5a5ad647970340e8584ce779699f Mon Sep 17 00:00:00 2001 From: mika kuns Date: Tue, 9 Jun 2026 22:00:55 +0200 Subject: [PATCH] docs: refresh CLAUDE.md files and open.md to current code state - Ui CLAUDE.md rewritten around the islands architecture (old MainWindow/TaskList/StatusBar VMs no longer exist) - Worker: folder layout (Refine/, Lifecycle/Planning extras), full hub method/event surface, external MCP tool inventory - Data: complete GitService operation list incl. commit-range diffs - App: missing DI registrations; Tests: current test-area overview - root: project list (Localization, Installer, six test projects) and honest docs index; plan.md/improvement-plan.md marked historical - open.md: date bump + visual check for new diff viewer / attention band Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 14 ++++-- docs/improvement-plan.md | 2 + docs/open.md | 3 +- docs/plan.md | 2 + src/ClaudeDo.App/CLAUDE.md | 4 +- src/ClaudeDo.Data/CLAUDE.md | 2 +- src/ClaudeDo.Ui/CLAUDE.md | 71 ++++++++++++++------------- src/ClaudeDo.Worker/CLAUDE.md | 30 +++++++---- tests/ClaudeDo.Worker.Tests/CLAUDE.md | 22 +++++---- 9 files changed, 89 insertions(+), 61 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3feed2d..c257ef1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,11 @@ Two-process system communicating over SignalR (`127.0.0.1:47821`): - **ClaudeDo.Ui** — Views, ViewModels, SignalR client (MVVM with CommunityToolkit.Mvvm) - **ClaudeDo.Data** — SQLite data layer, repositories, models, GitService - **ClaudeDo.Worker** — ASP.NET Core hosted service, task queue, Claude CLI runner -- **ClaudeDo.Worker.Tests** — xUnit integration tests with real SQLite and real git +- **ClaudeDo.Localization** — `locales/en.json` + `locales/de.json` and the lookup service +- **ClaudeDo.Installer** — WPF (`UseWPF`) setup app; install/update/uninstall step pipeline +- **tests/** — six xUnit projects (Worker, Data, Ui, Localization, Installer, Releases); Worker.Tests run real SQLite and real git + +Each project has its own `CLAUDE.md` — those are the living per-project docs. ## Tech Stack @@ -75,6 +79,8 @@ dotnet test tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj -c Release ## Docs -- `docs/plan.md` — full architecture and design spec -- `docs/open.md` — verification checklist and improvement backlog -- `docs/improvement-plan.md` — prioritized improvement items +- `docs/open.md` — open verification items and remaining code TODOs (the only doc kept current besides the CLAUDE.md files) +- `docs/plan.md` — original design spec (historical; tag-queue/schema.sql parts are outdated) +- `docs/improvement-plan.md` — improvement snapshot from 2026-04-13 (historical) +- `docs/prompts-inventory.md`, `docs/mailbox-proposal.md` — reference material (mailbox integration is parked) +- `CHANGELOG.md` — Keep a Changelog format, maintained on release diff --git a/docs/improvement-plan.md b/docs/improvement-plan.md index 261e8f3..ca04e52 100644 --- a/docs/improvement-plan.md +++ b/docs/improvement-plan.md @@ -1,5 +1,7 @@ # ClaudeDo — Improvement Plan (Session 2026-04-13) +> **Hinweis (2026-06-09):** Historischer Snapshot — bewusst nicht nachgepflegt. U.a. erledigt/überholt: IP-1 (Auto-Reconnect ist implementiert), `schema.sql` → EF-Core-Migrations, `StatusBarViewModel` existiert nicht mehr (Connection-State lebt in `IslandsShellViewModel`), Tags sind Junction-Tabellen statt JSON-Spalten. Offene Punkte stehen in `open.md`. + Erfasst während manuellem Walkthrough der App. Priorisiert nach Schmerz/Aufwand. --- diff --git a/docs/open.md b/docs/open.md index 630f7c0..84641e2 100644 --- a/docs/open.md +++ b/docs/open.md @@ -1,6 +1,6 @@ # ClaudeDo — Offene Punkte -Stand: 2026-06-04. **Nur noch offene Punkte.** Was erledigt ist, steht in den Commits und im Code — nicht hier. +Stand: 2026-06-09. **Nur noch offene Punkte.** Was erledigt ist, steht in den Commits und im Code — nicht hier. --- @@ -13,6 +13,7 @@ Kein Code-Aufwand, nur Durchspielen mit explizit notiertem Pass-Kriterium. Der G - No-Changes-Run → `status='Done'`, `head_commit IS NULL`, `diff_stat IS NULL`. - Kein Git-Repo (`working_dir=C:\Temp`) → `status='Failed'`, **keine** `worktrees`-Row, Git-Fehler im Log. - **Feature-Walkthroughs:** Planning-Session-Flow (Draft→Finalize→Chain), Prime/Daily-Prep-Trigger, Weekly-Report-Generierung, Self-Update (Banner → Update → „up to date"). +- **UI-Sichtprüfung (neu, 2026-06-09):** Diff-Viewer (Dateiliste, Added/Deleted/Renamed/Binary-Erkennung, Commit-Range-Diff nach Merge) und das „children need attention"-Band auf dem Session-Tab des Parents. - **Worker-Autostart am Gerät:** Logoff/Logon-Autostart, Update-Pfad, Uninstall entfernt die Startup-`.lnk`. ## Offene Code-Punkte diff --git a/docs/plan.md b/docs/plan.md index fb912ce..78dc894 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -1,5 +1,7 @@ # ToDo-App mit autonomem Agent-Worker — Design +> **Hinweis (2026-06-09):** Historisches Design-Dokument vom Projektstart — bewusst nicht nachgepflegt. Überholt sind insbesondere: die Tag-basierte Queue (entfernt; der Picker nutzt `Status=Queued` + `BlockedByTaskId IS NULL`), `schema.sql` (Schema läuft über EF-Core-Migrations) und das Projektlayout (inzwischen sechs Testprojekte). Lebende Doku sind die `CLAUDE.md`-Dateien pro Projekt. + ## Context Ziel: eine persönliche ToDo-App als Desktop-Anwendung, in der mehrere Listen verwaltet werden können. Ein Teil der Tasks soll autonom von Claude abgearbeitet werden (z.B. Recherche, Code-Aufgaben, Notizen-Verarbeitung). Die Autonomie läuft in einem getrennten Hintergrund-Prozess, damit die UI davon entkoppelt bleibt. diff --git a/src/ClaudeDo.App/CLAUDE.md b/src/ClaudeDo.App/CLAUDE.md index 07c1c7c..b18566a 100644 --- a/src/ClaudeDo.App/CLAUDE.md +++ b/src/ClaudeDo.App/CLAUDE.md @@ -19,8 +19,8 @@ Desktop entry point for the ClaudeDo application. Configures DI, initializes the ## DI Registration Pattern -- **Singletons**: `IDbContextFactory`, all Repositories, GitService, WorkerClient, `IReleaseClient`, `InstallerLocator` / `WorkerLocator`, the island VMs (`ListsIslandViewModel`, `TasksIslandViewModel`, `DetailsIslandViewModel`) and `IslandsShellViewModel` (the window's DataContext) -- **Transients**: modal VMs (`SettingsModalViewModel`, `MergeModalViewModel`, `ListSettingsModalViewModel`, `RepoImportModalViewModel`, `WorktreeModalViewModel`, `WorktreesOverviewModalViewModel`, `PrimeClaudeTabViewModel`), several exposed as `Func` factories for on-demand dialog creation +- **Singletons**: `IDbContextFactory`, all Repositories, GitService, WorkerClient, `IReleaseClient`, `UpdateCheckService`, `IPrimeScheduleApi`/`WorkerPrimeScheduleApi`, `INotesApi`/`WorkerNotesApi`, `InstallerLocator` / `WorkerLocator`, the island VMs (`ListsIslandViewModel`, `TasksIslandViewModel`, `DetailsIslandViewModel`) and `IslandsShellViewModel` (the window's DataContext) +- **Transients**: modal VMs (`SettingsModalViewModel`, `MergeModalViewModel`, `ListSettingsModalViewModel`, `RepoImportModalViewModel`, `WeeklyReportModalViewModel`, `WorktreeModalViewModel`, `WorktreesOverviewModalViewModel`, `PrimeClaudeTabViewModel`), several exposed as `Func` factories for on-demand dialog creation; `ConflictResolverViewModel` via a `Func` factory keyed by taskId (singleton factory, handed to `IslandsShellViewModel.ConflictResolverFactory`) ## Notes diff --git a/src/ClaudeDo.Data/CLAUDE.md b/src/ClaudeDo.Data/CLAUDE.md index c156295..5809147 100644 --- a/src/ClaudeDo.Data/CLAUDE.md +++ b/src/ClaudeDo.Data/CLAUDE.md @@ -35,7 +35,7 @@ All repositories use EF Core LINQ queries via `ClaudeDoDbContext`. The atomic `Q ## Git -- **GitService** — async wrapper around git CLI (ProcessStartInfo, no shell). Operations: worktree add/remove, add all, commit (stdin for message), merge ff-only, rev-parse, diff-stat, has-changes, is-git-repo, `PreviewMergeAsync` (non-destructive mergeability check via `git merge-tree --write-tree`), `CountChangedFilesAsync` +- **GitService** — async wrapper around git CLI (ProcessStartInfo, no shell). Worktree ops (add — serialized to avoid a commondir race —, remove, prune, list paths for branch), branch ops (current, list local, checkout, delete), staging/commit (status porcelain, add-all, add-path, commit via stdin), diffs (working tree, branch vs base, commit range `base..head` — used to show a merged task's diff after the worktree is gone —, per-file, diff-stat, committed files, has-changes), merge (ff-only, no-ff, abort, mid-merge detection, conflicted files, show-stage for conflict hunks), `PreviewMergeAsync` (non-destructive mergeability check via `git merge-tree --write-tree`), `CountChangedFilesAsync`, rev-parse, is-git-repo ## Schema diff --git a/src/ClaudeDo.Ui/CLAUDE.md b/src/ClaudeDo.Ui/CLAUDE.md index 3d72658..72ec1d1 100644 --- a/src/ClaudeDo.Ui/CLAUDE.md +++ b/src/ClaudeDo.Ui/CLAUDE.md @@ -8,56 +8,61 @@ MVVM with CommunityToolkit.Mvvm source generators: - `[ObservableProperty]` for bindable properties - `[RelayCommand]` for commands (supports async and CanExecute) - All ViewModels inherit `ViewModelBase` (extends `ObservableObject`) +- All views use compiled bindings (`x:DataType`) -## Views +## Layout: Islands -- **MainWindow** — 3-column DockPanel layout (lists | tasks | detail) with GridSplitter, status bar at bottom -- **TaskListView** — ListBox of tasks with add/edit/delete toolbar -- **TaskDetailView** — Task info, live log output, worktree section (merge/keep/discard) -- **TaskEditorView** — Modal dialog for task create/edit -- **ListEditorView** — Modal dialog for list create/edit -- **StatusBarView** — Connection status indicator, active task display -- **ListSettingsModalView** — edits list name, working dir, default commit type, and per-list Model/SystemPrompt/AgentPath/MaxTurns, each showing the inherited (global) value with a source-aware "inherited · Global / override" badge and a reset-to-inherited button; also deletes the list (and its tasks) via a confirmed "Delete list" button. Opened via context menu or gear button on a list row. -- **RepoImportModalView** — bulk-creates lists from git repos discovered under chosen parent folders. Opened via the folder button beside "New list" in the Lists island, or the "Add repos as lists…" Help-menu item. Repos already wired to a list show as disabled/"(already added)". -- **DetailsIslandView** — contains an "Agent settings (overrides)" expander with per-task Model/MaxTurns/AgentPath (override semantics, each showing the resolved inherited value as a placeholder plus a source-aware "inherited · List / inherited · Global / override" badge and reset button via the reusable `InheritedBadge` control + `InheritanceResolver`) and a SystemPrompt text box (additive — shows the inherited prompt as a "prepended automatically" note). Disabled while task is running. When notes mode is active (`IsNotesMode`), it hosts **NotesEditorView** instead of the task detail. When prep mode is active (`IsPrepMode`), it hosts the daily-prep panel (Plan day button, empty-state hint, embedded **SessionTerminalView**). The task header, metadata footer (delete/close), and **AgentStripView** are gated on `IsTaskDetailVisible` — they are hidden in both notes and prep mode. -- **WeeklyReportModalView** — opened from Help menu ("Wochenbericht…"); date-range pickers default to "since last standup weekday → today"; Generate/Regenerate button; renders markdown via MarkdownView; reports are cached per range. -- **NotesEditorView** — day navigator (prev/next/date-picker/Today), bullet add/edit/delete for daily notes. -- **SessionTerminalView** — reusable log terminal; exposes StyledProperties `Entries`, `Label`, `IsRunning`, `IsDone`, `IsFailed`. Used for both the task `Log` and the prep `PrepLog`. -- **SettingsModalView** — Prime Claude tab contains a `DailyPrepMaxTasks` numeric editor. -- **TasksIslandView** (MyDay header) — icon buttons visible only when `IsMyDayList`: broom icon = `ClearDayCommand`, stroked-sun icon ("Plan My Day") = `ShowPrepLogCommand`. +`MainWindow` hosts three "islands" (lists | tasks | details). There is no MainWindowViewModel, StatusBarView, or task/list editor modal — the root coordinator is **IslandsShellViewModel**, and task/list editing happens inline in the islands. -All views use compiled bindings (`x:DataType`). +``` +ViewModels/ + IslandsShellViewModel.cs — root coordinator + Islands/ — ListsIsland, TasksIsland, DetailsIsland, TaskRow, ListNavItem, + NotesEditor, MergePreviewPresenter + Modals/ — About, Diff, ListSettings, Merge, RepoImport, Settings (+ Settings/ tab VMs), + UnfinishedPlanning, WeeklyReport, WorkerConnection, Worktree, + WorktreesOverview, UnifiedDiffParser + Planning/ — PlanningDiffViewModel, ConflictResolutionViewModel + Conflicts/ — ConflictResolverViewModel +Views/ — mirrors the VM layout; Islands/Detail/ holds TaskHeaderBar, + DescriptionStepsCard, WorkConsole; plus AgentStripView, SessionTerminalView +Views/Controls/ — MarkdownView, ModalShell, ThemedDatePicker, DiffLinesView, InheritedBadge +Design/ — Tokens.axaml (design tokens; merged before styles) + IslandStyles.axaml + (component styles + the filled icon geometry library) +``` ## ViewModels -- **MainWindowViewModel** — root coordinator; manages list collection, selected list, dialog creation via `Func` factories -- **TaskListViewModel** — manages task collection for selected list; handles CRUD, "Run Now" -- **TaskDetailViewModel** — displays task details, streams live log, controls worktree operations -- **TaskItemViewModel** / **ListItemViewModel** — lightweight display VMs -- **TaskEditorViewModel** / **ListEditorViewModel** — dialog VMs with validation -- **StatusBarViewModel** — connection state and active tasks -- **WeeklyReportModalViewModel** — drives the weekly report modal -- **NotesEditorViewModel** — manages daily note bullet CRUD for the selected day -- **DetailsIslandViewModel** gains `IsNotesMode`, `ShowNotes()`, and hosts `NotesEditorViewModel`. Also gains daily-prep mode: `IsPrepMode`, `PrepLog` (`ObservableCollection`), `ShowPrep()`, `PlanDayCommand` (calls `RunDailyPrepNowAsync`), `ShowPrepEmptyState`, and computed `IsTaskDetailVisible` (= `!IsNotesMode && !IsPrepMode`). Subscribes to `PrepStartedEvent`, `PrepLineEvent`, `PrepFinishedEvent`; streams lines into `PrepLog` via `StreamLineFormatter` (same path as task logs). On open, if log is empty and no run is in progress, loads persisted last run via `GetLastPrepLogAsync`. The WorkConsole Session tab gains a mergeability indicator (`MergePreviewPresenter`) and a single-task Merge button; indicator is populated via `PreviewMergeAsync` and displayed for tasks in WaitingForReview. -- **TasksIslandViewModel** gains a pinned "Notes" pseudo-row (`ShowNotesRow`, `OpenNotesCommand`, `NotesRequested` event) that switches the Details island to notes mode. Also gains `IsMyDayList` (true when selected list is `smart:my-day`), `ShowPrepLogCommand` (raises `PrepRequested` event → shell calls `Details.ShowPrep()`), and `ClearDayCommand` (calls `ClearMyDayAsync`). +- **IslandsShellViewModel** — root coordinator; owns the three island VMs and the `WorkerClient`, wires cross-island events (selection, notes/prep mode, conflict resolution), owns connection state, the update banner, the inline worker-log strip, responsive-layout flags (`ShowLists`/`ShowDetails` by window width), `PrimeStatus` flash, and the modal openers (About, RepoImport, WeeklyReport, WorktreesOverview, WorkerConnection help) plus `RestartWorkerAsync`/`CheckForUpdatesAsync`. Hosts `UpdateCheckService`. +- **ListsIslandViewModel** — smart lists (My Day, Important, Planned, virtual queued/running/review), user lists, selection, list CRUD, drag-reorder, badge counts, opens list settings / repo import / worktrees overview, `OpenInExplorer`/`OpenInTerminal`. +- **TasksIslandViewModel** — open/overdue/completed groups for the selected list with hierarchy-aware regrouping; task CRUD, drag-reorder, toggle done/star, schedule, enqueue/dequeue, cancel; review actions (approve, reject-rerun, reject-park, cancel); planning session lifecycle (open/resume/discard/finalize, `QueuePlanningSubtasksAsync`); `RunInteractivelyAsync`, `RefineTask`; MyDay extras (`IsMyDayList`, `ClearDayCommand`, `ShowPrepLogCommand`) and the pinned Notes pseudo-row (`ShowNotesRow`, `OpenNotesCommand`). Raises `NotesRequested`/`PrepRequested` events consumed by the shell. +- **DetailsIslandViewModel** — the detail pane for a bound `TaskRowViewModel`. Live-log streaming (`Log` via `StreamLineFormatter`), debounced title/description editing, subtasks, merge-target selection + mergeability indicator (`MergePreviewPresenter` over `PreviewMergeAsync`, shown in WaitingForReview), session-outcome/roadblock split (splits `Result` at the roadblock marker into two cards), per-task agent-settings overrides (Model/MaxTurns/AgentPath with `InheritedBadge` + `InheritanceResolver`; SystemPrompt is additive), and a three-tab work console (`output`/`git`/`session`). Child surfacing: `ChildOutcomes` rows for any parent plus `ChildrenNeedingAttention`/`HasChildrenNeedingAttention` (children that failed, were cancelled, await review, or reported roadblocks) drive an attention band on the Session tab, which is only visible when `HasChildOutcomes`. `OpenDiffAsync` opens the diff modal from the live worktree or — after merge — by commit range; `ReviewCombinedDiffCommand` opens `PlanningDiffViewModel`. Modes: `IsNotesMode` (hosts `NotesEditorViewModel`), `IsPrepMode` (daily-prep panel: `PrepLog`, `PlanDayCommand` → `RunDailyPrepNowAsync`, persisted last run via `GetLastPrepLogAsync`), computed `IsTaskDetailVisible = !IsNotesMode && !IsPrepMode`. Helper rows (`ChildOutcomeRowViewModel`, `SubtaskRowViewModel`, `LogLineViewModel`) live in the same file. +- **TaskRowViewModel** / **ListNavItemViewModel** — lightweight display VMs (task row: status, planning phase, parent/blocked links, roadblock count, computed `IsDraft`/`IsPlanned`/`IsChild`/`IsPlanningParent`/`CanRefine`; list row: kind Smart/Virtual/User, count, icon/dot keys, drop hints). +- **NotesEditorViewModel** — day navigator + bullet CRUD for daily notes via `INotesApi`. +- **Modal VMs** — `SettingsModalViewModel` (four tabs: General, Worktrees, Files prompt-paths, Prime Claude incl. `DailyPrepMaxTasks` + prime-schedule rows), `ListSettingsModalViewModel` (name, working dir, commit type, per-list Model/SystemPrompt/AgentPath/MaxTurns with inherited-badge + reset, delete list), `RepoImportModalViewModel` (bulk-create lists from git repos found under chosen parents; already-wired repos disabled), `WeeklyReportModalViewModel` (range pickers default "since last standup weekday → today", cached per range, markdown via MarkdownView), `MergeModalViewModel` (single-task merge form, called from the diff modal), `WorktreesOverviewModalViewModel` (global/per-list worktree rows, batch merge + state ops), `UnfinishedPlanningModalViewModel` (Resume/FinalizeNow/Discard for a draft planning session), `WorkerConnectionModalViewModel` (offline help), `AboutModalViewModel`. +- **Diff stack** — `UnifiedDiffParser` (static; parses `git diff` output into `DiffFileViewModel`s, detecting added/deleted/renamed/binary files and per-line numbers; `Flatten` injects file-header rows for a combined single-pane view). `DiffModalViewModel` has two modes: live worktree (branch diff vs base, with a Merge action) and commit-range `base..head` (`FromCommitRange = true` — shows a merged task's diff after its worktree is gone; no merge action). The view renders a file list with binary/empty placeholders via `DiffLinesView`. +- **Planning/Conflicts** — `PlanningDiffViewModel` (per-subtask diffs via `GetPlanningAggregateAsync`, toggle to combined integration-branch diff, conflict warnings), `ConflictResolutionViewModel` (unit-merge conflict dialog: conflicted files, open in VS Code, continue/abort planning merge), `ConflictResolverViewModel` (in-app hunk-by-hunk resolver for single-task merges: start conflict merge, resolve hunks, write resolution, continue/abort). ## Services -- **WorkerClient** / **IWorkerClient** — SignalR client connecting to `http://127.0.0.1:47821/hub`. Auto-reconnect with exponential backoff. Methods: StartAsync, RunNowAsync, CancelTaskAsync, WakeQueueAsync, ContinueTaskAsync, ResetTaskAsync, GetAgentsAsync, UpdateAppSettingsAsync, UpdateListAsync, UpdateListConfigAsync, GetListConfigAsync, UpdateTaskAgentSettingsAsync, `ApproveReviewAsync(taskId, targetBranch) -> MergeResultDto`, `PreviewMergeAsync(taskId, targetBranch) -> MergePreviewDto`, `MergeTaskAsync`, `GetWeekReportAsync`, `GenerateWeekReportAsync`, `GetDailyNotesAsync`, `AddDailyNoteAsync`, `UpdateDailyNoteAsync`, `DeleteDailyNoteAsync`, `RunDailyPrepNowAsync`, `ClearMyDayAsync`, `GetLastPrepLogAsync`. Events: TaskStarted, TaskFinished, TaskMessage, TaskUpdated, WorktreeUpdated, ListUpdated, `PrepStartedEvent`, `PrepLineEvent`, `PrepFinishedEvent` -- **INotesApi** / **WorkerNotesApi** — thin wrapper over the daily-note WorkerClient methods (mirrors `IPrimeScheduleApi`). UI DTO: `DailyNoteDto(Id, Date, Text, SortOrder)`. +- **WorkerClient** / **IWorkerClient** — SignalR client connecting to `http://127.0.0.1:47821/hub`, auto-reconnect with exponential backoff. The surface tracks `WorkerHub` (see `src/ClaudeDo.Worker/CLAUDE.md` for the canonical method/event list); groups: task execution (RunNow/Cancel/Continue/Reset/SetTaskStatus), review (`ApproveReviewAsync(taskId, targetBranch) -> MergeResultDto`, reject-to-queue/idle, cancel review, `PreviewMergeAsync -> MergePreviewDto`), planning sessions (start/resume/discard/finalize, queue subtasks, pending draft count, interactive terminal, refine), planning aggregate/integration-branch diffs, unit-merge continue/abort, single-task conflict resolving (start/get-conflicts/write-resolution/continue/abort), worktrees (overview, set state, force remove, cleanup, reset all), agents, app settings, lists/config, weekly report, daily notes, daily prep (`RunDailyPrepNowAsync`, `ClearMyDayAsync`, `GetLastPrepLogAsync`), prime schedules. Events mirror `HubBroadcaster` (task/worktree/list/run updates, prep events, planning-merge events, refine events, worker log). Lifecycle (`StartAsync`/`StopAsync`) and a few admin methods live only on the concrete `WorkerClient`. +- **INotesApi** / **WorkerNotesApi** — daily-note CRUD (`ListAsync(day)`, `AddAsync`, `UpdateAsync`, `DeleteAsync`); UI DTO `DailyNoteDto(Id, Date, Text, SortOrder)`. +- **IPrimeScheduleApi** — prime-schedule CRUD (`ListAsync`, `UpsertAsync`, `DeleteAsync`). +- **UpdateCheckService** — polls releases, exposes `LastCheckStatus`/`LatestVersion`/`CheckNowAsync` (feeds the shell's update banner). +- **InheritanceResolver** — resolves the task → list → global override chain to `(value, source)` for the inherited badges. +- **RepoScanner**, **InstallArtifactLocator**/**InstallerLocator**/**WorkerLocator**, **ForegroundHelper** (Win32 foreground before launching a terminal), **FocusClearing**. ## Converters -- **StatusColorConverter** — task status string -> color (Queued=Blue, Running=Orange, Done=Green, Failed=Red, Manual=Gray) -- **ConnectionColorConverter** — connection state -> color (Online=Green, Offline=Red) +`StatusColorConverter` (+ `ConnectionColorConverter` in the same file), `WorktreeStateColorConverter`, `WorkerLogLevelToBrushConverter`, `DotBrushConverter`, `EqStatusConverter`, `IconKeyConverter`, `CheckboxBorderConverter`, `StrikeIfTrueConverter`, `BoolToItalicConverter`, `BoolToDraftOpacityConverter`, `NotNullToBoolConverter`, `UpperCaseConverter`, `DateOnlyToDateTimeConverter`. ## Dialog Pattern -Editor dialogs use `TaskCompletionSource` — the dialog sets the result on save/cancel, and the caller awaits the TCS. +Modals use `TaskCompletionSource` results behind the reusable `ModalShell` control — the dialog sets the result on save/cancel, and the caller awaits the TCS. ## Notes -- Context menus are on both list items and task items -- Right-click selects the item before showing the context menu +- Context menus exist on both list rows and task rows; right-click selects before opening the menu - "Run Now" CanExecute re-evaluates when worker connection state changes - Icon gotcha: `PathIcon` fills geometry. Line-art/stroke icons must be defined as filled geometry or rendered as a stroked `Path` (e.g. `Icon.PlanDay` via the `Path.plan-icon` style); a pure stroke path used with `PathIcon` is invisible. +- `SessionTerminalView` is the reusable log terminal (StyledProperties `Entries`, `Label`, `IsRunning`, `IsDone`, `IsFailed`) used for both the task `Log` and the prep `PrepLog`. diff --git a/src/ClaudeDo.Worker/CLAUDE.md b/src/ClaudeDo.Worker/CLAUDE.md index 4aa86af..862727e 100644 --- a/src/ClaudeDo.Worker/CLAUDE.md +++ b/src/ClaudeDo.Worker/CLAUDE.md @@ -8,12 +8,14 @@ ASP.NET Core hosted service that executes tasks via Claude CLI in isolated envir Worker/ State/ — TaskStateService + TransitionResult (sole owner of Status/PlanningPhase/BlockedBy writes) Queue/ — IQueueWaker, IQueuePicker, QueueService (BackgroundService), OverrideSlotService - Lifecycle/ — StaleTaskRecovery, TaskResetService, TaskMergeService + Lifecycle/ — StaleTaskRecovery, TaskResetService, TaskMergeService, ClaudeCliPreflight, OrphanRecovery, PlanningLineageRecovery Worktrees/ — WorktreeMaintenanceService Agents/ — AgentFileService, DefaultAgentSeeder - Runner/ — TaskRunner + Claude CLI integration - Planning/ — PlanningSessionManager, PlanningChainCoordinator, PlanningMcpService - External/ — ExternalMcpService + Runner/ — TaskRunner + Claude CLI integration; TaskRunMcpService/TaskRunMcpContext/TaskRunTokenRegistry (in-task MCP wired during execution) + Planning/ — PlanningSessionManager, PlanningChainCoordinator, PlanningMcpService, PlanningMergeOrchestrator, PlanningAggregator, PlanningSessionContext/PlanningTokenAuth/PlanningMcpContextAccessor, WindowsTerminalPlanningLauncher (IPlanningTerminalLauncher) + Refine/ — RefineRunner + RefinePrompt (hub `RefineTask`; broadcasts RefineStarted/RefineFinished) + External/ — ExternalMcpService + sibling tool classes + Config/ — WorkerConfig Hub/ — WorkerHub, HubBroadcaster Report/ — ClaudeHistoryReader, WeekReportPromptBuilder, WeekReportService; interfaces in Report/Interfaces/ Prime/ — daily-prep ("Prime Claude"): PrimeScheduler (BackgroundService), PrimeRunner (runs the daily prep), DailyPrepPrompt (fixed prompt + CLI args + LogPath() helper), NextDueCalculator, PrimeScheduleSignal; interfaces in Prime/Interfaces/ (IPrimeRunner, IPrimeClock, IPrimeScheduleSignal, IPrimeBroadcaster) @@ -29,11 +31,11 @@ Interfaces (e.g. `IQueueWaker`, `IPrimeClock`, `ITaskStateService`) live in an ` - **OverrideSlotService** — owns `RunNow` / `ContinueTask`; goes through `TaskStateService.StartRunningAsync` (caller-driven, serialized by slot lock). - **StaleTaskRecovery** — startup-only service; calls `TaskStateService.RecoverStaleRunningAsync` to flip orphaned `Running` rows to `Failed`. - **External/*** — always-on MCP tools for general Claude sessions, scoped to *starting* and *observing* sessions (no worktree/merge, multi-turn, planning, or app-settings writes). Auth via optional `X-ClaudeDo-Key` header. Registered explicitly in `Program.cs`'s external app via `.WithTools()`. Organized by concern: - - `ExternalMcpService` — task CRUD + execution: `ListTaskLists`, `ListTasks`, `GetTask`, `AddTask`, `UpdateTask`, `UpdateTaskStatus` (`Idle` / `Queued`), `ReviewTask` (`approve` / `reject_rerun` / `reject_park` / `cancel` for a WaitingForReview task), `RunTaskNow`, `CancelTask`, `DeleteTask` + - `ExternalMcpService` — task CRUD + execution: `ListTaskLists`, `ListTasks`, `GetTask`, `AddTask`, `AddSubtask`, `UpdateTask`, `UpdateTaskStatus` (`Idle` / `Queued`), `GetTaskStatusValues`, `ReviewTask` (`approve` / `reject_rerun` / `reject_park` / `cancel` for a WaitingForReview task), `RunTaskNow`, `ContinueTask`, `CancelTask`, `DeleteTask`; worktree/git: `GetTaskWorktree`, `GetTaskDiff`, `MergeTask`, `ListWorktrees`, `CleanupTaskWorktree` - `ListMcpTools` — `CreateList`, `UpdateList`, `DeleteList` - - `ConfigMcpTools` — `GetListConfig`, `SetListConfig`, `SetTaskConfig` + - `ConfigMcpTools` — `GetListConfig`, `SetListConfig`, `GetTaskConfig`, `SetTaskConfig` - `RunHistoryMcpTools` — `ListRuns`, `GetRun`, `GetTaskLog` (latest run's log, tail-capped at 256 KB) - - `AgentMcpTools` — `ListAgents` + - `AgentMcpTools` — `ListAgents` (class lives in `LifecycleMcpTools.cs`) - `LifecycleMcpTools` — `ResetFailedTask` - `AppSettingsMcpTools` — `GetAppSettings` (read-only) - `ExternalMcpService` also exposes two daily-prep tools: @@ -67,7 +69,7 @@ Allowed transitions (enforced by `TaskStateService`): ``` Idle → Queued | Running (RunNow) -Queued → Running | Cancelled | Idle +Queued → Running | Cancelled | Idle | Failed (runner guard) Running → WaitingForReview (standalone success, no children) | WaitingForChildren (parent with pending children) | Done (planning/improvement child success) | Failed | Cancelled @@ -143,9 +145,17 @@ Each CLI invocation is recorded in the `task_runs` table via `TaskRunRepository` ## SignalR Hub -**WorkerHub** methods: `Ping`, `GetActive`, `RunNow`, `CancelTask`, `WakeQueue`, `ContinueTask`, `ResetTask`, `ApproveReview(taskId, targetBranch) -> MergeResultDto` (childless task: merges its worktree then Done, conflict stays WaitingForReview; task with children: drives `PlanningMergeOrchestrator` to merge the whole unit), `ContinuePlanningMerge` / `AbortPlanningMerge` (resolve a unit-merge conflict), `PreviewMerge(taskId, targetBranch) -> MergePreviewDto` (non-destructive mergeability check), `RejectReviewToQueue`, `RejectReviewToIdle`, `CancelReview`, `GetAgents`, `RefreshAgents`, `GetAppSettings`, `UpdateAppSettings`, `CleanupFinishedWorktrees`, `ResetAllWorktrees`, `MergeTask`, `GetMergeTargets`, `UpdateList`, `UpdateListConfig`, `GetListConfig`, `UpdateTaskAgentSettings`, `GetWeekReport`, `GenerateWeekReport`, `GetDailyNotes`, `AddDailyNote`, `UpdateDailyNote`, `DeleteDailyNote`, `RunDailyPrepNow`, `ClearMyDay`, `GetLastPrepLog` +**WorkerHub** methods, grouped: -**HubBroadcaster** events: `TaskStarted`, `TaskFinished`, `TaskMessage`, `WorktreeUpdated`, `TaskUpdated`, `RunCreated`, `ListUpdated`, `PrimeFired`, `PrepStarted`, `PrepLine`, `PrepFinished` +- Execution: `Ping`, `GetActive`, `RunNow`, `CancelTask`, `WakeQueue`, `ContinueTask`, `ResetTask`, `SetTaskStatus`, `RefineTask` +- Review/merge: `ApproveReview(taskId, targetBranch) -> MergeResultDto` (childless task: merges its worktree then Done, conflict stays WaitingForReview; task with children: drives `PlanningMergeOrchestrator` to merge the whole unit), `ContinuePlanningMerge` / `AbortPlanningMerge` (resolve a unit-merge conflict), `PreviewMerge(taskId, targetBranch) -> MergePreviewDto` (non-destructive mergeability check), `RejectReviewToQueue`, `RejectReviewToIdle`, `CancelReview`, `MergeTask`, `GetMergeTargets` +- Single-task conflict resolver (Layer C): `StartConflictMerge`, `GetMergeConflicts` (hunks), `WriteConflictResolution`, `ContinueMerge`, `AbortMerge` +- Planning sessions: `StartPlanningSession`, `ResumePlanningSession`, `DiscardPlanningSession`, `FinalizePlanningSession`, `QueuePlanningSubtasks`, `GetPendingDraftCount`, `OpenInteractiveTerminal`, `GetPlanningAggregate` (per-subtask diffs), `BuildPlanningIntegrationBranch` (combined diff) +- Worktrees: `CleanupFinishedWorktrees`, `ResetAllWorktrees`, `GetWorktreesOverview`, `SetWorktreeState`, `ForceRemoveWorktree` +- Agents/settings/lists: `GetAgents`, `RefreshAgents`, `RestoreDefaultAgents`, `GetAppSettings`, `UpdateAppSettings`, `UpdateList`, `UpdateListConfig`, `GetListConfig`, `UpdateTaskAgentSettings` +- Reports/notes/prep: `GetWeekReport`, `GenerateWeekReport`, `GetDailyNotes`, `AddDailyNote`, `UpdateDailyNote`, `DeleteDailyNote`, `RunDailyPrepNow`, `ClearMyDay`, `GetLastPrepLog`, `ListPrimeSchedules`, `UpsertPrimeSchedule`, `DeletePrimeSchedule` + +**HubBroadcaster** events: `TaskStarted`, `TaskFinished`, `TaskMessage`, `WorktreeUpdated`, `TaskUpdated`, `RunCreated`, `ListUpdated`, `WorkerLog`, `PrimeFired`, `PrepStarted`, `PrepLine`, `PrepFinished`, `PlanningMergeStarted`, `PlanningSubtaskMerged`, `PlanningMergeConflict`, `PlanningMergeAborted`, `PlanningCompleted`, `RefineStarted`, `RefineFinished` ## Config diff --git a/tests/ClaudeDo.Worker.Tests/CLAUDE.md b/tests/ClaudeDo.Worker.Tests/CLAUDE.md index 1f29911..fff6f16 100644 --- a/tests/ClaudeDo.Worker.Tests/CLAUDE.md +++ b/tests/ClaudeDo.Worker.Tests/CLAUDE.md @@ -1,6 +1,6 @@ # ClaudeDo.Worker.Tests -xUnit integration tests for the Worker and Data layers. +xUnit integration tests for the Worker and Data layers. One of six test projects under `tests/` (also: `ClaudeDo.Data.Tests`, `ClaudeDo.Ui.Tests`, `ClaudeDo.Localization.Tests`, `ClaudeDo.Installer.Tests`, `ClaudeDo.Releases.Tests`). ## Framework @@ -17,15 +17,17 @@ xUnit integration tests for the Worker and Data layers. ## Test Areas -| Area | File | What it covers | -|------|------|----------------| -| Repositories | `ListRepositoryTests` | CRUD, tag junctions | -| | `TaskRepositoryTests` | CRUD, status transitions, stale flip | -| Runner | `WorktreeManagerTests` | Worktree creation, commit detection, error on non-git dir | -| | `CommitMessageBuilderTests` | Slug generation, title/description truncation | -| | `StreamAnalyzerTests` | NDJSON parsing, session/token/turn extraction | -| Services | `QueueServiceTests` | FIFO ordering, override slot contention, cancellation, active tracking | -| | `StaleTaskRecoveryTests` | Flips orphaned running tasks to failed | +Tests are organized by Worker area (mirroring the source folders); 30+ test files in total. Highlights per area: + +| Area | Covers | +|------|--------| +| Repositories | `ListRepositoryTests`/`TaskRepositoryTests` + config, delete-config, agent-settings, planning, orphan-guard, and roadblock variants | +| Runner | `WorktreeManagerTests`, `CommitMessageBuilderTests`, `StreamAnalyzerTests`, standalone-children routing | +| Queue / Services | `QueueServiceTests` (FIFO, override slot contention, cancellation, active tracking), `QueueServiceSlotGuardTests`, `StaleTaskRecoveryTests`, `TaskResetServiceTests`, `TaskMergeServiceTests`, `WorktreeMaintenanceServiceTests`, `AgentFileServiceTests`, `DefaultAgentSeederTests` | +| State | `TaskStateService` transition coverage | +| Planning | session manager, chain coordinator, merge orchestrator, end-to-end planning flow | +| Prime / Report / External / Lifecycle / Hub | daily prep, weekly report, external MCP tools, recovery services, hub methods | +| UiSchema / UiVm | UI-facing DTO schemas and viewmodel behavior driven from Worker fakes | ## Conventions