`DispatchPromptDto` carries `parentKey` — promote the parent the prompt already renders as prose into a structural field
Carved out of MOTIR-2422 by a re-plan (2026-08-08). That card wants the run's pull-request TITLE to name the shared parent of the cards it carried, and its acceptance criterion is that the parent read costs one request per run. No such read exists.
The finding that produced this card
parentKey is on exactly three generated components — WorkItemDetail, WorkItemLinkGroups, WorkItemRef — and every operation returning one is addressed by a single {key}: GET /work-items/{key}, PATCH /work-items/{key}, POST …/{key}/transitions · …/archive · …/restore, GET …/{key}/links, POST /projects/{projectKey}/work-items.
The three collection rows a loop could read in bulk all omit it:
ReadyItem—key · kind · title · priority · status · type · executor · assigneeId · assignee · descriptionExcerpt · inheritedSessionBranch · dependenciesWorkItemSummary(GET …/projects/{projectKey}/work-items)- the search page's rows
So parents for a four-card run is four requests. The criterion is unsatisfiable as written, and the two obvious workarounds each trade away something 2422 names as the point.
Why the DISPATCH PROMPT is the right place
The parent is already in it — as prose. lib/dispatch/promptTemplate.ts §contextSection renders - Parent: PROD-2 — Ready surface (or - Parent: none (top-level item)) via refLine. So the server already resolves the parent for every dispatch, and the loop already makes that read once per item.
Promoting it to a field on DispatchPromptDto costs zero additional requests and removes the alternative's real defect: a CLI that regex'd the prompt text would be coupled to the server's prompt GRAMMAR, and a wording change would silently degrade every title to the fallback with nothing failing.
It also does not reopen the collection-row question 2422 forbids. targetRepo set the precedent in the other direction — ADR Amendment 10 Q2 kept it OFF the ready row and read it from the dispatch prompt instead, for the same reason: a per-item read is the honest home for a per-item fact.
What to build
parentKey: string | nullonDispatchPromptDto(lib/dto/dispatch.ts), populated from the parent rowdispatchPromptServiceALREADY resolves — it readsparentRowfor the prompt today and drops everything but the rendered line.- The v1
DispatchPromptschema + the emitted document, so the generated client sees it. Additive under ADR §8 — a new nullable field on an existing response — so it is a MINOR contract bump, not a major. - The MCP
dispatch_promptpayload too, so the two surfaces stay identical (the two-surface conformance suite asserts they agree; a field on one and not the other fails it). - The CLI's
DispatchPromptview model + its adapter, somotir autocan read it. - The prompt TEXT is unchanged. The field mirrors what the prose already says; changing the rendering would be a separate decision and would break the byte-identical prompt contract MOTIR-881 asserts.
Scope BOUNDARY
The field, end to end: DTO → v1 schema → emitted spec → MCP payload → generated client → CLI view model. It does NOT build the title (MOTIR-2422, which this unblocks). It does NOT add the field to any COLLECTION row — that is the decision 2422 forbids reopening and this card deliberately routes around. It does NOT change the prompt's rendered text, its assembly, or assembleDispatchPrompt's signature.
Acceptance criteria
DispatchPromptDto.parentKeyis the parent'sMOTIR-<n>key, ornullfor a top-level item — asserted for both, against a real item with a parent and one without.- The value equals what the prompt's own
- Parent:line names, asserted on the same assembled prompt — the field and the prose cannot disagree, which is the whole reason to prefer a field over parsing one. - The v1 response validates against the regenerated client, and the contract's MINOR version is bumped with its changelog entry (ADR §8 — additive within a major).
- The MCP
dispatch_promptpayload carries it too, and the two-surface conformance suite still passes. - No new request is made anywhere: the parent row is already read by
dispatchPromptService, asserted on the query count. - The prompt TEXT is byte-identical to its pre-change form, asserted — this card adds a field, it does not touch the grammar.
Context refs
lib/services/dispatchPromptService.ts— resolvesparentRowtoday and uses it only for the prompt line.lib/dispatch/promptTemplate.ts§contextSection/refLine— where the parent is rendered as prose.lib/dto/dispatch.ts·lib/api/v1/workLoop/schema.ts— the DTO and the v1 shape.packages/cli/src/client.ts§DispatchPrompt·src/adapters/reads.ts§toDispatchPrompt.- ADR Amendment 10 Q2 — the precedent: a per-item fact belongs on the per-item read, not on a collection row.
- Unblocks: MOTIR-2422.
- Story: MOTIR-1855.