MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-3524

(motir-core) The re-plan submit SETS `context.replanTrigger` — MOTIR-3324 ships a consumer that nothing populates

To Do
Description

The PRODUCER half of MOTIR-3324's seam. That card shipped the CONSUMER — motir-ai declares and defensively parses context.replanTrigger off the re-plan job envelope, and refuses to capture a planning mistake when the field is absent or unrecognised. Nothing sets it. So parseReplanTrigger returns null on every real re-plan in production, replanMayCaptureMistakes refuses, and the capture tools are withheld from every re-plan — the consumer is correct, tested, shipped, and permanently in its fallback arm.

Filed by the close-out of MOTIR-3369, the planner-bug record for how the seam went unowned: MOTIR-3324's body resolved the cross-repository question with a CONDITIONAL ("if the envelope has to change in the other repository, that half is a named sibling card"), and the run that met the conditional is the one actor that creates no work items — so the criterion asking it to NAME the sibling could only be discharged in prose.

What to build

motir-core composes the re-plan job envelope. It must populate context.replanTrigger on it:

  • agent_card_wrong — when a dispatched agent's run concludes the card is wrong: the motir run / scoped-run re-plan path.
  • user_initiated — when a person re-plans from the planning UI.

The value set and the parse are already shipped on the consumer side (motir-ai src/envelope.ts: JobContextBag.replanTrigger, REPLAN_TRIGGERS, parseReplanTrigger, replanMayCaptureMistakes), so this card adds no new vocabulary — it populates a reserved hole in a loosely-typed context bag that already accepts it. No motir-ai change is required and none is in scope (one subtask = one repo = one PR).

Acceptance criteria

  1. Every re-plan job envelope motir-core submits carries context.replanTrigger, set to agent_card_wrong on the agent-driven re-plan path and user_initiated on the human one. The two call sites are named in the pull-request body.
  2. A test at the submit seam asserts the field is present and correct for BOTH paths, read back off the envelope the submitter actually sends — not off a hand-built object.
  3. The consumer's own refusal is proven to flip: a test drives an envelope carrying agent_card_wrong through the re-plan submit and asserts the field survives to the wire shape motir-ai parses. Where the boundary makes that unassertable from motir-core, use a recorded contract-seam fixture of the envelope's shape rather than weakening the criterion (plan-rules/phase-deepen.md's SUBSTRATE limb).
  4. An envelope submitted by any path that is NOT a re-plan is unchanged — no field added, no shape change.
  5. The pull request states what the field currently does in production (nothing is set, so every re-plan refuses capture) and what changes after deploy.

Context refs

  • MOTIR-3324 — the consumer, shipped and correct; its fallback is deliberate and defended.
  • MOTIR-3369 — the planner-bug record that filed this.
  • motir-ai src/envelope.ts · src/jobs/handlers/replan.ts — the consumer side, EVIDENCE not deliverables; nothing here edits them.

Parentless at the root deliberately. Every ancestor of MOTIR-3324 is done (MOTIR-3322, and the epic MOTIR-3293), and a not-done card may not acquire a done parent — a create recomputes the parent from its current child set and applies the result BACKWARD, re-opening the whole ancestor chain. We plan forward; relates_to carries the discovery trace.

Status
To Do
Type
Feature