Skip to content

fix(queue): prevent expired publications from starving later results#607

Closed
snowzlmbot wants to merge 1 commit into
openclaw:mainfrom
snowzlmbot:fix/exact-review-publication-starvation
Closed

fix(queue): prevent expired publications from starving later results#607
snowzlmbot wants to merge 1 commit into
openclaw:mainfrom
snowzlmbot:fix/exact-review-publication-starvation

Conversation

@snowzlmbot

@snowzlmbot snowzlmbot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

First submitted: July 15, 2026, 12:57 PM (US Eastern Time) / 16:57 UTC.
Last body edit: July 15, 2026, 11:23 PM (US Eastern Time) / 03:23 UTC.
Latest head commit: July 15, 2026, 11:08 PM (US Eastern Time) / 03:08 UTC.

Related: #606

Summary

Prevent repeatedly unclaimed exact-review publications from monopolizing the bounded publication lane after their claim leases expire.

The original broad #607 patch has been rebased onto current main and reduced to the one fairness gap not already covered by #610, #614, #616, and #617.

Breaking changes

None. Queue payloads, stored item schema, publication capacity, claim and completion tuples, stale-lease rejection, workflow permissions, immutable artifact validation, and target-serialized routing are unchanged.

What Problem This Solves

Fixes an issue where later completed review results could remain unpublished when the oldest publication artifacts repeatedly failed to claim a publisher lease.

Current main admits up to 24 exact publishers. When an unchanged publication lease expires, however, the item was returned to pending with nextAttemptAt = now. Admission sorts ready work by original creation time, so the same oldest item could immediately consume the slot again. One repeatedly unclaimed artifact can starve later results when capacity is configured to one; 24 such artifacts can monopolize the production lane.

Why This Change Was Made

Expired unchanged publications now use the queue's existing bounded exponential retry backoff before re-admission. Newer source revisions still become immediately eligible, ordinary review recovery remains immediate, and one-shot failed-shard recovery behavior is unchanged.

User Impact

Later completed reviews can reach their durable comments even when older publication dispatches repeatedly fail before claim. The change improves fairness without reducing the current 24-publication throughput limit.

Implementation

  • Detect publication items in reclaimExpiredExactReviewLease before clearing the expired tuple.
  • Increment the existing attempt counter and schedule unchanged publications with exactReviewRetryDelayMs.
  • Keep newer revisions immediately eligible so current maintainer or source context is not delayed.
  • Add a capacity-one regression that expires the oldest publication, proves the later artifact is dispatched, and proves the stale tuple still receives 409 lease_not_active.
  • Document the 15-minute publication claim window and fairness backoff.

Code-path analysis

  • Runtime entry and owner: ExactReviewQueue.alarm in dashboard/worker.ts reclaims expired leases, computes admitted items, and dispatches signed repository_dispatch payloads.
  • Reclaim callee: reclaimExpiredExactReviewLease owns state transition from expired dispatching/leased work back to pending.
  • Admission caller: exactReviewQueueAdmittedItems selects ready publications up to EXACT_REVIEW_PUBLICATION_MAX_CONCURRENT, ordered by createdAt and key.
  • Retry sibling: finishExactReviewQueueItem already uses exactReviewRetryDelayMs for failed attempts; this patch applies the same bounded policy to unclaimed publication expiry.
  • Workflow boundary: .github/workflows/sweep.yml keeps exact publication on current main, validates immutable producer artifacts, rejects stale tuples, and defers verdict routing through the target-serialized router. This PR does not change that workflow.
  • Tests: test/dashboard-worker.test.ts covers publication capacity, legacy lease recovery, stale claims, and the new fairness behavior.

Mainline comparison

Branch / base provenance

  • Base: openclaw/clawsweeper:main@0a17516dd286800c2cca4d818b2a75255f4b5c70
  • Head: snowzlmbot/clawsweeper:fix/exact-review-publication-starvation@258c1279d0aa6a65a3edd59b58290d6e60138a19
  • The branch contains one dedicated commit changing three files.
  • The previous overlapping workflow, lease, health, config, and serialization changes were dropped during rebase because current main already contains stronger replacements.
  • The fork default branch was not modified by this work.

Dependency / contract verification

  • No dependency, lockfile, workflow, permission, token, schema, or configuration changes.
  • Protocol v2 item key, lease revision, run attempt, claim generation, immutable decision, and stale-claim checks are unchanged.
  • Publication capacity remains bounded and configurable; production remains at 24.
  • The backoff is capped by the existing retry helper and only affects unchanged expired publication leases.

Labels considered

  • bug
  • impact:other
  • merge-risk: availability
  • merge-risk: automation

These are contributor suggestions; no upstream metadata change is assumed.

Validation

