Build item_store v2 with per-kind fields and batches #315
Description
The largest part of #309. Built on the existing data model: the revision removal is #320 and the visibility change is #321, both after the switch.
Done (cceec82 single items, 12c0d1d batches)
src/Conderis/Services/Items/ItemStoreTools.cs (not registered until #317), TaskService.Move and CreateMany, DocumentService.CreateMany, BatchLedger; tests in ItemStoreToolsTests, and the tool in BuiltV2ToolsMatchTheMeasuredSchemas.
Single items
fieldsper kind validated on the server; a field of another kind is refused naming its kind and the allowed fields ("'summary' is a field of a memory, not of a task"),descriptionon a task points tocontent.- One patch rule: omitted keeps,
nullclears;nullon a required field (title, summary, status, priority) is refused. - One
version: a content change needs the version fromitem_get; a missing or stale one is refused naming the current version. For memories, pages and instructions the version is mapped to its revision internally; proposals recordbaseVersionnext tobaseRevisionId. No revision id in any request or response. - Moves need no version and keep it:
TaskService.Movechecks the parent and cycles in a serializable transaction; a page move repeats itself when another move landed in between, so the last move wins. A text change succeeds after a concurrent move (tested). status: blockedis refused with a pointer toitem_action block; a new task starts open.typeandvisibilityof a memory are fixed after creation. Instructions need the version once they exist.propose: trueforces a proposal for shared memories, pages and instructions; tasks are never reviewed. A missing write permission is the outcomedeniedwithrequiredCapability.- The agent key setting "always review" was split off as #323.
Batches (decided 2026-09-19: mixed kinds, each kind atomic on its own)
- Tasks, pages and memories are written by separate services with their own transactions, so a mixed batch cannot be atomic as a whole without rebuilding them on one transaction. Each kind is stored atomically; a failing kind stores nothing of itself, is reported with its error, and leaves the other kinds stored (
outcome: partial). - Every kind records its result under
idempotencyKey:task,:pageand:memory. Sending the same batch again replays the stored kinds and retries only the failed one; a reused key with another payload is refused. - Up to 100 items and 1 MB; keys unique;
parentnames an earlier item of the same kind or an existing number; the instructions are not batched. - Pages in a batch are published directly and need moderation rights; without them the page group is refused with a hint to propose pages one at a time. Shared memories of a caller who must be reviewed become proposals, one per memory, as memory batches did before.
- The Conderis Memory Batch v1 file is accepted unchanged under its own idempotency key, so files sent through
memory_storereplay the same result. - The
item_storedescription now says "each kind atomically"; the v2 list is 6,462 characters.
Not covered by an automated concurrency test: two crossed task moves that would form a cycle, and two simultaneous page moves. Both rely on the serializable transactions the services already use (#271).