docs: neue Config-Felder + Migration-Fixture-Falle in den CLAUDE.md-Dateien
This commit is contained in:
@@ -4,14 +4,15 @@ Shared data layer: models, repositories, SQLite infrastructure, and git operatio
|
||||
|
||||
## Models
|
||||
|
||||
- **TaskEntity** — Id, ListId, Title, Description, Status, PlanningPhase, BlockedByTaskId (FK to predecessor in a chain), DependsOnTaskId (FK to a user/MCP-declared predecessor, distinct from BlockedByTaskId), ScheduledFor, Result, ReviewFeedback, LogPath, timestamps, CommitType, Model / SystemPrompt / AgentPath / MaxTurns (nullable overrides), IsStarred, IsMyDay, IsManual, Notes, ParentTaskId, PlanningSessionId / PlanningSessionToken / PlanningFinalizedAt, CreatedBy, HandlerBaseCommit / HandlerHeadCommit, InteractiveSessionId, Number (global immutable human-readable alias).
|
||||
- **TaskEntity** — Id, ListId, Title, Description, Status, PlanningPhase, BlockedByTaskId (FK to predecessor in a chain), DependsOnTaskId (FK to a user/MCP-declared predecessor, distinct from BlockedByTaskId), ScheduledFor, Result, ReviewFeedback, LogPath, timestamps, CommitType, Model / SystemPrompt / AgentPath / MaxTurns / PermissionMode (nullable overrides), IsStarred, IsMyDay, IsManual, Notes, ParentTaskId, PlanningSessionId / PlanningSessionToken / PlanningFinalizedAt, CreatedBy, HandlerBaseCommit / HandlerHeadCommit, InteractiveSessionId, Number (global immutable human-readable alias).
|
||||
- Status / PlanningPhase / BlockedByTaskId / DependsOnTaskId semantics + allowed transitions: `ClaudeDo.Worker/CLAUDE.md` → Status Model.
|
||||
- `HandlerBaseCommit`/`HandlerHeadCommit` = the review range for a **worktree-less "list handler" host task** ("Let Claude handle it"), which commits straight into the list's working dir instead of a per-task worktree. Everything that reads a task's diff falls back to this pair whenever `Worktree` is null → [conpty-sessions](../../docs/explore-notes/conpty-sessions.md).
|
||||
- `InteractiveSessionId` = the claude session id an embedded ConPTY interactive task session runs under, persisted by `InteractiveLaunchSpecService` before launch so a closed/aborted session can be resumed → [conpty-sessions](../../docs/explore-notes/conpty-sessions.md).
|
||||
- `Number` (INTEGER NOT NULL, unique index `idx_tasks_number`) — a global, monotonically increasing display alias for tasks. **Never reused**: deleting a task leaves a gap in numbering, ensuring that a task number that appears in a log or report always points to the same task (if it exists). Allocated by `TaskNumberAllocator.AddWithNumberAsync` on every insert via a persistent counter (`app_settings.next_task_number`). **Why not `MAX(number) + 1`:** deleting the highest-numbered task would free its number for reuse, breaking the immutability guarantee. The allocator uses an `UPDATE…RETURNING` statement to claim numbers atomically, retrying up to 5 times if a uniqueness collision occurs (the counter advances on each attempt, so retries always allocate fresh numbers). The one-time backfill for pre-existing rows lived in the `AddTaskNumbers` migration, squashed away 2026-08-26.
|
||||
- Legacy status values `Manual`/`Planning`/`Planned`/`Draft`/`Waiting` were retired. The backfill migration was squashed away (2026-08-26) — a database still holding those values can't be upgraded, see Schema below.
|
||||
- **ListEntity** — Id, Name, WorkingDir, DefaultCommitType, CreatedAt, IsManual (reminder list — tasks created here default to `IsManual`)
|
||||
- **ListConfigEntity** — ListId (PK, 1:1), Model, SystemPrompt, AgentPath, MaxTurns, SessionSkills, VerifyCommand (all nullable). `VerifyCommand` is an optional post-merge gate; null/blank = no gate → [review-merge](../../docs/explore-notes/review-merge.md).
|
||||
- **ListConfigEntity** — ListId (PK, 1:1), Model, SystemPrompt, AgentPath, MaxTurns, SessionSkills, VerifyCommand, PermissionMode (all nullable) + SerializeOnFileOverlap (bool). `VerifyCommand` is an optional post-merge gate; null/blank = no gate → [review-merge](../../docs/explore-notes/review-merge.md). `PermissionMode` is null = inherit the global default; resolution order task → list → global lives in `EffectiveRunConfigResolver`.
|
||||
- ⚠️ `ListRepository.SetConfigAsync` copies the entity **verbatim**, so every writer must carry the fields it doesn't own (`SessionSkills`, `SerializeOnFileOverlap`, `PermissionMode`) or they silently reset. `UpdateListConfigDto.SerializeOnFileOverlap` is tri-state (`null` = keep stored) for exactly that reason — only the list-settings modal sends an explicit value.
|
||||
- **WorktreeEntity** — TaskId (PK, 1:1), Path, BranchName, BaseCommit, HeadCommit, DiffStat, MergeCommit (nullable — SHA of the merge commit this branch produced; the only thing making `revert_merge` possible without searching `git log`), State (`Active|Merged|Discarded|Kept`)
|
||||
- **TaskRunEntity** — per-run record: session_id, turns, result, structured output, exit code, log path, nullable `Model` (what the run actually executed with), and `TokensIn`/`TokensOut`/`CacheReadTokens`/`CacheWriteTokens`. ⚠️ Token fields come from the **session transcript**, not the stream-json event, as a per-run delta → [usage-monitoring](../../docs/explore-notes/usage-monitoring.md).
|
||||
- **PrimeScheduleEntity** — Id, Days (`[Flags] PrimeDays` weekday bitmask, column `days_of_week`), TimeOfDay, Enabled, LastRunAt, PromptOverride, Kind (`PrimeActionKind`, column `action_kind`, default `ping`), CreatedAt. Recurs on selected weekdays; no date range. `PromptOverride`'s role depends on `Kind`: ignored for `Ping`, appended to the daily-prep prompt for `FillMyDay`, and the entire prompt for `Custom`.
|
||||
@@ -106,8 +107,14 @@ not a migration chain. Consequences:
|
||||
at `20260825063230_AddPrimeActionKind`). A database that stopped *mid*-chain can no longer be
|
||||
upgraded and throws with a reinstall message instead of being stamped onto a schema it lacks.
|
||||
Covered by `MigrationBaselineTests` — the only test that runs a real `Migrate()` (every other
|
||||
Data.Tests fixture uses `EnsureCreated`, which skips migrations entirely).
|
||||
- Don't hand-edit the migration; add new ones on top as usual.
|
||||
Data.Tests fixture uses `EnsureCreated`, which skips migrations entirely). Its fixture builds the
|
||||
legacy database by migrating **to** `InitialCreate` and seeding rows with raw SQL: `EnsureCreated`
|
||||
would build *today's* schema, so every post-squash migration would then re-add an existing column
|
||||
("duplicate column name"). Assert "nothing pending", never "InitialCreate is the only history row".
|
||||
- Don't hand-edit the squashed migration; add new ones on top as usual.
|
||||
`dotnet ef migrations add <Name> --project src/ClaudeDo.Data/ClaudeDo.Data.csproj --configuration
|
||||
Release` — `Data` is its own startup project (it holds the `Design` package and a design-time
|
||||
factory), and `--configuration Release` is needed because a running Worker locks `Debug`.
|
||||
|
||||
`tasks` holds `status`, `planning_phase` (default `none`),
|
||||
`blocked_by_task_id` (FK to `tasks.id`, `ON DELETE SET NULL`), and `depends_on_task_id` (same FK
|
||||
|
||||
@@ -245,14 +245,21 @@ non-obvious, behaviour-changing. A fixed bug is git history, not a finding.
|
||||
- `db_path`, `sandbox_root`, `log_root`
|
||||
- `worktree_root_strategy` (`sibling` | `central`), `central_worktree_root`
|
||||
- `queue_backstop_interval_ms` (30000) — also the gate/throttle recovery timer
|
||||
- `signalr_port` (47821), `claude_bin`
|
||||
- `signalr_port` (47821), `claude_bin` — `claude_bin` is the one field the UI can write
|
||||
(Settings → Dateien → CLAUDE CLI, hub `GetClaudeBin`/`SetClaudeBin`). It edits the DI-singleton
|
||||
`WorkerConfig` in place *and* persists via `SaveClaudeBin`, so it applies to the next spawn
|
||||
without a restart. Every other field here is hand-edit only.
|
||||
- `usage_poll_interval_seconds` (60, clamped to min 15 on load)
|
||||
- `online_inbox` — `enabled` (false by default; when false the entire `Online/` stack is not registered), `api_base_url` (must be HTTPS or loopback, validated at startup), `poll_interval_seconds` (60), `zitadel.authority`/`client_id`/`scopes`. The refresh token is **not** in this file — DPAPI-encrypted at `~/.claudeDo/online-inbox.token`.
|
||||
|
||||
Per-list config (`list_config` in DB) provides defaults for `model`, `system_prompt`,
|
||||
`agent_path`, `max_turns`, `session_skills`; tasks override each individually. `verify_command` is
|
||||
list-only — there is no task-level override — and is written via `set_list_config`'s
|
||||
`verifyCommand` parameter (`ConfigMcpTools`), the only writer besides the UI's list config editor.
|
||||
`agent_path`, `max_turns`, `session_skills`, `permission_mode`; tasks override each individually
|
||||
(resolution lives in `EffectiveRunConfigResolver`, so `TaskRunner` and
|
||||
`get_effective_run_config` can't drift). `verify_command` and `serialize_on_file_overlap` are
|
||||
list-only — no task-level override. `verify_command` is written via `set_list_config`'s
|
||||
`verifyCommand` parameter (`ConfigMcpTools`) and the UI's list config editor;
|
||||
`serialize_on_file_overlap` and `permission_mode` are UI-only (`set_list_config` preserves but
|
||||
does not expose them).
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user