Planning bug: a card's post-merge PUBLISH obligation was recorded as a comment and offered as a question ("say so and I will propose one") instead of filed as a card — MOTIR-1456 went `done` with `@motir/brand` unpublished, and MOTIR-1152 hit it eight hours later
Found by motir run MOTIR-1152, 2026-08-28, which halted at guard #4 because the landing it was told to build composes @motir/brand and that package does not exist on npm.
What happened
MOTIR-1456 shipped packages/brand/ correctly (motir-core#2387, merged 2026-08-28, version 0.1.0 on origin/main). Its own acceptance criteria included the artifact-obtainable gate, in its own words: "bump the version, merge, push the release tag, and pull the published tarball anonymously from npm, quoting the digest in the PR body and on this card — the tag push is a post-merge step, not a fake one."
That step was never performed, and the card closed anyway. Measured 2026-08-28:
npm view @motir/brand -> E404 (the deliverable)
npm view @motir/design-system -> 0.1.0 (control, same registry)
npm view @motir/cli -> 0.3.0 (control, same registry)
git ls-remote --tags origin | grep -E 'brand|design-system'
-> design-system-v0.1.0 only; no brand-v*
The defect is the DISPOSITION, not the omission
The run that built MOTIR-1456 knew, said so precisely, and then wrote the obligation into a place nothing re-reads. From its closing comment:
"⚠️ The remaining step is yours, and it is the one an agent cannot do…
@motir/brand@0.1.0must be published by hand… This card is not genuinely finished until that tarball is pulled anonymously from npm and its digest recorded here — I will do that and comment the digest once 0.1.0 is up. If you would rather the hand-publish were its own trackedmanualcard, say so and I will propose one."
Three rules were in scope and each says the same thing:
run.md— A RECORDED DEVIATION that names an OPEN defect is abugto FILE — never a paragraph. The discriminator is "does the text describe something that will STILL BE TRUE after this card isdone?" It plainly does. The tell-phrases that rule lists as grep-able are present almost verbatim ("the remaining step is yours", "I will do that… once").run.md— the artifact-obtainable pre-donecheck. It already routes this exact case: "If a human must cut it or flip a visibility switch…, that is amanualcard you surface per guard #2, not something you fake."run.md—motir runNEVER asks the user a question (a hard rule). The run converted a MANDATORY filing into an offer conditional on the user answering. Nobody answered — the expected outcome of an unprompted offer at the end of a long comment — and the merge then flipped the carddone(thelikely-ordering-violationthe run had itself read and left).
And the containing card gave no signal, structurally. motir-core consumes the package as "@motir/brand": "workspace:*" with pnpm --filter @motir/brand build in postinstall, so its build, typecheck, tests and all thirteen BrandMark import sites resolve through the workspace link and never touch the registry. Every in-repo signal was green and correct. The only consumer that would have noticed is a separate repository — i.e. the card this one blocks.
Cost
Eight hours later motir run MOTIR-1152 claimed the landing card, read blocked_by MOTIR-1456: done, readiness.ready: true, openBlockers: [], and was one pnpm add from a build failure — or, worse, from one of the two "workarounds" the tree forbids: copying the .brand-* block into motir-marketing (contradicting MOTIR-3724's ADR, decided the day before) or shipping motir.co with no logo. It was caught only because the run ran the CONSUME-side artifact check by hand — npm view before pnpm add — rather than trusting a done sibling.
Fix
- A LESSON row in
motir-aisrc/seed/lessons.base.ts+ its generated migration. GLOBAL by the strip-the-identifiers test: nothing in the takeaway is Motir-specific — it is a property of workspace-protocol monorepos and of npm/OIDC trusted publishing. That row is this card's deliverable. - The remedy for the instance is not this card: it is the
manualpublish subtask proposed as8.3.13on plancmtd9uvb5012shwn8r5gek4ro. - No rule change is owed. All three rules above already exist and already say the right thing; this is a rule that was not applied, not a rule that was missing. Do not write a fourth restatement of it in
motir-meta— that is why this card pins one repository and not two.
Acceptance criteria
- A lesson exists in the GLOBAL corpus whose takeaway is that a card shipping a new distributable can go
donewith nothing published — because in-repo consumers resolve it by workspace link and never read the registry — and that a first publish only a human can perform owes its own card BEFORE the producing card can close, never a comment and never an offer to file one. - The row names no repository, work-item key, file path or date in
title/body/howToApply(the seed suite asserts exactly this); the Motir-specific context goes inwhy, which is not embedded. - Its
kinds/types/phasesaxes are set deliberately rather than left empty, andsourceRefisMOTIR-3793. pnpm lessons:generate-migrationis run and the emitted migration is committed in the same pull request.- ORDERING — this card reads only on
motir-ai's own tree and is startable now. It does not wait on8.3.13, on the npm publish, or on MOTIR-1152: recording the takeaway is independent of repairing the instance.
Context refs
relates_toMOTIR-1152 — the run that found it · MOTIR-1456 — the card that closed with the obligation outstanding (its comment thread, 2026-08-27 23:10Z)motir-core/.github/workflows/release-brand.yml— the bootstrap constraint that makes the first publish a human act- Blocks nothing. This is telemetry about the planner; the correction to the plan is already submitted as a plan.
Comments (0)
No comments yet — be the first to weigh in.