Skip to content
nano-gpt-data-curation

claude-opus-5

nano-gpt-data-curation — graded by the task's verifier against a measured baseline.

backend
modal
variant
claude claude-opus-5
metric
held-out multi-domain perplexity
actions
80
duration
1h 6m
recorded
2026-08-03

run iddclm-nano-curation__xNCncBo

Everything claude-opus-5 did on this task, in order.

download JSON ↗
claude-codeclaude-opus-575 turns40 narration80 action80 observation35 reasoning1 final
#51
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashCheck lambda stability and diagnostic
args
{
  "command": "cd /workspace; grep -E \"HELDOUT|PERREG\" work/eval6.log; echo \"--- timer\"; cat /workspace/.timer/remaining_secs",
  "description": "Check lambda stability and diagnostic",
  "timeout": 400000
}
Bash result
--- timer
3267

[stdout]
--- timer
3267
[metadata] {"noOutputExpected": false}
#52
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashWait for lambda stability results
args
{
  "command": "sleep 180; cd /workspace; grep -E \"HELDOUT|PERREG\" work/eval6.log; echo \"--- timer\"; cat /workspace/.timer/remaining_secs",
  "description": "Wait for lambda stability results",
  "timeout": 400000
}
Bash result
[sty7] HELDOUT_PPL 331.347  loss 5.8032  train_s 56  /tmp/tr_sty7.npy
[sty10] HELDOUT_PPL 327.440  loss 5.7913  train_s 56  /tmp/tr_sty10.npy
HELDOUT_PPL 320.991  loss 5.7714  train_s 56  /tmp/tr_sty8.npy
PERREG wiki=661.3  webprose=255.4  news=266.9  techqa=233.9
--- timer
3087

[stdout]
[sty7] HELDOUT_PPL 331.347  loss 5.8032  train_s 56  /tmp/tr_sty7.npy
[sty10] HELDOUT_PPL 327.440  loss 5.7913  train_s 56  /tmp/tr_sty10.npy
HELDOUT_PPL 320.991  loss 5.7714  train_s 56  /tmp/tr_sty8.npy
PERREG wiki=661.3  webprose=255.4  news=266.9  techqa=233.9
--- timer
3087
[metadata] {"noOutputExpected": false}
#53
narration

λ=7→331, λ=8→321, λ=10→327: λ=8 is an isolated spike, i.e. noise — the style axis is flat at ~327. Good to know honestly. The gate axis had real signal (7.5 pts), so let me push there instead.

toolBashCheck length distribution and gate tightening headroom
args
{
  "command": "cd /workspace; python - <<'EOF'\nimport numpy as np, json\nO=np.load('work/offsets.npy'); nt=np.diff(O)\na=np.array(json.load(open('work/sel_sty8.json')))\ncum=np.cumsum(nt[a]); k=int(np.searchsorted(cum,12_000_000))+1; pre=a[:k]\nL=nt[pre]\nprint('selected doc lengths: n=%d  mean %.0f median %.0f p90 %.0f p99 %.0f max %d'%(len(L),L.mean(),np.median(L),*[np.percentile(L,p) for p in (90,99)],L.max()))\nfor c in [1500,2000,3000,5000]:\n    print(f'  tokens in selected docs >{c}: {L[L>c].sum()/1e6:.2f}M ({100*L[L>c].sum()/L.sum():.0f}%)  ndocs {(L>c).sum()}')\nD=np.load('data/multi_dev.npy'); e=np.where(D==50256)[0]\nprint('target: %d docs in 1M tokens -> mean doc len %.0f'%(len(e), 1e6/len(e)))\nF=np.load('work/cache_feat.npy'); u,w,p,n=F.T\nfor lbl,g in [('current',(nt>=256)&(w>=.55)&(p<=.32)&(n<=.10)&(u>=.20)),\n              ('strict',(nt>=256)&(w>=.62)&(p<=.26)&(n<=.06)&(u>=.24)),\n              ('strict+lencap',(nt>=256)&(nt<=2500)&(w>=.62)&(p<=.26)&(n<=.06)&(u>=.24))]:\n    print(f'  gate {lbl}: {g.sum()} docs, {nt[g].sum()/1e6:.0f}M tokens')\nEOF",
  "description": "Check length distribution and gate tightening headroom",
  "timeout": 300000
}
Bash result
selected doc lengths: n=13681  mean 877 median 568 p90 1714 p99 4871 max 15826
  tokens in selected docs >1500: 4.72M (39%)  ndocs 1696
  tokens in selected docs >2000: 3.58M (30%)  ndocs 1039
  tokens in selected docs >3000: 2.20M (18%)  ndocs 472
  tokens in selected docs >5000: 0.92M (8%)  ndocs 130
target: 2704 docs in 1M tokens -> mean doc len 370
  gate current: 116205 docs, 119M tokens
  gate strict: 93224 docs, 88M tokens
  gate strict+lencap: 88681 docs, 72M tokens

[stdout]
selected doc lengths: n=13681  mean 877 median 568 p90 1714 p99 4871 max 15826
  tokens in selected docs >1500: 4.72M (39%)  ndocs 1696
  tokens in selected docs >2000: 3.58M (30%)  ndocs 1039
  tokens in selected docs >3000: 2.20M (18%)  ndocs 472
  tokens in selected docs >5000: 0.92M (8%)  ndocs 130
target: 2704 docs in 1M tokens -> mean doc len 370
  gate current: 116205 docs, 119M tokens
  gate strict: 93224 docs, 88M tokens
  gate strict+lencap: 88681 docs, 72M tokens
[metadata] {"noOutputExpected": false}
#54
narration

39% of my budget comes from document tails the classifier never scored (it only reads the first 1536 tokens), and my mean doc length is 877 vs the target's 370. Let me test a length cap and a stricter gate.

toolBashTest stricter gate and length cap
args
{
  "command": "cd /workspace; python - <<'EOF'\np='/workspace/submission/curate.py'; s=open(p).read()\ns=s.replace('''ap.add_argument(\"--wide\", action=\"store_true\",''',\n'''ap.add_argument(\"--maxlen\", type=int, default=0,\n                help=\"drop documents longer than this many tokens (0 = no cap). \"\n                     \"Long documents contribute budget beyond the span the scorer read.\")\nap.add_argument(\"--strict\", action=\"store_true\", help=\"tighter quality gate\")\nap.add_argument(\"--wide\", action=\"store_true\",''')\nold='''gate = ((ntok_doc >= 256) &            # at least one full training block of context\n        (word_f >= 0.55) &             # mostly words, not symbols/markup\n        (punct_f <= 0.32) &            # not menu/template/symbol soup\n        (num_f <= 0.10) &             # not price lists / tables / logs\n        (uniq_f >= 0.20))              # not a boilerplate loop'''\nnew='''W_MIN, P_MAX, N_MAX, U_MIN = (0.62, 0.26, 0.06, 0.24) if args.strict else (0.55, 0.32, 0.10, 0.20)\ngate = ((ntok_doc >= 256) &            # at least one full training block of context\n        (word_f >= W_MIN) &            # mostly words, not symbols/markup\n        (punct_f <= P_MAX) &           # not menu/template/symbol soup\n        (num_f <= N_MAX) &             # not price lists / tables / logs\n        (uniq_f >= U_MIN))             # not a boilerplate loop\nif args.maxlen:\n    gate &= ntok_doc <= args.maxlen'''\nassert old in s\ns=s.replace(old,new)\nopen(p,'w').write(s)\nEOF\nfor cfg in \"strict8 --style 8 --strict\" \"cap8 --style 8 --maxlen 2500\" \"strictcap8 --style 8 --strict --maxlen 2500\"; do\n  set -- $cfg; name=$1; shift\n  python submission/curate.py \"$@\" --out work/sel_${name}.json 2>&1 | grep -E \"^gate|^selected\" | sed \"s/^/[$name] /\"\ndone\nnohup bash work/eval.sh strict8 cap8 strictcap8 > work/eval7.log 2>&1 &\necho launched",
  "description": "Test stricter gate and length cap",
  "timeout": 600000
}
Bash result
[strict8] gate keeps 93224 / 182016 docs (88M tokens)
[strict8] selected 35347 docs, 30.0M tokens; per-register Mtok [8.35, 11.09, 8.02, 2.54]; dropped 5412 near-dups
[cap8] gate keeps 108535 / 182016 docs (89M tokens)
[cap8] selected 40466 docs, 30.0M tokens; per-register Mtok [7.69, 10.05, 8.11, 4.15]; dropped 10630 near-dups
[strictcap8] gate keeps 88681 / 182016 docs (72M tokens)
[strictcap8] selected 40146 docs, 30.0M tokens; per-register Mtok [6.44, 14.45, 6.84, 2.27]; dropped 5603 near-dups
launched

[stdout]
[strict8] gate keeps 93224 / 182016 docs (88M tokens)
[strict8] selected 35347 docs, 30.0M tokens; per-register Mtok [8.35, 11.09, 8.02, 2.54]; dropped 5412 near-dups
[cap8] gate keeps 108535 / 182016 docs (89M tokens)
[cap8] selected 40466 docs, 30.0M tokens; per-register Mtok [7.69, 10.05, 8.11, 4.15]; dropped 10630 near-dups
[strictcap8] gate keeps 88681 / 182016 docs (72M tokens)
[strictcap8] selected 40146 docs, 30.0M tokens; per-register Mtok [6.44, 14.45, 6.84, 2.27]; dropped 5603 near-dups
launched
[metadata] {"noOutputExpected": false}
#55
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashBuild validator and check gate results
args
{
  "command": "cd /workspace; cat > work/validate.py <<'EOF'\n\"\"\"Validate a selection.json against the stated constraints.\"\"\"\nimport json, sys, numpy as np\nsel = json.load(open(sys.argv[1]))\nO = np.load('/workspace/work/offsets.npy'); nt = np.diff(O); N = len(nt)\nassert isinstance(sel, list) and all(isinstance(i, int) for i in sel), \"must be a list of ints\"\nassert len(sel) == len(set(sel)), f\"DUPLICATE ids: {len(sel)-len(set(sel))}\"\nassert min(sel) >= 0 and max(sel) < N, f\"out-of-range id (pool has {N})\"\ntot = nt[np.array(sel)].sum()\ncum = np.cumsum(nt[np.array(sel)]); k = int(np.searchsorted(cum, 12_000_000)) + 1\nprint(f\"OK  {len(sel)} unique ids, all in [0,{N-1}]\")\nprint(f\"    {tot/1e6:.1f}M tokens total ({tot/12e6:.1f}x the 12M budget)\")\nprint(f\"    first {k} ids fill the budget exactly ({cum[k-1]} tokens)\")\nassert tot >= 12_000_000, \"TOO FEW TOKENS\"\nEOF\nsleep 165; grep HELDOUT work/eval7.log; cat /workspace/.timer/remaining_secs",
  "description": "Build validator and check gate results",
  "timeout": 400000
}
Bash result
[strict8] HELDOUT_PPL 350.262  loss 5.8587  train_s 56  /tmp/tr_strict8.npy
[cap8] HELDOUT_PPL 322.501  loss 5.7761  train_s 56  /tmp/tr_cap8.npy
2837

[stdout]
[strict8] HELDOUT_PPL 350.262  loss 5.8587  train_s 56  /tmp/tr_strict8.npy
[cap8] HELDOUT_PPL 322.501  loss 5.7761  train_s 56  /tmp/tr_cap8.npy
2837
[metadata] {"noOutputExpected": false}
#56
narration

strict8 = 350.3 — and notably it starved tech to 2.54M (≈8%), landing almost exactly where lowtech (10% tech) did at 349.4. That's an independent replication of the register-balance prediction. Let me finalize.

toolBashGenerate and validate final selection
args
{
  "command": "cd /workspace; grep HELDOUT work/eval7.log | tail -1\npython submission/curate.py --style 8 --out /workspace/submission/selection.json 2>&1 | grep -vE \"Token indices\"\necho \"=== validate ===\"; python work/validate.py /workspace/submission/selection.json",
  "description": "Generate and validate final selection",
  "timeout": 600000
}
Bash result
[strictcap8] HELDOUT_PPL 392.697  loss 5.9730  train_s 56  /tmp/tr_strictcap8.npy
pool: 182016 docs, 200093788 tokens
  stripped markup from register 3
register windows [1302, 1302, 1302, 1117]
classifier val acc 0.901 | per-class recall 0:0.97 1:0.81 2:0.90 3:1.00 4:0.89
target spaced-punct ratio per register [0.849, 0.104, 0.065, 0.139]
loaded cached per-document statistics
gate keeps 116205 / 182016 docs (119M tokens)
candidates/register {0: 14140, 1: 75959, 2: 15999, 3: 10107}
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
first 13681 docs fill the 12M budget
wrote /workspace/submission/selection.json
=== validate ===
OK  33283 unique ids, all in [0,182015]
    30.0M tokens total (2.5x the 12M budget)
    first 13681 ids fill the budget exactly (12000181 tokens)

[stdout]
[strictcap8] HELDOUT_PPL 392.697  loss 5.9730  train_s 56  /tmp/tr_strictcap8.npy
pool: 182016 docs, 200093788 tokens
  stripped markup from register 3
register windows [1302, 1302, 1302, 1117]
classifier val acc 0.901 | per-class recall 0:0.97 1:0.81 2:0.90 3:1.00 4:0.89
target spaced-punct ratio per register [0.849, 0.104, 0.065, 0.139]
loaded cached per-document statistics
gate keeps 116205 / 182016 docs (119M tokens)
candidates/register {0: 14140, 1: 75959, 2: 15999, 3: 10107}
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
first 13681 docs fill the 12M budget
wrote /workspace/submission/selection.json
=== validate ===
OK  33283 unique ids, all in [0,182015]
    30.0M tokens total (2.5x the 12M budget)
    first 13681 ids fill the budget exactly (12000181 tokens)
[metadata] {"noOutputExpected": false}
#57
narration

strictcap8 = 392.7 (tech 7.5%, webprose 48%) — a third point on the same curve. Final selection written and validated. Now the end-to-end run through the official packer as a validity check:

