11.7.1 Decision — amend the ADR for the work-loop resources: paths and verbs, scope MIRRORING, the job-handle response shape, and the three projections as §8 additions
Deliverable: a new amendment to docs/decisions/public-api-conventions.md. Four questions, and the first is smaller than it looks because the shipped code already answers most of it.
Q1 — paths and verbs for ten operations
The ADR's §7 pins resource naming; these are the first operations that are not plain CRUD on a noun, so the shapes need deciding rather than deriving. Settle each, with the rejected alternative in one line:
- Dispatch prompt — a pure READ that assembles text.
GET /api/v1/work-items/{key}/dispatch-prompt, withsessionBranchas a query parameter? A sub-resource GET is the shape §7 implies; the alternative (POST …/dispatch-prompts) reads like a creation and this creates nothing. - Integration —
POST /api/v1/work-items/{key}/integration, or aPATCHon the item? It stampssession_branchand moves status in one transaction, so it is a state transition with a body, not a field edit. - Session close-out —
POST /api/v1/sessions/{sessionBranch}/complete. NotesessionBranchis a git ref and can contain/; decide the encoding rather than discovering it (a path segment needs escaping; a body field does not). - Expansion —
POST /api/v1/work-items/{key}/expansions, returning202-shaped semantics. - Plan sessions — addressed by SCOPE, never by id.
projectKey+ optional target keys is a composite address, which does not fit a path segment cleanly; decide where the anchor set travels. - Plan reads —
GET /api/v1/plans/{planId}and its status. Is status a sub-resource or a field on the plan? - Activity —
GET /api/v1/work-items/{key}/activity?view=, alongside the shipped…/comments. Decide whethercommentsstays a separate endpoint or becomes a view of this one; the shipped endpoint is public API under §8 and cannot be withdrawn either way.
Q2 — scopes MIRROR the shipped map; record WHY, do not re-derive
lib/mcp/scopes.ts already carries a total, reasoned Record<McpToolName, TokenScope> map covering all ten operations. The decision is to mirror it, and the amendment records the principle: one capability model, two transports — a token granting read means the same thing whichever door it arrives at. A v1-only mapping would make a scope's meaning depend on transport, which is the drift this epic exists to end.
⚠️ Verify the map rather than trusting this card's summary, then state the derived table. If mirroring looks wrong for a specific operation, the remedy is an amendment to the SHARED map with its reasoning updated — not a divergence. Note in particular that the map gates expand_item and the plan-session writes on work_items:write, explicitly reasoned as "the narrowest shipped scope that admits a plan-mutating, billable submit"; that reasoning has already rejected the integration alternative.
Q3 — how a JOB-SUBMITTING endpoint publishes "accepted, not finished"
Expansion and plan-submit return the instant motir-ai accepts the job. Nothing has been planned yet, and what eventually appears is a Plan of PROPOSALS that only a human approving turns into work items. Decide: the HTTP status (202 vs 200), whether the body carries a poll URL, and how the schema itself — not just its description — keeps a reader from mistaking the handle for a result. A response that reads like a finished outcome is a worse defect than a divergent one, because it will be consistently wrong on both surfaces.
Q4 — the three field projections are §8 ADDITIONS, and say so
Per-child dependencies, per-row dependencies, and the blocked ancestor's title are additions to shipped, published response schemas. §8 promises additive-only within a major, so they are permitted — but the amendment should say it explicitly, because "we added a field to a published response" is exactly the sentence a future reader will want to find a decision behind. Confirm the bounded-projection form (ADR Amendment 3 Q4) covers the two edge blocks, and that the ancestor title is a pure widening of data the DTO already carries.
Scope BOUNDARY
Ends at the ADR amendment. No code, no schema, no route, no test. It does NOT re-open §5 (pagination), §6 (rate limits) or Amendment 3's envelope split — those apply unchanged. It does NOT decide anything about the MCP surface, which this story does not touch.
Acceptance criteria
- The ADR carries a new amendment answering Q1–Q4, each with one chosen option and one line per rejected alternative.
- Q1 pins a path and verb for all ten operations, and explicitly settles the two shapes that do not fit a path segment cleanly: a
sessionBranchcontaining/, and a plan session's composite scope address. - Q2 states the mirroring principle, cites the shipped map as verified rather than remembered, and reproduces the derived operation→scope table.
- Q3 pins the status code and body shape for both job-submitting endpoints and says how the schema itself signals "accepted".
- Q4 records the three projections as §8-permitted additions with the bounded-projection form named.
- Every rejected option carries the reason it lost, in one line.
- No code changes: this card ships a document.
Context refs
docs/decisions/public-api-conventions.md— §7 (resource naming), §8 (additive-only), Amendment 3 Q4 (the bounded page-level projection), Amendment 5 (schema ownership).lib/mcp/scopes.ts— the map Q2 mirrors; read it, do not take this card's table as the source.lib/mcp/tools/dispatchPrompt.ts·markIntegrated.ts·completeSession.ts·expandItem.ts·planSession.ts·getPlan.ts·getWorkItemActivity.ts— the argument shapes Q1 turns into paths.app/api/v1/work-items/[key]/comments/route.ts— the shipped endpoint Q1's activity question has to live beside.lib/api/v1/pagination.ts— the cursor envelope the activity view's composite cursor must fit.- Story: 11.7.