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
144
planned
1,362
shipped

Motir · Work items

MOTIR-3130Done

Planning bug: `run.md` says the design-result publish is "keyed off the `design/MOTIR-<n>-<slug>` branch" — it is keyed off ANY resolvable `MOTIR-<n>` in the branch ref or the PR title, on every PR

Found 2026-08-19 while running MOTIR-3126, whose AC 1 puts a design asset and its implementation in one card — so the PR is a subtask/* one carrying design/repository-set/**.

The inaccuracy

motir-meta/prompts/run.md, in the motir run <parent> step-5 design-stopper block, states:

CI publishes the note + mock + screenshot onto the card from a step in ci.yml's design-guards job, keyed off the design/MOTIR-<n>-<slug> branch

The second half is narrower than the mechanism. Read on origin/main:

  • ci.yml's design-guards job has no branch condition — it runs on every pull_request (and on push: main, where the publish step alone is gated by if: github.event_name == 'pull_request').
  • scripts/upload-design-assets.mjs's resolveTargetKey takes the FIRST resolvable <PREFIX>-<number> from, in order: DESIGN_TARGET_KEY (explicit) → DESIGN_PR_REF (the branch ref) → DESIGN_PR_TITLE. The design/ prefix is not read, and no other branch check exists.

So any PR whose branch or title carries a MOTIR-<n> publishes its changed design assets to that card.

Evidence

PR #2158, branch subtask/MOTIR-3126-effective-repo-domain, run 32278643416, job 96151884665:

Published 3 design artifact(s) to MOTIR-3126 (target from branch); evidence cmt0c7tib01aai2phqh2mj761.

(target from branch) is the resolver naming which rung answered — a subtask/* branch, publishing exactly as a design/* one would.

Why it is worth correcting

The sentence reads as a precondition, and the cost of believing it runs in both directions:

  • A run that ships a design asset on a subtask/* branch concludes nothing was published, and either hand-publishes or splits the card into two PRs to get a prefix it never needed — which is a real cost, because ONE SUBTASK = ONE PR.
  • The opposite, and worse: a run that ships design assets on a branch carrying a DIFFERENT card's id (a drive-by asset edit inside a code PR) does not expect to publish and does — onto the wrong card. Nothing in the runbook warns about that today.

Acceptance criteria

  1. The run.md sentence names the real resolution order — DESIGN_TARGET_KEY → branch ref → PR title, first resolvable key wins — and says the job runs on every PR regardless of prefix.

  2. It states the consequence the current wording hides: a PR carrying design assets publishes them to whichever card its branch/title names, so a drive-by asset edit inside another card's PR lands on that other card.

  3. What the design/* prefix ACTUALLY buys is stated separately and correctly (it is a CI-SKIP prefix — Playwright/Vitest/images — not a publish key), so the two are not re-conflated.

    ⚠️ AMENDED 2026-08-20, motir run MOTIR-3130 — the PARENTHETICAL is FALSIFIED BY DRIFT, and the criterion is discharged as a POINTER. MOTIR-3148 (99826661, merged 2026-08-19T22:39+02:00 = 20:39 UTC) replaced ci.yml's startsWith(head_ref, …) gate with a changes job that reads the DIFF — every expensive lane now reads needs.changes.outputs.app / .images, and app is false only when every changed path is docs / design / plan-seed. This card was created 17:02 UTC the same day, so the parenthetical was TRUE when written and the drift POSTDATES it by ~3.5 h: genuine drift, not an enumeration that was wrong at authoring time.

    Restating it would put a freshly-false mechanism back into run.md, and MOTIR-3265 (todo, ready, same parent — "run.md's branch-prefix rule still cites the startsWith(head_ref, …) CI gate that MOTIR-3148 replaced") already OWNS that correction across step 8's paragraph, the worktree block and the Vercel prefixes. So the "not a publish key" half — this card's own claim — is stated, and the "what it IS" half is a POINTER to step 8 carrying no mechanism (notes.html #219: make the runner READ the shipped check rather than restate it in prose that can drift).

    Co-located write, NAMED not wired. One line inside the block this card rewrites also stated the stale mechanism ("the ONE CI lane a design/* branch does NOT skip (ci.yml skips Vitest / E2E / images on that prefix)"); leaving it would have made this card's own block self-contradictory three lines apart, so it became a pointer to step 8. That advances MOTIR-3265's AC 1 by one line and blocks none of its scope — whichever merges second rebases and must not replace. No blocked_by is owed; either order is correct. run.md line 1233 — step 8's own sentence — is left UNTOUCHED.

  4. No behaviour change in motir-core: this is a runbook correction only.

Context refs

  • motir-meta/prompts/run.md — the motir run <parent> step-5 design-stopper block
  • motir-core/.github/workflows/ci.yml — the design-guards job and its Publish the design result step
  • motir-core/scripts/upload-design-assets.mjsresolveTargetKey
  • motir-core/vitest.design.config.ts + ci.yml's skip conditions — what the design/* prefix actually gates

Delivered (2026-08-20, motir run MOTIR-3130)

motir-meta PR #297, branch docs/MOTIR-3130-design-publish-key — one file, prompts/run.md, +53/−4. Re-verified on origin/main ebd3a3df: ci.yml:350 (no if:/needs: on the job; only the publish STEP is gated on github.event_name == 'pull_request'), scripts/upload-design-assets.mjs:85 resolveTargetKey and :66 parseWorkItemKey, :362 collectChangedDesignFiles (-- design/**) and :336 classifyDesignPath. Every claim on this card holds exactly.

Two realisations of the AC-2 hazard, both POSTDATING this card, are now cited in the rule:

  • notes.html #337 / MOTIR-3177 — one transposed digit in a commit subject addressed 126 design artifacts to a manual billing task in another epic. Guarded since by DESIGN_EVIDENCE_NOT_A_CHILD.
  • MOTIR-3213MOTIR-3183's three design/ai-chat/* artifacts published onto MOTIR-3049, a pure /api/v1 card with no design subtask, evidence cmt1a0dcd0016i2n8a2sfu5gu, under a green check. Guarded since by failing RED on an untrusted diff base.

So the block now names the three structural guards that DO exist — NotALeafError, DESIGN_EVIDENCE_NOT_A_CHILD, the untrusted-base red — and says plainly that a drive-by asset edit on an ordinary LEAF branch passes all three (the key parses, the card is a leaf, the base is trusted). Naming which guards do not cover the case is what stops the next reader assuming one of them does.

One addition beyond the literal ACs, argued in the PR body: the run most likely to commit a drive-by asset edit is a plain motir run <leaf>, which never opens the motir run <parent> section — so the artifact-obtainable pre-done check (Build/serve rules, read by every run) gains a two-sentence pointer at the mis-publish direction. The mechanism itself is stated once.

Checks: motir-meta has no CI, no package.json, no lint/format gate. plan-rules/'s measure.py / conserve.py / verify.py are scoped to prompts/plan-rules/*.md and never read run.md — nothing to run, and nothing trimmed to chase a script. Not a UI change, so no "How to test" is owed. AC 4 holds: no motir-core file is touched.