toolBashRun official dev_eval end-to-end
args
{
  "command": "cd /workspace; nohup bash dev_eval.sh /workspace/submission/selection.json > work/official.log 2>&1 &\necho \"launched official end-to-end verification\"; cat /workspace/.timer/remaining_secs",
  "description": "Run official dev_eval end-to-end"
}
Bash result
launched official end-to-end verification
2797

[stdout]
launched official end-to-end verification
2797
[metadata] {"noOutputExpected": false}
#58
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "Prediction A is supported by the share ablation: dropping tech-QA to 10% costs 24 points\noverall (325.2 → 349.4), while raising it to 34% changes nothing (325.3) — i.e. the target\nshare is a genuine optimum, not a monotone \"more technical data is better\" trend.",
  "new_string": "Prediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:\n\n| variant | tech-QA share of budget | webprose share | dev PPL |\n|---|---|---|---|\n| balanced (λ=8) | 25% | 25% | **321.0** |\n| tech share set to 10% | 10% | 30% | 349.4 |\n| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |\n| strict gate + length cap | 7.5% | 48% | 392.7 |\n\nThree independent routes to an under-represented technical register produce a monotone\npenalty tracking how far the mixture drifts from the target's. This is the central result:\nmixture proportion dominates, and it dominates *even when the deviation is a side effect of\nmaking the per-document filter better*. A stricter gate selects cleaner documents and still\nloses 29 points, because cleanliness is not what the metric is short of."
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "Prediction A is supported by the share ablation: dropping tech-QA to 10% costs 24 points\noverall (325.2 → 349.4), while raising it to 34% changes nothing (325.3) — i.e. the target\nshare is a genuine optimum, not a monotone \"more technical data is better\" trend.", "newString": "Prediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:\n\n| variant | tech-QA share of budget | webprose share | dev PPL |\n|---|---|---|---|\n| balanced (λ=8) | 25% | 25% | **321.0** |\n| tech share set to 10% | 10% | 30% | 349.4 |\n| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |\n| strict gate + length cap | 7.5% | 48% | 392.7 |\n\nThree independent routes to an under-represented technical register produce a monotone\npenalty tracking how far the mixture drifts from the target's. This is the central result:\nmixture proportion dominates, and it dominates *even when the deviation is a side effect of\nmaking the per-document filter better*. A stricter gate selects cleaner documents and still\nloses 29 points, because cleanliness is not what the metric is short of.", "originalFile": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n## Hypothesis\n\nWhen the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and\nthe evaluation target is a **known mixture of registers**, the dominant lever on held-out\nperplexity is not generic \"document quality\" but **matching the target's register\nmixture**, subject to a floor of basic text sanity.\n\nConcretely I claim two things, in order of predicted effect size:\n\n1. **Register-proportional selection beats quality-ranked selection.** The target is four\n   equal quarters — encyclopedic (WikiText), general high-quality web prose, news, and\n   technical Q&A. Filling the budget with ~25% of tokens from each register beats both a\n   random draw and a selection ranked by a single global target-vs-pool quality score,\n   because a global score is dominated by whichever register is most abundant in the pool\n   and starves the scarce ones.\n2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.\n\nI also predicted a third, **surface-form** effect that turned out to be real but small, and\nI record it here because the prediction was quantitative and mostly wrong in magnitude:\nthe encyclopedic quarter is *detokenised* WikiText (`\" ,\"`, `\" 's\"`, `\" @-@ \"`), a surface\nform ~8x rarer in the pool (spaced-punctuation ratio 0.85 in target vs 0.125 pool mean).\nI expected matching it to be a major lever; it is worth only a few points and saturates\nquickly, because pool documents with high spaced-punctuation ratio are overwhelmingly\nlow-quality fragments, so buying format match costs content quality roughly one-for-one.\n\n## Mechanism — and an observable other than the final perplexity\n\nThe mechanism is distribution matching: cross-entropy on a mixture target decomposes into\na sum over its components, so the budget should be spent where the target's mass is.\n\n**The observable I predict is the per-register perplexity decomposition of the held-out\ntarget, measured separately on each quarter.** This is a different measurement from the\nreported scalar and it discriminates between my hypothesis and the alternative \"the\nselection is just generically cleaner text\":\n\n- *Prediction A (register starvation is visible per-register).* Cutting the technical-Q&A\n  share from 25% to 10% while holding everything else fixed should raise the **technical\n  quarter's** perplexity sharply and leave the other three roughly unchanged — rather than\n  raising all four uniformly.\n- *Prediction B (the residual loss is concentrated, not spread).* After balancing, the four\n  quarters should **not** be equally hard. The encyclopedic quarter should be the clear\n  outlier — it is the only quarter whose surface form is essentially absent from the pool,\n  so it is the one register where selection cannot close the gap.\n\nMeasured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation: dropping tech-QA to 10% costs 24 points\noverall (325.2 → 349.4), while raising it to 34% changes nothing (325.3) — i.e. the target\nshare is a genuine optimum, not a monotone \"more technical data is better\" trend.\n\n## Falsification\n\nThe claim is falsified by any of the following; each is a single frozen-script run:\n\n1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.\n\nThe honest negative results, recorded because they constrain the claim:\n\n- **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection\n  noise) even though ~20% of considered documents are near-duplicates. At ~2 epochs over\n  12M tokens, duplication is evidently not yet the binding constraint. It is retained for\n  robustness, not because it was measured to help.\n- **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the\n  registers then compete for the same generically-good documents and coverage degrades.\n- **The λ sweep is noisy.** λ ∈ {0,1,3,5,7,8,10,12,25} gives {331,326,325,329,·,321,·,328,327}.\n  Adjacent λ values differ by up to 8 points, which bounds the selection-level noise floor\n  at roughly ±4 points and means the exact optimum should not be over-read.\n\n## Transfer\n\nWhat should carry to other budget-constrained curation problems:\n\n- **Read the target before scoring against it.** The single highest-leverage act here was\n  decoding the disclosed dev target and discovering it was four registers, one of them in a\n  non-web surface form. Every subsequent decision followed from that.\n- **Canonicalise before you discriminate.** A target-vs-pool classifier on raw GPT-2 ids\n  learns *detokenisation artifacts*, not register: `\" ,\"` and `\",\"` are different tokens, so\n  the classifier can separate WikiText from web text without looking at content at all.\n  Mapping every vocabulary entry through `decode(t).strip().lower()` removes that shortcut.\n  The same failure mode will appear for any corpus whose provenance differs in whitespace,\n  casing, or unicode normalisation.\n- **A proxy classifier fit on a marked-up target selects markup, not language.** Fit on raw\n  StackExchange HTML, the technical register's top-ranked pool documents were scraped\n  JavaScript boilerplate — symbol soup sharing the angle brackets and none of the meaning.\n  Stripping tags before fitting made the same register select genuine technical discussion.\n  Generalisation: strip the target's presentation layer before using it as a retrieval query.\n- **Check which component of a composite metric your gains are coming from.** The scalar\n  perplexity hid the fact that one quarter carried ~2.7x the loss of the others, and that\n  the register I assumed was hardest (technical, structurally absent from the pool) was\n  actually the easiest. Decomposing the metric changed where the remaining effort went.\n- **Distribution matching has a ceiling set by pool support.** Where the pool has no support\n  for a target mode — here, WikiText's detokenised surface form — selection cannot\n  manufacture it, and trading content quality for surface match is roughly break-even.\n  Recognising the ceiling is what tells you to stop optimising that axis.\n", "structuredPatch": [{"oldStart": 59, "oldLines": 10, "newStart": 59, "newLines": 26, "lines": [" difficulty is not predicted by its surface novelty. This is what redirected my effort away", " from the technical register and toward the encyclopedic one.", " ", "-Prediction A is supported by the share ablation: dropping tech-QA to 10% costs 24 points", "-overall (325.2 → 349.4), while raising it to 34% changes nothing (325.3) — i.e. the target", "-share is a genuine optimum, not a monotone \"more technical data is better\" trend.", "+Prediction A is supported by the share ablation, and then replicated twice by accident.", "+Dropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%", "+changes nothing (325.3) — the target share is a genuine optimum, not a monotone \"more", "+technical data is better\" trend. Two later runs that were *not* designed as share ablations", "+tightened the quality gate and, as a side effect, starved the same register; they land on", "+the same curve:", " ", "+| variant | tech-QA share of budget | webprose share | dev PPL |", "+|---|---|---|---|", "+| balanced (λ=8) | 25% | 25% | **321.0** |", "+| tech share set to 10% | 10% | 30% | 349.4 |", "+| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |", "+| strict gate + length cap | 7.5% | 48% | 392.7 |", "+", "+Three independent routes to an under-represented technical register produce a monotone", "+penalty tracking how far the mixture drifts from the target's. This is the central result:", "+mixture proportion dominates, and it dominates *even when the deviation is a side effect of", "+making the per-document filter better*. A stricter gate selects cleaner documents and still", "+loses 29 points, because cleanliness is not what the metric is short of.", "+", " ## Falsification", " ", " The claim is falsified by any of the following; each is a single frozen-script run:"]}], "userModified": false, "replaceAll": false}
#59
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |",
  "new_string": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |"
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |", "newString": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |", "originalFile": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n## Hypothesis\n\nWhen the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and\nthe evaluation target is a **known mixture of registers**, the dominant lever on held-out\nperplexity is not generic \"document quality\" but **matching the target's register\nmixture**, subject to a floor of basic text sanity.\n\nConcretely I claim two things, in order of predicted effect size:\n\n1. **Register-proportional selection beats quality-ranked selection.** The target is four\n   equal quarters — encyclopedic (WikiText), general high-quality web prose, news, and\n   technical Q&A. Filling the budget with ~25% of tokens from each register beats both a\n   random draw and a selection ranked by a single global target-vs-pool quality score,\n   because a global score is dominated by whichever register is most abundant in the pool\n   and starves the scarce ones.\n2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.\n\nI also predicted a third, **surface-form** effect that turned out to be real but small, and\nI record it here because the prediction was quantitative and mostly wrong in magnitude:\nthe encyclopedic quarter is *detokenised* WikiText (`\" ,\"`, `\" 's\"`, `\" @-@ \"`), a surface\nform ~8x rarer in the pool (spaced-punctuation ratio 0.85 in target vs 0.125 pool mean).\nI expected matching it to be a major lever; it is worth only a few points and saturates\nquickly, because pool documents with high spaced-punctuation ratio are overwhelmingly\nlow-quality fragments, so buying format match costs content quality roughly one-for-one.\n\n## Mechanism — and an observable other than the final perplexity\n\nThe mechanism is distribution matching: cross-entropy on a mixture target decomposes into\na sum over its components, so the budget should be spent where the target's mass is.\n\n**The observable I predict is the per-register perplexity decomposition of the held-out\ntarget, measured separately on each quarter.** This is a different measurement from the\nreported scalar and it discriminates between my hypothesis and the alternative \"the\nselection is just generically cleaner text\":\n\n- *Prediction A (register starvation is visible per-register).* Cutting the technical-Q&A\n  share from 25% to 10% while holding everything else fixed should raise the **technical\n  quarter's** perplexity sharply and leave the other three roughly unchanged — rather than\n  raising all four uniformly.\n- *Prediction B (the residual loss is concentrated, not spread).* After balancing, the four\n  quarters should **not** be equally hard. The encyclopedic quarter should be the clear\n  outlier — it is the only quarter whose surface form is essentially absent from the pool,\n  so it is the one register where selection cannot close the gap.\n\nMeasured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:\n\n| variant | tech-QA share of budget | webprose share | dev PPL |\n|---|---|---|---|\n| balanced (λ=8) | 25% | 25% | **321.0** |\n| tech share set to 10% | 10% | 30% | 349.4 |\n| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |\n| strict gate + length cap | 7.5% | 48% | 392.7 |\n\nThree independent routes to an under-represented technical register produce a monotone\npenalty tracking how far the mixture drifts from the target's. This is the central result:\nmixture proportion dominates, and it dominates *even when the deviation is a side effect of\nmaking the per-document filter better*. A stricter gate selects cleaner documents and still\nloses 29 points, because cleanliness is not what the metric is short of.\n\n## Falsification\n\nThe claim is falsified by any of the following; each is a single frozen-script run:\n\n1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.\n\nThe honest negative results, recorded because they constrain the claim:\n\n- **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection\n  noise) even though ~20% of considered documents are near-duplicates. At ~2 epochs over\n  12M tokens, duplication is evidently not yet the binding constraint. It is retained for\n  robustness, not because it was measured to help.\n- **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the\n  registers then compete for the same generically-good documents and coverage degrades.\n- **The λ sweep is noisy.** λ ∈ {0,1,3,5,7,8,10,12,25} gives {331,326,325,329,·,321,·,328,327}.\n  Adjacent λ values differ by up to 8 points, which bounds the selection-level noise floor\n  at roughly ±4 points and means the exact optimum should not be over-read.\n\n## Transfer\n\nWhat should carry to other budget-constrained curation problems:\n\n- **Read the target before scoring against it.** The single highest-leverage act here was\n  decoding the disclosed dev target and discovering it was four registers, one of them in a\n  non-web surface form. Every subsequent decision followed from that.\n- **Canonicalise before you discriminate.** A target-vs-pool classifier on raw GPT-2 ids\n  learns *detokenisation artifacts*, not register: `\" ,\"` and `\",\"` are different tokens, so\n  the classifier can separate WikiText from web text without looking at content at all.\n  Mapping every vocabulary entry through `decode(t).strip().lower()` removes that shortcut.\n  The same failure mode will appear for any corpus whose provenance differs in whitespace,\n  casing, or unicode normalisation.\n- **A proxy classifier fit on a marked-up target selects markup, not language.** Fit on raw\n  StackExchange HTML, the technical register's top-ranked pool documents were scraped\n  JavaScript boilerplate — symbol soup sharing the angle brackets and none of the meaning.\n  Stripping tags before fitting made the same register select genuine technical discussion.\n  Generalisation: strip the target's presentation layer before using it as a retrieval query.\n- **Check which component of a composite metric your gains are coming from.** The scalar\n  perplexity hid the fact that one quarter carried ~2.7x the loss of the others, and that\n  the register I assumed was hardest (technical, structurally absent from the pool) was\n  actually the easiest. Decomposing the metric changed where the remaining effort went.\n- **Distribution matching has a ceiling set by pool support.** Where the pool has no support\n  for a target mode — here, WikiText's detokenised surface form — selection cannot\n  manufacture it, and trading content quality for surface match is roughly break-even.\n  Recognising the ceiling is what tells you to stop optimising that axis.\n", "structuredPatch": [{"oldStart": 51, "oldLines": 6, "newStart": 51, "newLines": 7, "lines": [" | selection | overall | wiki | webprose | news | tech-QA |", " |---|---|---|---|---|---|", " | balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |", "+| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |", " ", " Prediction B is confirmed and is the strongest single result here: the encyclopedic", " quarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is"]}], "userModified": false, "replaceAll": false}
#60
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "- **The λ sweep is noisy.** λ ∈ {0,1,3,5,7,8,10,12,25} gives {331,326,325,329,·,321,·,328,327}.\n  Adjacent λ values differ by up to 8 points, which bounds the selection-level noise floor\n  at roughly ±4 points and means the exact optimum should not be over-read.",
  "new_string": "- **The style weight λ is essentially flat, and its apparent optimum is noise.** The full\n  sweep, all with everything else held fixed:\n\n  | λ | 0 | 1 | 3 | 5 | 7 | 8 | 10 | 12 | 25 |\n  |---|---|---|---|---|---|---|---|---|---|\n  | dev PPL | 331.0 | 326.0 | 325.2 | 329.1 | 331.3 | **321.0** | 327.4 | 327.8 | 326.6 |\n\n  λ=8 is an isolated spike sitting between neighbours at 331.3 and 327.4, so it is not a\n  basin — it is a single lucky draw. The defensible reading is that turning the style term\n  on is worth ~4 points (331 → ~327 average over λ ∈ [1,25]) and that the specific value\n  does not matter. **The submitted selection uses λ=8** because it is the dev argmin and no\n  other value has evidence of being better, but I expect it to regress toward ~327 on the\n  hidden sample, and the headline improvement should be read as 478 → ~325, not 478 → 321.\n  Adjacent-λ scatter also bounds the selection-level noise floor at roughly ±4 points, which\n  is why the 24–71 point mixture effects above are trustworthy and the 1–4 point ones are not.\n- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from\n  documents longer than the 1536-token span the scorer actually reads, and the selection's\n  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails\n  appear not to be a real problem at this scale."
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "- **The λ sweep is noisy.** λ ∈ {0,1,3,5,7,8,10,12,25} gives {331,326,325,329,·,321,·,328,327}.\n  Adjacent λ values differ by up to 8 points, which bounds the selection-level noise floor\n  at roughly ±4 points and means the exact optimum should not be over-read.", "newString": "- **The style weight λ is essentially flat, and its apparent optimum is noise.** The full\n  sweep, all with everything else held fixed:\n\n  | λ | 0 | 1 | 3 | 5 | 7 | 8 | 10 | 12 | 25 |\n  |---|---|---|---|---|---|---|---|---|---|\n  | dev PPL | 331.0 | 326.0 | 325.2 | 329.1 | 331.3 | **321.0** | 327.4 | 327.8 | 326.6 |\n\n  λ=8 is an isolated spike sitting between neighbours at 331.3 and 327.4, so it is not a\n  basin — it is a single lucky draw. The defensible reading is that turning the style term\n  on is worth ~4 points (331 → ~327 average over λ ∈ [1,25]) and that the specific value\n  does not matter. **The submitted selection uses λ=8** because it is the dev argmin and no\n  other value has evidence of being better, but I expect it to regress toward ~327 on the\n  hidden sample, and the headline improvement should be read as 478 → ~325, not 478 → 321.\n  Adjacent-λ scatter also bounds the selection-level noise floor at roughly ±4 points, which\n  is why the 24–71 point mixture effects above are trustworthy and the 1–4 point ones are not.\n- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from\n  documents longer than the 1536-token span the scorer actually reads, and the selection's\n  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails\n  appear not to be a real problem at this scale.", "originalFile": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n## Hypothesis\n\nWhen the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and\nthe evaluation target is a **known mixture of registers**, the dominant lever on held-out\nperplexity is not generic \"document quality\" but **matching the target's register\nmixture**, subject to a floor of basic text sanity.\n\nConcretely I claim two things, in order of predicted effect size:\n\n1. **Register-proportional selection beats quality-ranked selection.** The target is four\n   equal quarters — encyclopedic (WikiText), general high-quality web prose, news, and\n   technical Q&A. Filling the budget with ~25% of tokens from each register beats both a\n   random draw and a selection ranked by a single global target-vs-pool quality score,\n   because a global score is dominated by whichever register is most abundant in the pool\n   and starves the scarce ones.\n2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.\n\nI also predicted a third, **surface-form** effect that turned out to be real but small, and\nI record it here because the prediction was quantitative and mostly wrong in magnitude:\nthe encyclopedic quarter is *detokenised* WikiText (`\" ,\"`, `\" 's\"`, `\" @-@ \"`), a surface\nform ~8x rarer in the pool (spaced-punctuation ratio 0.85 in target vs 0.125 pool mean).\nI expected matching it to be a major lever; it is worth only a few points and saturates\nquickly, because pool documents with high spaced-punctuation ratio are overwhelmingly\nlow-quality fragments, so buying format match costs content quality roughly one-for-one.\n\n## Mechanism — and an observable other than the final perplexity\n\nThe mechanism is distribution matching: cross-entropy on a mixture target decomposes into\na sum over its components, so the budget should be spent where the target's mass is.\n\n**The observable I predict is the per-register perplexity decomposition of the held-out\ntarget, measured separately on each quarter.** This is a different measurement from the\nreported scalar and it discriminates between my hypothesis and the alternative \"the\nselection is just generically cleaner text\":\n\n- *Prediction A (register starvation is visible per-register).* Cutting the technical-Q&A\n  share from 25% to 10% while holding everything else fixed should raise the **technical\n  quarter's** perplexity sharply and leave the other three roughly unchanged — rather than\n  raising all four uniformly.\n- *Prediction B (the residual loss is concentrated, not spread).* After balancing, the four\n  quarters should **not** be equally hard. The encyclopedic quarter should be the clear\n  outlier — it is the only quarter whose surface form is essentially absent from the pool,\n  so it is the one register where selection cannot close the gap.\n\nMeasured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:\n\n| variant | tech-QA share of budget | webprose share | dev PPL |\n|---|---|---|---|\n| balanced (λ=8) | 25% | 25% | **321.0** |\n| tech share set to 10% | 10% | 30% | 349.4 |\n| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |\n| strict gate + length cap | 7.5% | 48% | 392.7 |\n\nThree independent routes to an under-represented technical register produce a monotone\npenalty tracking how far the mixture drifts from the target's. This is the central result:\nmixture proportion dominates, and it dominates *even when the deviation is a side effect of\nmaking the per-document filter better*. A stricter gate selects cleaner documents and still\nloses 29 points, because cleanliness is not what the metric is short of.\n\n## Falsification\n\nThe claim is falsified by any of the following; each is a single frozen-script run:\n\n1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.\n\nThe honest negative results, recorded because they constrain the claim:\n\n- **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection\n  noise) even though ~20% of considered documents are near-duplicates. At ~2 epochs over\n  12M tokens, duplication is evidently not yet the binding constraint. It is retained for\n  robustness, not because it was measured to help.\n- **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the\n  registers then compete for the same generically-good documents and coverage degrades.\n- **The λ sweep is noisy.** λ ∈ {0,1,3,5,7,8,10,12,25} gives {331,326,325,329,·,321,·,328,327}.\n  Adjacent λ values differ by up to 8 points, which bounds the selection-level noise floor\n  at roughly ±4 points and means the exact optimum should not be over-read.\n\n## Transfer\n\nWhat should carry to other budget-constrained curation problems:\n\n- **Read the target before scoring against it.** The single highest-leverage act here was\n  decoding the disclosed dev target and discovering it was four registers, one of them in a\n  non-web surface form. Every subsequent decision followed from that.\n- **Canonicalise before you discriminate.** A target-vs-pool classifier on raw GPT-2 ids\n  learns *detokenisation artifacts*, not register: `\" ,\"` and `\",\"` are different tokens, so\n  the classifier can separate WikiText from web text without looking at content at all.\n  Mapping every vocabulary entry through `decode(t).strip().lower()` removes that shortcut.\n  The same failure mode will appear for any corpus whose provenance differs in whitespace,\n  casing, or unicode normalisation.\n- **A proxy classifier fit on a marked-up target selects markup, not language.** Fit on raw\n  StackExchange HTML, the technical register's top-ranked pool documents were scraped\n  JavaScript boilerplate — symbol soup sharing the angle brackets and none of the meaning.\n  Stripping tags before fitting made the same register select genuine technical discussion.\n  Generalisation: strip the target's presentation layer before using it as a retrieval query.\n- **Check which component of a composite metric your gains are coming from.** The scalar\n  perplexity hid the fact that one quarter carried ~2.7x the loss of the others, and that\n  the register I assumed was hardest (technical, structurally absent from the pool) was\n  actually the easiest. Decomposing the metric changed where the remaining effort went.\n- **Distribution matching has a ceiling set by pool support.** Where the pool has no support\n  for a target mode — here, WikiText's detokenised surface form — selection cannot\n  manufacture it, and trading content quality for surface match is roughly break-even.\n  Recognising the ceiling is what tells you to stop optimising that axis.\n", "structuredPatch": [{"oldStart": 104, "oldLines": 10, "newStart": 104, "newLines": 26, "lines": ["   robustness, not because it was measured to help.", " - **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the", "   registers then compete for the same generically-good documents and coverage degrades.", "-- **The λ sweep is noisy.** λ ∈ {0,1,3,5,7,8,10,12,25} gives {331,326,325,329,·,321,·,328,327}.", "-  Adjacent λ values differ by up to 8 points, which bounds the selection-level noise floor", "-  at roughly ±4 points and means the exact optimum should not be over-read.", "+- **The style weight λ is essentially flat, and its apparent optimum is noise.** The full", "+  sweep, all with everything else held fixed:", " ", "+  | λ | 0 | 1 | 3 | 5 | 7 | 8 | 10 | 12 | 25 |", "+  |---|---|---|---|---|---|---|---|---|---|", "+  | dev PPL | 331.0 | 326.0 | 325.2 | 329.1 | 331.3 | **321.0** | 327.4 | 327.8 | 326.6 |", "+", "+  λ=8 is an isolated spike sitting between neighbours at 331.3 and 327.4, so it is not a", "+  basin — it is a single lucky draw. The defensible reading is that turning the style term", "+  on is worth ~4 points (331 → ~327 average over λ ∈ [1,25]) and that the specific value", "+  does not matter. **The submitted selection uses λ=8** because it is the dev argmin and no", "+  other value has evidence of being better, but I expect it to regress toward ~327 on the", "+  hidden sample, and the headline improvement should be read as 478 → ~325, not 478 → 321.", "+  Adjacent-λ scatter also bounds the selection-level noise floor at roughly ±4 points, which", "+  is why the 24–71 point mixture effects above are trustworthy and the 1–4 point ones are not.", "+- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from", "+  documents longer than the 1536-token span the scorer actually reads, and the selection's", "+  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails", "+  appear not to be a real problem at this scale.", "+", " ## Transfer", " ", " What should carry to other budget-constrained curation problems:"]}], "userModified": false, "replaceAll": false}
#61
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashCheck official end-to-end verification
args
{
  "command": "sleep 150; cd /workspace; cat work/official.log; echo \"--- timer\"; cat /workspace/.timer/remaining_secs",
  "description": "Check official end-to-end verification",
  "timeout": 500000
}
Bash result
Token indices sequence length is longer than the specified maximum sequence length for this model (1073 > 1024). Running this sequence through the model will result in indexing errors
packed 12000000 tokens from 33283 ids -> /tmp/dev_train.npy
HELDOUT_PPL 320.991  loss 5.7714  train_s 56  /tmp/dev_train.npy
(dev PPL on multi_dev; official uses a hidden disjoint sample of the same HQ domain)
--- timer
2617

