(motir-ai) The lesson-delivery guard still reads the PRE-`occ:` marker grammar, so the first migration generated after MOTIR-3552 fails CI on a correct corpus
MOTIR-3552 appended an occurrence field to the generator's marker — -- lesson:<ref> content:<hash> embed:<hash> occ:<ref|-> — and moved the generator's own parser (emittedState) with it, keeping occ: optional so the 205 pre-existing markers still read. tests/lessonsMigrationDelivery.test.ts was not moved, and it spells the grammar twice, both times anchoring $ immediately after embed:[0-9a-f]+.
Nothing went red at the time, because the last migration then in the chain had been generated before MOTIR-3552 and carries no occ:. The failure waits for the NEXT generated migration, whichever it is:
AssertionError: curated rows no generated migration inserts: MOTIR-3618 —
run `pnpm lessons:generate-migration` and commit the emitted file.
AssertionError: marker carries no hashes, so drift can never be detected:
-- lesson:MOTIR-3618 content:250191fd3600 embed:1da5264c2639 occ:-
Both are false. The row IS carried and the marker DOES carry both hashes — the reader is stale, and its message sends whoever hits it to re-run a generator that will emit exactly the same bytes again.
What to build
Spell the marker grammar ONCE in that file, with occ: optional, mirroring emittedState(), and add a case over synthetic marker lines — with occ:<ref>, with occ:-, and with no occ: at all — so the grammar is asserted independently of whether the committed chain happens to contain one of each yet. That last part is what stops the same class recurring: the two existing assertions only exercise whatever markers are on disk, so a grammar widening can pass them for weeks and fail on the next author's PR.
Acceptance criteria
pnpm vitest run tests/lessonsMigrationDelivery.test.tsis green against a chain containing a marker withocc:.- A marker with no
occ:field still parses, and its sourceRef still reads as carried. - The synthetic case fails if the pattern is re-anchored after
embed:.
Context refs
tests/lessonsMigrationDelivery.test.ts— the two spellings (thematchAllin the MOTIR-3307 describe, and the hash assertion in the MOTIR-3320 describe).scripts/generate-lessons-migration.ts—emittedState()(the parser that IS current) andmarker()(the emitter). It runsmain()on import, so a test cannot import it and the grammar is necessarily restated.- Surfaced by PR #311 (motir-ai), whose CI it blocks; that PR's diff is one lesson row plus its generated migration and is not the cause.