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-3273

Planning bug: a STACKED design PR merged into its already-merged base branch, so its deliverable never reached main while the card read done

Done
Description

Type: process / tooling defect found by motir run MOTIR-3232 · Parent: MOTIR-1465 (the planner-bug home) · Repo: motir-core.

What happened

Story MOTIR-3232 has two design children that both amend the same area. Their deliverables were cut as stacked branchesMOTIR-3234's PR (#2226) based on MOTIR-3233's branch — because at the time both cards amended the SAME three files, including a binary .png, so two branches off main would have conflicted by construction.

Both were merged by hand, 13 seconds apart:

merged at
#2225 (MOTIR-3233) → main2026-08-20T21:28:51Z
#2226 (MOTIR-3234) → design/MOTIR-3233-plans-list-part-vii2026-08-20T21:29:04Z

GitHub retargets a stacked PR to main when its base branch merges, but that retarget had not happened yet. So #2226 merged into the already-merged, now-stale base branch and its content never reached main. Verified: git ls-tree origin/main design/ai-planning/ holds plans-tabbed-list.* (Part VII) and no plan-detail-list-view.* (Part VIII).

Why it is a PLANNING bug and not just an operator slip

Every signal was green and none of them was looking at the branch.

  1. The status sync flipped MOTIR-3234 to done on a merged linked pull request without checking which branch it landed on. changeRequestStatusSync resolves a delivery to a work item and acts on merged; the base ref is not part of the verdict.
  2. Readiness therefore said yes: MOTIR-3239, MOTIR-3240 and MOTIR-3259 are blocked_by MOTIR-3234, so a done card made all three claimable — against a design asset that is not in the repository. The next run would have built to a mockup it could not open.
  3. The design result was published onto the card (evidence cmt20to6g001si4phk3b9ifg1), from a job that ran on the branch — so even the artifact-obtainable check passes on a deliverable main does not have.

This is the merged ≠ in the tree shape one tier up from merged ≠ deployed: the card records that a pull request merged, and nothing records where.

Fix direction — two halves, and the second is the durable one

  1. The immediate repair (already done, NOT this card's scope): the same commit cherry-picked onto current origin/main as #2227, and MOTIR-3234 rolled done → in_progress → implemented so it reads as what it is.
  2. The general rule. A merged pull request whose baseRefName is not the repository default branch must NOT close its work item. Options, in order of preference:
    • the sync compares the delivery's base ref against the repo default branch and, when they differ, records the merge and defers — the same shape as MOTIR-1604's deferred_open_pr — with a new outcome such as deferred_stacked_base;
    • failing that, it closes the card only once the merge commit is an ancestor of the default branch.

And a corpus half: run.md has no rule about stacked pull requests at all, which is how a run reached for one without recording the merge-ordering hazard it creates. A stacked PR set is safe only if the base is RETARGETED before the stack is merged — 13 seconds was enough to lose this one.

Acceptance criteria

  1. A merged pull request whose base is not the repository default branch does not transition its linked work item to done; the outcome is recorded and named, and a test drives a merge with a non-default base and asserts the card stays where it was.
  2. The existing behaviour for a default-branch merge is unchanged — a test asserts a normal merge still closes its card.
  3. The decision is recorded where the sync's other deferral is (MOTIR-1604's deferred_open_pr neighbourhood), so a reader meets both deferrals together.
  4. run.md gains one paragraph on stacked pull requests: when a run may cut one, and that the base must be retargeted before the stack is merged.

Context refs

  • lib/services/changeRequestStatusSync.tsresolveChangeRequestWorkItem and the merged-delivery path; countOtherOpenByWorkItem is the existing deferral to sit beside.
  • The two pull requests above, and #2227 which repairs the content.
  • motir-meta/prompts/run.md — the build/serve rules, which today say nothing about a stacked PR.