docs: update for task-numbers features (Slice 5)
Document task-number allocation in Data layer (TaskEntity.Number,
next_task_number counter, invariants, insert paths).
Update Worker docs to clarify TaskIdResolver wiring (#123 → GUID lookup),
Number in MCP payloads, and correct the 'Two hard conventions' statement
(only the first is test-enforced).
Bump external-mcp.md verified-against commit to 38af549 (Slice 4 merge)
and add new sections on task ID resolution and numbering.
Add Slice 4 visual verification items to open.md (row/detail number display,
worker-log messages).
Verified against:
- src/ClaudeDo.Data/TaskNumberAllocator.cs
- src/ClaudeDo.Data/Repositories/TaskRepository.cs (AddAsync line 20, CreateChildAsync line 276)
- src/ClaudeDo.Worker/External/TaskIdResolver.cs
- src/ClaudeDo.Worker/External/ExternalMcpService.cs (TaskDto/TaskRefDto DTOs)
- tests/ClaudeDo.Worker.Tests/External/ExternalMcpToolSchemaTests.cs (only first convention test-enforced)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# External MCP tool surface
|
||||
|
||||
> **Explore-note — verify before trusting.** Distilled map of a subsystem, not authoritative.
|
||||
> Last verified against commit `6a2a19c` (2026-08-10).
|
||||
> Drift check: `git log --oneline 6a2a19c..HEAD -- src/ClaudeDo.Worker/External`
|
||||
> Last verified against commit `38af549` (2026-08-11).
|
||||
> Drift check: `git log --oneline 38af549..HEAD -- src/ClaudeDo.Worker/External`
|
||||
> Stable structure only (no line numbers). See docs/explore-notes/README.md.
|
||||
|
||||
Covers `src/ClaudeDo.Worker/External/` — the always-on MCP tools ClaudeDo exposes to general
|
||||
@@ -14,11 +14,34 @@ need no `--mcp-config`.
|
||||
and git/merge operations. They deliberately do **not** expose multi-turn control, planning
|
||||
session internals, or app-settings writes. Auth via an optional `X-ClaudeDo-Key` header.
|
||||
|
||||
## Hard conventions (enforced by tests)
|
||||
## Task ID resolution and numbering
|
||||
|
||||
Every tool parameter accepting a task id — `taskId`, `parentId`, `taskIds` arrays, and similar —
|
||||
is wired through `TaskIdResolver`, which resolves:
|
||||
- `#123` (with or without the `#` prefix) → look up by `TaskEntity.Number`
|
||||
- Bare GUID string → use as-is
|
||||
- Unknown number → `InvalidOperationException` (`no task with number 123`)
|
||||
|
||||
This is **not** ambiguous: a GUID is never all-digits, so a pure-integer parameter is always a
|
||||
number, not a partial GUID. All task-returning tools (`GetTask`, `ListTasks`, `AddTask`,
|
||||
`BatchGetTasks`, etc.) stamp the resolved task's `Number` in the DTO — both `TaskDto` and the
|
||||
lean `TaskRefDto` carry an `int Number` field. **Branch names and worktree paths** (`claudedo/{id}`)
|
||||
continue to use the GUID; the number is a display alias, never the identity.
|
||||
|
||||
Every tool description carries a shared boilerplate clause (defined in `McpToolDocs.TaskNumberHint`)
|
||||
instructing the agent to **refer to tasks as `#<number>` when reporting results to the user** —
|
||||
without this the agent sees the number in every payload but never learns to speak it.
|
||||
|
||||
## Conventions
|
||||
|
||||
### Test-enforced
|
||||
|
||||
1. **Every optional/filter parameter needs a C# default value** (e.g. `string? status = null`).
|
||||
The MCP schema only marks a parameter optional when it has one — nullability alone does
|
||||
not do it. `ExternalMcpToolSchemaTests` guards this by reflection.
|
||||
|
||||
### Not test-enforced, but strongly observed
|
||||
|
||||
2. **No tool returns bare `Task` or a nullable payload directly.** An MCP client cannot tell
|
||||
an empty/omitted response apart from a dropped one.
|
||||
- *Write* tools return a small confirmation record — `{ ok/deleted/removed/reset/started:
|
||||
@@ -32,13 +55,15 @@ session internals, or app-settings writes. Auth via an optional `X-ClaudeDo-Key`
|
||||
`ListTasksResult`/`BatchGetTaskResult`, where exactly one of the lean (`TaskRefDto`) and
|
||||
full (`TaskDto`, incl. Description/Result) fields is populated per the flag — keeps a
|
||||
list of verbosely-described tasks from blowing past the response size limit by default.
|
||||
|
||||
3. **Description style is documented in `McpToolDocs`** (same folder) and shared boilerplate
|
||||
lives there as `const` strings. Rules: the first sentence says what the tool does *and* when
|
||||
to reach for it (MCP clients rank tools by that text, so the trigger must not sit behind
|
||||
return-shape prose); parameters are documented with `[Description]` **on the parameter**, not
|
||||
in the tool description; result fields appear only where the caller must branch on them
|
||||
before calling (`isEmpty`, `truncated`, `conflicts`, `available`); no design rationale or
|
||||
"since this feature was introduced" history. Not test-enforced — review it in PRs.
|
||||
"since this feature was introduced" history.
|
||||
|
||||
4. `ExternalMcpExceptionFilter.Wrap` is registered as a call-tool filter so
|
||||
`InvalidOperationException` / `ArgumentException` messages survive as `McpException` —
|
||||
otherwise the SDK's catch-all replaces any non-`McpException` with a generic
|
||||
|
||||
@@ -81,6 +81,21 @@ verifiziert und deshalb hier entfernt. Es bleiben die Entscheidungen, die daran
|
||||
`dotnet test` invocation as the configured command) — only fast synthetic commands (`exit N`,
|
||||
`ping` for timeout) were exercised.
|
||||
|
||||
## Offene Verifikation (2026-08-11, Task numbers in UI)
|
||||
|
||||
Slice 4 der Task-Numbers-Features (UI-Display) ist gemerged (commit 38af549); Build + Tests grün,
|
||||
aber **nicht visuell verifiziert**:
|
||||
|
||||
- **Task Row Display:** `TaskRowViewModel.Number` (Zeile 39, TaskRowViewModel.cs) zeigt die
|
||||
Nummer als `#<number>` dimmed vor dem Titel in der Row an (`TaskRowView.axaml` Zeile 45+). Prüfen:
|
||||
offene Task in der Übersicht hat sichtbar `#<number>` vor dem Titel.
|
||||
- **Detail Pane Header:** `DetailsIslandViewModel.TaskIdBadge` (Zeile 77, DetailsIslandViewModel.cs)
|
||||
zeigt jetzt `#<number>` statt des alten GUID-Präfix. Prüfen: Task-Detail-Chip zeigt
|
||||
`#<number>`.
|
||||
- **Worker Log Messages:** Geschäftsereignisse in `TaskRunner` (Zeile 199+), `TaskMergeService`
|
||||
(Zeile 174+), und `TaskResetService` (Zeile 84+) prefixen Task-Titel mit `#<number>`. Prüfen:
|
||||
Footer Worker-Log zeigt Task-Messages wie „`#42 finished`" statt nur dem GUID.
|
||||
|
||||
## Offene Verifikation (2026-08-06, Fix-Batch aus der Sichtprüfung)
|
||||
|
||||
Fünf Findings der Sichtprüfung sind gefixt, Build + Tests grün, aber **noch nicht in der App
|
||||
|
||||
Reference in New Issue
Block a user