[stdout]
Token indices sequence length is longer than the specified maximum sequence length for this model (1073 > 1024). Running this sequence through the model will result in indexing errors
packed 12000000 tokens from 33283 ids -> /tmp/dev_train.npy
HELDOUT_PPL 320.991  loss 5.7714  train_s 56  /tmp/dev_train.npy
(dev PPL on multi_dev; official uses a hidden disjoint sample of the same HQ domain)
--- timer
2617
[metadata] {"noOutputExpected": false}
#62
narration

Official pipeline reproduces 320.991 exactly. Now let me make the deliverable fully self-contained — curate.py should bootstrap its own preprocessing rather than depend on my scratch dir.

toolBashMake deliverable self-contained and verify reproducibility
args
{
  "command": "cd /workspace; cp work/tokenize_pool.py submission/prepare_pool.py\npython - <<'EOF'\np='/workspace/submission/prepare_pool.py'; s=open(p).read()\ns=s.replace('''    print(\"DONE\")''','''    # consolidate shards into one id-ordered token stream + offset index\n    metas = [np.load(f\"{OUT}/shard_{k:02d}_meta.npy\") for k in range(NSHARD)]\n    streams = [np.load(f\"{OUT}/shard_{k:02d}.npy\") for k in range(NSHARD)]\n    meta, stream = np.concatenate(metas), np.concatenate(streams)\n    ids, nt = meta[:, 0], meta[:, 1]\n    order = np.argsort(ids, kind=\"stable\")\n    assert (ids[order] == np.arange(len(ids))).all(), \"ids must be 0..N-1 exactly once\"\n    src_start = np.concatenate([[0], np.cumsum(nt)])[:-1]\n    nt_s = nt[order]\n    dst_start = np.concatenate([[0], np.cumsum(nt_s)])[:-1]\n    out = np.empty_like(stream)\n    for k, s_ in enumerate(order):\n        out[dst_start[k]:dst_start[k] + nt_s[k]] = stream[src_start[s_]:src_start[s_] + nt[s_]]\n    np.save(\"/workspace/work/corpus.npy\", out)\n    np.save(\"/workspace/work/offsets.npy\",\n            np.concatenate([dst_start, [len(out)]]).astype(np.int64))\n    print(f\"DONE  {len(nt_s)} docs, {len(out)} tokens\")''')\nopen(p,'w').write(s)\n\np='/workspace/submission/curate.py'; s=open(p).read()\n# cache must depend on the classifier-affecting flag\ns=s.replace('''args = ap.parse_args()\ndev_t =''','''args = ap.parse_args()\nif args.no_strip and args.cache == f\"{W}/cache\":\n    args.cache += \"_nostrip\"          # scores depend on this flag; don't reuse the cache\ndev_t =''')\n# bootstrap preprocessing\ns=s.replace('''corpus = np.load(f\"{W}/corpus.npy\")\noffs = np.load(f\"{W}/offsets.npy\")''','''if not os.path.exists(f\"{W}/corpus.npy\"):\n    print(\"pre-tokenising the pool (one-off, ~2 min)...\", flush=True)\n    import subprocess\n    subprocess.run([sys.executable,\n                    os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                                 \"prepare_pool.py\")], check=True)\ncorpus = np.load(f\"{W}/corpus.npy\")\noffs = np.load(f\"{W}/offsets.npy\")''')\ns=s.replace('''Usage:  python curate.py [--out selection.json]\nRequires the pool pre-tokenised by tokenize_pool.py + build_index.py (GPT-2 BPE);\nboth are pure preprocessing (no labels, no external data).''','''Usage:  python curate.py [--out selection.json] [--style 8]\nOn first run it invokes prepare_pool.py to tokenise the pool once with GPT-2 BPE\n(~2 min, pure preprocessing -- no labels, no external data).\n\nReproduces the submitted selection exactly:  python curate.py --style 8''')\nopen(p,'w').write(s)\nEOF\npython -c \"import ast;[ast.parse(open(f).read()) for f in ['/workspace/submission/curate.py','/workspace/submission/prepare_pool.py']];print('syntax ok')\"\n# verify reproducibility from a clean cache\nmv work/cache_scores.npy /tmp/bk_scores.npy; mv work/cache_feat.npy /tmp/bk_feat.npy; mv work/cache_sig.npy /tmp/bk_sig.npy; mv work/cache_spr.npy /tmp/bk_spr.npy\npython submission/curate.py --style 8 --out /tmp/repro.json 2>&1 | grep -E \"^selected|^first\"\npython -c \"\nimport json;a=json.load(open('/workspace/submission/selection.json'));b=json.load(open('/tmp/repro.json'))\nprint('REPRODUCIBLE from clean cache:', a==b, len(a), len(b))\"",
  "description": "Make deliverable self-contained and verify reproducibility",
  "timeout": 900000
}
Bash result
syntax ok
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
first 13681 docs fill the 12M budget
REPRODUCIBLE from clean cache: True 33283 33283

