docs: Ticketsystem-Anbindung in den CLAUDE.md-Dateien
Tickets/-Ordner, TaskStateService.NotifyAsync, ticket_api_base_url und TicketRef/
TicketProjectId dokumentiert. Verbatim-Copy-Warnung um TicketProjectId ergänzt und
den PermissionMode-Vorbestandsbug (SetConfigAsync liess das Feld im Update-Zweig
aus, gefixt in f0a3a186) vermerkt. docs/open.md um die fuenf offenen Punkte aus der
manuellen Verifikation des Specs ergänzt, inkl. Hinweis dass die Bandel-Response-
Shapes nie live verifiziert wurden.
This commit is contained in:
@@ -36,6 +36,10 @@ Worker/
|
||||
Prime/ — "Prime Claude" schedules: PrimeScheduler, PrimeRunner, PrimePrompts,
|
||||
DailyPrepPrompt, PrimeScheduleValidation, NextDueCalculator, PrimeScheduleSignal
|
||||
Online/ — optional Online Inbox sync (off by default; zero network when disabled)
|
||||
Tickets/ — Bandel ticket-system integration (per-list import + status write-back),
|
||||
inactive without ticket_api_base_url: TicketSystemConfig/TicketClientFactory,
|
||||
BandelTicketClient, TicketDtos, TicketStatusMap, TicketStatusSync,
|
||||
TicketImportService
|
||||
Usage/ — OAuth usage monitor, gate, throttle, per-session token reader;
|
||||
TokenTracker/ = the external analytics backend (cost + per-model/per-task breakdown)
|
||||
```
|
||||
@@ -46,7 +50,7 @@ subfolder within their area; the namespace stays the area namespace.
|
||||
## Architecture
|
||||
|
||||
- **Program.cs** — loads config, inits schema, registers DI, configures SignalR on `/hub`, binds to `127.0.0.1:47821`
|
||||
- **TaskStateService** — the **only** component that writes `Status`, `PlanningPhase`, `BlockedByTaskId`, `DependsOnTaskId`. All transitions return a `TransitionResult` (no exceptions on invalid moves). Wakes the queue and broadcasts `TaskUpdated` automatically; advances the planning chain on child terminal transitions. `SetDependsOnAsync` rejects a self-reference, an unknown dependency id, or a link that would create a cycle (walks the proposed predecessor's own `DependsOnTaskId` chain).
|
||||
- **TaskStateService** — the **only** component that writes `Status`, `PlanningPhase`, `BlockedByTaskId`, `DependsOnTaskId`. All transitions return a `TransitionResult` (no exceptions on invalid moves). Wakes the queue and advances the planning chain on child terminal transitions. Every transition broadcasts via a private `NotifyAsync(taskId)` — never call `_broadcaster.TaskUpdated` directly from this class, `NotifyAsync` also drives `TicketStatusSync.SyncAsync` (see Tickets below) and a direct call skips that transition's ticket write-back. `SetDependsOnAsync` rejects a self-reference, an unknown dependency id, or a link that would create a cycle (walks the proposed predecessor's own `DependsOnTaskId` chain).
|
||||
- **IQueueWaker / IQueuePicker / QueueService** — waker is a singleton `SemaphoreSlim`; picker performs the atomic `Queued → Running` claim filtered by `BlockedByTaskId IS NULL`, `is_manual = 0`, schedule, and (`DependsOnTaskId IS NULL` OR the dependency's `Status = 'done'`); QueueService is a thin `BackgroundService` looping on the waker, dispatching via `TaskRunner`. Per tick it also applies the usage throttle and gate → [usage-monitoring](../../docs/explore-notes/usage-monitoring.md).
|
||||
- **RunCancellationRegistry** — taskId → running-run CTS. Lets `TaskStateService.CancelAsync` kill a cancelled task's process without a DI cycle.
|
||||
- **OverrideSlotService** — owns `RunNow` / `ContinueTask`; goes through `TaskStateService.StartRunningAsync` (caller-driven, serialized by slot lock).
|
||||
@@ -245,10 +249,12 @@ 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` — `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.
|
||||
- `signalr_port` (47821), `claude_bin`, `ticket_api_base_url` — the two UI-writable fields
|
||||
(`claude_bin`: Settings → Dateien → CLAUDE CLI, hub `GetClaudeBin`/`SetClaudeBin`;
|
||||
`ticket_api_base_url`: Settings → Ticketsystem, hub `GetTicketSettings`/`SetTicketApiBaseUrl`).
|
||||
Both edit the DI-singleton `WorkerConfig` in place *and* persist via their own `SaveKey` call
|
||||
(`SaveClaudeBin`/`SaveTicketApiBaseUrl`), so each applies 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`.
|
||||
|
||||
@@ -258,8 +264,35 @@ Per-list config (`list_config` in DB) provides defaults for `model`, `system_pro
|
||||
`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).
|
||||
`serialize_on_file_overlap`, `permission_mode`, and `ticket_project_id` are UI-only
|
||||
(`set_list_config` preserves but does not expose them).
|
||||
|
||||
## Tickets (Bandel ticket system)
|
||||
|
||||
Optional, off by default. `TicketSystemConfig.IsConfigured` is the single gate (`worker.config.json`'s
|
||||
`ticket_api_base_url` set **and** a PAT present) — false costs nothing: no DB query, no network. The
|
||||
PAT is DPAPI-encrypted at `~/.claudeDo/ticket.pat` via `DpapiTokenStore` (same class the Online Inbox
|
||||
refresh token uses, one instance per file, DI markers `OnlineRefreshTokenStore`/`TicketPatStore`
|
||||
distinguish the two singletons). The token never touches `worker.config.json` or the DB.
|
||||
|
||||
- **Import** (`TicketImportService`, hub `ImportTickets`) — per-list, manual only (no polling): pulls
|
||||
the linked project's board (`ListConfigEntity.TicketProjectId`), keeps tickets that are `StatusId
|
||||
== 1` (Offen) *and* assigned to the PAT owner (case-insensitive name match), skips any `TicketRef`
|
||||
already present on the list, and creates one `Idle` task per remainder via `TaskRepository.AddAsync`
|
||||
(so it gets a `Number` like every other task). Already-imported tickets are never updated — a
|
||||
re-import would overwrite task notes.
|
||||
- **Write-back** (`TicketStatusSync`) hangs off `TaskStateService.NotifyAsync` — the one place every
|
||||
status transition passes through. Mapping: `Running`/`WaitingForReview` → ticket status `2
|
||||
InBearbeitung`, `Done` → `3 Fertig`, everything else writes nothing (`1 Offen` is never written
|
||||
back — it's the entry state). A task without a `TicketRef`, or a `TicketRef` not shaped
|
||||
`bandel:<id>`, is a no-op before any DB read. Per-process de-dupe (`taskId → last-written status`)
|
||||
skips the redundant `Running → WaitingForReview` PATCH. Never throws — a ticket-system failure logs
|
||||
a warning and does not block the status transition or the queue.
|
||||
- `BandelTicketClient` wraps the four REST calls (`GET /api/ticketsystem/pat/me`, `GET
|
||||
/api/Navigation/sidebar`, `GET /api/Board/project/{id}`, `PATCH /api/Ticket/{id}/status`); every
|
||||
response is unwrapped from `BandelEnvelope<T>` and a non-2xx/`success:false` throws
|
||||
`TicketApiException` with a readable message. ⚠️ The endpoint shapes were taken from the
|
||||
`Bandel.APIs` source, never confirmed against a live call — see `docs/open.md`.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user