Ticket lifecycle sweeps, dry run by default (GET) — cronstaleinprogressget
const url = 'https://example.com/api/cron/stale-in-progress?dry_run=0';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://example.com/api/cron/stale-in-progress?dry_run=0'The hourly ticket-lifecycle tick (HO-15546). Runs, in order and under one shared
~75s deadline: the closing-line close (a parked closing-line ticket closes once its
deploy is recorded, or once its merge is on the default branch when its repo
reports no deploys; never on elapsed time), the in-progress move-back (no agent for
48h returns the ticket to up next) and the 30-day archive (an untouched backlog or
validation ticket is archived). Also trims the agent_notifications catch-up log to
14 days.
DRY RUN BY DEFAULT: the sweeps only count and sample unless dry_run=0 is sent
explicitly; any other value, or none, stays dry. Each sweep result carries
scanned/acted/skipped/errors, a truncated flag and up to 25 sample ticket
ids. A truncation is not a failure; top-level ok is the AND of the three sweeps
(the retention sweep is best-effort and never affects it). One sweep throwing sets
ok: false and does not stop the others.
Protected by CRON_SECRET via the x-cron-secret header ONLY — a token
query parameter is rejected (secrets do not belong in URLs).
Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”Dry run is the DEFAULT. Only 0 runs the lifecycle sweeps for real; 1, an empty value, any other value and an absent parameter all count and sample without writing.
Responses
Section titled “ Responses ”Lifecycle sweep result
object
AND of the three sweeps’ ok. The best-effort retention sweep never affects it.
True unless the caller sent an explicit dry_run=0.
object
False when a read the sweep depends on failed, or the sweep threw. A truncation never sets it.
Candidate rows read.
Tickets closed, moved or archived (in a dry run, the tickets that would be).
Eligible tickets left alone — a lost race, a refused write, or a read that failed closed.
True when the per-tick cap, the shared deadline or the scan cap stopped the sweep before every candidate was seen.
Up to 25 tickets the sweep acted on or skipped.
object
Closed | would_close | returned | would_return | archived | would_archive | skipped
object
False when a read the sweep depends on failed, or the sweep threw. A truncation never sets it.
Candidate rows read.
Tickets closed, moved or archived (in a dry run, the tickets that would be).
Eligible tickets left alone — a lost race, a refused write, or a read that failed closed.
True when the per-tick cap, the shared deadline or the scan cap stopped the sweep before every candidate was seen.
Up to 25 tickets the sweep acted on or skipped.
object
Closed | would_close | returned | would_return | archived | would_archive | skipped
object
False when a read the sweep depends on failed, or the sweep threw. A truncation never sets it.
Candidate rows read.
Tickets closed, moved or archived (in a dry run, the tickets that would be).
Eligible tickets left alone — a lost race, a refused write, or a read that failed closed.
True when the per-tick cap, the shared deadline or the scan cap stopped the sweep before every candidate was seen.
Up to 25 tickets the sweep acted on or skipped.
object
Closed | would_close | returned | would_return | archived | would_archive | skipped
object
Missing or invalid CRON_SECRET