Skip to content

Round 14: make the 1M synthetic corpus release reachable - #13

Merged
cosmicbboy merged 7 commits into
mainfrom
round14-throughput
Sep 10, 2026
Merged

cosmicbboy merged 7 commits into
mainfrom
round14-throughput

Conversation

@cosmicbboy

Copy link
Copy Markdown
Contributor

The round-13 1M run (upnz22h5cdt6gdgrtshv) succeeded at 31,704 rows of a requested 1,000,000 — 78 surviving archetypes × 400 variants, plus 504 measured calibration rows. It reported success because require_target=False turns shipping short into a warning.

Four mechanisms are fixed here, all of them post-mortem findings.

1. The wave loop could not stop itself

Wave 1 ran 19.5h against a 15h generation deadline, because the deadline was only tested after asyncio.gather returned. The run generated once, spent its whole budget in a single un-adapted wave, and never reached wave 2 — the adaptive sizing that was supposed to respond to the observed keep rate never executed at all.

The deadline is now checked inside build_archetype, wave sizing is bounded by the time actually left (plan_wave, extracted as a pure function and unit tested), and wave 1 is deliberately small so there is a keep-rate observation to size wave 2 with.

2. Work kept going to dead teachers

277 archetypes died on HTTP 504 after exhausting all three retries — and the histogram is the tell: 291 first retries, 290 second, 288 third. Essentially every retry failed too, because the endpoints were persistently unavailable rather than hiccuping. Each burned 5+10+20s of backoff first: ~2.8 hours of pure sleeping against the concurrency limit for zero recovered work.

