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

(motir-core) `docs/jobs.md` — the emit seam, engine-side idempotency, and what "cut over" means to an operator

Done
Description

Bring docs/jobs.md up to what this story actually shipped. Audience: whoever adds a job, and whoever operates the cutover — the two readers who will otherwise learn these rules by breaking them.

Read the file first, and write only what is missing

Three sections are owed. Grep for each before writing it — this card asserts they are absent and that assertion is unverified at authoring time, so the criteria below are phrased as obligations that close as verified-no-change if the text is already there.

1. The emit seam. Every event goes through sendEvent / sendSystemEvent; nothing else calls inngest.send. Say WHY, in one line: the per-job cutover switch is read there, so an emitter that bypasses it is an emitter the switch cannot route. Name the ESLint rule and the guard test that now enforce it, so a reader who trips one knows what it is protecting rather than how to silence it.

2. Engine-side idempotency, and the ONE place it differs from Inngest. How defineJob's idempotency option behaves on the engine, which template forms the resolver accepts, and — stated plainly rather than buried — that engine dedup is unbounded where Inngest's is windowed. That divergence was argued and chosen on the idempotency card; this is where it becomes findable. MOTIR-3413's scope boundary says no job's observable behaviour changes, so a documented, argued exception is the difference between a decision and a discrepancy.

3. What "cut over" means to an operator. MOTIR_POSTGRES_JOB_IDS is a comma-separated set of defineJob ids; absent means Inngest; the switch is read live, so a change takes effect without a deploy; and rolling back is removing an id. Say where to look to confirm a job moved — a job_queue row and a job_run row for that id — and what the Inngest dashboard shows for a migrated job ({ skipped: 'routed-to-postgres-engine' }), because a run that did nothing is otherwise indistinguishable from a job that broke.

Scope boundary

Does NOT rewrite the existing "Concurrency" or "Debounce" sections. They document measured Inngest behaviour, both lanes are live, and that measurement is still true of the lane it describes. Removing Inngest-specific claims is MOTIR-3418's, which owns the retirement and the epic criterion about it.

Does NOT document the scheduled jobs' cutover (MOTIR-3416) or the supervisors' (MOTIR-3417).

Prose only. No file outside docs/ is modified.

Acceptance criteria

  • docs/jobs.md carries the three sections above — each added if absent, and left alone if a grep shows it already says the same thing. The PR body quotes the grep for each.
  • The idempotency section states the unbounded-vs-windowed divergence explicitly, and says it was chosen rather than inherited.
  • The operator section names the env var, the two tables to look in, and the Inngest-side marker for a migrated job.
  • Every claim about behaviour matches the merged code: read the shipped files, not the sibling cards' descriptions, and cite each in the PR body.
  • No file outside docs/ is modified.

Context refs

  • docs/jobs.md — the file, and its existing Concurrency / Debounce sections which stay
  • lib/jobs/engine/cutover.ts — the env var, the live read, and the switch's own documented end
  • lib/jobs/sendEvent.ts — the emit seam as merged
  • lib/jobs/defineJob.ts — the skipped: 'routed-to-postgres-engine' marker and why it is a marker rather than a silent return
  • eslint.config.mjs — the widened import boundary to name