docs(tickets): document cross-project ticket import and open checks
This commit is contained in:
@@ -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*
|
||||
|
||||
Reference in New Issue
Block a user