TeacherPool now round-robins over healthy endpoints only and trips a breaker after N consecutive transport failures (content rejections don't count — that's a prompt problem, and dropping the endpoint wouldn't fix it), never the last one standing, with a half-open probe each wave since these apps scale from zero and do come back. Per-call retries drop from 3/5s to 2/2s.

3. Broken code cost 7 pods to discover

The largest rejection bucket was curated out: execution failed — 462 pods of code that passed the AST screen, imported fine, and raised at runtime.

A viability probe now runs the cheapest calibration point first and stops there if the code cannot execute. It costs nothing when it passes, because that point is a measurement we needed anyway. It fires only on execution/pod failure, never on a point merely landing out of bounds — that's a property of the parameter point, not the code, and rejecting there would throw away archetypes the probe was never meant to judge.

4. A dozen new libraries had one line of guidance each

Round 13 admitted polars/duckdb/dask/jax/lightning/faiss/langgraph/llama-index with a sentence apiece, which names a library but pins none of the call signatures that decide whether a module runs. STACK_PITFALLS adds a narrow API contract per stack — polars group_by, lightgbm's removed verbose_eval, networkx from_numpy_array, faiss float32 contiguity, langgraph recursion limits, lightning's writes-to-cwd defaults, transformers hidden_size % num_heads — and the prompt now says outright that the module is executed at its range lows first and discarded if it raises there.

Sizing follows from the measured unit cost

upnz22h5 ran ~1,550 oracle pods in 19.5h at concurrency 24: ~17 minutes of wall clock per pod, of which only ~1–2 min is the workload. The rest is node scale-up and pulling the (much fatter) round-13 harness image. That cost isn't going away, so the levers are width and pod count:

  • oracle_concurrency 24 → 160 (pods are one per t3a.xlarge on a 3–250 node pool — 24 was using a tenth of the available fan-out)
  • variants_per_archetype 400 → 1200 (~834 archetypes for 1M: 10× what round 13 shipped, and well inside both gates that bound this axis — near-duplication is measured over archetype code, so variants don't affect it, and concentration admits 2% per archetype = 20,000 rows at 1M)
  • 150s peak-hold dropped from the rotation (paid by every calibration pod)
  • generation deadline 16h → 20h, task runtime 24h → 36h, so a release that generates to its deadline still has time to ship

Also fixes an int default on a float task parameter that was aborting flyte deploy partway through the task list.

Tests

23 new tests over the wave planner, the circuit breaker, the probe classifier and the stack contracts (tests/test_wave_throughput.py); 209 pass overall.

Research log

Adds research_log/2026-09-09-round-12-14-corpus-at-scale.md covering rounds 12–14 — the quality-gate work (including two gate bugs that failed a perfectly good corpus, recovered via flyte fork), the stack axis and teacher tiers, and the post-mortem above.

Run

uqjsqswf4fntdjrq9qzq is the first 1M attempt on this code, launched 2026-09-09 and running now. The ~14–16h projection is an estimate from one prior run's unit cost, not a measurement.

🤖 Generated with Claude Code

https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e

cosmicbboy and others added 4 commits September 9, 2026 23:32
The round-13 1M run (upnz22h5cdt6gdgrtshv) SUCCEEDED at 31,704 rows of a
requested 1,000,000: 78 archetypes survived x 400 variants + 504 measured
rows. Four mechanisms are fixed here, all of them post-mortem findings.

1. The wave loop could not stop itself. Wave 1 ran 19.5h against a 15h
   generation deadline, because the deadline was only tested AFTER
   asyncio.gather returned -- so the run generated once, blew the whole
   budget in an un-adapted first wave, and never reached wave 2. The
   deadline is now checked inside build_archetype, wave sizing is bounded
   by the time actually left (plan_wave, extracted and unit-tested), and
   wave 1 is deliberately small so there IS a keep-rate observation to
   size wave 2 with.

2. Work kept going to dead teachers. 277 archetypes died on HTTP 504 after
   exhausting all three retries -- retries 1/2/3 failed at essentially the
   same rate, because the endpoints were persistently unavailable rather
   than hiccuping. Each burned 5+10+20s of backoff first: ~2.8 hours of
   pure sleeping against the concurrency limit for zero recovered work.
   TeacherPool now round-robins over HEALTHY endpoints only and trips a
   breaker after N consecutive transport failures (never the last one
   standing), with a half-open probe each wave since these apps scale from
   zero and do come back. Per-call retries drop from 3/5s to 2/2s.

3. A broken archetype cost 7 pods to find out. The largest rejection
   bucket was `curated out: execution failed` (462 pods) -- code that
   imported fine and raised at runtime. A viability probe now runs the
   CHEAPEST calibration point first and stops there if the code cannot
   execute; it costs nothing when it passes, because that point is a
   measurement we needed anyway. It fires only on execution/pod failure,
   never on a point merely landing out of bounds -- that is a property of
   the parameter point, not the code, and rejecting there would throw away
   archetypes the probe was never meant to judge.

4. The new libraries had a one-line hint each. Round 13 admitted a dozen
   libraries with a sentence of guidance apiece, which names a library but
   pins none of the call signatures that decide whether a module runs.
   STACK_PITFALLS adds a narrow API contract per stack -- polars group_by,
   lightgbm's removed verbose_eval, networkx from_numpy_array, faiss
   float32 contiguity, langgraph recursion limits, lightning's
   writes-to-cwd defaults, transformers hidden_size % num_heads -- and the
   prompt now says outright that the module is executed at its range LOWS
   first and discarded if it raises there.

Sizing follows from the measured unit cost: ~1,550 oracle pods in 19.5h at
concurrency 24 is ~17 min of wall clock per pod, nearly all node scale-up
and pulling the (much fatter) round-13 harness image. So oracle_concurrency
24 -> 160 (pods are one per t3a.xlarge on a 3-250 node pool), variants
400 -> 1200 (~834 archetypes for 1M: 10x what round 13 shipped, and well
inside both gates that bound this axis -- near-duplication is measured over
archetype code, not variants), peak-hold 150s dropped from the rotation,
generation deadline 16h -> 20h and task runtime 24h -> 36h so a release
that generates to its deadline still has time to ship.

23 tests over the wave planner, the breaker, the probe classifier and the
stack contracts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
flyte's deploy-time literal conversion rejected an int default on a float
parameter ("Failed to convert default value for parameter
'gpu_max_vram_mib'"), aborting the deploy partway through the task list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
Covers the quality-gate work (and the two gate bugs that failed a good
corpus, recovered via flyte fork), the round-13 stack axis and teacher
tiers, and the round-14 post-mortem of the 1M release that shipped 31,704
rows and reported success.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
Run uqjsqswf4fntdjrq9qzq started with only qwen38-27b: the three frontier
teachers each needed GPU nodes and were still scaling when the 300s grace
expired. All four were ACTIVE ~30 min later, by which point the release was
locked to a single teacher for its whole 20-hour life -- throwing away the
multi-family diversity that is the point of running them.

300s was tuned when the pool was two similar models. Waiting longer is also
much safer than it was: a teacher that wakes and then goes bad now gets
dropped mid-run by the circuit breaker rather than absorbing its share of
archetypes forever.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
@cosmicbboy

Copy link
Copy Markdown
Contributor Author

Relaunched as us86v7zcfphfz76gjrdw after aborting the first attempt.

The first run (uqjsqswf4fntdjrq9qzq) started with only qwen38-27b: the three frontier teachers each needed GPU nodes and were still scaling when the 300s grace expired. All four were ACTIVE ~30 min later — by which point the release was locked to a single teacher for its whole 20-hour life, throwing away the multi-family diversity that is the point of running them.

Grace raised 300s → 1800s (commit 8027b49). That 300s was tuned when the pool was two similar models, and waiting longer is much safer now than it was: a teacher that wakes and then goes bad gets dropped mid-run by the new circuit breaker rather than absorbing its share of archetypes forever.

cosmicbboy and others added 3 commits September 10, 2026 00:26
Run us86v7zcfphfz76gjrdw generated with qwen38-27b alone. The logs name the
cause: qwen35-397b and minimax-m3 timed out on BOTH their svc DNS and
public URLs, every poll, for 30 minutes, while both apps reported ACTIVE.

llama.cpp blocks its HTTP listener while loading weights, so a
frontier-size model does not answer 503-while-loading -- it does not answer
at all. The 20s probe gave up before the server could ever reply. Probing
the same endpoints once they finished loading: HTTP 200 in ONE second.

Separately, glm-5-2 is genuinely gone -- svc DNS NXDOMAIN and public
HTTP 404, so nothing is behind the ACTIVE app record. Dropped from the
teacher list for this round; that one needs an llm-service redeploy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
Run ukh2f7p6jhzbp8bm247x recruited qwen35-397b via the longer health probe,
then got HTTP 503 {"message":"Loading model"} on its completions:
/health returns 200 once llama.cpp's listener is up, but the weights are
not in yet. So a teacher can pass the wake check and still 503 every
request for minutes.

Two consequences, both wrong before this commit. The 2-retry/2s budget --
right for an endpoint that is simply down -- gave up after 6 seconds on a
model that was minutes from being the strongest teacher in the pool. And
those failures counted toward the circuit breaker, which would drop the
endpoint for the offence of becoming useful.

Loading now gets its own patient budget (20 retries, 30s apart) and is
excluded from the breaker. Every other failure keeps the short budget.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
variants_per_archetype is an INPUT GUESS about how many archetypes will
survive, not a quality requirement. The thing that actually protects the
corpus from being N tasks photocopied is the concentration gate -- and it
has enormous headroom: it admits 2% of the corpus per archetype, so 700
archetypes scaled to 1M rows sit at 0.14%.

So a shortfall now raises the variant count to cover the target, as far as
that gate still allows. 780 of 834 archetypes at 1283 variants each is the
same corpus by every measure we gate on; failing there would discard a
20-hour release over the input guess.

What it will NOT do is rescue a thin release. 40 archetypes stretched to 1M
would be 2.5% each and the gate refuses -- as it does for the 78 archetypes
round 13 actually shipped, where inflating to 1M would have been a lie.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016huuSPKsdzj5YwzV846E8e
@cosmicbboy
cosmicbboy merged commit c1fb8dd into main Sep 10, 2026
3 checks passed
@cosmicbboy
cosmicbboy deleted the round14-throughput branch September 10, 2026 13:43
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