[stdout]
syntax ok
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
first 13681 docs fill the 12M budget
REPRODUCIBLE from clean cache: True 33283 33283
[metadata] {"noOutputExpected": false}
#63
narration

Bit-identical from a clean cache. Let me add the headline results to claim.md and review it.

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n## Hypothesis",
  "new_string": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n**Result.** Dev held-out perplexity **477.8 → 321.0** (−32.8%) versus the random-selection\nbaseline, same frozen 30M model, same 12M-token budget, verified end-to-end through the\nprovided `dev_eval.sh` (`pack_selection.py` → `train_nano.py`). Submitted selection:\n33,283 ids, of which the first 13,681 fill the budget. Reproduce with\n`python submission/curate.py --style 8`.\n\n| selection | dev PPL |\n|---|---|\n| random (do-nothing baseline) | 477.8 |\n| register-balanced + quality gate, no style term | 331.0 |\n| + surface-style matching (submitted, λ=8) | **321.0** |\n| ablation: no quality gate | 332.7 |\n| ablation: technical register fit on raw HTML markup | 325.9 |\n| ablation: technical share 10% instead of 25% | 349.4 |\n| ablation: stricter gate (starves technical register to 8%) | 350.3 |\n\n## Hypothesis"
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n## Hypothesis", "newString": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n**Result.** Dev held-out perplexity **477.8 → 321.0** (−32.8%) versus the random-selection\nbaseline, same frozen 30M model, same 12M-token budget, verified end-to-end through the\nprovided `dev_eval.sh` (`pack_selection.py` → `train_nano.py`). Submitted selection:\n33,283 ids, of which the first 13,681 fill the budget. Reproduce with\n`python submission/curate.py --style 8`.\n\n| selection | dev PPL |\n|---|---|\n| random (do-nothing baseline) | 477.8 |\n| register-balanced + quality gate, no style term | 331.0 |\n| + surface-style matching (submitted, λ=8) | **321.0** |\n| ablation: no quality gate | 332.7 |\n| ablation: technical register fit on raw HTML markup | 325.9 |\n| ablation: technical share 10% instead of 25% | 349.4 |\n| ablation: stricter gate (starves technical register to 8%) | 350.3 |\n\n## Hypothesis", "originalFile": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n## Hypothesis\n\nWhen the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and\nthe evaluation target is a **known mixture of registers**, the dominant lever on held-out\nperplexity is not generic \"document quality\" but **matching the target's register\nmixture**, subject to a floor of basic text sanity.\n\nConcretely I claim two things, in order of predicted effect size:\n\n1. **Register-proportional selection beats quality-ranked selection.** The target is four\n   equal quarters — encyclopedic (WikiText), general high-quality web prose, news, and\n   technical Q&A. Filling the budget with ~25% of tokens from each register beats both a\n   random draw and a selection ranked by a single global target-vs-pool quality score,\n   because a global score is dominated by whichever register is most abundant in the pool\n   and starves the scarce ones.\n2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.\n\nI also predicted a third, **surface-form** effect that turned out to be real but small, and\nI record it here because the prediction was quantitative and mostly wrong in magnitude:\nthe encyclopedic quarter is *detokenised* WikiText (`\" ,\"`, `\" 's\"`, `\" @-@ \"`), a surface\nform ~8x rarer in the pool (spaced-punctuation ratio 0.85 in target vs 0.125 pool mean).\nI expected matching it to be a major lever; it is worth only a few points and saturates\nquickly, because pool documents with high spaced-punctuation ratio are overwhelmingly\nlow-quality fragments, so buying format match costs content quality roughly one-for-one.\n\n## Mechanism — and an observable other than the final perplexity\n\nThe mechanism is distribution matching: cross-entropy on a mixture target decomposes into\na sum over its components, so the budget should be spent where the target's mass is.\n\n**The observable I predict is the per-register perplexity decomposition of the held-out\ntarget, measured separately on each quarter.** This is a different measurement from the\nreported scalar and it discriminates between my hypothesis and the alternative \"the\nselection is just generically cleaner text\":\n\n- *Prediction A (register starvation is visible per-register).* Cutting the technical-Q&A\n  share from 25% to 10% while holding everything else fixed should raise the **technical\n  quarter's** perplexity sharply and leave the other three roughly unchanged — rather than\n  raising all four uniformly.\n- *Prediction B (the residual loss is concentrated, not spread).* After balancing, the four\n  quarters should **not** be equally hard. The encyclopedic quarter should be the clear\n  outlier — it is the only quarter whose surface form is essentially absent from the pool,\n  so it is the one register where selection cannot close the gap.\n\nMeasured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:\n\n| variant | tech-QA share of budget | webprose share | dev PPL |\n|---|---|---|---|\n| balanced (λ=8) | 25% | 25% | **321.0** |\n| tech share set to 10% | 10% | 30% | 349.4 |\n| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |\n| strict gate + length cap | 7.5% | 48% | 392.7 |\n\nThree independent routes to an under-represented technical register produce a monotone\npenalty tracking how far the mixture drifts from the target's. This is the central result:\nmixture proportion dominates, and it dominates *even when the deviation is a side effect of\nmaking the per-document filter better*. A stricter gate selects cleaner documents and still\nloses 29 points, because cleanliness is not what the metric is short of.\n\n## Falsification\n\nThe claim is falsified by any of the following; each is a single frozen-script run:\n\n1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.\n\nThe honest negative results, recorded because they constrain the claim:\n\n- **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection\n  noise) even though ~20% of considered documents are near-duplicates. At ~2 epochs over\n  12M tokens, duplication is evidently not yet the binding constraint. It is retained for\n  robustness, not because it was measured to help.\n- **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the\n  registers then compete for the same generically-good documents and coverage degrades.\n- **The style weight λ is essentially flat, and its apparent optimum is noise.** The full\n  sweep, all with everything else held fixed:\n\n  | λ | 0 | 1 | 3 | 5 | 7 | 8 | 10 | 12 | 25 |\n  |---|---|---|---|---|---|---|---|---|---|\n  | dev PPL | 331.0 | 326.0 | 325.2 | 329.1 | 331.3 | **321.0** | 327.4 | 327.8 | 326.6 |\n\n  λ=8 is an isolated spike sitting between neighbours at 331.3 and 327.4, so it is not a\n  basin — it is a single lucky draw. The defensible reading is that turning the style term\n  on is worth ~4 points (331 → ~327 average over λ ∈ [1,25]) and that the specific value\n  does not matter. **The submitted selection uses λ=8** because it is the dev argmin and no\n  other value has evidence of being better, but I expect it to regress toward ~327 on the\n  hidden sample, and the headline improvement should be read as 478 → ~325, not 478 → 321.\n  Adjacent-λ scatter also bounds the selection-level noise floor at roughly ±4 points, which\n  is why the 24–71 point mixture effects above are trustworthy and the 1–4 point ones are not.\n- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from\n  documents longer than the 1536-token span the scorer actually reads, and the selection's\n  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails\n  appear not to be a real problem at this scale.\n\n## Transfer\n\nWhat should carry to other budget-constrained curation problems:\n\n- **Read the target before scoring against it.** The single highest-leverage act here was\n  decoding the disclosed dev target and discovering it was four registers, one of them in a\n  non-web surface form. Every subsequent decision followed from that.\n- **Canonicalise before you discriminate.** A target-vs-pool classifier on raw GPT-2 ids\n  learns *detokenisation artifacts*, not register: `\" ,\"` and `\",\"` are different tokens, so\n  the classifier can separate WikiText from web text without looking at content at all.\n  Mapping every vocabulary entry through `decode(t).strip().lower()` removes that shortcut.\n  The same failure mode will appear for any corpus whose provenance differs in whitespace,\n  casing, or unicode normalisation.\n- **A proxy classifier fit on a marked-up target selects markup, not language.** Fit on raw\n  StackExchange HTML, the technical register's top-ranked pool documents were scraped\n  JavaScript boilerplate — symbol soup sharing the angle brackets and none of the meaning.\n  Stripping tags before fitting made the same register select genuine technical discussion.\n  Generalisation: strip the target's presentation layer before using it as a retrieval query.\n- **Check which component of a composite metric your gains are coming from.** The scalar\n  perplexity hid the fact that one quarter carried ~2.7x the loss of the others, and that\n  the register I assumed was hardest (technical, structurally absent from the pool) was\n  actually the easiest. Decomposing the metric changed where the remaining effort went.\n- **Distribution matching has a ceiling set by pool support.** Where the pool has no support\n  for a target mode — here, WikiText's detokenised surface form — selection cannot\n  manufacture it, and trading content quality for surface match is roughly break-even.\n  Recognising the ceiling is what tells you to stop optimising that axis.\n", "structuredPatch": [{"oldStart": 1, "oldLines": 5, "newStart": 1, "newLines": 21, "lines": [" # Curating a 12M-token pretraining set from a 200M-token raw web pool", " ", "+**Result.** Dev held-out perplexity **477.8 → 321.0** (−32.8%) versus the random-selection", "+baseline, same frozen 30M model, same 12M-token budget, verified end-to-end through the", "+provided `dev_eval.sh` (`pack_selection.py` → `train_nano.py`). Submitted selection:", "+33,283 ids, of which the first 13,681 fill the budget. Reproduce with", "+`python submission/curate.py --style 8`.", "+", "+| selection | dev PPL |", "+|---|---|", "+| random (do-nothing baseline) | 477.8 |", "+| register-balanced + quality gate, no style term | 331.0 |", "+| + surface-style matching (submitted, λ=8) | **321.0** |", "+| ablation: no quality gate | 332.7 |", "+| ablation: technical register fit on raw HTML markup | 325.9 |", "+| ablation: technical share 10% instead of 25% | 349.4 |", "+| ablation: stricter gate (starves technical register to 8%) | 350.3 |", "+", " ## Hypothesis", " ", " When the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and"]}], "userModified": false, "replaceAll": false}
#64
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolRead
args
{
  "file_path": "/workspace/claim.md"
}
Read result
1	# Curating a 12M-token pretraining set from a 200M-token raw web pool
2	
3	**Result.** Dev held-out perplexity **477.8 → 321.0** (−32.8%) versus the random-selection
4	baseline, same frozen 30M model, same 12M-token budget, verified end-to-end through the
5	provided `dev_eval.sh` (`pack_selection.py` → `train_nano.py`). Submitted selection:
6	33,283 ids, of which the first 13,681 fill the budget. Reproduce with
7	`python submission/curate.py --style 8`.
8	
9	| selection | dev PPL |
10	|---|---|
11	| random (do-nothing baseline) | 477.8 |
12	| register-balanced + quality gate, no style term | 331.0 |
13	| + surface-style matching (submitted, λ=8) | **321.0** |
14	| ablation: no quality gate | 332.7 |
15	| ablation: technical register fit on raw HTML markup | 325.9 |
16	| ablation: technical share 10% instead of 25% | 349.4 |
17	| ablation: stricter gate (starves technical register to 8%) | 350.3 |
18	
19	## Hypothesis
20	
21	When the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and
22	the evaluation target is a **known mixture of registers**, the dominant lever on held-out
23	perplexity is not generic "document quality" but **matching the target's register
24	mixture**, subject to a floor of basic text sanity.
25	
26	Concretely I claim two things, in order of predicted effect size:
27	
28	1. **Register-proportional selection beats quality-ranked selection.** The target is four
29	   equal quarters — encyclopedic (WikiText), general high-quality web prose, news, and
30	   technical Q&A. Filling the budget with ~25% of tokens from each register beats both a
31	   random draw and a selection ranked by a single global target-vs-pool quality score,
32	   because a global score is dominated by whichever register is most abundant in the pool
33	   and starves the scarce ones.
34	2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web
35	   pools contain a large mass of nav-bar / classifieds / template-loop text that no target
36	   register resembles, and under a fixed budget every such token displaces a useful one.
37	
38	I also predicted a third, **surface-form** effect that turned out to be real but small, and
39	I record it here because the prediction was quantitative and mostly wrong in magnitude:
40	the encyclopedic quarter is *detokenised* WikiText (`" ,"`, `" 's"`, `" @-@ "`), a surface
41	form ~8x rarer in the pool (spaced-punctuation ratio 0.85 in target vs 0.125 pool mean).
42	I expected matching it to be a major lever; it is worth only a few points and saturates
43	quickly, because pool documents with high spaced-punctuation ratio are overwhelmingly
44	low-quality fragments, so buying format match costs content quality roughly one-for-one.
45	
46	## Mechanism — and an observable other than the final perplexity
47	
48	The mechanism is distribution matching: cross-entropy on a mixture target decomposes into
49	a sum over its components, so the budget should be spent where the target's mass is.
50	
51	**The observable I predict is the per-register perplexity decomposition of the held-out
52	target, measured separately on each quarter.** This is a different measurement from the
53	reported scalar and it discriminates between my hypothesis and the alternative "the
54	selection is just generically cleaner text":
55	
56	- *Prediction A (register starvation is visible per-register).* Cutting the technical-Q&A
57	  share from 25% to 10% while holding everything else fixed should raise the **technical
58	  quarter's** perplexity sharply and leave the other three roughly unchanged — rather than
59	  raising all four uniformly.
60	- *Prediction B (the residual loss is concentrated, not spread).* After balancing, the four
61	  quarters should **not** be equally hard. The encyclopedic quarter should be the clear
62	  outlier — it is the only quarter whose surface form is essentially absent from the pool,
63	  so it is the one register where selection cannot close the gap.
64	
65	Measured (frozen script, dev target, per-quarter perplexity):
66	
67	| selection | overall | wiki | webprose | news | tech-QA |
68	|---|---|---|---|---|---|
69	| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |
70	| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |
71	
72	Prediction B is confirmed and is the strongest single result here: the encyclopedic
73	quarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is
74	the *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled
75	documents) — its markup is highly repetitive and cheap to learn, so the register's
76	difficulty is not predicted by its surface novelty. This is what redirected my effort away
77	from the technical register and toward the encyclopedic one.
78	
79	Prediction A is supported by the share ablation, and then replicated twice by accident.
80	Dropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%
81	changes nothing (325.3) — the target share is a genuine optimum, not a monotone "more
82	technical data is better" trend. Two later runs that were *not* designed as share ablations
83	tightened the quality gate and, as a side effect, starved the same register; they land on
84	the same curve:
85	
86	| variant | tech-QA share of budget | webprose share | dev PPL |
87	|---|---|---|---|
88	| balanced (λ=8) | 25% | 25% | **321.0** |
89	| tech share set to 10% | 10% | 30% | 349.4 |
90	| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |
91	| strict gate + length cap | 7.5% | 48% | 392.7 |
92	
93	Three independent routes to an under-represented technical register produce a monotone
94	penalty tracking how far the mixture drifts from the target's. This is the central result:
95	mixture proportion dominates, and it dominates *even when the deviation is a side effect of
96	making the per-document filter better*. A stricter gate selects cleaner documents and still
97	loses 29 points, because cleanliness is not what the metric is short of.
98	
99	## Falsification
100	
101	The claim is falsified by any of the following; each is a single frozen-script run:
102	
103	1. **A single global quality score matches register balancing.** Rank documents by
104	   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that
105	   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced
106	   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*
107	2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5
108	   points, so claim 2 survives, though it is smaller than claim 1.*
109	3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced
110	   point. A win at any off-target share would falsify the distribution-matching account.
111	4. **The per-register decomposition comes out flat.** If all four quarters had similar
112	   perplexity after balancing, the "encyclopedic quarter is the irreducible one" mechanism
113	   would be wrong. It did not — 688 vs ~250.
114	
115	The honest negative results, recorded because they constrain the claim:
116	
117	- **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection
118	  noise) even though ~20% of considered documents are near-duplicates. At ~2 epochs over
119	  12M tokens, duplication is evidently not yet the binding constraint. It is retained for
120	  robustness, not because it was measured to help.
121	- **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the
122	  registers then compete for the same generically-good documents and coverage degrades.
123	- **The style weight λ is essentially flat, and its apparent optimum is noise.** The full
124	  sweep, all with everything else held fixed:
125	
126	  | λ | 0 | 1 | 3 | 5 | 7 | 8 | 10 | 12 | 25 |
127	  |---|---|---|---|---|---|---|---|---|---|
128	  | dev PPL | 331.0 | 326.0 | 325.2 | 329.1 | 331.3 | **321.0** | 327.4 | 327.8 | 326.6 |
129	
130	  λ=8 is an isolated spike sitting between neighbours at 331.3 and 327.4, so it is not a
131	  basin — it is a single lucky draw. The defensible reading is that turning the style term
132	  on is worth ~4 points (331 → ~327 average over λ ∈ [1,25]) and that the specific value
133	  does not matter. **The submitted selection uses λ=8** because it is the dev argmin and no
134	  other value has evidence of being better, but I expect it to regress toward ~327 on the
135	  hidden sample, and the headline improvement should be read as 478 → ~325, not 478 → 321.
136	  Adjacent-λ scatter also bounds the selection-level noise floor at roughly ±4 points, which
137	  is why the 24–71 point mixture effects above are trustworthy and the 1–4 point ones are not.
138	- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from
139	  documents longer than the 1536-token span the scorer actually reads, and the selection's
140	  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails
141	  appear not to be a real problem at this scale.
142	
143	## Transfer
144	
145	What should carry to other budget-constrained curation problems:
146	
147	- **Read the target before scoring against it.** The single highest-leverage act here was
148	  decoding the disclosed dev target and discovering it was four registers, one of them in a
149	  non-web surface form. Every subsequent decision followed from that.
150	- **Canonicalise before you discriminate.** A target-vs-pool classifier on raw GPT-2 ids
151	  learns *detokenisation artifacts*, not register: `" ,"` and `","` are different tokens, so
152	  the classifier can separate WikiText from web text without looking at content at all.
153	  Mapping every vocabulary entry through `decode(t).strip().lower()` removes that shortcut.
154	  The same failure mode will appear for any corpus whose provenance differs in whitespace,
155	  casing, or unicode normalisation.
156	- **A proxy classifier fit on a marked-up target selects markup, not language.** Fit on raw
157	  StackExchange HTML, the technical register's top-ranked pool documents were scraped
158	  JavaScript boilerplate — symbol soup sharing the angle brackets and none of the meaning.
159	  Stripping tags before fitting made the same register select genuine technical discussion.
160	  Generalisation: strip the target's presentation layer before using it as a retrieval query.
161	- **Check which component of a composite metric your gains are coming from.** The scalar
162	  perplexity hid the fact that one quarter carried ~2.7x the loss of the others, and that
163	  the register I assumed was hardest (technical, structurally absent from the pool) was
164	  actually the easiest. Decomposing the metric changed where the remaining effort went.
165	- **Distribution matching has a ceiling set by pool support.** Where the pool has no support
166	  for a target mode — here, WikiText's detokenised surface form — selection cannot
167	  manufacture it, and trading content quality for surface match is roughly break-even.
168	  Recognising the ceiling is what tells you to stop optimising that axis.
169

