11.5.17 `searchWorkItems` onto the v1 collection, and the four `total` readers onto `countWorkItems`
Port MotirClient.searchWorkItems onto GET /api/v1/projects/{projectKey}/work-items, and carry out the consumer half of ADR Amendment 11 Q3: SearchPage.total goes away, countWorkItems arrives over 11.5.16's …/work-items/count, and each of the six total reads routes to whichever of the two it actually meant.
Why this is NOT part of 11.5.4
Same shape as nextReady, and the same rule. Amendment 11 Q3 settles that the count-only sites stop pretending to be searches — but three of the six total reads live in command files, which 11.5.4's boundary forbids touching ("does NOT change … any command file"):
packages/cli/src/commands/read.ts:105—inFlightCount: search.total, from alimit: 1searchpackages/cli/src/commands/read.ts:188—renderSprintItems(result.items, result.total)packages/cli/src/commands/doctor.ts:80—total: page.total, from alimit: 1searchpackages/cli/src/commands/plan.ts:163—if (page.total > 0) return;
The other two are outside that boundary but belong with them: packages/cli/src/session.ts:128 (total = page.total, inside a full page walk) and packages/cli/src/doctor.ts:319 (renders the ServerProbe.project.total the command sets).
Keeping total on SearchPage by having searchWorkItems ALSO call /count was considered and rejected: it makes two requests where one sufficed on motir status and motir doctor, and it ships the shape Amendment 11 explicitly named as the wrong one.
The split, per read
| site | becomes |
|---|---|
commands/read.ts:105 · commands/doctor.ts:80 | countWorkItems — they send limit: 1 and discard the row. They are counts. |
commands/plan.ts:163 | countWorkItems — > 0 is a count question. |
session.ts:128 | items.length — it already walks every page, so it HAS the number. |
commands/read.ts:188 | Follows whatever collectSprintItems returns after the session.ts change. |
doctor.ts:319 | Unchanged — it renders ServerProbe.project.total, which the command still sets. |
Scope BOUNDARY
searchWorkItems, the new countWorkItems, and the six reads above. It does NOT touch render.ts (a diff on it fails this card, the same as 11.5.4), any other command, any flag, or any output string — motir status, motir doctor and motir plan must print byte-identically. It does NOT change a server endpoint: 11.5.16 shipped everything the server owes this card.
Acceptance criteria
searchWorkItemscalls/api/v1/projects/{projectKey}/work-itemsthrough the transport, sending the versioned FilterAST envelope, and returns the same result set the MCP tool did for an identical filter.countWorkItemscalls…/work-items/countand is the ONLY way the CLI learns a match count.SearchPageno longer declarestotal; no file reads it.motir status,motir doctorandmotir planproduce byte-identical output to the MCP-era implementation for the same underlying data, asserted per command.motir statusandmotir doctoreach make ONE request for their count, not a paging walk and not a search-plus-count.render.tsis byte-identical to its pre-card state.- No generated wire type is imported outside the adapter module.
- The per-file coverage floor (≥90%) holds on every new and modified file.
Context refs
- ADR
docs/decisions/public-api-conventions.mdAmendment 11 — Q3 is this card's brief. - 11.5.16 — the count operation this consumes.
- 11.5.4 — the adapter module and transport wiring this builds on.
packages/cli/src/mcpClient.ts—searchWorkItems,SearchPage.packages/cli/test/helpers/mcpTestServer.ts— must serve/api/v1for these wrappers, as 11.5.4 establishes.- Story: 11.5.