docs(tickets): document cross-project ticket import and open checks

This commit is contained in:
mika kuns
2026-10-01 08:45:54 +02:00
parent cb775958a7
commit 7724f5eb70
3 changed files with 30 additions and 7 deletions
+16 -5
View File
@@ -144,21 +144,25 @@ a follow-up prompt to an existing session via `--resume <session_id>`.
## Prime Claude
Every schedule carries a `PrimeActionKind` (`Ping` — the default for new schedules — `FillMyDay`,
or `Custom`). `PrimeRunner.FireAsync` holds one `SemaphoreSlim` gate for **all** kinds, then
`ImportTickets`, or `Custom`). `PrimeRunner.FireAsync` holds one `SemaphoreSlim` gate for **all** kinds, then
branches:
| Kind | Prompt | Args | Log + `Prep*` events |
|---|---|---|---|
| `Ping` | `PrimePrompts.PingPrompt`, fixed | `--max-turns 1 --strict-mcp-config` (no MCP server loads at all) | none |
| `FillMyDay` | `DailyPrepPrompt.BuildPrompt` (+ the schedule's prompt as an *addition*) | the two MyDay MCP tools | `daily-prep.log`, truncated per run, + `PrepStarted`/`PrepLine`/`PrepFinished` |
| `ImportTickets` | `TicketImportPrompt.BuildPrompt`, then the FillMyDay prompt (override appended to both) | step 1: `get_ticket_import_candidates` + `import_ticket`, max-turns 60; step 2: as FillMyDay | one `daily-prep.log` for both steps, one `PrepStarted`/`PrepFinished` |
| `Custom` | the schedule's prompt *verbatim* | `--allowedTools mcp__claudedo` — no Read/Write/Edit/Bash | none |
Ping and Custom deliberately write **no** log and raise **no** `Prep*` events: the prep log
belongs to the MyDay selection and would otherwise be overwritten with ping noise. All three
belongs to the MyDay selection and would otherwise be overwritten with ping noise. All four
kinds still broadcast `PrimeFired` and update `last_run_at`.
`WorkerHub.RunDailyPrepNow` (the "Plan day" button) pins its synthetic schedule to `FillMyDay` —
the button means "fill my day" no matter how the schedules are configured.
`WorkerHub.RunTicketImportNow` (the "Tickets + plan day" button) does the same for `ImportTickets`.
A failed import step never blocks the FillMyDay step; without a configured ticket system the kind
runs plain FillMyDay.
`WorkerHub.UpsertPrimeSchedule` runs `PrimeScheduleValidation.Validate` first, so a `Custom`
schedule can never be saved without a prompt.
@@ -287,6 +291,12 @@ distinguish the two singletons). The token never touches `worker.config.json` or
2026-09-01), so the original filter imported nothing, ever. `personInChargeName` is the wrong
source too: it holds the login on some rows and the display name ("Mika Kuns") on others, while
`ticketAssignees[].assigneeName` matches `/pat/me`'s `userName` format exactly.
- **Cross-project import** (Prime `ImportTickets`, MCP `get_ticket_import_candidates` / `import_ticket`) —
`TicketImportService.GetCandidatesAsync`/`ImportItemAsync` sweep sidebar → every project board. Tickets
match on `ticketAssignees`, tasks (`tasks[]`) on `ticketTaskAssignees`; board tasks with `hasChildren` are
skipped. Dedupe on `TicketRef` is across all lists (also in the per-list `ImportAsync`). `import_ticket`
without `list` uses `AppSettings.TicketFallbackListId` (written only via `SetTicketFallbackListIdAsync` /
hub `SetTicketFallbackList`, never by `UpdateAsync`); with no fallback set the item is skipped.
- **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
@@ -294,10 +304,11 @@ distinguish the two singletons). The token never touches `worker.config.json` or
`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
- `BandelTicketClient` wraps the five REST calls (`GET /api/ticketsystem/pat/me`, `GET
/api/Navigation/sidebar`, `GET /api/Board/project/{id}`, `GET /api/ticket/{id}` — works for tasks too,
live-verified 2026-10-01 — `PATCH /api/Ticket/{id}/status`); every
response is unwrapped from `BandelEnvelope<T>` and a non-2xx/`success:false` throws
`TicketApiException` with a readable message. All four are **live-verified (2026-09-01)** against
`TicketApiException` with a readable message. The first four are **live-verified (2026-09-01)** against
`http://192.168.45.161`.
⚠️ `PATCH /api/Ticket/{id}/status` needs **both** `statusId` and `statusName` — omitting the name
is a 400 (`"The StatusName field is required."`) and no status is written. The name is *not*