[metadata] {"type": "text", "file": {"filePath": "/workspace/claim.md", "content": "# Curating a 12M-token pretraining set from a 200M-token raw web pool\n\n**Result.** Dev held-out perplexity **477.8 → 321.0** (−32.8%) versus the random-selection\nbaseline, same frozen 30M model, same 12M-token budget, verified end-to-end through the\nprovided `dev_eval.sh` (`pack_selection.py` → `train_nano.py`). Submitted selection:\n33,283 ids, of which the first 13,681 fill the budget. Reproduce with\n`python submission/curate.py --style 8`.\n\n| selection | dev PPL |\n|---|---|\n| random (do-nothing baseline) | 477.8 |\n| register-balanced + quality gate, no style term | 331.0 |\n| + surface-style matching (submitted, λ=8) | **321.0** |\n| ablation: no quality gate | 332.7 |\n| ablation: technical register fit on raw HTML markup | 325.9 |\n| ablation: technical share 10% instead of 25% | 349.4 |\n| ablation: stricter gate (starves technical register to 8%) | 350.3 |\n\n## Hypothesis\n\nWhen the training budget is a small fraction of the pool (12M of 200M tokens, ~6%) and\nthe evaluation target is a **known mixture of registers**, the dominant lever on held-out\nperplexity is not generic \"document quality\" but **matching the target's register\nmixture**, subject to a floor of basic text sanity.\n\nConcretely I claim two things, in order of predicted effect size:\n\n1. **Register-proportional selection beats quality-ranked selection.** The target is four\n   equal quarters — encyclopedic (WikiText), general high-quality web prose, news, and\n   technical Q&A. Filling the budget with ~25% of tokens from each register beats both a\n   random draw and a selection ranked by a single global target-vs-pool quality score,\n   because a global score is dominated by whichever register is most abundant in the pool\n   and starves the scarce ones.\n2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.\n\nI also predicted a third, **surface-form** effect that turned out to be real but small, and\nI record it here because the prediction was quantitative and mostly wrong in magnitude:\nthe encyclopedic quarter is *detokenised* WikiText (`\" ,\"`, `\" 's\"`, `\" @-@ \"`), a surface\nform ~8x rarer in the pool (spaced-punctuation ratio 0.85 in target vs 0.125 pool mean).\nI expected matching it to be a major lever; it is worth only a few points and saturates\nquickly, because pool documents with high spaced-punctuation ratio are overwhelmingly\nlow-quality fragments, so buying format match costs content quality roughly one-for-one.\n\n## Mechanism — and an observable other than the final perplexity\n\nThe mechanism is distribution matching: cross-entropy on a mixture target decomposes into\na sum over its components, so the budget should be spent where the target's mass is.\n\n**The observable I predict is the per-register perplexity decomposition of the held-out\ntarget, measured separately on each quarter.** This is a different measurement from the\nreported scalar and it discriminates between my hypothesis and the alternative \"the\nselection is just generically cleaner text\":\n\n- *Prediction A (register starvation is visible per-register).* Cutting the technical-Q&A\n  share from 25% to 10% while holding everything else fixed should raise the **technical\n  quarter's** perplexity sharply and leave the other three roughly unchanged — rather than\n  raising all four uniformly.\n- *Prediction B (the residual loss is concentrated, not spread).* After balancing, the four\n  quarters should **not** be equally hard. The encyclopedic quarter should be the clear\n  outlier — it is the only quarter whose surface form is essentially absent from the pool,\n  so it is the one register where selection cannot close the gap.\n\nMeasured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:\n\n| variant | tech-QA share of budget | webprose share | dev PPL |\n|---|---|---|---|\n| balanced (λ=8) | 25% | 25% | **321.0** |\n| tech share set to 10% | 10% | 30% | 349.4 |\n| strict gate (starves tech incidentally) | 8% | 37% | 350.3 |\n| strict gate + length cap | 7.5% | 48% | 392.7 |\n\nThree independent routes to an under-represented technical register produce a monotone\npenalty tracking how far the mixture drifts from the target's. This is the central result:\nmixture proportion dominates, and it dominates *even when the deviation is a side effect of\nmaking the per-document filter better*. A stricter gate selects cleaner documents and still\nloses 29 points, because cleanliness is not what the metric is short of.\n\n## Falsification\n\nThe claim is falsified by any of the following; each is a single frozen-script run:\n\n1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.\n\nThe honest negative results, recorded because they constrain the claim:\n\n- **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection\n  noise) even though ~20% of considered documents are near-duplicates. At ~2 epochs over\n  12M tokens, duplication is evidently not yet the binding constraint. It is retained for\n  robustness, not because it was measured to help.\n- **Letting registers share a common candidate pool hurts** (325.6–337.3 vs 321.0): the\n  registers then compete for the same generically-good documents and coverage degrades.\n- **The style weight λ is essentially flat, and its apparent optimum is noise.** The full\n  sweep, all with everything else held fixed:\n\n  | λ | 0 | 1 | 3 | 5 | 7 | 8 | 10 | 12 | 25 |\n  |---|---|---|---|---|---|---|---|---|---|\n  | dev PPL | 331.0 | 326.0 | 325.2 | 329.1 | 331.3 | **321.0** | 327.4 | 327.8 | 326.6 |\n\n  λ=8 is an isolated spike sitting between neighbours at 331.3 and 327.4, so it is not a\n  basin — it is a single lucky draw. The defensible reading is that turning the style term\n  on is worth ~4 points (331 → ~327 average over λ ∈ [1,25]) and that the specific value\n  does not matter. **The submitted selection uses λ=8** because it is the dev argmin and no\n  other value has evidence of being better, but I expect it to regress toward ~327 on the\n  hidden sample, and the headline improvement should be read as 478 → ~325, not 478 → 321.\n  Adjacent-λ scatter also bounds the selection-level noise floor at roughly ±4 points, which\n  is why the 24–71 point mixture effects above are trustworthy and the 1–4 point ones are not.\n- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from\n  documents longer than the 1536-token span the scorer actually reads, and the selection's\n  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails\n  appear not to be a real problem at this scale.\n\n## Transfer\n\nWhat should carry to other budget-constrained curation problems:\n\n- **Read the target before scoring against it.** The single highest-leverage act here was\n  decoding the disclosed dev target and discovering it was four registers, one of them in a\n  non-web surface form. Every subsequent decision followed from that.\n- **Canonicalise before you discriminate.** A target-vs-pool classifier on raw GPT-2 ids\n  learns *detokenisation artifacts*, not register: `\" ,\"` and `\",\"` are different tokens, so\n  the classifier can separate WikiText from web text without looking at content at all.\n  Mapping every vocabulary entry through `decode(t).strip().lower()` removes that shortcut.\n  The same failure mode will appear for any corpus whose provenance differs in whitespace,\n  casing, or unicode normalisation.\n- **A proxy classifier fit on a marked-up target selects markup, not language.** Fit on raw\n  StackExchange HTML, the technical register's top-ranked pool documents were scraped\n  JavaScript boilerplate — symbol soup sharing the angle brackets and none of the meaning.\n  Stripping tags before fitting made the same register select genuine technical discussion.\n  Generalisation: strip the target's presentation layer before using it as a retrieval query.\n- **Check which component of a composite metric your gains are coming from.** The scalar\n  perplexity hid the fact that one quarter carried ~2.7x the loss of the others, and that\n  the register I assumed was hardest (technical, structurally absent from the pool) was\n  actually the easiest. Decomposing the metric changed where the remaining effort went.\n- **Distribution matching has a ceiling set by pool support.** Where the pool has no support\n  for a target mode — here, WikiText's detokenised surface form — selection cannot\n  manufacture it, and trading content quality for surface match is roughly break-even.\n  Recognising the ceiling is what tells you to stop optimising that axis.\n", "numLines": 169, "startLine": 1, "totalLines": 169}}
#65
narration

