Jobs and lanes
One job: the executable unit
A job is one durable unit an executor (or the pump) can run: a kind, an opaque payload, a standing machine of queued → claimed → completed/failed, with leases and bounded attempts.
-
job_create: conductor plus explicit project grant (broad scope never suffices). Starts queued; no executor assigned. -
job_claim: atomic single-winner lease. Exactly one holder at a time; stale holders cannot complete; attempts are bounded (five) and recorded for executor-side dedup. Nothing available and nothing authorised answer identically. -
job_complete: claimed → completed/failed. Re-completing with the same outcome is a quiet idempotent no-op; anything else on a terminal job is rejected. -
job_release: back to queued with attempts kept, for another executor to claim.
Lane association never moves the claim gate: claiming checks the lease, not the org chart.
One lane: the coordinated stream
A lane is a named stream of work under one quorum (one branch, one assignee, one task thread), generating many jobs over time.
-
lane_create: inherits its quorum's project immutably; validates assignee, task, and same-quorum dependencies now, not later. -
lane_set_state: the execution axis (open → in progress → done/failed; anything non-terminal → cancelled; terminal states immutable). Conductor moves it; review and merge states stay untouched. -
lane_review: coordination verdicts only. Submit by conductor or assignee; approve or request-changes by conductor; verdicts gate on privilege before touching the entry. Completing a job never moves review. -
lane_merge: records the outcome (merged needs done plus approved plus a commit pointer). Merge records; it never executes. -
lane_list: what the caller may see, silently filtered.
The pump's place
saphira-memory-pump materialises recurring timers, drains delivery
jobs, and retries with backoff: foreground, per-profile, with
lease-based claiming so concurrent instances stay safe. It writes
only job delivery, lease, and result facts. Lane decision, review, and
merge standing are quorum-layer writes; the pump never touches them, by
architectural rule rather than convention.
When to use, when not to
- Use jobs for units with exactly-once lease semantics (one holder, bounded attempts, idempotent completion), not literal single execution, which only idempotent executors can promise.
- Use lanes when one agreement fans out into streams with owners, branches, and review gates. A single one-shot job needs no lane.
- Keep payloads idempotent where it matters: carry idempotency keys for external effects, because at-least-once delivery plus exactly-once lease still means the executor must dedup the world outside.