Die Build-Sektion hat bisher ein Rezept mit allen sechs Testprojekten vorgegeben; Implementer haben daraus "volle Suite vor fertig" gelesen. Bei bis zu 5 parallelen Tasks kostet das Stunden - und kann das nicht finden, wofuer es teuer ist: jeder Task arbeitet in seinem eigenen Worktree mit nur seiner eigenen Aenderung, eine Kollision zwischen zwei parallelen Tasks ist fuer beide unsichtbar. Kollisionen zeigen sich nach dem Merge, und genau dort laeuft verify_merges den Verify-Command einmal pro Batch. Neue Regel: Solution-Build immer (42s, faengt projektuebergreifende Compile-Brueche), Tests nur --no-build --filter auf das Beruehrte, und melden welcher Filter benutzt wurde. Die Messwerte stehen dabei, damit die Regel nicht als Geschmacksfrage gelesen wird. Messung 2026-09-02, sequenziell nach einem Build: Worker.Tests 507s, Ui 33s, Data 8s, Rest je 3s, Build 42s. Parallel ueber die Solution ist es schlechter, nicht besser (Worker 801s, Ui 82s) - diese Tests legen echte Git-Worktrees an und spawnen Prozesse, sie drangeln sich statt sich zu teilen. Ausserdem korrigiert: die Zeile "dotnet build ClaudeDo.slnx requires .NET 9" war veraltet.
115 lines
7.8 KiB
Markdown
115 lines
7.8 KiB
Markdown
# ClaudeDo
|
||
|
||
A desktop task management app that executes tasks autonomously via Claude CLI in isolated git worktrees.
|
||
|
||
## Architecture
|
||
|
||
Two-process system communicating over SignalR (`127.0.0.1:47821`):
|
||
|
||
- **ClaudeDo.App** — Avalonia desktop entry point, DI container setup
|
||
- **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.Localization** — `locales/en.json` + `locales/de.json` and the lookup service
|
||
- **ClaudeDo.Releases** — Gitea release client (`IReleaseClient`), used by the Ui update check and the Installer
|
||
- **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
|
||
|
||
Per-project `CLAUDE.md` files exist for **App, Data, Installer, Ui, Worker, and Worker.Tests** —
|
||
those are the living per-project docs. Localization, Releases, and the other five test projects
|
||
have none; this file plus the code is all there is for them.
|
||
|
||
## Tech Stack
|
||
|
||
- .NET 8.0, Avalonia 12.0.0 (Fluent theme)
|
||
- SQLite (WAL mode) via Entity Framework Core (Microsoft.EntityFrameworkCore.Sqlite)
|
||
- SignalR for real-time IPC
|
||
- CommunityToolkit.Mvvm (`[ObservableProperty]`, `[RelayCommand]`)
|
||
- Git worktrees for task isolation
|
||
|
||
## Key Paths
|
||
|
||
- DB: `~/.claudeDo/todo.db`
|
||
- UI config: `~/.claudeDo/ui.config.json`
|
||
- Worker config: `~/.claudeDo/worker.config.json`
|
||
- Logs: `~/.claudeDo/logs/`
|
||
- Worktrees: configured per worker (sibling or central strategy)
|
||
|
||
## Conventions
|
||
|
||
- Repository pattern — each entity has its own async repository
|
||
- All data operations are async with CancellationToken support
|
||
- EF Core migrations manage schema (Migrations/ folder in ClaudeDo.Data)
|
||
- `IDbContextFactory<ClaudeDoDbContext>` used by singleton consumers (e.g. Worker)
|
||
- Entity configuration via `IEntityTypeConfiguration<T>` in Configuration/ folder
|
||
- Task status flow: `Idle | Queued -> Running -> WaitingForReview -> Done | Failed | Cancelled`; a task with children passes through `WaitingForChildren` first. **Approve is the single review+merge action** (no separate "Merge all"), and in the detail pane it's gated behind opening the diff. Full transition table → `src/ClaudeDo.Worker/CLAUDE.md`; merge/review/gate mechanics → `docs/explore-notes/review-merge.md`.
|
||
- Worktree state flow: Active -> Merged | Discarded | Kept
|
||
- The queue picker claims tasks by `Status=Queued` (with `BlockedByTaskId IS NULL`); the legacy tag system was removed
|
||
- Interfaces live in an `Interfaces/` subfolder beside their consumers (namespace unchanged)
|
||
- Small single-consumer helper types live in their consumer's file, not standalone files
|
||
- Commit messages use conventional format: `{commitType}(slug): title`
|
||
- Views use compiled bindings (`x:DataType`)
|
||
- ViewModels use `[ObservableProperty]` and `[RelayCommand]` source generators
|
||
|
||
## Working style (autonomous)
|
||
|
||
For any non-trivial feature, bug, or change, run this loop without hand-holding:
|
||
|
||
1. **Brainstorm first** (superpowers:brainstorming) — ask clarifying questions one at a time, propose 2–3 options with a recommendation, present a short design, get approval before building.
|
||
2. **Write it down** — a spec in `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` and a step-by-step plan in `docs/superpowers/plans/` (superpowers:writing-plans). Commit the docs.
|
||
3. **Implement on main** with superpowers:subagent-driven-development — one subagent per task, TDD, build + test, commit per task with Conventional Commits. Once the plan is approved, do NOT pause for re-approval between tasks; only stop for genuine decisions or blockers.
|
||
4. **Trust but verify** — read each subagent's diff and run the build/tests yourself before marking a task done.
|
||
5. **Bugs** → superpowers:systematic-debugging (find the root cause before any fix).
|
||
6. **Never claim UI works without running it** — explicitly flag visual-verification gaps for the user to check.
|
||
|
||
Commit freely (per task + the spec/plan docs). Never push without asking.
|
||
|
||
## Building & Testing
|
||
|
||
**Build the whole solution, test only what you touched.** Always `-c Release` — a running Worker locks the `Debug` output.
|
||
|
||
```bash
|
||
dotnet build ClaudeDo.slnx -c Release # ~40s, catches cross-project breaks
|
||
dotnet test tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj -c Release --no-build \
|
||
--filter "FullyQualifiedName~Handoff" # seconds, not minutes
|
||
```
|
||
|
||
`.slnx` needs SDK 9+ (this machine is on 10). On an older SDK build the projects individually:
|
||
`src/ClaudeDo.App` (pulls in Ui + Data) and `src/ClaudeDo.Worker`.
|
||
|
||
### Do NOT run the full test suite to finish a task
|
||
|
||
Measured 2026-09-02, sequentially after one build: **Worker.Tests 507s**, Ui.Tests 33s, Data.Tests 8s,
|
||
Localization/Installer/Releases 3s each, build 42s — ~10 min for all six. Run in parallel across
|
||
projects it is *worse*, not better (Worker.Tests 801s, Ui.Tests 82s): these tests create real git
|
||
worktrees and spawn processes, so they thrash rather than share.
|
||
|
||
With up to 5 implementer tasks running at once, a full suite per task costs hours — and **cannot find
|
||
what it costs that for.** Each task works in its own worktree containing only its own change, so a
|
||
collision between two parallel tasks is invisible to both. Collisions surface after the merge, which
|
||
is exactly where `verify_merges` runs the list's verify command **once per batch**. The full suite is
|
||
the merge gate's job, not the task's.
|
||
|
||
So, per task:
|
||
- **Build:** the whole solution, always. It's cheap and it catches the compile break your change
|
||
caused three projects over.
|
||
- **Tests:** `--no-build --filter` scoped to what you touched. Add a filter for the classes covering
|
||
your change; if you genuinely can't scope it, run the one relevant test project, never all six.
|
||
- **Report** what you ran and what you did not, so the merge session knows what is still unverified.
|
||
- Never report "all tests pass" when you ran a filtered subset. Say which filter you used.
|
||
|
||
### Gotchas
|
||
- **Subagents:** use the `sonnet` model; stage files explicitly by path — never `git add -A` (parallel sessions often leave unrelated WIP in the tree).
|
||
- **Icons:** `PathIcon` *fills* its geometry — line-art icons must be filled geometry or a `Path Classes="icon-stroke"`, else they render invisible. Colour comes from the `ICON PAINTING` block in `IslandStyles.axaml` (class + state); setting `Foreground`/`Stroke` inline kills the hover state.
|
||
- **Localization:** `locales/en.json` and `locales/de.json` keys must stay in parity (Localization.Tests enforces it).
|
||
- **Test fakes:** changing `IWorkerClient` / `WorkerHub` / ViewModel constructors breaks hand-rolled fakes in both test projects — update them.
|
||
|
||
## Docs
|
||
|
||
- `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
|
||
- `docs/explore-notes/` — distilled maps of complex subsystems (detail too fine for a CLAUDE.md, read on demand). **Before** deep-exploring a subsystem, check for a matching note first; **after** a deep explore, distill durable findings back and bump its "verified against" commit. Always verify against current code before trusting. See `docs/explore-notes/README.md`. Current notes: `worker-task-pipeline`, `usage-monitoring`, `external-mcp`, `review-merge`, `conpty-sessions`, `installer-preflight`.
|