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

Planning bug: a story planned building a column that already shipped, and a `manual` card the pipeline can do — the lesson forbidding the second was IN the store, where the runbook planner cannot read it

Done
Description

Discovered 2026-08-21 by Yue, on MOTIR-3296: "we will add new lessons in the future, so we should add lesson with db migration which will run automatically in CI." Verifying that instruction surfaced a second, larger defect in the same plan.

Defect 1 — a negative asserted, not grepped

MOTIR-3294 was authored claiming the lesson store has "no way to say which kind or type of card a lesson applies to", and its children planned a schema change and migration to add one. All of it already ships:

planned as newon origin/main
a set-valued category columnLesson.categories String[]
set-membership filteringAND "categories" && ARRAY[…]::text[]
empty ⇒ universalthe clause is OMITTED when no categories are supplied
categorized rows['ordering','design','task-type','tooling'] on seed rows

The real gap is two orders smaller: the values are topical rather than structural, and SelectForInjectionInput has no categories field, so the planner's one shared helper cannot reach a filter that exists one layer below it.

This is an occurrence of phase-deepen.md's NEGATIVE limba negative is the only claim you can write without looking at anything — not a new rule. Bump that limb's warrant count; do not add a sibling rule. One git grep categories on the model would have closed it.

Defect 2 — a manual card the pipeline can do, forbidden by a lesson already in the store

MOTIR-3307 was authored type: manual, executor: human: run the seed against the deployed database. fly.toml's release_command is pnpm prisma migrate deploy, so the pipeline applies data migrations on every release with no operator.

lessons.base.ts already carries the lesson that forbids exactly this:

"check whether the service's deploy pipeline already runs migrations automatically on release … ship environment-specific DATA as a forward-only, guarded, idempotent data migration rather than a hand-run script … Reserve manual/human for work the pipeline genuinely cannot do — dashboards, secrets, third-party accounts — not for data a migration can carry."

It could not reach the planner who needed it. The runbook searches notes.html (the MOTIR-819 rule); this lesson lives in the product's retrieval store, which the runbook never queries. A lesson that is correct, on-point and unreachable is the exact failure MOTIR-3293 exists to fix, demonstrated against the plan for that epic.

Acceptance criteria

  • The NEGATIVE limb's warrant count is bumped with this occurrence; no new rule is added for defect 1.
  • run.md's mistakes-corpus step (MOTIR-819) states that the runbook's lesson search covers notes.html ONLY, and that the product's store holds lessons the runbook cannot see — so a planner authoring against motir-ai reads lessons.base.ts too, until the epic makes one corpus of them.
  • The store's deploy-pipeline lesson is present in notes.html as well, or the card records that it is and names the entry.
  • notes.html carries the matching entry for this incident, with both defects.
  • Lands via a branch + PR; no direct commit to main.

Context refs

  • motir-ai prisma/schema.prismaLesson.categories String[], the column planned as new work.
  • motir-ai src/repositories/lessonRepository.ts — the overlap clause and its omit-when-empty behaviour.
  • motir-ai src/seed/lessons.base.ts — the deploy-pipeline lesson, and the rows already carrying categories.
  • motir-ai fly.toml release_command · .github/workflows/ci.yml:107.
  • motir-meta prompts/plan-rules/phase-deepen.md — the NEGATIVE limb this is an occurrence of.
  • motir-meta prompts/run.md — the MOTIR-819 mistakes-corpus step that searches notes.html alone.