Type: code · Executor: coding_agent · Repo pinned motir-ai — where the seed source, the migration generator and embedMissingLessons all live. If the diagnosis lands in motir-core's search seam instead, re-pin before building; the pin is a claim, not a finding.
Found 2026-08-29 while running MOTIR-3876, whose planning defect is described by a curated global lesson that the run could not retrieve. Filed here because it carries no dependency edge into that story — the project owes this fix, that story does not.
motir-ai src/seed/lessons.base.ts on origin/main holds 221 scope: 'global' rows.
search_lessons(projectKey: 'MOTIR', limit: 50), queried with the near-verbatim body of the row whose sourceRef is MOTIR-3794 ("A container cannot hold the card that verifies the deployment its own merge produces…") returned 50 rows. The target was absent. Worst distance in the window: 0.751 — so it was not merely ranked below the cut, it was not in the ranked set at all.global rows, and every single one carries a cmr11… id — the original day-one seed batch. The other 5 are tenant rows, three of them recent (cmta2k…, cmt9xy…, cmteai…), which are written through add_lesson / the capture path.limit: 5 with the near-verbatim title of the MOTIR-3805 row ("A precondition that is a RELEASE cannot be carried by a dependency edge…"): five rows, all cmr11…, target absent, best distance 0.474 on an unrelated row.So: a row written through the MCP retrieves; a row written through the seed migration does not. That is the shape of the defect, and it is the shape of a lot of work — every global lesson authored since the day-one batch, which is what the sourceRef: 'MOTIR-<n>' convention exists for.
The CAUSE. Two candidates, and this card must distinguish them before it changes anything:
scripts/generate-lessons-migration.ts says the release runs src/seed/embedMissingLessons.ts "immediately after", and embedMissingLessons.ts's own header calls an unembedded row a silent failure — so the failure mode is anticipated in the code and the backfill may simply not be running, or may be failing without failing the release.*_lessons_base_data migrations landed between 2026-08-28 18:19 and 2026-08-29 00:01; fly.toml's release_command applies them, so this requires a release not to have happened — check the deployment, not the repository.Read it from the deployed database, inside a machine (DATABASE_URL_UNPOOLED): count Lesson rows by scope, and count how many have a null embedding. That single query separates the two candidates and is the reproduction this card is built on.
The corpus has two halves, and only one of them is working. Lessons are still being WRITTEN — carefully, with a curation discipline, a totality suite and a per-row routing decision — and every one of them since the seed batch has been written into a corpus that no planner can read. Every motir run and every planning pass is calling search_lessons, getting outcome: "matched" and a plausible ranked list, and being handed the day-one corpus while believing it has been handed the whole one. A retrieval that returns the wrong rows is indistinguishable from one that returns the right ones, which is why this stood.
It has already cost at least one concrete failure: the MOTIR-3794 row states the exact defect that shipped into MOTIR-3876 a day later — the container that cannot hold the card verifying its own merge's deployment — and neither the plan pass that authored the story nor the run that refused it could retrieve it. See MOTIR-3904.
Lesson rows, by scope, and how many carry no embedding), read inside a machine, with the timestamp — before any fix. The two candidate causes above are decided by that reading, and the losing one is stated as excluded.*_lessons_base_data migration retrievable by search_lessons, whatever the cause turns out to be — the backfill actually running on release, or the release actually happening, or both.search_lessons returns the MOTIR-3794 row for a query naming a container that cannot hold a post-deploy child, and the MOTIR-3805 row for one naming a precondition that is a release. Both are quoted in the close-out.motir-ai/src/seed/lessons.base.ts — the 221 global rows and the sourceRef: 'MOTIR-<n>' convention for new onesmotir-ai/src/seed/embedMissingLessons.ts — the backfill, and its own note that an unembedded row is a silent failuremotir-ai/scripts/generate-lessons-migration.ts — the generator, and its claim that the release runs the backfill immediately aftermotir-ai/prisma/migrations/*_lessons_base_data/ — five between 2026-08-28 and 2026-08-29motir-ai/fly.toml — the release_command that applies themmotir-core lib/mcp/tools/searchLessons.ts → POST /v1/lessons/search — the read path, if the cause is on that sidesearch_lessons