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

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

Done
Description

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. recordStart really 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

  1. 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.
  2. This card is closed once read — it is telemetry about the planner, holding up no work.

Evidence

  • The two greps above, run on origin/main at c25fb4ff5.
  • lib/jobs/engine/ledger.ts:113-127 (the memoized job-run:start step), lib/jobs/engine/step.ts (the memo contract), prisma/schema.prisma model JobRun (no unique index on function_id) vs model JobQueueRun (@@unique([jobId, scheduledFor]), @@unique([eventId, jobId])).
  • Fix PR: motir-core#2409.