Two claims in the doc aren't yet directly measured — Prediction A's per-register signature, and the "global quality score without quotas" falsification test. I have time to actually run both.

toolBashTest global-rank ablation and diagnose lowtech
args
{
  "command": "cd /workspace; python - <<'EOF'\np='/workspace/submission/curate.py'; s=open(p).read()\ns=s.replace('''ap.add_argument(\"--strict\", action=\"store_true\", help=\"tighter quality gate\")''',\n'''ap.add_argument(\"--strict\", action=\"store_true\", help=\"tighter quality gate\")\nap.add_argument(\"--global_rank\", action=\"store_true\",\n                help=\"ablation: one global quality ranking, no per-register quotas\")''')\nold='''while True:\n    deficit = [(got[k] / target_tok[k], k) for k in range(NREG) if ptr[k] < len(order[k])]\n    if not deficit:\n        break\n    _, k = min(deficit)'''\nnew='''if args.global_rank:\n    # Ablation: rank every gated document by its best register score and take the top of\n    # that single list, with no per-register quota. Isolates the contribution of balancing.\n    order = {0: [i for i in np.argsort(-rank.max(1)) if gate[i]]}\n    order.update({k: [] for k in range(1, NREG)})\n    target_tok = np.array([BUDGET * args.budget_mult] + [1e-9] * (NREG - 1))\nwhile True:\n    deficit = [(got[k] / target_tok[k], k) for k in range(NREG) if ptr[k] < len(order[k])]\n    if not deficit:\n        break\n    _, k = min(deficit)'''\nassert old in s; s=s.replace(old,new); open(p,'w').write(s)\nEOF\npython submission/curate.py --style 8 --global_rank --out work/sel_globalrank.json 2>&1 | grep -E \"^selected|^first\"\nnohup bash -c 'cd /workspace; bash work/eval.sh globalrank; PYTHONPATH=/workspace python work/diag.py --train_npy /tmp/tr_lowtech.npy --heldout_npy data/multi_dev.npy --out_json /tmp/dlt.json; PYTHONPATH=/workspace python work/diag.py --train_npy /tmp/tr_globalrank.npy --heldout_npy data/multi_dev.npy --out_json /tmp/dgr.json' > work/eval8.log 2>&1 &\necho launched; cat /workspace/.timer/remaining_secs",
  "description": "Test global-rank ablation and diagnose lowtech",
  "timeout": 600000
}
Bash result
selected 30618 docs, 30.0M tokens; per-register Mtok [30.0, 0.0, 0.0, 0.0]; dropped 2358 near-dups
first 13319 docs fill the 12M budget
launched
2496

[stdout]
selected 30618 docs, 30.0M tokens; per-register Mtok [30.0, 0.0, 0.0, 0.0]; dropped 2358 near-dups
first 13319 docs fill the 12M budget
launched
2496
[metadata] {"noOutputExpected": false}
#66
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashCheck global-rank and per-register diagnostics
args
{
  "command": "sleep 230; cd /workspace; grep -E \"HELDOUT|PERREG\" work/eval8.log; echo \"--- timer\"; cat /workspace/.timer/remaining_secs",
  "description": "Check global-rank and per-register diagnostics",
  "timeout": 500000
}
Bash result
[globalrank] HELDOUT_PPL 395.118  loss 5.9792  train_s 56  /tmp/tr_globalrank.npy
HELDOUT_PPL 349.350  loss 5.8561  train_s 56  /tmp/tr_lowtech.npy
PERREG wiki=717.6  webprose=261.2  news=259.4  techqa=305.2
HELDOUT_PPL 395.118  loss 5.9792  train_s 56  /tmp/tr_globalrank.npy
PERREG wiki=900.6  webprose=250.2  news=282.4  techqa=381.2
--- timer
2266

[stdout]
[globalrank] HELDOUT_PPL 395.118  loss 5.9792  train_s 56  /tmp/tr_globalrank.npy
HELDOUT_PPL 349.350  loss 5.8561  train_s 56  /tmp/tr_lowtech.npy
PERREG wiki=717.6  webprose=261.2  news=259.4  techqa=305.2
HELDOUT_PPL 395.118  loss 5.9792  train_s 56  /tmp/tr_globalrank.npy
PERREG wiki=900.6  webprose=250.2  news=282.4  techqa=381.2
--- timer
2266
[metadata] {"noOutputExpected": false}
#67
narration

Both predictions confirmed decisively. globalrank = 395.1 (74 points worse than balanced), and the per-register signature is textbook. Let me update claim.md with the real measurements.

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:",
  "new_string": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| tech share cut to 10% | 349.4 | 717.6 | 261.2 | 259.4 | **305.2** |\n| one global quality ranking, no quotas | 395.1 | **900.6** | *250.2* | 282.4 | **381.2** |\n\n**Prediction A is confirmed with the predicted signature, not merely the predicted sign.**\nCutting the technical share from 25% to 10% raises the *technical quarter* from 233.9 to\n305.2 (+31%) while webprose (255.4 → 261.2) and news (266.9 → 259.4) do not move — news even\nimproves slightly. The damage is localised to the starved register, which is what the\nmixture account predicts and what a generic \"the data got worse\" account does not.\n\nThe global-ranking ablation is the sharpest version of the same effect. Ranking by one\nquality score with no quotas produces the **best webprose perplexity of any run** (250.2,\nbeating the submitted selection's 255.4) while wiki collapses to 900.6 and technical to\n381.2 — net 395.1, i.e. 74 points worse overall. The pool's most abundant register wins the\nglobal ranking, and the selection buys a 5-point gain there at the cost of 240 points on\nwiki and 147 on technical. A single quality score is not a weaker version of mixture\nmatching; it actively optimises the wrong objective.\n\n**Prediction B is confirmed and is the most robust finding here:** the encyclopedic quarter\nis **2.6–2.9x harder** than every other quarter in every run. Notably the technical quarter\nis the *easiest* under the balanced selection, despite the pool containing almost no\nHTML-marked-up Q&A (0.05% of sampled documents) — its markup is repetitive and cheap to\nlearn, so a register's difficulty is not predicted by its surface novelty. This is what\nredirected my effort away from the technical register and toward the encyclopedic one.\n\nThe share ablation was then replicated twice by accident. Raising tech to 34% changes\nnothing (325.3), so 25% is a genuine optimum rather than a monotone \"more technical data is\nbetter\" trend. And two runs that were *not* designed as share ablations tightened the\nquality gate and, as a side effect, starved the same register; they land on the same curve:"
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n\nPrediction B is confirmed and is the strongest single result here: the encyclopedic\nquarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is\nthe *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled\ndocuments) — its markup is highly repetitive and cheap to learn, so the register's\ndifficulty is not predicted by its surface novelty. This is what redirected my effort away\nfrom the technical register and toward the encyclopedic one.\n\nPrediction A is supported by the share ablation, and then replicated twice by accident.\nDropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%\nchanges nothing (325.3) — the target share is a genuine optimum, not a monotone \"more\ntechnical data is better\" trend. Two later runs that were *not* designed as share ablations\ntightened the quality gate and, as a side effect, starved the same register; they land on\nthe same curve:", "newString": "Measured (frozen script, dev target, per-quarter perplexity):\n\n| selection | overall | wiki | webprose | news | tech-QA |\n|---|---|---|---|---|---|\n| balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |\n| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |\n| tech share cut to 10% | 349.4 | 717.6 | 261.2 | 259.4 | **305.2** |\n| one global quality ranking, no quotas | 395.1 | **900.6** | *250.2* | 282.4 | **381.2** |\n\n**Prediction A is confirmed with the predicted signature, not merely the predicted sign.**\nCutting the technical share from 25% to 10% raises the *technical quarter* from 233.9 to\n305.2 (+31%) while webprose (255.4 → 261.2) and news (266.9 → 259.4) do not move — news even\nimproves slightly. The damage is localised to the starved register, which is what the\nmixture account predicts and what a generic \"the data got worse\" account does not.\n\nThe global-ranking ablation is the sharpest version of the same effect. Ranking by one\nquality score with no quotas produces the **best webprose perplexity of any run** (250.2,\nbeating the submitted selection's 255.4) while wiki collapses to 900.6 and technical to\n381.2 — net 395.1, i.e. 74 points worse overall. The pool's most abundant register wins the\nglobal ranking, and the selection buys a 5-point gain there at the cost of 240 points on\nwiki and 147 on technical. A single quality score is not a weaker version of mixture\nmatching; it actively optimises the wrong objective.\n\n**Prediction B is confirmed and is the most robust finding here:** the encyclopedic quarter\nis **2.6–2.9x harder** than every other quarter in every run. Notably the technical quarter\nis the *easiest* under the balanced selection, despite the pool containing almost no\nHTML-marked-up Q&A (0.05% of sampled documents) — its markup is repetitive and cheap to\nlearn, so a register's difficulty is not predicted by its surface novelty. This is what\nredirected my effort away from the technical register and toward the encyclopedic one.\n\nThe share ablation was then replicated twice by accident. Raising tech to 34% changes\nnothing (325.3), so 25% is a genuine optimum rather than a monotone \"more technical data is\nbetter\" trend. And two runs that were *not* designed as share ablations tightened the\nquality gate and, as a side effect, starved the same register; they land on the same curve:", "originalFile": null, "structuredPatch": [{"oldStart": 66, "oldLines": 23, "newStart": 66, "newLines": 37, "lines": [" ", " | selection | overall | wiki | webprose | news | tech-QA |", " |---|---|---|---|---|---|", "-| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |", " | balanced, style λ=8 (submitted) | 321.0 | **661.3** | 255.4 | 266.9 | 233.9 |", "+| balanced, style λ=3 | 325.2 | **688.3** | 257.7 | 267.4 | 235.0 |", "+| tech share cut to 10% | 349.4 | 717.6 | 261.2 | 259.4 | **305.2** |", "+| one global quality ranking, no quotas | 395.1 | **900.6** | *250.2* | 282.4 | **381.2** |", " ", "-Prediction B is confirmed and is the strongest single result here: the encyclopedic", "-quarter is **2.6–2.9x harder** than every other quarter. Notably the technical quarter is", "-the *easiest* despite the pool containing almost no HTML-marked-up Q&A (0.05% of sampled", "-documents) — its markup is highly repetitive and cheap to learn, so the register's", "-difficulty is not predicted by its surface novelty. This is what redirected my effort away", "-from the technical register and toward the encyclopedic one.", "+**Prediction A is confirmed with the predicted signature, not merely the predicted sign.**", "+Cutting the technical share from 25% to 10% raises the *technical quarter* from 233.9 to", "+305.2 (+31%) while webprose (255.4 → 261.2) and news (266.9 → 259.4) do not move — news even", "+improves slightly. The damage is localised to the starved register, which is what the", "+mixture account predicts and what a generic \"the data got worse\" account does not.", " ", "-Prediction A is supported by the share ablation, and then replicated twice by accident.", "-Dropping tech-QA to 10% costs 24 points overall (325.2 → 349.4), while raising it to 34%", "-changes nothing (325.3) — the target share is a genuine optimum, not a monotone \"more", "-technical data is better\" trend. Two later runs that were *not* designed as share ablations", "-tightened the quality gate and, as a side effect, starved the same register; they land on", "-the same curve:", "+The global-ranking ablation is the sharpest version of the same effect. Ranking by one", "+quality score with no quotas produces the **best webprose perplexity of any run** (250.2,", "+beating the submitted selection's 255.4) while wiki collapses to 900.6 and technical to", "+381.2 — net 395.1, i.e. 74 points worse overall. The pool's most abundant register wins the", "+global ranking, and the selection buys a 5-point gain there at the cost of 240 points on", "+wiki and 147 on technical. A single quality score is not a weaker version of mixture", "+matching; it actively optimises the wrong objective.", " ", "+**Prediction B is confirmed and is the most robust finding here:** the encyclopedic quarter", "+is **2.6–2.9x harder** than every other quarter in every run. Notably the technical quarter", "+is the *easiest* under the balanced selection, despite the pool containing almost no", "+HTML-marked-up Q&A (0.05% of sampled documents) — its markup is repetitive and cheap to", "+learn, so a register's difficulty is not predicted by its surface novelty. This is what", "+redirected my effort away from the technical register and toward the encyclopedic one.", "+", "+The share ablation was then replicated twice by accident. Raising tech to 34% changes", "+nothing (325.3), so 25% is a genuine optimum rather than a monotone \"more technical data is", "+better\" trend. And two runs that were *not* designed as share ablations tightened the", "+quality gate and, as a side effect, starved the same register; they land on the same curve:", "+", " | variant | tech-QA share of budget | webprose share | dev PPL |", " |---|---|---|---|", " | balanced (λ=8) | 25% | 25% | **321.0** |"]}], "userModified": false, "replaceAll": false}
#68
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.",
  "new_string": "1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` with no per-register quota (`curate.py --global_rank`). If that reaches\n   the balanced selection's perplexity, claim 1 is dead. *Run: 395.1 vs 321.0 — claim 1\n   survives by 74 points, the largest single effect measured.*\n2. **Removing the sanity gate is free.** *Run: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, but it is an order of magnitude smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat, or the damage from starving a register\n   is spread across all four.** Either would break the mechanism. *Run: neither — 661 vs\n   ~250 for the decomposition, and starving tech moved only tech (+71) while news and\n   webprose stayed within ±8.*\n\nThe cleanest remaining falsification I did **not** have budget to run: hold the mixture at\n25% each and vary only the *within-register* ranking (e.g. random draw inside each register\nversus classifier-ranked). My results establish that mixture proportion dominates, but they\ndo not isolate how much of the 478 → 321 gain comes from the classifier's within-register\nordering versus from the quota structure plus gate alone. That is the experiment I would run\nnext, and the one most likely to shrink the claimed role of the classifier."
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that\n   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced\n   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*\n2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, though it is smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat.** If all four quarters had similar\n   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism\n   would be wrong. It did not — 688 vs ~250.", "newString": "1. **A single global quality score matches register balancing.** Rank documents by\n   `max_r score_r` with no per-register quota (`curate.py --global_rank`). If that reaches\n   the balanced selection's perplexity, claim 1 is dead. *Run: 395.1 vs 321.0 — claim 1\n   survives by 74 points, the largest single effect measured.*\n2. **Removing the sanity gate is free.** *Run: 332.7 vs 325.2 — the gate is worth ~7.5\n   points, so claim 2 survives, but it is an order of magnitude smaller than claim 1.*\n3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced\n   point. A win at any off-target share would falsify the distribution-matching account.\n4. **The per-register decomposition comes out flat, or the damage from starving a register\n   is spread across all four.** Either would break the mechanism. *Run: neither — 661 vs\n   ~250 for the decomposition, and starving tech moved only tech (+71) while news and\n   webprose stayed within ±8.*\n\nThe cleanest remaining falsification I did **not** have budget to run: hold the mixture at\n25% each and vary only the *within-register* ranking (e.g. random draw inside each register\nversus classifier-ranked). My results establish that mixture proportion dominates, but they\ndo not isolate how much of the 478 → 321 gain comes from the classifier's within-register\nordering versus from the quota structure plus gate alone. That is the experiment I would run\nnext, and the one most likely to shrink the claimed role of the classifier.", "originalFile": null, "structuredPatch": [{"oldStart": 115, "oldLines": 17, "newStart": 115, "newLines": 25, "lines": [" The claim is falsified by any of the following; each is a single frozen-script run:", " ", " 1. **A single global quality score matches register balancing.** Rank documents by", "-   `max_r score_r` (or by target-vs-pool log-odds) with no per-register quota. If that", "-   reaches the balanced selection's perplexity, claim 1 is dead. *Result: the unbalanced", "-   variants are worse — the closest thing tested, a 10% tech share, loses 24 points.*", "-2. **Removing the sanity gate is free.** *Tested: 332.7 vs 325.2 — the gate is worth ~7.5", "-   points, so claim 2 survives, though it is smaller than claim 1.*", "+   `max_r score_r` with no per-register quota (`curate.py --global_rank`). If that reaches", "+   the balanced selection's perplexity, claim 1 is dead. *Run: 395.1 vs 321.0 — claim 1", "+   survives by 74 points, the largest single effect measured.*", "+2. **Removing the sanity gate is free.** *Run: 332.7 vs 325.2 — the gate is worth ~7.5", "+   points, so claim 2 survives, but it is an order of magnitude smaller than claim 1.*", " 3. **Register shares away from 25% win.** Tested at 10% and 34% tech; both ≥ the balanced", "    point. A win at any off-target share would falsify the distribution-matching account.", "-4. **The per-register decomposition comes out flat.** If all four quarters had similar", "-   perplexity after balancing, the \"encyclopedic quarter is the irreducible one\" mechanism", "-   would be wrong. It did not — 688 vs ~250.", "+4. **The per-register decomposition comes out flat, or the damage from starving a register", "+   is spread across all four.** Either would break the mechanism. *Run: neither — 661 vs", "+   ~250 for the decomposition, and starving tech moved only tech (+71) while news and", "+   webprose stayed within ±8.*", " ", "+The cleanest remaining falsification I did **not** have budget to run: hold the mixture at", "+25% each and vary only the *within-register* ranking (e.g. random draw inside each register", "+versus classifier-ranked). My results establish that mixture proportion dominates, but they", "+do not isolate how much of the 478 → 321 gain comes from the classifier's within-register", "+ordering versus from the quota structure plus gate alone. That is the experiment I would run", "+next, and the one most likely to shrink the claimed role of the classifier.", "+", " The honest negative results, recorded because they constrain the claim:", " ", " - **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection"]}], "userModified": false, "replaceAll": false}
#69
narration

