Ask: Add DISPATCH_STALE_WORK_INTERVAL_MS (and DISPATCH_STALE_WORK_MAX_AGE_MS / DISPATCH_STALE_WORK_BATCH_SIZE if they become env-driven) to .env.example, mirroring the DISPATCH_*_INTERVAL_MS section so operators can disable or tune the stale-work sweep without reading src/lib/scheduler.ts.
Expected files: .env.example, src/lib/stale-work.ts (only if env knobs are promoted)
Problem: src/lib/scheduler.ts:114 reads DISPATCH_STALE_WORK_INTERVAL_MS (along with DISPATCH_SYNC_INTERVAL_MS, DISPATCH_GROOMER_INTERVAL_MS, DISPATCH_PR_FOLLOWUP_INTERVAL_MS, DISPATCH_PRUNE_CLOSED_INTERVAL_MS, DISPATCH_RECONCILE_INTERVAL_MS), but only the other five intervals are documented in .env.example. The stale-work sweep is the recovery path for the exact failure mode that #867 ("agent dies mid-work, leases never reclaimed") and #874 ("reclaim stale claims automatically") landed to fix — making its interval invisible to operators is a documentation regression. Operators tuning the cadence of self-healing against GitHub-write budget have to read the scheduler source to discover the knob exists, and the test suite explicitly pins "disable when set to 0" semantics for DISPATCH_STALE_WORK_INTERVAL_MS that no operator-facing doc mentions.
Evidence:
- src/lib/scheduler.ts:114:
intervalMs: jobIntervalFromEnv(env.DISPATCH_STALE_WORK_INTERVAL_MS, DEFAULT_STALE_WORK_INTERVAL_MS),
- src/lib/scheduler.test.ts:69–70: a test that pins DISPATCH_STALE_WORK_INTERVAL_MS=0 disables the stale-work job.
- .env.example lines 209–233 document DISPATCH_SYNC_INTERVAL_MS, DISPATCH_GROOMER_INTERVAL_MS, DISPATCH_PR_FOLLOWUP_INTERVAL_MS, DISPATCH_PRUNE_CLOSED_INTERVAL_MS, DISPATCH_RECONCILE_INTERVAL_MS — but not DISPATCH_STALE_WORK_INTERVAL_MS.
- src/lib/stale-work.ts defines DEFAULT_STALE_WORK_MAX_AGE_MS / DEFAULT_STALE_WORK_BATCH_SIZE as constants only (not env-driven yet); if this issue promotes them, document those too.
Acceptance: .env.example gains a DISPATCH_STALE_WORK_INTERVAL_MS entry under the existing scheduler block, with the same default-ms-to-readable-units conversion as the neighbours (e.g. "Default 300000 (5 min)" or whatever DEFAULT_STALE_WORK_INTERVAL_MS is set to — verify against src/lib/scheduler.ts). Optional follow-on: promote DEFAULT_STALE_WORK_MAX_AGE_MS / DEFAULT_STALE_WORK_BATCH_SIZE to env-driven knobs (DISPATCH_STALE_WORK_MAX_AGE_MS / DISPATCH_STALE_WORK_BATCH_SIZE) and document them. No code regression: current defaults must stay unchanged when the env var is unset.
Ask: Add DISPATCH_STALE_WORK_INTERVAL_MS (and DISPATCH_STALE_WORK_MAX_AGE_MS / DISPATCH_STALE_WORK_BATCH_SIZE if they become env-driven) to .env.example, mirroring the DISPATCH_*_INTERVAL_MS section so operators can disable or tune the stale-work sweep without reading src/lib/scheduler.ts.
Expected files: .env.example, src/lib/stale-work.ts (only if env knobs are promoted)
Problem: src/lib/scheduler.ts:114 reads DISPATCH_STALE_WORK_INTERVAL_MS (along with DISPATCH_SYNC_INTERVAL_MS, DISPATCH_GROOMER_INTERVAL_MS, DISPATCH_PR_FOLLOWUP_INTERVAL_MS, DISPATCH_PRUNE_CLOSED_INTERVAL_MS, DISPATCH_RECONCILE_INTERVAL_MS), but only the other five intervals are documented in .env.example. The stale-work sweep is the recovery path for the exact failure mode that #867 ("agent dies mid-work, leases never reclaimed") and #874 ("reclaim stale claims automatically") landed to fix — making its interval invisible to operators is a documentation regression. Operators tuning the cadence of self-healing against GitHub-write budget have to read the scheduler source to discover the knob exists, and the test suite explicitly pins "disable when set to 0" semantics for DISPATCH_STALE_WORK_INTERVAL_MS that no operator-facing doc mentions.
Evidence:
intervalMs: jobIntervalFromEnv(env.DISPATCH_STALE_WORK_INTERVAL_MS, DEFAULT_STALE_WORK_INTERVAL_MS),Acceptance: .env.example gains a DISPATCH_STALE_WORK_INTERVAL_MS entry under the existing scheduler block, with the same default-ms-to-readable-units conversion as the neighbours (e.g. "Default 300000 (5 min)" or whatever DEFAULT_STALE_WORK_INTERVAL_MS is set to — verify against src/lib/scheduler.ts). Optional follow-on: promote DEFAULT_STALE_WORK_MAX_AGE_MS / DEFAULT_STALE_WORK_BATCH_SIZE to env-driven knobs (DISPATCH_STALE_WORK_MAX_AGE_MS / DISPATCH_STALE_WORK_BATCH_SIZE) and document them. No code regression: current defaults must stay unchanged when the env var is unset.