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

(motir-meta) Narrow the motir-meta PR-id rule — carry `MOTIR-<n>` when `targetRepo` IS motir-meta, so a card whose deliverable is a prompts change closes on its own merge

Done
Description

Repo: motir-meta. One PR. Amends one section of prompts/run.md; changes no other rule.

run.md's "PR titles drive the status sync" section says NEVER put MOTIR-<n> in a motir-meta PR's title or branch. Its stated premise is "a motir-meta PR is ABOUT a card, not that card's deliverable" — true of the lesson PRs it was written from, false of every card whose targetRepo is motir-meta.

The evidence, re-read

  • The mechanism is repo-agnostic. motir-core/lib/services/changeRequestStatusSync.tsresolveChangeRequestWorkItem parses `${cr.headRef} ${cr.title ?? ''}` and resolves within the connection's workspace. Nothing in the code distinguishes motir-meta; the rule is pure convention. (run.md also cites this as githubWebhookService.resolveWorkItem, which is not the shipped symbol — fix the citation in the same edit.)
  • The 2026-07-04 fixture does not support the blanket form. Lesson PRs #12–#14 carried planning-bug ids and the sync no-op'd. That was recorded as "todo cards survive only by luck". It was not luck: the default workflow has no todo → in_review and no todo → done edge, so no transition was ever legal. And MOTIR-1597's own body names "notes.html mistake #140 (motir-meta PR #13)" as where its lesson landed — the PR was the deliverable there too.
  • The cost is now measurable. MOTIR-2619 is a story with four children, every one targetRepo: motir-meta, delivered by one PR that — under the blanket rule — could not carry the id and so could not close any of them.

The narrowing

Carry the id iff the card's targetRepo is motir-meta — iff the PR IS the deliverable. Otherwise no id, in branch or title.

targetRepo is the discriminator deliberately: "is this PR about a card, or is it the card?" is a judgement a tired reader gets wrong, and targetRepo is a column set at plan time by gate 1.

The hazard the narrowing must NOT open

A run working a motir-core / motir-ai card that also lands a motir-meta lesson PR. If that lesson carried the code card's id, the lesson's merge would flip the card Done before its code PR merged — and MOTIR-1604's deferred_open_pr only defers when the code PR row already exists, so a lesson merging first counts zero open siblings and closes the card early. That case keeps the no-id rule, and run.md's drive-by rule already says the run closes such a card by hand.

Acceptance criteria

  1. prompts/run.md's "PR titles drive the status sync" section states the targetRepo-based condition, replacing the blanket NEVER, and keeps the no-id rule for a motir-meta change that RECORDS something about a card shipping elsewhere.
  2. The retained hazard is written with its mechanism — that the MOTIR-1604 defer counts open PR ROWS and cannot protect a card whose other PR does not exist yet.
  3. The 2026-07-04 evidence is re-read on the record rather than deleted, so the next reader does not re-derive the blanket form from the same near-miss.
  4. The stale githubWebhookService.resolveWorkItem citation is corrected to changeRequestStatusSync.resolveChangeRequestWorkItem, verified on origin/main.
  5. This card's own PR carries MOTIR-<n> in its title — the change dogfoods itself, and its merge closing this card is the proof.
  6. No other rule in run.md is touched.

Context refs

  • prompts/run.md"PR titles drive the status sync — carry MOTIR-<id> in the code repos, NEVER in motir-meta", the section amended.
  • motir-core lib/services/changeRequestStatusSync.tsresolveChangeRequestWorkItem + parseKeyCandidates, the shipped resolver.
  • MOTIR-2619 — the fixture: five cards one merge could not close.