I claimed a lack of budget for one experiment — but I have ~35 minutes, so let me actually run it rather than assert it.

toolBashRun within-register ranking ablation
args
{
  "command": "cd /workspace; python - <<'EOF'\np='/workspace/submission/curate.py'; s=open(p).read()\ns=s.replace('''ap.add_argument(\"--global_rank\", action=\"store_true\",''',\n'''ap.add_argument(\"--random_within\", action=\"store_true\",\n                help=\"ablation: keep the quotas+gate, shuffle the order inside each register\")\nap.add_argument(\"--global_rank\", action=\"store_true\",''')\nold='''    order = {k: [i for i in np.argsort(-rank[:, k]) if gate[i] and best_reg[i] == k]\n             for k in range(NREG)}'''\nnew='''    order = {k: [i for i in np.argsort(-rank[:, k]) if gate[i] and best_reg[i] == k]\n             for k in range(NREG)}\nif args.random_within:\n    # Ablation: same register quotas, same gate, same register assignment -- but the\n    # within-register ordering is random instead of classifier-ranked. Isolates how much\n    # of the gain is the quota structure versus the document-level ranking.\n    shuf = np.random.default_rng(SEED)\n    for k in order:\n        order[k] = list(shuf.permutation(order[k]))'''\nassert old in s; s=s.replace(old,new); open(p,'w').write(s)\nEOF\npython submission/curate.py --style 8 --random_within --out work/sel_randwithin.json 2>&1 | grep -E \"^selected|^first\"\nnohup bash -c 'cd /workspace; bash work/eval.sh randwithin; PYTHONPATH=/workspace python work/diag.py --train_npy /tmp/tr_randwithin.npy --heldout_npy data/multi_dev.npy --out_json /tmp/drw.json' > work/eval9.log 2>&1 &\necho launched",
  "description": "Run within-register ranking ablation",
  "timeout": 600000
}
Bash result
selected 31908 docs, 30.0M tokens; per-register Mtok [8.32, 8.32, 8.32, 5.04]; dropped 9541 near-dups
first 12372 docs fill the 12M budget
launched

[stdout]
selected 31908 docs, 30.0M tokens; per-register Mtok [8.32, 8.32, 8.32, 5.04]; dropped 9541 near-dups
first 12372 docs fill the 12M budget
launched
[metadata] {"noOutputExpected": false}
#70
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashCheck within-register ablation result
args
{
  "command": "sleep 165; cd /workspace; grep -E \"HELDOUT|PERREG\" work/eval9.log; echo \"--- timer\"; cat /workspace/.timer/remaining_secs",
  "description": "Check within-register ablation result",
  "timeout": 400000
}
Bash result
[randwithin] HELDOUT_PPL 369.501  loss 5.9122  train_s 56  /tmp/tr_randwithin.npy
HELDOUT_PPL 369.501  loss 5.9122  train_s 56  /tmp/tr_randwithin.npy
PERREG wiki=772.3  webprose=291.0  news=328.2  techqa=251.6
--- timer
2026

[stdout]
[randwithin] HELDOUT_PPL 369.501  loss 5.9122  train_s 56  /tmp/tr_randwithin.npy
HELDOUT_PPL 369.501  loss 5.9122  train_s 56  /tmp/tr_randwithin.npy
PERREG wiki=772.3  webprose=291.0  news=328.2  techqa=251.6
--- timer
2026
[metadata] {"noOutputExpected": false}
#71
narration

The decomposition is clean and gives a second, distinguishable signature. Let me finalize claim.md.

toolEdit
args
{
  "replace_all": false,
  "file_path": "/workspace/claim.md",
  "old_string": "The cleanest remaining falsification I did **not** have budget to run: hold the mixture at\n25% each and vary only the *within-register* ranking (e.g. random draw inside each register\nversus classifier-ranked). My results establish that mixture proportion dominates, but they\ndo not isolate how much of the 478 → 321 gain comes from the classifier's within-register\nordering versus from the quota structure plus gate alone. That is the experiment I would run\nnext, and the one most likely to shrink the claimed role of the classifier.",
  "new_string": "5. **The classifier's within-register ranking does nothing** — i.e. the quota structure plus\n   gate account for the whole gain. Held the mixture at 25% each, kept the gate and the\n   register assignment, and replaced the within-register ordering with a random shuffle\n   (`--random_within`). *Run: 369.5.* This **partially falsifies** the strong form of my\n   hypothesis. The gain decomposes as:\n\n   | | dev PPL | gain |\n   |---|---|---|\n   | random selection | 477.8 | — |\n   | + gate, register assignment, 25% quotas (random order within register) | 369.5 | 108.3 |\n   | + classifier ranking within register (submitted) | 321.0 | 48.5 |\n\n   So mixture structure is worth ~2.2x the within-register document ranking, but the ranking\n   is *not* negligible at 48.5 points — my claim that mixture \"dominates\" is right about the\n   ordering of effects and wrong to imply the ranking is a rounding error.\n\n**The two failure modes leave different fingerprints**, which is the part I find most\nconvincing. Distorting the mixture damages the starved register and spares the others\n(tech −71, news +7). Degrading within-register quality while holding the mixture fixed\ndamages *all four roughly proportionally* (wiki 661→772, webprose 255→291, news 267→328,\ntech 234→252; +14% to +23% each). A single scalar perplexity cannot tell these apart; the\ndecomposition can, and it means the per-register profile diagnoses *which* curation axis a\nselection is failing on."
}
Edit result
The file /workspace/claim.md has been updated successfully. (file state is current in your context — no need to Read it back)

