Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-2445Done

`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:

  • ReadyItemkey · kind · title · priority · status · type · executor · assigneeId · assignee · descriptionExcerpt · inheritedSessionBranch · dependencies
  • WorkItemSummary (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

  1. parentKey: string | null on DispatchPromptDto (lib/dto/dispatch.ts), populated from the parent row dispatchPromptService ALREADY resolves — it reads parentRow for the prompt today and drops everything but the rendered line.
  2. The v1 DispatchPrompt schema + 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.
  3. The MCP dispatch_prompt payload 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).
  4. The CLI's DispatchPrompt view model + its adapter, so motir auto can read it.
  5. 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.parentKey is the parent's MOTIR-<n> key, or null for 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_prompt payload 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 — resolves parentRow today 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.