GitHub-hosted validation:

  • Exact PR-head CI on 258c1279d0aa6a65a3edd59b58290d6e60138a19 — both affected queue tests passed, including the new fairness regression; Windows launcher and crawl-remote toolchain jobs passed. The aggregate pnpm check job reported only five established fork-context failures in test/failed-review-retry.test.ts because the fixture models openclaw/clawsweeper while GITHUB_REPOSITORY names the fork.
  • Full CI proof on evidence head 6042fbd4b9ff7b8e53426c4417c1c5252cd8eab5 — success; pnpm check completed in 9m31s and the Windows launcher and crawl-remote toolchain jobs passed. The evidence branch differs from the PR head only by the historical public screenshot/report and a three-line proof-only test normalization of GITHUB_REPOSITORY; all three PR-changed files are byte-identical.
  • CodeQL proof on the exact PR head — success for both Actions and JavaScript/TypeScript.

Local pre-submit checks were limited to static gates:

  • git diff --check — passed.
  • Focused oxfmt --check for all three changed files — passed.
  • Sensitive-data diff scan — passed; only synthetic test fixture identifiers were present.

Evidence source map

  • Live queue status, sampled July 16, 2026 at 02:53 UTC: publication lane at 24/24 active with 1,886 ready items and zero items in publication backoff.
  • Exact PR-head CI: both changed queue tests passed; the five remaining failures are the existing fork repository-name fixture mismatch described above.
  • Full CI proof: repository-wide build, lint, unit, repair, coverage, workflow, formatting, Windows launcher, and toolchain gates with the proof-only repository-context normalization.
  • CodeQL proof: JavaScript/TypeScript and Actions security analysis for the exact PR head.
  • The focused regression configures publication capacity to one, dispatches artifact 901, expires its unclaimed lease, enqueues artifact 902, and verifies dispatch order [901, 902] while 901 enters backoff.

Sanitized logs

observed_at=2026-07-16T02:53:35Z
publication.capacity=24
publication.active=24
publication.pending=1886
publication.ready=1886
publication.backoff=0
publication.available_slots=0

regression.expected_dispatch_order=901,902
expired_artifact.state=pending
expired_artifact.attempts=1
expired_artifact.next_attempt_at=future
later_artifact.state=dispatching
stale_claim.status=409
stale_claim.error=lease_not_active

Media evidence

No visual surface changes. The behavior is a deterministic Durable Object scheduling transition; the public Actions run and focused assertion provide the inspectable proof. No production mutation or private environment was used.

Risk

  • A repeatedly unclaimed publication waits 30 seconds after its first expired handoff, increasing to the existing five-minute cap on repeated failures. This is intentional fairness and remains much shorter than artifact retention.
  • Newer revisions bypass the backoff and reset attempts, preserving current source context.
  • Stale jobs still fail closed because clearing the old tuple is unchanged and explicitly asserted.
  • No authorization, artifact trust, target mutation, state schema, or routing ownership boundary changes.

Rollback

Revert the single commit. No data migration, configuration migration, workflow change, or irreversible mutation is introduced. Existing queue rows remain compatible in either direction.

Docs updated

  • docs/limits.md now documents the publication-specific 15-minute claim window and bounded fairness backoff.

Related issue / PR

Review context addressed

  • The earlier review found no discrete correctness or security defect in the original patch but required stronger proof.
  • Current-main comparison showed that the workflow serialization, 15-minute lease, health correction, and config changes were superseded; they have been removed from this PR.
  • The remaining fairness behavior is now isolated in one owner function and covered by a capacity-bound regression plus stale-claim assertion.

Not tested / limitations

  • No production deployment was performed from this contribution.
  • The hosted regression proves deterministic queue behavior; production backlog drain remains an operational post-deploy observation.
  • Upstream pull-request CI may remain in GitHub's external-contribution state; the linked downstream CI and CodeQL runs execute the exact head publicly.

@snowzlmbot

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@snowzlmbot
snowzlmbot marked this pull request as ready for review July 15, 2026 17:06
@snowzlmbot
snowzlmbot requested a review from a team as a code owner July 15, 2026 17:06
@snowzlmbot
snowzlmbot force-pushed the fix/exact-review-publication-starvation branch 2 times, most recently from 617da3b to 0aab94a Compare July 16, 2026 03:00
@snowzlmbot
snowzlmbot force-pushed the fix/exact-review-publication-starvation branch from 0aab94a to 258c127 Compare July 16, 2026 03:08
@snowzlmbot snowzlmbot changed the title fix(queue): unblock exact-review publication fix(queue): prevent expired publications from starving later results Jul 16, 2026
@snowzlmbot

Copy link
Copy Markdown
Contributor Author

Rebased onto current main with superseded changes removed. The remaining publication-fairness fix has full hosted CI and exact-head CodeQL evidence in the updated PR body.

@clawsweeper review-pr

@clawsweeper

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@brokemac79

Copy link
Copy Markdown
Contributor

Thanks for rebasing the PR and narrowing the publication-fairness suggestion.

Recent maintainer work resolving the incident has restored live review publication and backlog drain. To keep the system stable while maintainers discuss the intended wider queue and state model following #592, we are closing this PR without merging.

The expired-unclaimed-publication fairness idea remains useful context for any future maintainer-led work; this close is not a reflection on the effort or evidence in the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants