Skip to content

GPT-6 lane: capacity retry, idle watchdog that ignores reconnect notices, completed-turn success, per-lane effort (ultra disclosed as xhigh + delegation) and web search - #549

Merged
seathatflowsinourveins merged 4 commits into
mainfrom
claude/gpt6-lane-capacity-retry-idle-watchdog-20260930
Oct 1, 2026
Merged

seathatflowsinourveins merged 4 commits into
mainfrom
claude/gpt6-lane-capacity-retry-idle-watchdog-20260930

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes: it hardens the landscape-sweep GPT-6 lane harness (codex_job.py) against the failures seen on 2026-09-30, and adds per-lane effort and web search:
    • Codex's terminal "Selected model is at capacity." error is retried twice with capped, jittered backoff.
    • An idle watchdog ignores reconnect notices.
    • Success requires a completed turn.
    • Effort and web search are set per lane, following the user's 2026-09-30 GPT standard.
  • Base commit: 11227bfd
  • Lane: lane:foundation
  • Owned paths touched:
    • tools/sota-convergence/landscape-sweep/{codex_job.py,codex_call.sh,README.md}
    • tests/test_landscape_sweep_harness.py
    • docs/decisions/2026-09-29-codex-lane-default-effort.md (dated amendment)
    • manifests/evidence.json (hash re-registration only)

Why. These are the failures observed on 2026-09-30, all retained in the lane work dirs:

  • Two jobs ended at once with turn.failed "Selected model is at capacity." (exit 1, no output).
  • One native job printed its last event (item.completed web_search) and then nothing for hours until it was killed by hand.
  • A research job was still working when the 3000 s budget ended it.
  • A job whose codex process group got SIGTERM was recorded as done, exit 0, empty output. A rerun with the same inputs would then have answered "already done".

SOTA sources

Every rule was checked against openai/codex at tag rust-v0.159.2 (commit ff6aec96948b), which is the installed client (codex-cli 0.159.2):

  • Capacity is terminal upstream. codex-rs/protocol/src/error.rs:384-412: retry_delay() returns None for ServerOverloaded. The retry therefore lives in the harness.
  • SIGTERM exit 0. codex-cli/bin/codex.js:270-293: the npm wrapper forwards the signal. When the child dies by signal, the wrapper re-raises it on itself while its own listener is still registered, so the listener catches it and the wrapper exits 0. The native binary handles only ctrl_c (codex-rs/exec/src/lib.rs:1126-1132). exec prints turn.completed and then writes -o (codex-rs/exec/src/event_processor_with_jsonl_output.rs:525-536,631-636). Success therefore requires exit 0, turn.completed and a non-empty -o file; anything else is exit 126, incomplete.
  • Reconnect notices are JSONL error events. The chain is core/src/session/mod.rs:5030 → app-server/src/bespoke_event_handling.rs:1054-1070 (will_retry: true) → exec/src/event_processor_with_jsonl_output.rs:447-458. So:
    • the watchdog does not count error events as progress;
    • the silent hang was not a reconnect loop, and its cause stays unknown;
    • the upstream default unbounded_connection_retries (Stable, on: features/src/lib.rs:1292-1297; backoff 5→60 s: core/src/responses_retry.rs:71-96) is kept. Codex rides out short outages, and the watchdog stops a loop longer than the idle budget.
  • What ultra means at 0.159.2.
    • For gpt-6.1-sol and gpt-6-astra, ultra resolves to the model's multi_agent_reasoning_effort "xhigh" on every root request (models-manager/models.json:22,196; protocol/src/openai_models/reasoning_effort.rs:12-35; core/src/client.rs:863-872), and it enables proactive delegation (core/src/session/multi_agents.rs:77-103). The live catalog cache (fetched 2026-09-30T18:54Z, client 0.159.2) agrees.
    • A root multi-agent wait may block up to 3600 s (core/src/config/mod.rs:257; tools/handlers/multi_agents_v2/wait.rs:53-64), and exec drops sub-agent items (exec/src/lib.rs:1624-1629). Ultra lanes therefore default to idle 4200 s and total 14400 s, and a staged ultra idle of 3600 s or less is refused.
    • exec reports primary-thread usage only (exec/src/lib.rs:1636-1638), so ultra usage is labelled primary_thread_only.
    • A model outside the catalog gets fallback metadata (models-manager/src/model_info.rs:98-106), where ultra would resolve to medium, so it is refused.
  • Web search modes: protocol/src/config_types.rs:371-382.
  • Backoff shape: capped exponential backoff with jitter (AWS Architecture Blog, "Exponential Backoff And Jitter").

Evidence-class table

Claim Evidence class Command / receipt
Upstream behaviours above (capacity terminal, SIGTERM exit 0, reconnect events, ultra resolution, wait cap, primary-thread usage) source_review the rust-v0.159.2 locators above; all re-read by the Claude Opus cross-family review
A SIGTERM'd job is no longer recorded as success native_proven live control on 2026-09-30 through this harness: before the fix done 0 with empty output; at head db75ddca failed 126 incomplete
The native lane runs at max and at ultra on the built-in provider native_proven at db75ddca: max probe done 0, request_effort max, usage reported (20,258 in / 52 out); ultra probe done 0, request_effort xhigh, usage primary_thread_only (20,308 in / 19 out); argv has no provider or reconnect override
Capacity retry and backoff cap, shared budget, idle stop and retry, LIMIT/429 precedence, 300 s retry floor, completed-turn grace, inputs_changed, failure.json on every terminal path synthetic 166 fixture tests in tests/test_landscape_sweep_harness.py (3 skipped)
A real capacity error or a real silent hang is recovered not yet observed will be recorded when one occurs

Local commands run

$ TMPDIR=<outside /tmp> python3 -m unittest tests.test_landscape_sweep_harness
Ran 166 tests ... OK (skipped=3)
$ python3 scripts/validate.py
{"components": 69, "hashed_files": 8515, "profiles": 4, "receipts": 176, "status": "passed"}
$ git diff --check   -> exit 0

Decision record

docs/decisions/2026-09-29-codex-lane-default-effort.md, "Amendment (2026-09-30)":

  • the user's decision (verbatim): "yes no limit, for highest quality resolution, gpt6.1sol at ultra and astra when tasks truly needed it";
  • the harness default stays max;
  • a lane may stage ultra;
  • blind or isolated review lanes stay at max, because ultra delegates;
  • the resolved-effort fact and the ultra idle rule.

Overturn conditions:

  • a Codex release makes ServerOverloaded retryable, or fixes the wrapper's exit status: drop the matching harness rule;
  • the catalog changes ultra's resolved effort: update the map.

Review history

  1. Draft cc00dbd9, from a gpt-6.1-sol research lane.

  2. Finalization 9aff1344, by a native gpt-6.1-sol builder at ultra: the completion rule, the error-event rule, per-lane effort and web search.

  3. Claude Opus cross-family review: repair. Findings:

    • blocking: a 7200 s default outlasted the sweep wrapper's 4320 s wait;
    • ultra shows "ultra" but sends xhigh;
    • ultra delegation can outlast the idle budget;
    • ultra usage leaves out sub-agents;
    • the reconnect override cost outage ride-out;
    • the named provider had become a no-op;
    • eight low-severity items.
  4. Repair round db75ddca, by the same native builder with coordinator decisions. It fixes all of the above in the allowed paths, and is verified by the tests and the live checks above.

  5. Hot-file protocol: rebuilt as b019b900 (content, no hot file) + ed818625 (last commit: manifests/evidence.json only) on main 8fc86119; tree byte-identical to the reviewed head 9f68193c; Gate A owner (6d): no objection, merge after c5's train.

Residuals

These are outside this PR. All three files are also touched by the open #541, and I've notified its owner.

  • sweep.js:92: the 4320 s wrapper wait. Queued jobs, and ultra lanes, can still outlast it.
  • convert.py:200-208,291: it drops request_effort and failure, and would treat primary_thread_only usage as complete.
  • build_args.py:508: it always stages max, which is correct for the sweep's blind lanes, and has no flags for effort, web search or budgets.

Checklist

  • No new or changed GitHub Actions.
  • No new or changed workflows.
  • No secrets printed, logged or committed; the gitleaks pre-commit hook passed on every commit.
  • No new paid hosting, subscription or billing surface.
  • Peer-owned untracked files and worktrees preserved.

🤖 Generated with Claude Code

@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Sep 30, 2026
seathatflowsinourveins pushed a commit that referenced this pull request Sep 30, 2026
… progress; bounded reconnects on every lane; per-lane effort and web search

Found while finalizing #549 against openai/codex rust-v0.159.2:
- A SIGTERM'd `codex exec` exits 0: the npm wrapper re-raises the child's signal on itself while its own listener is still
  registered (codex-cli/bin/codex.js:270-293). The harness recorded such a job as done with empty output, and a
  same-input start answered "already done". Success now needs exit 0, a turn.completed event and a non-empty -o file;
  otherwise exit 126, failure kind incomplete (also applied to results and to the already-done check, so earlier
  false successes rerun).
- Each stream reconnect prints a JSONL {"type":"error"} event (core/src/session/mod.rs:5030 ->
  app-server/src/bespoke_event_handling.rs:1054-1070 -> exec/src/event_processor_with_jsonl_output.rs:447-458), so the
  idle watchdog no longer counts error events as progress. The 4-hour hang printed no events at all, so it was not a
  reconnect loop; its cause stays unknown.
- features.unbounded_connection_retries=false now applies to every lane: it is provider-independent, and the pool lane
  still had the default-on loop (features/src/lib.rs:1292-1297).
- Budgets from observation: idle 1800 s (healthy jobs were silent for at least 473 s), total 7200 s (a research job was
  still working at 3000 s); both configurable in staged.json.
- staged.json codex.effort follows the user's 2026-09-30 GPT standard (work lanes ultra, blind review lanes max;
  default max), validated against the 0.159.2 catalog. Ultra is refused for models outside the catalog, where Codex
  would resolve it to medium (protocol/src/openai_models/reasoning_effort.rs:10-35). codex.web_search takes an
  upstream WebSearchMode value (default live). Both are bound into inputs.json.

Built by a native gpt-6.1-sol builder at ultra from a coordinator brief. The coordinator then corrected the
out-of-catalog effort rule and restored a dropped web-search evidence comment.
- Tests: 147 passing (3 skipped).
- Live native checks, codex-cli 0.159.2:
  - SIGTERM control: before this change done 0; after it failed 126 incomplete;
  - the earlier false success now reads failed 126;
  - an ultra job: done 0, output returned.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins changed the title GPT-6 lane: retry "model at capacity" with capped backoff, idle watchdog, bounded native reconnects GPT-6 lane: capacity retry, idle watchdog that ignores reconnect notices, completed-turn success, per-lane effort (ultra disclosed as xhigh + delegation) and web search Sep 30, 2026
@seathatflowsinourveins
seathatflowsinourveins marked this pull request as ready for review September 30, 2026 19:22
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/gpt6-lane-capacity-retry-idle-watchdog-20260930 branch from 9f68193 to ed81862 Compare September 30, 2026 19:50
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/gpt6-lane-capacity-retry-idle-watchdog-20260930 branch from ed81862 to 941d71d Compare September 30, 2026 22:54
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Darwin killpg fix, landed by the coordinator (c5) because the lane owner's session has ended. Head 941d71dc on main 29458b43; three commits: content b25e1fe6 (the previous b019b900, rebased), fix d1766430, re-register 941d71dc (manifests/evidence.json and the four generated reports change only in the last commit).

Diagnosis (run 36768476923, job 110068536952, artifact full-suite-macos.log: Ran 8671 tests, failures=5; ubuntu on the same head: OK). RecoveryRunnerTests test_idle_failure_can_recover, test_reconnect_error_events_are_not_progress, test_stderr_and_incomplete_json_are_not_progress, test_total_timeout_remains_terminal and RunnerTests.test_completion_grace_is_bounded returned exit 2 with failure kind refused and attempts [], while test_idle_stops_the_group_retries_once_and_retains_both_failures passed. The five stop a process group that dies at TERM; the passing one keeps a child that ignores TERM. Cause: XNU's killpg1 skips SZOMB members and returns EPERM when nothing was signalled (apple-oss-distributions/xnu xnu-12377.121.6, bsd/kern/kern_sig.c: the p->p_stat != SZOMB filter in the pgrp_iterate block and error = (karg.nfound > 0 ? 0 : (posix ? EPERM : ESRCH))); Linux signals a zombie silently. With kill_grace_s 0.1 the runner's loop polls once, the SIGKILL after the grace period reaches a group whose only member is a zombie, PermissionError propagates out of stop_group and run() records it as a refusal. The five tests pass on Linux at ed818625 (local run: 3 of them, OK).

Fix (d1766430): signal_group() treats ESRCH and EPERM alike, since every member of the group is the runner's own descendant; group_alive() no longer reads EPERM as alive; one README sentence. Tests: ProcessGroupStopTests (3 tests; synthetic fixture that patches os.killpg to answer EPERM once only exited members remain; failing-first on the previous runner: 1 error PermissionError, 1 failure), and RunnerCase.job() now fails with the runner's stderr.txt and failure.json whenever a started job is refused, so the next platform difference is readable in the CI log. Real observation: this head's validate-macos job.

Checks at 941d71dc: python3 -m unittest tests.test_landscape_sweep_harness exit 0, Ran 169 tests, OK (skipped=3); python3 scripts/validate.py passed; privacy scan of origin/main...HEAD: 1230 added lines, 0 hits. osv-scanner stays red on every head until the litellm relock (GHSA-3cv6-jpf6-8222) merges; this PR rebases again in its train slot after #557.

SOTA sources: apple-oss-distributions/xnu xnu-12377.121.6 bsd/kern/kern_sig.c (killpg1, killpg1_callback); openai/codex rust-v0.159.2 citations already in the runner are unchanged.

🤖 Generated with Claude Code

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Cross-family review of the Darwin fix delta (b25e1fe6..941d71dc), GPT-6.1 Sol at max through the OmniRoute gateway, read-only codex exec, web search off, 2026-09-30 ~23:10Z: verdict approve, no actionable findings ("the XNU citation matches upstream, focused regression tests and evidence validation pass, and failing-first behavior is verified; native macOS CI remains in progress"). The macOS job on this head is the real observation and is still pending.

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Real observation: the validate-macos job on head 941d71dc passed (the full suite on macOS, including the five watchdog tests that failed on ed818625), confirming the Darwin killpg EPERM diagnosis; only osv-scanner remains red until #562 merges.

@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/gpt6-lane-capacity-retry-idle-watchdog-20260930 branch 2 times, most recently from 1f6b20d to daef405 Compare October 1, 2026 00:48
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Stacked-state fix: hosted validate on the stacked head 1f6b20d4 (job 110160196706) failed one subtest of unit A4's tests/test_task_model_routing.py (below this PR in the merge train): the routing record quoted EFFORT = "max" from codex_job.py:94-95, and this PR renamed that constant to DEFAULT_EFFORT and moved both constants to lines 131-132. The record row now quotes DEFAULT_MODEL / DEFAULT_EFFORT at their current lines (one-line change, no routing change); tests.test_task_model_routing 10 OK at the new head. New head daef4050 on F3's 9dae8c41, manifests/evidence.json last commit only. Lesson recorded for the train: a unit's tests are rerun in the stacked order, and the whole suite rather than the touched modules when a sibling unit adds repository-wide checks.

Scout and others added 4 commits September 30, 2026 23:47
…ect notices, completed-turn success, per-lane effort (ultra disclosed as xhigh + delegation) and web search

Upstream reference: openai/codex rust-v0.159.2 (ff6aec96948b), the installed client.

What changes:
- Capacity: "Selected model is at capacity." is terminal upstream (protocol/src/error.rs:384-412). The harness retries
  it twice with capped, jittered backoff.
- Idle watchdog: after 1800 s without a complete non-error JSONL event the process group is stopped (exit 125) and
  the job retries once. Reconnect notices are JSONL error events (core/src/session/mod.rs:5030 ->
  app-server/src/bespoke_event_handling.rs:1054-1070 -> exec/src/event_processor_with_jsonl_output.rs:447-458), so
  they are not progress. The upstream unbounded reconnect stays on: it rides out short outages, and the watchdog stops
  longer ones.
- Success: exit 0 plus turn.completed plus a non-empty -o file; otherwise exit 126, incomplete. The npm wrapper exits
  0 on SIGTERM (codex-cli/bin/codex.js:270-293). The same rule applies to result, wait and the already-done check.
- Budgets: 4000 s total by default, which fits the sweep wrapper's 8 x 540 s wait. Ultra lanes default to idle
  4200 s and total 14400 s, and a staged ultra idle of 3600 s or less is refused, because a root multi-agent wait
  can block up to 3600 s (core/src/config/mod.rs:257).
- Effort: per-lane codex.effort, validated against the 0.159.2 catalog, default max. For gpt-6.1-sol and gpt-6-astra
  ultra resolves to xhigh per root request plus delegation (models-manager/models.json:22,196;
  protocol/src/openai_models/reasoning_effort.rs:12-35). That value is recorded as request_effort, and ultra usage is
  labelled primary_thread_only.
- Web search: per-lane codex.web_search, default live.
- Other: failure.json on every terminal path; inputs_changed on a restage; a quota probe before every attempt; a
  300 s floor before any retry; completed-turn grace at the deadline; the built-in native provider is kept.
- Dated amendment in docs/decisions/2026-09-29-codex-lane-default-effort.md, recording the user's 2026-09-30 GPT
  standard.

How it was built and checked:
- Built by native gpt-6.1-sol workers from coordinator briefs, with coordinator corrections.
- Claude Opus cross-family review: repair. All repairs are applied in this commit.
- Tests: 166 OK (3 skipped).
- Live native controls on codex-cli 0.159.2:
  - SIGTERM control: before the fix "done 0" with empty output; after it "failed 126 incomplete";
  - max probe: done 0;
  - ultra probe: done 0, request_effort xhigh.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…'s group holds only exited members

The 2026-09-30 macOS full-suite job on this branch (run 36768476923) failed the five watchdog tests whose process group
dies at TERM (idle-recover, reconnect, partial, total-timeout, completed-stuck) with exit 2 "refused": XNU's killpg1
skips zombies and returns EPERM when nothing was signalled (apple-oss-distributions/xnu xnu-12377.121.6,
bsd/kern/kern_sig.c), so the SIGKILL sent after the grace period raised PermissionError, which run() reports as a
refusal; Linux signals a zombie silently, and the stubborn-child test passed on macOS because its group still had a
live member. signal_group() now treats ESRCH and EPERM alike for the runner's own descendants, group_alive() no longer
reads EPERM as alive, ProcessGroupStopTests fix the behaviour (failing-first: 1 error, 1 failure on the previous
runner) and RunnerCase.job() retains the runner's stderr.txt and failure.json whenever a started job is refused, so a
future platform difference is readable in the CI log.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
…his PR renamed (EFFORT → DEFAULT_EFFORT)

tests/test_task_model_routing.py (unit A4, below this PR in the merge train) looks each quoted value up in its
cited file; this PR renamed EFFORT to DEFAULT_EFFORT and moved both constants, so the Codex sweep-vote row now
quotes DEFAULT_MODEL / DEFAULT_EFFORT at their current lines. Hosted validate on the stacked head 1f6b20d failed
exactly that subtest (job 110160196706); no routing changes.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/gpt6-lane-capacity-retry-idle-watchdog-20260930 branch from daef405 to e9ef08d Compare October 1, 2026 03:47
@seathatflowsinourveins
seathatflowsinourveins merged commit 50bba7b into main Oct 1, 2026
25 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/gpt6-lane-capacity-retry-idle-watchdog-20260930 branch October 1, 2026 04:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant