- Status: active generated/validated configuration reference
- Owner: ClawSweeper maintainers
- Source of truth:
config/automation-limits.json, Worker overrides, andscripts/check-limits.ts - Last verified:
openclaw/clawsweeper@647503ec44b8e777dd172adf974a945367da0d19 - Update when: worker budgets, lane ratios, workflow literals, or production
capacity overrides change; run
pnpm run check:limits
Read when changing ClawSweeper throughput, Codex fan-out, or repair dispatch capacity.
config/automation-limits.json is the source of truth for the global worker
budget. It deliberately has one main global knob, workers.max, because that is
the number we normally tune when Codex or GitHub rate limits get tight. Most
lane-specific limits are derived from that budget; imported cluster repair has
a separate explicit knob so it can stay tightly bounded unless a maintainer
intentionally opens it wider. Safety thresholds such as
close age floors, apply delays, retry counts, and comment caps stay near the
code that owns those decisions.
Review-intake rate limits and the default-off per-author PR-budget and obsolescence policies follow that safety-threshold rule. Their tunables and safety floors live beside the owning policy rather than in the global worker budget:
| Environment variable | Default | Meaning |
|---|---|---|
CLAWSWEEPER_AUTHOR_PR_BUDGET_CLOSE_ENABLED |
false |
Enables live per-author budget closes. |
CLAWSWEEPER_AUTHOR_PR_BUDGET |
15 | Allowed open PRs per external author and repository. |
CLAWSWEEPER_AUTHOR_PR_BUDGET_MAX_CLOSES_PER_RUN |
5 | Gradual trim cap per author in one apply run. |
CLAWSWEEPER_BULK_FILER_THRESHOLD |
10 | Recent authored issues not closed as completed. |
CLAWSWEEPER_BULK_FILER_WINDOW_DAYS |
7 | Lookback window ending at the issue's creation. |
CLAWSWEEPER_STALE_VERSION_BUG_CLOSE_ENABLED |
false |
Enables stale-version bug closes after 120 days. |
CLAWSWEEPER_OBSOLETE_FIX_PR_CLOSE_ENABLED |
false |
Enables obsolete small-fix PR closes after 90 days. |
The bulk-filer count leaves out issues closed as completed. Every other issue in the window counts, including open, rated, not-planned, and duplicate issues. Rating labels and priority labels do not change the count: a rating can still change between reviews of an unchanged issue, so it is not yet a stable signal (#1752).
See author-pr-budget-close-policy.md for
the rating, proof, inactivity, engagement, and fail-closed gates.
See obsolescence-close-policies.md for the
120/90-day issue and 90/30-day PR age/inactivity contracts.
GitHub repository variables still override selected live limits. When a variable
is unset, workflows read the checked-in budget after checkout. Broad manual
review uses the same queue limits as scheduled feeds; manual shard/batch
controls are retired. pnpm run check:limits verifies the remaining derived
Worker, workflow, and documentation values.
The mental model:
workers.maxis the global Codex capacity budget.- GitHub Actions workflows that only route comments, publish exact-review results, or reconcile leases do not execute Codex and do not consume that budget.
- Priority lanes are repair, issue implementation, and exact-item review.
- Background lanes are normal review and hot intake.
- Assist has a small fixed cap because it is lightweight maintainer Q&A, not a derived review or repair lane.
- Background lanes shrink when priority work is already active.
- Runtime overrides are escape hatches, not the normal tuning surface.
Audit hydration is bounded independently of review capacity:
| Name | Current | Meaning |
|---|---|---|
audit.max_parallel_targets |
3 | Target audits dispatched per wave; wait for every run to complete before the next wave. |
The fanout reads this limit through AUTOMATION_LIMITS in src/limits.ts.
The signed audit cursor checkpoints remaining targets and outstanding children;
resumed batches drain those children before admitting a new wave.
It does not alter worker budgets, exact-review admission, or target selection.
| Name | Current | Meaning |
|---|---|---|
workers.max |
128 | Maximum global Codex worker budget used to derive lane limits. |
workers.reserve_for_interactive |
16 | Worker slots background lanes leave open for exact/manual/urgent work. |
workers.expansion_reserve |
8 | Extra slots background lanes leave open for independently planned matrix expansion. |
workers.minimum_background |
16 | Target floor for background progress when enough global capacity is available. |
lanes.exact_review.max_concurrent |
80 | Maximum concurrent exact-item review workflow runs admitted to Codex. |
lanes.exact_review.target_max_concurrent |
64 | Maximum concurrent exact-item review workflow runs one target repository may consume. |
lanes.exact_review.actions_budget |
194 | Separate Actions budget; preserves publication and control-plane headroom without raising the review ceiling. |
lanes.assist.max |
10 | Maximum concurrent lightweight assist jobs. |
lanes.repair.cluster_max_live_runs |
2 | Default live repair workflow cap for imported gitcrawl cluster dispatches. |
Review limits are percentages of workers.max, with small fixed floors. With
workers.max = 128, normal and hot intake have configured ceilings of 89 and 44.
The interactive and expansion reserves leave 104 background slots when quiet.
| Name | Current | Meaning |
|---|---|---|
exact_review.concurrent_max |
80 | Exact-item review admission cap, clamped to workers.max. |
exact_review.target_concurrent_max |
64 | Exact-item per-target admission cap, clamped to global exact-review capacity. |
assist.default |
10 | Maintainer assist job cap. |
review_shards.normal_default |
89 | Quiet-system normal review shard ceiling. |
review_shards.normal_active_floor |
38 | Minimum active normal review shards to keep queued for openclaw/openclaw. |
review_shards.hot_intake_default |
44 | Quiet-system broad hot-intake review shard ceiling. |
review_shards.exact_item_default |
1 | Exact-item hot-intake shard count. |
review_shards.hard_cap |
128 | Maximum accepted review shard count. |
Formula summary:
- normal review: 70% of
workers.max - normal active floor: 30% of
workers.max - hot intake: 35% of
workers.max - review hard caps:
workers.max
Manual normal review and manual hot intake are background lanes.
Before they dispatch, the workflow asks
pnpm run workflow -- worker-limit <lane> for the current allowance. Automated
normal and hot cycles enqueue exact-review work instead, so the Durable Object's
rate, backlog, and claim limits own their concurrency.
The scheduler does this for background lanes:
- start with
workers.max - subtract active priority work, currently exact-item sweep runs
- subtract active background work already known to the workflow, meaning other active normal/hot sweep runs
- reserve
workers.reserve_for_interactive - reserve
workers.expansion_reservefor independently planned matrix waves - cap the result at the lane's derived quiet-system ceiling
- return at least 1 so an enabled lane can still make slow progress
The normal result is then reduced when the exact-review queue is under pressure.
Each planner reads the public, unauthenticated GET /api/exact-review-queue
endpoint once and uses its review-lane pending count and oldest-pending age. The
top-level pending, ready, admissible, handoff, and pressure fields are aliases
for that review lane; publication health and backlog remain under
lanes.publication and never throttle review producers. A failed, timed-out, or
malformed response uses the conservative unavailable-pressure budget until the
next healthy probe.
| Tier | Trigger, either condition | Background budget |
|---|---|---|
| none | Below both soft thresholds | Normal dynamic budget |
| soft | At least 150 pending or oldest pending is at least 30 minutes | ceil(normal dynamic budget * 0.5) |
| hard | At least 400 pending or oldest pending is at least 2 hours | max(1, floor(normal dynamic budget * 0.1)) |
The thresholds can be overridden with repository variables or process environment variables. Values are non-negative counts or millisecond durations; unset, empty, or invalid values use the defaults.
| Environment variable | Default |
|---|---|
CLAWSWEEPER_QUEUE_PRESSURE_SOFT_PENDING |
150 |
CLAWSWEEPER_QUEUE_PRESSURE_HARD_PENDING |
400 |
CLAWSWEEPER_QUEUE_PRESSURE_SOFT_AGE_MS |
1800000 |
CLAWSWEEPER_QUEUE_PRESSURE_HARD_AGE_MS |
7200000 |
Broad manual and scheduled review both use queue-advertised candidate capacity and the shared admission target. Planners serialize by target, offer candidates, and finish without reserving matrix workers. The legacy worker-limit pressure multiplier remains a helper for other callers; it no longer controls a hosted manual review matrix. Repair, assist, issue implementation, cluster repair, and exact-item admission retain their existing priority budgets.
Priority lanes do not subtract the interactive reserve. They cap themselves at their derived lane ceiling and at the remaining global budget after other active priority work.
Exact-item webhooks are admitted by the dashboard Worker's durable
ExactReviewQueue, not by a live Actions semaphore. Its production queue logic,
including storage migrations, leasing, reclamation, debounce, and shedding, lives
in dashboard/exact-review-queue.ts; dashboard/worker.ts is the fetch and
dashboard router and only imports that service boundary. The queue coalesces
deliveries by repository and item number, so a new webhook updates the latest
desired review rather than consuming another runner. Only
EXACT_REVIEW_QUEUE_MAX_CONCURRENT leased items may dispatch an exact-review
workflow at once; production sets this to 80. EXACT_REVIEW_TARGET_MAX_CONCURRENT bounds
how many of those slots one target repository may consume; production sets it
to 64 so other target repositories retain 16 global slots during an OpenClaw
backlog drain. Exact capacity is consumed only while queue work is pending. As
those priority workers start, normal and hot-intake planners
count them and reduce their next background wave.
EXACT_REVIEW_ACTIONS_BUDGET is deliberately separate from the 128-slot Codex
worker budget. Its production value remains 194: at 80 exact reviews and up to
32 publishers it preserves the 16-slot control-plane reserve plus 66 slots of
Actions headroom. Full review admission therefore
cannot reduce verdict publication to zero, while repair and broad review
derivations remain anchored to workers.max = 128.
EXACT_REVIEW_SCHEDULED_MAX_CONCURRENT caps combined scheduled hot intake and
normal backfill at 32 active reviews in production. Both dispatching and leased owners count,
using the immutable lease decision while a newer desired revision waits. Lowering
the cap does not cancel owners or remove pending work. Organic/manual requests
remain eligible when the scheduled cap is full. The same bound governs admission,
admissible statistics and next-wake calculation, so held backlog does not cause
one-second polling. Public scheduled_feed.max_concurrent and active expose
these counts; OpenClaw Bay remains observer-only and needs no new controls.
The public scheduled_feed also reports the admission budget itself:
burstandtoken_balancefor the global bucket. The balance is negative while organic debt is outstanding, down to-burst.lanes.hot_intakeandlanes.normal_backfill, each withtarget_rate_per_hour,burstandtoken_balance.throttle_observed_atandthrottle_recovery_atafter a review completion has reported a GitHub throttle. Scheduled admission is paused until the recovery time.
lanes.review.shed_reasons_since_reset splits review sheds into backpressure, scheduled_rate and unattributed. Together these show whether scheduled backfill is held back by organic debt, by lane rates, by a throttle pause, or by queue backpressure. They are aggregate numbers with no item, repository or credential detail.
Ordinary automatic PR reviews first observe the live head, title, body, and
draft state, then wait for EXACT_REVIEW_INITIAL_PR_QUIET_MS (ten minutes).
Meaningful changes restart that quiet window, including changes discovered
without a webhook. Comments and label-only activity do not extend it. There is
no maximum-wait shortcut: a continuously changing PR waits until it settles.
Draft-state changes restart the window; existing draft and oversized-PR gates remain in force.
Explicit review requests bypass this initial hold.
Once a PR has a completed canonical review, ordinary webhooks and scheduled
hot/normal passes cannot review it again. Request @clawsweeper re-review after
finishing changes. The additive exact_review_pull_request_answers table records
that fact across restarts, report replacement, archive moves, and queue cleanup;
existing verified canonical reports with retained completion provenance seed it
on first use. Reports whose old receipts were already pruned remain eligible
for one fresh answer. Unverified attempts and stale-source requeues do not
consume the first answer. Issues keep their existing cadence.
Fresh webhook work waits for EXACT_REVIEW_DISPATCH_DEBOUNCE_MS (90 seconds by
default) so rapid edits and pushes coalesce before dispatch. Repeated pending
revisions extend that delay up to EXACT_REVIEW_DISPATCH_DEBOUNCE_MAX_MS (three
minutes by default) from the item's first enqueue. A superseding source event
immediately revokes the old queue lease and starts a fresh debounce window for
the latest revision. The old workflow's tuple heartbeat then returns 409; its
review step terminates the local review process instead of using GitHub's
run-id-only cancellation API, which cannot safely distinguish a later rerun
attempt. The replacement is durably scheduled before the old worker observes
the revocation, and
review_superseded_total records the terminalized review generation. Recovery
events never supersede an existing item; only a fresh source revision can revoke
an active review. Duplicate workflow deliveries remain non-cancelling and rely
on the lease claim tuple, so they cannot terminate the sole valid owner. An older
unclaimed workflow cannot pass the replacement lease tuple and exits before
review compute. After setup, generation also checks the full lease tuple
synchronously before either ordinary or oversized review starts. Known
lease_superseded / lease_not_active conflicts exit as successful no-ops;
unverified ownership fails before generation and leaves recovery to the queue.
This adds one heartbeat request per generation attempt (with the existing
bounded transport retries), not a faster polling loop. Earlier checkout/setup
is not interrupted, and supersession after that check still relies on the
ordinary-review one-minute heartbeat plus request/termination time. Oversized
generation retains its post-generation finalization check rather than an active
stop loop. Finalization and publication fences remain unchanged. The startup proof
records the isolated workflow/process boundary and its limits.
Explicit command work and publication work bypass the delay. The PR quiet
window above takes precedence for ordinary automatic PRs.
Items under active churn wait longer. When an item has already completed
EXACT_REVIEW_ACTIVE_ITEM_REVIEW_THRESHOLD (2 by default) successful review
generations within the trailing EXACT_REVIEW_ACTIVE_ITEM_WINDOW_MS (one hour
by default), its next organic source revision (a review-triggering issue or pull
request webhook action such as synchronize or edited) waits
EXACT_REVIEW_ACTIVE_ITEM_DEBOUNCE_MS (ten minutes by default) from the latest
pending revision. Further revisions still coalesce into that one pending entry,
capped at EXACT_REVIEW_ACTIVE_ITEM_DEBOUNCE_MAX_MS (15 minutes by default) from
the first pending enqueue, so a continuously pushed pull request is still
reviewed. The active delay only ever lengthens the ordinary debounce. A
superseding event still revokes an in-flight lease immediately; only the next
dispatch waits. Explicit commands, publication, scheduled intake, repair
follow-ups, and recovery work keep their existing timing, as do items below the threshold. PR opened / ready_for_review intake
can observe live state immediately, but ordinary PR dispatch still waits for
the initial quiet window above. The queue keeps the completion history in an
additive exact_review_queue_review_completions table keyed by item and
workflow run, pruned to the window; a store without history behaves as before.
The next-wake calculation reads the delayed nextAttemptAt, so a held item does
not cause extra polling.
When pending depth reaches
EXACT_REVIEW_PENDING_SOFT_LIMIT (600 by default), new recovery and scheduled
feed work is shed; this threshold counts review work only, so publication
backlog cannot consume review admission capacity. Existing items, webhook
events, commands, and publications remain admitted, and so does recovery or
source-drift work that still carries a command's context, which also passes
a GitHub throttle window. The queue reports shed
counts under lanes.review.shed_reasons_since_reset and the rolling flow by
backpressure versus scheduled_rate; pre-migration totals remain
unattributed. Executed reviews debit a durable 220-review/hour
scheduled budget with a 24-item burst. The budget meters started review
generations, not admissions or claims: a claim records that its claim generation
owes one token, and the workflow's startup ownership check, immediately before
Codex generation, sends generation_start: true on the lease heartbeat to pay
it. Organic work therefore consumes the budget first, once per run that actually
reaches generation. Organic admission itself is free and always admitted. Work
that never starts generation is never charged: items superseded or coalesced
before claim, dedupes, items completed at the dispatch-time live check without a
run, runs that claim and then exit at live-item admission or lose the lease
during setup, publication work, and acknowledgement-only finalizers. A retried
generation-start heartbeat for the same claim generation is the same execution;
a rerun attempt, retry, or requeue that claims and starts again is another
execution. A scheduled admission debits its token when admitted, because
admission is where scheduled work is gated, and marks the item prepaid so its
first started generation is not charged again; later starts of that item are
charged like organic ones.
Organic debt carries on the global bucket down to minus the burst, so scheduled
work is admitted only after that bounded debt is repaid. Further organic debits
at the floor are forgotten, so this is not a total-work or spend cap. Scheduled work fills
the remainder through two lane buckets on top of that global bucket:
EXACT_REVIEW_HOT_INTAKE_RATE_PER_HOUR caps hot intake (production sets 30),
and normal backfill receives the total minus hot, so frequent hot offers cannot
take the remainder that oldest-first backfill needs. The burst splits 35% hot
and 65% normal (8 and 16 in production). Re-offering an item
that is already pending, dispatching, or leased is a semantic dedupe: it does not
advance the queue revision, revoke a lease, or count as new work.
A source-drift loop breaker bounds automatic re-review. The queue counts
consecutive source_drift_requeue review generations per item in an additive
exact_review_queue_source_drift_loops table, because each completed generation
deletes the queue item. Once an item has used
EXACT_REVIEW_SOURCE_DRIFT_REQUEUE_LIMIT (production: 3) such generations, the
next source-drift requeue is not admitted: the item is parked with reason
source_drift_loop, and later automatic requeues are deduped against it with
dedupe_scope: source_drift_loop. The publisher still receives a successful
dedupe, so the parked item is the only new state. The direct and batch
publishers both send that requeue as publisher-source-drift:<producer run id>:<attempt>, so one review generation is requeued at most once. A direct-publication
completion that owes a lifecycle requeue (direct_lifecycle_requeue) creates the
same automatic generation without /enqueue, so it counts and parks the same
way: below the limit its successor revision is pending; at the limit the
successor revision is parked with reason source_drift_loop, while the
completed revision keeps its requeue lifecycle fact. An organic webhook item action
(opened, reopened, edited, synchronize, ready_for_review,
converted_to_draft, unlocked, unlabeled), an explicit command, a manual
review, or an operator recover-fresh both resets the counter and admits the
item normally. A scheduled offer whose sourceUpdatedAt is later than the park
releases it for one review generation but does not reset the counter:
ClawSweeper's own post-review writes, such as lease-comment cleanup and label
syncs, move updated_at and feed hot intake. If that review ends in another
source-drift requeue, the item re-parks immediately. Older scheduled offers
dedupe with reason source_drift_loop. A source-drift
requeue that still carries command context continues that command's status
lifecycle, so it is neither counted nor parked. The parked item spends no review
capacity, appears under parked_reasons.source_drift_loop, is operator-listable
through the parked-review routes, and still receives the five-minute terminal
check that removes closed or advanced targets. Set the limit to 0 to disable
the breaker. A counter idle for seven days expires: the admission lookup treats
it as absent before the limit check, and parking never refreshes an expired row.
Deterministic no-op holds stop the other observed self-feeding shape without a
counter. When a review run completes successfully on the guarded locked-conversation
path, the oversized PR path, or the maintainer-request guard, sweep.yml sends
review_hold (locked_conversation, oversized_pull_request, or
maintainer_request_required) with the lease completion.
Without command context, without input that arrived during the lease, and (for
oversized PRs) with a pinned head, the queue keeps the row parked under that
reason instead of deleting it. Scheduled offers then dedupe with that
dedupe_reason, automatic recoveries dedupe with dedupe_scope: review_hold,
and neither claims a run, so neither debits the scheduled budget nor counts
toward review_runaway_health. Organic events, commands, manual reviews, the
parked terminal check, and parked-review fresh recovery release it exactly as
for source_drift_loop. The Worker must recognize a hold reason before a
workflow sends it; deploy the Worker first when adding a reason. Older workflows
that omit the field keep the previous behavior.
The queue also applies the maintainer-request hold before dispatch, so the
common case starts no runner. The live item check that runs before every
dispatch evaluates the same rule for automatic work (no command, manual request
or publication). GitHub shows a private org member to the App as CONTRIBUTOR,
so for a CONTRIBUTOR author the queue and the webhook gate read the author's
repository permission (admin or maintain counts as a maintainer, as in the
runner admission check), cached per author for one hour. A held item parks under
maintainer_request_required exactly as after a skipped run. A failed
permission read dispatches as before, and the runner check still applies.
The same queue keeps a trailing 24-hour history of claimed review runs per item
(exact_review_queue_review_generations, keyed by item, run ID, and attempt;
publication and finalizer-only claims are excluded). An item with more than
EXACT_REVIEW_RUNAWAY_REVIEWS_PER_DAY (production: 24) claimed reviews in that
window is a runaway. review_runaway_health reports degraded with reason
review_runaway, the runaway count, and up to five verified-public sample keys;
the dashboard health summary raises it amber. This alert observes; it never
changes admission.
Exact-review result publication has a separate adaptive Actions lane. Source
fallback minimum, base, and maximum are 4, 24, and 48; production overrides
them to 8, 32, and 32, independently of the larger review ceiling.
Canonical publication batches retain eight slots. The controller records GitHub
pressure, cooldown, recovery, and demand telemetry, and can scale within that
production range. Admission enforces a 16-slot control-plane reserve inside
EXACT_REVIEW_ACTIONS_BUDGET; with 80 active exact reviews and the current
production maximum of 32 publisher slots, another 66 slots remain as configuration
headroom rather than protected reserve.
Newly accepted, published batch members contribute one recovery success each
after cooldown, only when publication completes without requeueing. Replays, superseded
members, and requeued revisions earn no credit. A batch carrying quota
observations earns no positive credit, so its negative feedback takes precedence.
Its checkout, artifact handling, comment sync, and result routing are
deterministic control-plane work: they consume GitHub runners, but not Codex
slots. The comment router and the singleton lease reconciler follow the same
accounting rule. Dashboard Codex capacity therefore counts only jobs whose steps execute
Codex and does not deduct these control-plane workflows from workers.max.
Legacy state-repository publication once limited exact-review preparation to four concurrent size-8 batches. Canonical Worker publication removes that shared Git writer constraint, so production now admits 8 preparation batches (up to 64 publication members) while retaining the Durable Object's transactional SQLite ownership boundaries.
Each batch now prepares at most two members concurrently. This changes only per-batch preparation: publication maximum 32, eight batch owners, review and worker budgets, and intake limits are unchanged. A quota observation still defers later members without charging their retry budgets; at most the two already-started members may have requests in flight. The controlled trial and rollback criteria are in backlog recovery proof.
The durable control plane owns reset-aware GitHub credential circuits for both
review authority reads and publication batching. The
repository Actions pool is identified only as actions:openclaw/clawsweeper;
target App pools are identified by the non-secret target owner. A primary or
secondary rate-limit observation persists its reset deadline in the queue
dispatcher and suppresses new batch dispatch for only the affected pool. Each
matching member resumes at its reset-plus-deterministic-jitter boundary, and
the next alarm uses the earliest pending member recovery boundary. A later
observation may extend but cannot shorten an open circuit. When gh omits
response headers, the publisher
performs at most one same-credential /rate_limit lookup; the one-minute
fallback is used only when no authoritative reset is available.
Legacy exact-review payloads that do not carry target_branch are durably held
before admission while the target App resolves the repository default branch;
they never silently default to main. The same owner-scoped target App circuit
protects that lookup and direct-webhook pull-request head verification. The
first reset-aware 403/429 opens the circuit; later reservations for that owner
defer to the shared deadline without another GitHub request or another
reservation attempt, while other owners continue. A carried valid branch takes
the normal enqueue path with no branch lookup.
The status payload exposes these pre-admission records under
lanes.review.authority_pending; owner-scoped circuit affected_pending counts
include them, so quota pressure before normal queue admission remains visible.
The first quota failure in a preparation batch stops later members before
artifact download. The observing member records a normal retryable failure;
members that never made a GitHub request are requeued after the shared reset
with deterministic 1-30 second per-member recovery jitter and do not consume
their individual publication retry or dead-letter budgets. A classifier-approved
public openclaw/openclaw read may make one bounded fallback from the exhausted
Actions token to the already-authorized target App token. That success does not
close the Actions circuit, and mutations, private reads, and unsupported routes
never use the repository token.
lanes.publication.github_request_metrics measures the successful and failed
request budget by redacted credential scope, endpoint category, public-read
versus App-operation class, first versus repeated revision, and outcome. It
contains counts only: no repository item number, URL, content, token, token
hash, authorization header, or filesystem path is retained. Use these counters
to justify later cache or metadata-read consolidation; live freshness and
pre-mutation guards remain mandatory.
Each dispatched workflow claims its opaque lease before checkout. Protocol v2
binds claim and completion to the item key, lease revision, run attempt, claim
generation, source head (for pull requests), and an immutable decision snapshot.
For pull requests, the review-start reservation rejects a claimed source head
that no longer matches the live head, then heartbeats that full queue tuple
before deleting any different-revision placeholder. During the rolling-upgrade
window, dispatches nest the strict tuple under queue_claim, also carry the immutable v1 snapshot, and the Worker accepts
lease-id-only finalization only for claims recorded as protocol v1. Duplicate
dispatches and stale workflows cannot claim the same lease, and a completion
immediately schedules a known newer revision. Failed and cancelled executors
requeue their item with bounded retry backoff. Successful finalizer reports stay
leased until a signed terminal-run reconciliation backstop confirms that exact
GitHub attempt completed successfully; this backstop can also recover terminal
failed or cancelled runs before lease expiry. Event-triggered lease repair shares
one running and one pending job in exact-review-reconcile-workflow-run with
cancel-in-progress: false. A five-minute successful-reconciliation guard
suppresses redundant scans; skipped and observer-only runs do not reset it.
Per-run reliability observations retain their own jobs so no telemetry is lost.
The independent */15 sweep reads /internal/exact-review/claimed-runs, checks
exact GitHub attempts in batches of eight, and posts terminal tuples to
/internal/exact-review/reconcile. It bypasses the event cooldown, providing an
approximately 15-minute backstop for coalesced terminal events, subject to Actions
scheduling and API availability. See Scheduler for the bounded
Actions history reads that implement the cooldown. Unclaimed
dispatches expire after six minutes and receive a new opaque lease; delayed
workflows holding the expired lease cannot claim it. The six-minute timer covers
only the GitHub dispatch-to-claim handoff. Once the first workflow step claims
the item, the 130-minute execution lease and one-minute heartbeats take over, so
the handoff recycler cannot race a normal four-minute review completion.
Run-attempt binding and a per-claim generation check keep delayed terminal
decisions from releasing a later rerun; queued and in-progress runs are never
released. If a workflow never claims or completes, the Durable Object reclaims
the expired lease. Claimed review workers heartbeat every minute; after the first
heartbeat, EXACT_REVIEW_HEARTBEAT_GRACE_MS bounds liveness to 20 minutes by default while
never extending the original 130-minute execution lease. Leases created before heartbeat
support was deployed retain their original execution expiry. This keeps capacity waiting and
retry state out of GitHub Actions runners.
Publication completion distinguishes durable publishes from results superseded by a newer or closed remote tuple. Superseded publications terminate without a GitHub mutation and do not count as successful publishes. GitHub/transient failures retry for at most 12 attempts or 24 hours; deterministic permanent failures receive two confirmation retries before entering the bounded dead-letter store. An artifact unavailable for three attempts atomically queues one fresh review. Public queue status reports publish, supersede, retry, refresh, and dead-letter totals separately; signed internal endpoints list, replay, resolve, and exact-revision supersede records without exposing decisions publicly.
Examples with the current config:
- Quiet system: manual normal review can request 89 shards, with 104 background slots available after reserving 16 for interactive work and 8 for matrix expansion. When the queue capacity probe is unavailable, a single-target scheduled plan falls back to offering up to 50 candidates to the durable 220-review/hour admission target with a 24-item burst instead of starting matrix shards.
- Four active repair workers and 96 active background workers: normal review gets
four because
128 - 16 interactive reserve - 8 expansion reserve - 4 priority - 96 background = 4.
Use these commands to inspect the effective values from a checkout:
pnpm run --silent workflow -- worker-config
pnpm run --silent workflow -- limit review_shards.normal_default
pnpm run --silent workflow -- worker-limit normal_reviewChange workers.max first when tuning review-side rate-limit pressure. For
example, setting workers.max to 40 automatically makes normal review 28
and hot intake 14. Existing repair lanes keep their
40% derived caps, while imported cluster repair remains separately bounded until
lanes.repair.cluster_max_live_runs is raised.
/internal/state/records/export defaults to 200 records and accepts at most
200 per request. Its reconstruction cap is also 200, and the hydration client
requests 200 by default. A replay of 111,000 small records therefore needs
555 requests instead of 2,220 with the former 50-record cap.
The source-content budget remains 2 MiB and the serialized-entry budget remains
4 MiB. Byte preflight selects identities before a single batched source read;
chunked records retain their existing reassembly. Large records can end a page
before the count limit, and nextCursor advances only through returned records.
The existing single-record progress exception is retained: the first record is
returned even if it exceeds a page byte budget, preventing an unexportable record
from pinning the cursor. The serialized budget measures entries, not the outer
JSON envelope.
These limits are owned by dashboard/exact-review-queue.ts, implemented in
dashboard/exact-review-direct-publication.ts, and consumed by
scripts/worker-records.ts. Regression coverage lives in
test/record-export-bounds.test.ts and test/worker-records-request.test.ts.
EXACT_REVIEW_HOSTED_TARGET_ADMISSION_FRESH_MS: intake's no-probe public-admission cache window (default 60,000 ms).EXACT_REVIEW_HOSTED_TARGET_ADMISSION_MAX_STALE_MS: intake fallback after retryable probes (default 1,800,000 ms; zero disables caching; terminal probes revoke).EXACT_REVIEW_STALE_PUBLICATION_PRUNE_LIMIT: stale-revision cleanup per alarm (default 100; zero disables).EXACT_REVIEW_PUBLICATION_RECOVERY_SUCCESSESoverrides how many consecutive clean publications raise the adaptive publication ceiling by one step; the default is 10 (clamped 1-1000). The former hardcoded 50 pinned the lane at its minimum under hourly rate-limit bursts because the counter resets on every failure.CLAWSWEEPER_IDEA_REVIVAL_REACTIONSretains the positive-reaction threshold that prevents closing an old feature request with community traction; the default is 5. It no longer configures an automatic reopening watcher.REVIEW_PLACEHOLDER_MAX_CHECKSoverrides the number of search candidates examined per open and closed state class by each 15-minute orphaned-placeholder recovery pass; the default is 20 and the maximum is 1000. Independent durable cursors rotate both state classes so non-actionable matches cannot permanently pin later placeholders behind the bounded pass.REVIEW_PLACEHOLDER_MIN_AGE_HOURSoverrides how old the latest ClawSweeper bot review-start placeholder must be before recovery; the default is 2 hours and the maximum is 720 hours.REVIEW_PLACEHOLDER_MAX_RECOVERIESoverrides the number of orphaned review placeholders enqueued per recovery pass; the default is 5 and the maximum is 100.- Placeholder recovery logs GitHub Search
matchedand derivedremainingcounts for backlog telemetry. Search counts can lag comment mutations, so only failed cleanup or enqueue actions for live-verified orphans make the scheduled run fail. EXACT_REVIEW_DISPATCH_DEBOUNCE_MSoverrides the 90,000 ms coalescing delay for fresh non-command exact-review events.EXACT_REVIEW_DISPATCH_DEBOUNCE_MAX_MSoverrides the 180,000 ms maximum coalescing window measured from the item's first enqueue.EXACT_REVIEW_ACTIVE_ITEM_REVIEW_THRESHOLDoverrides the two completed review generations (clamped to 1-100) that mark an item as under active churn.EXACT_REVIEW_ACTIVE_ITEM_WINDOW_MSoverrides the 3,600,000 ms trailing window for counting those completions (at most 24 hours);0disables the active-item debounce.EXACT_REVIEW_ACTIVE_ITEM_DEBOUNCE_MSoverrides the 600,000 ms delay from the latest organic revision of an active item (at most one hour).EXACT_REVIEW_ACTIVE_ITEM_DEBOUNCE_MAX_MSoverrides the 900,000 ms cap for that delay, measured from the first pending enqueue (at most one hour).EXACT_REVIEW_PENDING_SOFT_LIMIToverrides the pending-depth threshold for shedding new recovery and scheduled exact-review work; production sets it to 600.EXACT_REVIEW_SOURCE_DRIFT_REQUEUE_LIMITsets how many consecutive automatic source-drift review generations an item may use before it parks assource_drift_loop; the default and production value is 3,0disables the breaker, and the maximum is 100.EXACT_REVIEW_RUNAWAY_REVIEWS_PER_DAYsets the claimed-review count per item in a trailing 24 hours above which queue health reportsreview_runaway; the default and production value is 24.EXACT_REVIEW_TARGET_RATE_PER_HOURsets the fleet-wide scheduled admission refill target; the source fallback is 60 and production sets 220. Claimed organic review executions consume it first and may carry debt down to minus the burst; scheduled work fills only the remainder. Unconditional organic work may exceed the target.EXACT_REVIEW_TARGET_BURSTbounds the admission burst and the organic debt floor; the source fallback is six and production sets 24, split 35/65 between the hot-intake and normal-backfill lane buckets.EXACT_REVIEW_HOT_INTAKE_RATE_PER_HOURcaps the hot-intake lane rate (clamped to at least one and below the total); normal backfill receives the total minus hot. When unset or invalid, hot intake keeps 35% of the total. Production sets 30.EXACT_REVIEW_SCHEDULED_MAX_CONCURRENTcaps active scheduled review owners; the source fallback is eight and production sets 32, clamped to the global review capacity.- Scheduled planners subtract active and pending review work from the 80-slot review capacity before selecting candidates. Target fanout gives every cursor-selected repository a one-candidate floor, then apportions the remaining free capacity by untracked backlog.
EXACT_REVIEW_HEARTBEAT_GRACE_MSoverrides the 1,200,000 ms exact-review worker heartbeat grace. It is clamped to at least 420,000 ms so a configured grace can never dip near the one-minute worker heartbeat interval during scheduler or network stalls.- Broad
review-plan.ymldispatches use queue-advertised candidate capacity, bounded byreview_shards.hard_cap; there is no per-run shard override.