Skip to content

queue: no 'current focus' concept exists, and oldest-first ordering is defeated by 5 of 8 regate producers omitting prCreatedAt #9499

Description

@JSONbored

Summary

The maintainer's expectation is that ORB works through PRs one at a time, oldest to newest. It does not, and there is no mechanism that could — no "current focus" concept exists anywhere in the codebase. The one real ordering mechanism that does exist is silently defeated by five of its eight producers.

Current state (verified at HEAD, 776c414)

No focus concept exists. The only mutex is per-PR — claimPrActuationLock(env, repoFullName, prNumber) (src/queue/transient-locks.ts:143-153). There is no repo-level or global serialization key; production Redis has zero keys matching *focus*. Queue concurrency is 8 (src/selfhost/pg-queue.ts:306-308), so up to eight PRs are actively processed at once.

The merge train is not it. src/review/merge-train.ts constrains merging only — checked at src/services/agent-action-executor.ts:643 behind if (action.actionClass === "merge" && ctx.mergeTrainMode !== "off"). It does not gate processing and does not gate update_branch. It is also overlap-scoped, not FIFO (merge-train.ts:130): an unrelated older sibling never blocks a newer PR.

Worth checking separately: on current main, mergeTrainMode is hardcoded "off" in the settings row mapper (src/db/repositories.ts:914) with no manifest override anywhere in src/ — i.e. the train appears to be dead code on HEAD. Production (orb-v3.5.0-beta.10) logged 17 merge_train_blocked events, so the deployed build predates that change. If the train is meant to be live, that is a separate regression.

Ordering exists but is defeated. jobClaimSortKey (src/selfhost/queue-common.ts:837-846) sorts agent-regate-pr rows by PR createdAt ascending, consumed by ORDER BY priority DESC, claim_sort_key, run_after, id (pg-queue.ts:1286). That is genuine oldest-first, and JobMessage.prCreatedAt's own doc (src/types.ts:43) says it exists so queues "drain contributor PR work oldest-first". Three things break it:

  1. github-webhook jobs are priority 10 vs regate's 9 — any webhook preempts the ordered work.
  2. Concurrency 8 claims eight rows at once, so "first" is eight-wide.
  3. Five of the eight regate producers omit prCreatedAt entirely, falling back to LEGACY_AGENT_REGATE_SORT_BASE_MS + prNumber ≈ 9.5e11 — which sorts ahead of every real 2026 PR (≈1.78e12). Offenders: processors.ts:5032 (trailing mergeable-unknown), processors.ts:5086 (over-cap sibling wake), src/review/pr-reconciliation.ts:132, src/review/surface-disposition-reconciler.ts:81, src/api/routes.ts:4933 (manual, priority 99 — intentional).

Deliverables

Phase 1 — make the existing ordering actually work (low risk, do first)

  • Thread prCreatedAt through the four unintentional omissions (processors.ts:5032, processors.ts:5086, pr-reconciliation.ts:132, surface-disposition-reconciler.ts:81). Leave the manual route as-is; document why.
  • Add a coalesce key to maybeEnqueueSiblingRegateForMergedPr (processors.ts:1402-1437) — it is the only wake producer in that file without one, so three merges six seconds apart currently fan out 45 jobs for the same 15 siblings.
  • Re-key isRegateRepairExhausted's budget on repo#pr instead of repo#pr#headSha (processors.ts:1121-1123). A successful rebase changes the head SHA and resets the 5-attempt budget to zero — the identical bug already fixed for the fresh-rebase counter at :4787-4790, which the comment there explains at length.
  • Add a lint or type-level guard so a new agent-regate-pr producer cannot omit prCreatedAt silently.

Phase 2 — an explicit focus gate, if still wanted after Phase 1

Gate at actuation, never at job admission. Admission-gating would break the readiness/CI-wait machinery, starve the surface publish contributors depend on, and stall the repair and reconciliation paths.

Known interaction to handle: sweepRepoRegate stamps last_regated_at at dispatch (processors.ts:1567-1580), so a PR that loses the focus race and defers would burn its one sweep-eligible regate under #never-endless-reregate (src/settings/agent-sweep.ts:161-174) and never be re-examined. Either move the stamp to completion, or give deferred PRs repair-priority treatment.

Trade-off to decide explicitly

Strict global oldest-first is a behaviour change, not a tightening. The merge train is overlap-scoped precisely so an unrelated older PR does not block a newer one; global FIFO means a slow PR at the head delays everything behind it, bounded only by the 24h eviction. Phase 1 may deliver enough of the desired ordering without that cost — worth measuring before committing to Phase 2.

Metadata

Metadata

Assignees

Labels

gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.maintainer-onlyOwner-only work — yields no Gittensor points.orbGittensory Orb related - maintainer self-hosting analytics.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions