Planning bug: a bug card's root cause was derived from a STALE COMMENT and from a call path a memo makes unreachable — two mechanisms, both falsified at the first grep
About · MOTIR-3738 — filed 2026-08-28 by a motir run triaging a CI red, executed the same day. Both defects are in the card's Root cause section; the card's conclusion and fix direction were correct, which is what makes this worth recording rather than obvious.
Filed under the planner-bug home, not the finding story: the fix changed the PLAN (the card's body, amended on the record), not product code.
What the card asserted, and what origin/main says
1. "One row PER ATTEMPT." The card cited jobRunsService.recordStart calling jobRunRepository.create — "a fresh row each invocation" — so an intermediate attempt's row "stays running for good". True of the function in isolation. It has exactly one caller:
$ grep -rn "recordStart(" --include='*.ts' lib/ app/ | grep -v "async recordStart"
lib/jobs/engine/ledger.ts:115: jobRunsService.recordStart({
and that call site wraps it in ctx.step.run('job-run:start', …), memoized on (run_id, step_id), whose own header says "A RETRY DOES NOT CLEAR THE STEP LEDGER" (lib/jobs/engine/step.ts). A retry writes no second row.
2. "This spec calls routeJobsToEngine(CATCH_UP_JOB) mid-spec (:134)." The card even gave a line number.
$ grep -rn "routeJobsToEngine" --include='*.ts' .
(no matches)
The helper went with 6dafd2ee8 (MOTIR-3418, retire Inngest). The card had read a stale COMMENT in the spec — "Route the daily sweep onto the engine MID-SPEC, through the file override the switch documents" — that described a call already deleted. The lane premise built on it ("an Inngest-lane row can already exist") is unreachable for any row written after that commit: lib/jobs/engine/ledger.ts:124 writes lane: 'engine' unconditionally.
Why it is worth a card
Neither error changed the verdict, and that is the hazard. The card was thorough — it falsified the obvious race hypothesis by reading JobWorker.settle's write ordering, warned in its own explanation that an expect.poll "fix" would make the spec permanently green against a dead row, and recorded that reasoning so the next reader would not re-derive it. All of that is right. The two wrong mechanisms sat inside that careful analysis and would have sent a repairing run at the wrong instrument (a lane filter defends against a lane that cannot write, and an orderBy defends against attempts that do not accumulate). The correct discriminator — job_run carries no uniqueness on function_id while job_queue carries two unique indexes — is a schema fact neither premise reached.
The two shapes, and they are worth separating:
- A COMMENT is not shipped code. The spec's comment was accurate when written; the code under it was deleted and the comment was not. A premise read out of a comment inherits its age, and nothing in the file says how old it is. (The fix PR corrects the comment.)
- A function's behaviour is a property of its CALL SITE, not of its body.
recordStartreally does create a row per invocation. What decides whether a retry invokes it is one line at the only place it is called, and reading only the definition — which the card's own Context refs pointed at (jobRunsService.ts:124) — cannot see it.
Acceptance criteria
- Nothing to build. The correction is already applied: MOTIR-3738's Root cause carries both falsifications struck through with the commands that produced them, plus the corrected mechanism.
- This card is closed once read — it is telemetry about the planner, holding up no work.
Evidence
- The two greps above, run on
origin/mainatc25fb4ff5. lib/jobs/engine/ledger.ts:113-127(the memoizedjob-run:startstep),lib/jobs/engine/step.ts(the memo contract),prisma/schema.prismamodel JobRun(no unique index onfunction_id) vsmodel JobQueueRun(@@unique([jobId, scheduledFor]),@@unique([eventId, jobId])).- Fix PR: motir-core#2409.