Skip to content

Per-task check_timeout_s: infrastructure-booting checks stop timing out#53

Open
davidfoy wants to merge 2 commits into
NateBJones-Projects:mainfrom
davidfoy:contrib/oa140-check-timeout
Open

Per-task check_timeout_s: infrastructure-booting checks stop timing out#53
davidfoy wants to merge 2 commits into
NateBJones-Projects:mainfrom
davidfoy:contrib/oa140-check-timeout

Conversation

@davidfoy

Copy link
Copy Markdown

Hi — courtesy PR from a fork. We hit this running Ringer daily and figured it might be useful upstream.

Problem

Verifier._run_check hard-codes CHECK_TIMEOUT_S = 60 for every check. Any check that boots real infrastructure before it can assert — a docker-backed test stack takes ~90s (Mongo + seed + uvicorn) — always trips the 60s cap and marks a correct worker failed, then burns the one retry on the same wall. In our case it cost a good first-try implementation ~104k tokens and polluted the model scoreboard until hand-annotated.

Change

Optional per-task manifest field check_timeout_s — opt-in, zero behavior change when unset.

  • TaskSpec.check_timeout_s: int | None — absent = today's behavior (module CHECK_TIMEOUT_S), present = positive int (validated), threaded through verify → _run_check's asyncio.wait_for, resolved at call time.
  • Timeout message names the limit and its source: check timed out after {n}s (task check_timeout_s) vs (default), so retry prompts and post-mortems show whether the cap was chosen or inherited.
  • lint warns when a check matches generic infra-boot signals (docker / compose up) while check_timeout_s is unset — the exact footgun. Patterns are intentionally generic; no product-specific script names.
  • README task-field table documents it.

Invariants preserved

Stdin closed (DEVNULL), sandbox mode explicit, verification executes the artifact, logs carry raw worker output only. No change to default behavior for any existing manifest.

Tests

Adds tests/test_check_timeout.py, red-proven before implementation (fails on unmodified ringer.py). Fast tier shrinks the module constant to prove both the task-override and default branches in seconds; a ticket-verbatim slow tier (real sleep 90 vs the real 60s default) is gated behind RINGER_SLOW_ORACLE=1. Full suite green locally (229 passed, 2 skipped) — including the ## Contributors credit rule.

Happy to adjust naming, the lint patterns, or the docs to fit your conventions — your call on all of it.

davidfoy and others added 2 commits July 16, 2026 15:49
Pins the contract before implementation: absent field = today's behavior
(module CHECK_TIMEOUT_S, consulted at call time); present = positive int
threaded into the check's wait_for; timeout message names the limit AND its
source (task check_timeout_s / default); lint warns on generic infra-boot
checks (docker/compose) lacking the field. Slow ticket-verbatim cases
(sleep 90 vs the real 60s default) gated behind RINGER_SLOW_ORACLE=1.

Fails on unmodified ringer.py; passes on the reference patch. Castle wall:
lint patterns are generic only — no product boot-script names in ringer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The verifier hard-coded CHECK_TIMEOUT_S = 60 for every check, so any check that
boots real infrastructure (a docker-backed test stack ~90s) always timed out and
marked a good worker failed — the OA-138 failure mode.

- TaskSpec gains optional check_timeout_s (int|None); absent = today's behavior
  (module CHECK_TIMEOUT_S), present = positive int, threaded through
  verify -> _run_check's asyncio.wait_for, resolved at call time.
- Timeout message names the limit AND its source: '(task check_timeout_s)' vs
  '(default)', so retry prompts and post-mortems show whether the cap was chosen
  or inherited.
- lint warns when a check matches generic infra-boot signals (docker / compose
  up) while check_timeout_s is unset — the OA-138 footgun. Patterns are generic
  only; product-specific boot-script names stay out of ringer (castle wall).
- README documents the field.

Invariants preserved: stdin closed, sandbox explicit, verification executes the
artifact, logs carry raw worker output only. Zero behavior change without the
field set. Implemented by a Ringer worker (gpt-5.5 high, first-try PASS) against
a red-proven oracle; independently reviewed and re-verified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@davidfoy
davidfoy marked this pull request as draft July 16, 2026 21:07
@davidfoy
davidfoy marked this pull request as ready for review July 16, 2026 21:08
@davidfoy
davidfoy marked this pull request as draft July 16, 2026 21:18
@davidfoy
davidfoy marked this pull request as ready for review July 16, 2026 21:18
seanpmgallagher added a commit to seanpmgallagher/ringer that referenced this pull request Jul 23, 2026
…r slow build-gate checks

# Conflicts:
#	README.md
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.

1 participant