diff --git a/CLAUDE.md b/CLAUDE.md index 1e8a0c4..da3a252 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,7 +15,7 @@ Two-process system communicating over SignalR (`127.0.0.1:47821`): ## Tech Stack - .NET 8.0, Avalonia 12.0.0 (Fluent theme) -- SQLite (WAL mode) via Microsoft.Data.Sqlite — raw ADO.NET, no ORM +- SQLite (WAL mode) via Entity Framework Core (Microsoft.EntityFrameworkCore.Sqlite) - SignalR for real-time IPC - CommunityToolkit.Mvvm (`[ObservableProperty]`, `[RelayCommand]`) - Git worktrees for task isolation @@ -27,12 +27,14 @@ Two-process system communicating over SignalR (`127.0.0.1:47821`): - Worker config: `~/.todo-app/worker.config.json` - Logs: `~/.todo-app/logs/` - Worktrees: configured per worker (sibling or central strategy) -- Schema: `schema/schema.sql` (embedded resource in ClaudeDo.Data) ## 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` used by singleton consumers (e.g. Worker) +- Entity configuration via `IEntityTypeConfiguration` in Configuration/ folder - Task status flow: Manual | Queued -> Running -> Done | Failed - Worktree state flow: Active -> Merged | Discarded | Kept - Tags "agent" and "manual" are seeded; "agent" tag marks tasks for automated queue pickup diff --git a/src/ClaudeDo.Data/CLAUDE.md b/src/ClaudeDo.Data/CLAUDE.md index 6720add..378c405 100644 --- a/src/ClaudeDo.Data/CLAUDE.md +++ b/src/ClaudeDo.Data/CLAUDE.md @@ -11,7 +11,7 @@ Shared data layer: models, repositories, SQLite infrastructure, and git operatio ## Repositories -All repositories use raw parameterized SQL via `Microsoft.Data.Sqlite`. Each method opens its own connection — no Unit of Work. +All repositories use EF Core LINQ queries via `ClaudeDoDbContext`. Exception: `TaskRepository.GetNextQueuedAgentTaskAsync` uses `FromSqlRaw` for atomic queue claim. - **TaskRepository** — CRUD, status transitions (`MarkRunningAsync`, `MarkDoneAsync`, `MarkFailedAsync`), `GetNextQueuedAgentTaskAsync` (queue polling), `GetEffectiveTagsAsync` (union of task + list tags), `FlipAllRunningToFailedAsync` - **ListRepository** — CRUD, tag junction management @@ -20,8 +20,8 @@ All repositories use raw parameterized SQL via `Microsoft.Data.Sqlite`. Each met ## Infrastructure -- **SqliteConnectionFactory** — creates connections, applies WAL mode once, enforces foreign keys via PRAGMA -- **SchemaInitializer** — applies embedded `schema/schema.sql` idempotently (IF NOT EXISTS, INSERT OR IGNORE) +- **ClaudeDoDbContext** — EF Core DbContext; configured with WAL mode and foreign keys via `UseSqlite` options +- **IDbContextFactory** — registered in DI; used by singleton consumers (e.g. Worker hosted service) - **Paths** — expands `~` and `%USERPROFILE%`, resolves relative paths. App root: `~/.todo-app` - **AppSettings** — loads `~/.todo-app/ui.config.json` (DbPath, SignalRUrl) @@ -31,11 +31,11 @@ All repositories use raw parameterized SQL via `Microsoft.Data.Sqlite`. Each met ## Schema -6 tables: `lists`, `tasks`, `tags`, `list_tags`, `task_tags`, `worktrees`. See `schema/schema.sql`. Seed data: tags "agent" and "manual". +6 tables: `lists`, `tasks`, `tags`, `list_tags`, `task_tags`, `worktrees`. Managed by EF Core migrations in the `Migrations/` folder. Seed data: tags "agent" and "manual". ## Conventions -- Enum <-> string mapping via explicit `ToDb()`/`FromDb()` static methods on each enum +- Enum <-> string mapping via EF Core `ValueConverter` (configured in `IEntityTypeConfiguration`) +- Entity configurations live in the `Configuration/` folder - Primary keys are `init`-only strings (GUIDs assigned at creation) -- Nullable fields use `DBNull.Value` checks - All methods are async with CancellationToken where applicable