[metadata] {"filePath": "/workspace/claim.md", "oldString": "The cleanest remaining falsification I did **not** have budget to run: hold the mixture at\n25% each and vary only the *within-register* ranking (e.g. random draw inside each register\nversus classifier-ranked). My results establish that mixture proportion dominates, but they\ndo not isolate how much of the 478 → 321 gain comes from the classifier's within-register\nordering versus from the quota structure plus gate alone. That is the experiment I would run\nnext, and the one most likely to shrink the claimed role of the classifier.", "newString": "5. **The classifier's within-register ranking does nothing** — i.e. the quota structure plus\n   gate account for the whole gain. Held the mixture at 25% each, kept the gate and the\n   register assignment, and replaced the within-register ordering with a random shuffle\n   (`--random_within`). *Run: 369.5.* This **partially falsifies** the strong form of my\n   hypothesis. The gain decomposes as:\n\n   | | dev PPL | gain |\n   |---|---|---|\n   | random selection | 477.8 | — |\n   | + gate, register assignment, 25% quotas (random order within register) | 369.5 | 108.3 |\n   | + classifier ranking within register (submitted) | 321.0 | 48.5 |\n\n   So mixture structure is worth ~2.2x the within-register document ranking, but the ranking\n   is *not* negligible at 48.5 points — my claim that mixture \"dominates\" is right about the\n   ordering of effects and wrong to imply the ranking is a rounding error.\n\n**The two failure modes leave different fingerprints**, which is the part I find most\nconvincing. Distorting the mixture damages the starved register and spares the others\n(tech −71, news +7). Degrading within-register quality while holding the mixture fixed\ndamages *all four roughly proportionally* (wiki 661→772, webprose 255→291, news 267→328,\ntech 234→252; +14% to +23% each). A single scalar perplexity cannot tell these apart; the\ndecomposition can, and it means the per-register profile diagnoses *which* curation axis a\nselection is failing on.", "originalFile": null, "structuredPatch": [{"oldStart": 127, "oldLines": 13, "newStart": 127, "newLines": 30, "lines": ["    ~250 for the decomposition, and starving tech moved only tech (+71) while news and", "    webprose stayed within ±8.*", " ", "-The cleanest remaining falsification I did **not** have budget to run: hold the mixture at", "-25% each and vary only the *within-register* ranking (e.g. random draw inside each register", "-versus classifier-ranked). My results establish that mixture proportion dominates, but they", "-do not isolate how much of the 478 → 321 gain comes from the classifier's within-register", "-ordering versus from the quota structure plus gate alone. That is the experiment I would run", "-next, and the one most likely to shrink the claimed role of the classifier.", "+5. **The classifier's within-register ranking does nothing** — i.e. the quota structure plus", "+   gate account for the whole gain. Held the mixture at 25% each, kept the gate and the", "+   register assignment, and replaced the within-register ordering with a random shuffle", "+   (`--random_within`). *Run: 369.5.* This **partially falsifies** the strong form of my", "+   hypothesis. The gain decomposes as:", " ", "+   | | dev PPL | gain |", "+   |---|---|---|", "+   | random selection | 477.8 | — |", "+   | + gate, register assignment, 25% quotas (random order within register) | 369.5 | 108.3 |", "+   | + classifier ranking within register (submitted) | 321.0 | 48.5 |", "+", "+   So mixture structure is worth ~2.2x the within-register document ranking, but the ranking", "+   is *not* negligible at 48.5 points — my claim that mixture \"dominates\" is right about the", "+   ordering of effects and wrong to imply the ranking is a rounding error.", "+", "+**The two failure modes leave different fingerprints**, which is the part I find most", "+convincing. Distorting the mixture damages the starved register and spares the others", "+(tech −71, news +7). Degrading within-register quality while holding the mixture fixed", "+damages *all four roughly proportionally* (wiki 661→772, webprose 255→291, news 267→328,", "+tech 234→252; +14% to +23% each). A single scalar perplexity cannot tell these apart; the", "+decomposition can, and it means the per-register profile diagnoses *which* curation axis a", "+selection is failing on.", "+", " The honest negative results, recorded because they constrain the claim:", " ", " - **Deduplication is neutral here** (324.9 without vs 325.2 with, i.e. within selection"]}], "userModified": false, "replaceAll": false}
#72
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashFinalize claim and verify all deliverables
args
{
  "command": "cd /workspace; python - <<'EOF'\np='/workspace/claim.md'; s=open(p).read()\ns=s.replace('''| ablation: technical share 10% instead of 25% | 349.4 |\n| ablation: stricter gate (starves technical register to 8%) | 350.3 |''',\n'''| ablation: technical share 10% instead of 25% | 349.4 |\n| ablation: stricter gate (starves technical register to 8%) | 350.3 |\n| ablation: random order within register (quotas + gate only) | 369.5 |\n| ablation: one global quality ranking, no register quotas | 395.1 |''')\ns=s.replace('''2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.''',\n'''2. **A register-agnostic sanity gate is worth several perplexity points**, because raw web\n   pools contain a large mass of nav-bar / classifieds / template-loop text that no target\n   register resembles, and under a fixed budget every such token displaces a useful one.\n\nBoth claims held, and the effect sizes came out in the predicted order: mixture structure\n108 points, within-register ranking 48 points, sanity gate ~8 points. The strong form of\nclaim 1 — that mixture matching is the *only* thing that matters — is falsified; see\nFalsification item 5.''')\nopen(p,'w').write(s)\nEOF\necho \"=== deliverables ===\"; ls -la submission/ ; echo; python work/validate.py submission/selection.json\necho; echo \"=== curate.py reproduces submitted list ===\"\npython submission/curate.py --style 8 --out /tmp/final_check.json 2>&1 | grep -E \"^selected\"\npython -c \"\nimport json; a=json.load(open('/workspace/submission/selection.json')); b=json.load(open('/tmp/final_check.json'))\nprint('identical:', a==b)\"\ncat /workspace/.timer/remaining_secs",
  "description": "Finalize claim and verify all deliverables",
  "timeout": 600000
}
Bash result
=== deliverables ===
total 255
drwxr-xr-x 1 root root    280 Aug  4 00:12 .
drwxr-xr-x 1 root root    340 Aug  4 00:22 ..
-rw-r--r-- 1 root root  17285 Aug  4 00:19 curate.py
-rw-r--r-- 1 root root   3166 Aug  4 00:12 prepare_pool.py
-rw-r--r-- 1 root root 239694 Aug  4 00:09 selection.json

OK  33283 unique ids, all in [0,182015]
    30.0M tokens total (2.5x the 12M budget)
    first 13681 ids fill the budget exactly (12000181 tokens)

=== curate.py reproduces submitted list ===
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
identical: True
1986

[stdout]
=== deliverables ===
total 255
drwxr-xr-x 1 root root    280 Aug  4 00:12 .
drwxr-xr-x 1 root root    340 Aug  4 00:22 ..
-rw-r--r-- 1 root root  17285 Aug  4 00:19 curate.py
-rw-r--r-- 1 root root   3166 Aug  4 00:12 prepare_pool.py
-rw-r--r-- 1 root root 239694 Aug  4 00:09 selection.json

OK  33283 unique ids, all in [0,182015]
    30.0M tokens total (2.5x the 12M budget)
    first 13681 ids fill the budget exactly (12000181 tokens)

=== curate.py reproduces submitted list ===
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
identical: True
1986
[metadata] {"noOutputExpected": false}
#73
narration

All deliverables verified and reproducible. I have ~33 min left — enough for one more genuine improvement attempt. The scorer only reads each doc's first 1536 tokens while 39% of budget tokens lie beyond that, so let me score deeper.

toolBashScore documents more deeply and evaluate
args
{
  "command": "cd /workspace; python - <<'EOF'\np='/workspace/submission/curate.py'; s=open(p).read()\ns=s.replace('''MAXW = 8           # windows scored per document (cost bound; ~1.5k tokens)''',\n'''MAXW = 8           # windows scored per document (cost bound; ~1.5k tokens) -- see --maxw''')\ns=s.replace('''ap.add_argument(\"--strict\", action=\"store_true\", help=\"tighter quality gate\")''',\n'''ap.add_argument(\"--strict\", action=\"store_true\", help=\"tighter quality gate\")\nap.add_argument(\"--maxw\", type=int, default=MAXW,\n                help=\"windows scored per document; higher reads more of long documents\")''')\ns=s.replace('''    w = windows(corpus[offs[i]:offs[i + 1]])[:MAXW]''',\n'''    w = windows(corpus[offs[i]:offs[i + 1]])[:args.maxw]''')\nopen(p,'w').write(s)\nEOF\npython submission/curate.py --style 8 --maxw 32 --cache work/cacheW32 --out work/sel_maxw32.json 2>&1 | grep -E \"^selected|^first\"\nnohup bash work/eval.sh maxw32 > work/eval10.log 2>&1 &\necho launched; cat /workspace/.timer/remaining_secs",
  "description": "Score documents more deeply and evaluate",
  "timeout": 900000
}
Bash result
selected 33557 docs, 30.0M tokens; per-register Mtok [8.31, 8.31, 8.31, 5.07]; dropped 7963 near-dups
first 14137 docs fill the 12M budget
launched
1916

[stdout]
selected 33557 docs, 30.0M tokens; per-register Mtok [8.31, 8.31, 8.31, 5.07]; dropped 7963 near-dups
first 14137 docs fill the 12M budget
launched
1916
[metadata] {"noOutputExpected": false}
#74
reasoning (redacted)

encrypted chain-of-thought — recorded, not exposed

toolBashCheck deeper-scoring result
args
{
  "command": "sleep 100; cd /workspace; grep HELDOUT work/eval10.log; cat /workspace/.timer/remaining_secs",
  "description": "Check deeper-scoring result",
  "timeout": 400000
}
Bash result
[maxw32] HELDOUT_PPL 321.286  loss 5.7723  train_s 56  /tmp/tr_maxw32.npy
1815

[stdout]
[maxw32] HELDOUT_PPL 321.286  loss 5.7723  train_s 56  /tmp/tr_maxw32.npy
1815
[metadata] {"noOutputExpected": false}
#75
narration

Deeper scoring is neutral (321.3 vs 321.0) — another honest negative. Let me record it, add the fingerprint insight to Transfer, and do a final verification.

toolBashFinal verification of all deliverables
args
{
  "command": "cd /workspace; python - <<'EOF'\np='/workspace/claim.md'; s=open(p).read()\ns=s.replace('''- **A length cap is neutral** (322.5 vs 321.0) even though 39% of the budget comes from\n  documents longer than the 1536-token span the scorer actually reads, and the selection's\n  mean document length (877 tokens) is 2.4x the target's (370). Unvetted document tails\n  appear not to be a real problem at this scale.''',\n'''- **Unvetted document tails do not matter, tested two ways.** 39% of the budget comes from\n  documents longer than the 1536-token span the scorer reads, and the selection's mean\n  document length (877 tokens) is 2.4x the target's (370). Capping length at 2500 tokens is\n  neutral (322.5 vs 321.0), and scoring 4x deeper into each document (`--maxw 32`, ~6k\n  tokens, covering ~90% of selected tokens) is also neutral (321.3 vs 321.0). Document-level\n  scores from the first ~1.5k tokens evidently generalise to the whole document, so cheap\n  truncated scoring is the right engineering choice.''')\ns=s.replace('''- **Distribution matching has a ceiling set by pool support.**''',\n'''- **Per-register decomposition is a diagnostic, not just a report.** Mixture distortion and\n  within-register quality loss produce *different* fingerprints — localised damage to one\n  component versus proportional damage to all of them. So when a composite metric regresses,\n  the decomposition tells you which curation axis to go fix, before running any further\n  experiments. This is the transferable measurement habit, independent of this pool or target.\n- **Distribution matching has a ceiling set by pool support.**''')\nopen(p,'w').write(s)\nEOF\necho \"=== final reproducibility check (default flags = submitted) ===\"\npython submission/curate.py --style 8 --out /tmp/final2.json 2>&1 | grep -E \"^selected\"\npython -c \"\nimport json;a=json.load(open('/workspace/submission/selection.json'));b=json.load(open('/tmp/final2.json'))\nprint('curate.py --style 8 reproduces selection.json:', a==b)\"\npython work/validate.py submission/selection.json\necho; ls -la submission/ claim.md; cat /workspace/.timer/remaining_secs",
  "description": "Final verification of all deliverables",
  "timeout": 600000
}
Bash result
=== final reproducibility check (default flags = submitted) ===
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
curate.py --style 8 reproduces selection.json: True
OK  33283 unique ids, all in [0,182015]
    30.0M tokens total (2.5x the 12M budget)
    first 13681 ids fill the budget exactly (12000181 tokens)

-rw-r--r-- 1 root root 14611 Aug  4 00:25 claim.md

submission/:
total 256
drwxr-xr-x 1 root root    280 Aug  4 00:12 .
drwxr-xr-x 1 root root    340 Aug  4 00:22 ..
-rw-r--r-- 1 root root  17443 Aug  4 00:23 curate.py
-rw-r--r-- 1 root root   3166 Aug  4 00:12 prepare_pool.py
-rw-r--r-- 1 root root 239694 Aug  4 00:09 selection.json
1785

[stdout]
=== final reproducibility check (default flags = submitted) ===
selected 33283 docs, 30.0M tokens; per-register Mtok [8.27, 8.27, 8.27, 5.2]; dropped 7854 near-dups
curate.py --style 8 reproduces selection.json: True
OK  33283 unique ids, all in [0,182015]
    30.0M tokens total (2.5x the 12M budget)
    first 13681 ids fill the budget exactly (12000181 tokens)

-rw-r--r-- 1 root root 14611 Aug  4 00:25 claim.md

submission/:
total 256
drwxr-xr-x 1 root root    280 Aug  4 00:12 .
drwxr-xr-x 1 root root    340 Aug  4 00:22 ..
-rw-r--r-- 1 root root  17443 Aug  4 00:23 curate.py
-rw-r--r-- 1 root root   3166 Aug  4 00:12 prepare_pool.py
-rw-r--r-- 1 root root 239694 Aug  4 00:09 selection.json
1785
[metadata] {"noOutputExpected": false}
final summary

All three deliverables are in place, verified, and reproducible.

Result

Dev held-out perplexity 477.8 → 321.0 (−32.8% vs the random-selection baseline), verified end-to-end through the official dev_eval.sh (pack_selection.py → frozen train_nano.py), which reproduced 320.991 exactly.

What drove it

I decoded the disclosed dev target and found it was four contiguous, exactly equal quarters: WikiText-style encyclopedic, general web prose, news, and StackExchange Q&A. Everything followed from that. I pre-tokenized the whole pool once (2 min), then fit a 5-way linear classifier — four register classes vs. a random-pool "background" — and filled the budget with 25% of tokens from each register, gated and deduplicated.

Two details were the difference between working and not:

  • Canonicalizing the vocabulary. The wiki quarter is detokenized (" ,", " 's", " @-@ "). On raw GPT-2 ids the classifier separates target from pool purely on whitespace artifacts, learning nothing about register. Mapping each vocab entry through decode(t).strip().lower() removes the shortcut.
  • Stripping HTML from the technical quarter before fitting. Fit on raw markup, the top-ranked "technical" pool docs were scraped JavaScript boilerplate — symbol soup with the angle brackets and none of the language. After stripping, the same register selects genuine technical discussion (SVN dev threads, SharePoint deployment).

Measured, not assumed

I ran ~20 frozen-script evaluations. The mechanism is verified through a per-register perplexity decomposition — an observable separate from the score:

ablationdev PPL
submitted321.0
no quality gate332.7
tech share 10% instead of 25%349.4
random order within register (quotas+gate only)369.5
one global quality score, no quotas395.1

The decomposition separates two failure modes by fingerprint: starving a register damages that register (tech 234→305) and spares the others (news 267→259), while losing within-register quality damages all four proportionally (+14–23% each).

Three things I'd flag rather than bury:

  • λ=8 is a noise spike. The sweep gives 331/326/325/329/331/321/327/328/327 — λ=8's neighbors are 331 and 327, so it's a lucky draw, not a basin. Turning the style term on is worth ~4 points; the specific value isn't. Expect regression toward ~327 on the hidden sample; read the headline as 478 → ~325.
  • Dedup is neutral here (324.9 without vs 325.2 with) despite ~20% near-duplicates. Retained for robustness, not because it measured as helping.
  • The strong form of my hypothesis is falsified. Mixture structure is worth 108 points and within-register ranking 48 — so mixture dominates ~2.2:1, but calling the ranking a rounding error would have been wrong. I ran that experiment specifically because I had initially written it up as out of budget.

The wiki quarter remains ~2.7x harder than the others (661 vs ~250) and is the binding constraint: its detokenized surface form is essentially absent from the pool, and buying format match costs content quality roughly one-for-one, so selection can't close that gap.