Gate-1 baseline run: chained weighted QRF - #40
Merged
Conversation
The first pre-registered model run of populace-dynamics. Scores the locked baseline earnings process -- populace-fit's regime-gated chained weighted QRF, run as a one-step BACKWARD biennial backcast -- against the gate-1 thresholds locked in gates.yaml (ratified, pull request 39, commit eaa7c47). The protocol is read from gates.yaml at runtime and implemented literally; no threshold is hardcoded and no model choice is tuned against holdout scores. VERDICT: gate_1 FAILS. Geometry passes 0/5 seeds and the battery passes 0/5 seeds (rule: >=4/5 on each). This is the scientifically expected outcome for a one-step chained baseline: the naive Markov backcast cannot reproduce the real earnings process's long-horizon persistence, which the lock's own prose predicted for a chained model. What fails, on every seed: * Geometry, runs view (window-3) c2st_auc: 0.553-0.566 vs the locked <= 0.54 (fails 5/5). The window-2 pairs view passes all six thresholds on all five seeds -- as the lock notes, a chained one-step candidate matches the pairs view by construction, so the runs view is where persistence understatement shows. * Battery autocorr_log_4yr (2 chained steps): 0.557-0.591 vs reference 0.657, tolerance 0.06 (fails 5/5). * Battery autocorr_log_10yr (5 chained steps): 0.309-0.368 vs reference 0.539, tolerance 0.07 (fails 5/5) -- the chain decays autocorrelation far faster than the real process. Everything else passes on all seeds: pairs-view geometry, the 2-year autocorrelation, the mobility diagonal, zero persistence, entry/exit rates, and mean spell length. Battery-reference reproduction: all eight committed battery_reference values in runs/noise_floor_psid_family_9822.json reproduce to float precision on the full filtered panel (autocorr 0.730123510230560 / 0.657166897978905 / 0.538879427219318, mobility diagonal 0.604051920570276, and the four spell statistics), proving the battery code path matches the committed definitions before any candidate is scored. Baseline design (fixed by the feature author, implemented as stated): * RegimeGatedQRF at DEFAULT hyperparameters (100 trees, zero_atol 1e-6, max_samples_leaf None), plain-table front door, seeded from the gate seed s. * Backward transition: target = earnings at t-2, predictors = (earnings at t, age at t-2), sample_weight = the pair's earlier (t-2) weight; fit on the 80% complement's adjacent 2-year pairs. * Generation: anchor each holdout person's last observed period at its real earnings, chain backward over observed periods, drawing each earlier period conditional on the next period's generated/anchor value and the earlier period's age; a 4+ year gap applies the one-step model once. Only earnings is generated; the candidate panel holds exactly the holdout persons on exactly their observed periods. Protocol: filter first (age 25-59, 1998-2022, positive weights), then per seed 0-4 split_panel_by_person(fraction=0.2) -- the drawn 20% is the holdout, the complement trains a fresh model. Geometry via panel_scorecard on both locked views; battery on the candidate panel vs the committed reference. Seed-level conjunction exactly as locked. Deliverables: * scripts/run_gate1_baseline.py -- deterministic runner (fit, generation, scoring, artifact write). * runs/gate1_qrf_baseline_v1.json -- evidence artifact: per-seed per-view geometry scores vs locked thresholds with per-metric pass/fail, per-seed battery values vs references/tolerances with pass/fail, the seed-conjunction table, the verdict, model description, revision pins, and per-seed n_persons/n_windows. * tests/test_gate1_qrf_baseline.py -- a seed-0 reproduction test (skipif PSID absent) pinning the artifact to float precision, and always-runnable internal-consistency tests that recompute every reported pass/fail from its own stored score vs stored threshold, check the stored thresholds against gates.yaml, and recompute the verdict from the seed table. Determinism verified: a fresh full run reproduces the artifact's scientific content byte-for-byte, and the seed-0 reproduction test matches every stored geometry and battery value to 1e-12. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
populace-fit pins scikit-learn below 1.9 (quantile-forest imports a symbol 1.9 removed), so it cannot coexist with this repo's default venv; gate runs use a dedicated venv. Without the guard the test raised ImportError instead of skipping on machines with the PSID files staged but no populace-fit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
July 5, 2026 15:14
This was referenced Jul 5, 2026
MaxGhenis
added a commit
that referenced
this pull request
Jul 5, 2026
The second pre-registered model run of the locked gate 1, following the failed baseline (#40). The candidate spec was frozen before the run in the issue #42 registration comment (comment 4886538087); every modeling degree of freedom is pinned there and implemented literally. One shot against the LOCKED gates.yaml thresholds, no tuning against holdout scores. Verdict: FAIL, geometry 3/5 and battery 0/5 (rule: >=4/5 each). The battery-reference bit-exact reproduction precheck passed before any candidate was scored. The latent permanent state put a floor under long-horizon autocorrelation roughly equal to the variance share the drawn perm explains, exactly as the registration memo argued. That share came out 0.52-0.55 (vs the memo's 0.467 back-out), which overcorrected the baseline's persistence shortfall: the 10-year autocorrelation moved from the baseline's 0.31-0.37 (far below the band) to 0.615-0.668, just above the locked band's upper edge on all five seeds. The only failing battery statistic on every seed is autocorr_log_10yr (deviation 0.076-0.130 vs the 0.07 tolerance); every other battery statistic passes. Geometry: the pairs view passes 5/5, the runs view (the persistence guard) passes 3/5, with seeds 0 and 4 clipping c2st_auc <= 0.54 at 0.5421 and 0.5467. The protocol mechanics (split, refit-per-seed, both locked views, panel_scorecard scoring, battery vs the committed battery_reference, seed-level conjunction, the reproduction precheck) are imported byte-for-byte from the baseline runner; only the model differs. The run used a dedicated venv (Python 3.14, scikit-learn 1.8, quantile-forest 1.4.2) because populace-fit pins scikit-learn < 1.9 (populace #318). The seed-0 reproduction test reruns Stages 0-3 and matches every stored geometry score, battery value, lambda, and perm-share diagnostic to float precision. Adds scripts/run_gate1_candidate2.py, runs/gate1_qrf_latent_perm_v1.json, and tests/test_gate1_qrf_candidate2.py. Registration: #42. Baseline: #40. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 5, 2026
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
The fifth pre-registered gate-1 run, and the first non-generative candidate: deterministic donor matching + age-indexed whole-career splicing, implemented literally from the frozen candidate-5a registration (issue #42 comment 4891949761). One shot on the locked gate; publishes the failure exactly as computed. VERDICT: gate_1_pass=False (geometry 0/5, battery 0/5). Geometry fails only on c2st_auc, on both locked views, all five seeds (pairs 0.590-0.612 vs 0.53; runs 0.605-0.628 vs 0.54); every other geometry metric passes. Battery fails 5/5 on mobility_diagonal (0.665 vs 0.604+/-0.05), exit_rate (0.227 vs 0.299+/-0.05) and its identity zero_persistence, 4/5 on mean_spell_length, and partially on the autocorr ladder overshoot; entry_rate passes. Realized ladder 0.779/0.704/0.616 (2/4/10yr) -- the closest long-horizon autocorrelation of any candidate, but over all three bands. Deterministic: no RNG, no model fit, no populace-fit; runs under the repo .venv. The gate seed enters only through the person-disjoint 0.2 split. The protocol machinery (filter-first load, split, two locked views, panel_scorecard, battery vs committed battery_reference with locked definitions, thresholds from gates.yaml at runtime, seed-level >=4/5 conjunction on both blocks, battery-reference bit-exact precheck) is imported byte-for-byte from the merged baseline runner (#40). To let that machinery import under .venv, the baseline's populace.fit import is made lazy (moved into the two fit functions); no gated logic changes and the baseline run path is unchanged under .venv-gate. Adds scripts/run_gate1_candidate5a.py, runs/gate1_splice_v1.json (same schema; spec_registration = the candidate-5a comment URL; reported-not- gated diagnostics: age-window widening distribution, nearest-age fallback rate, scaling-clip rate, donor reuse distribution), and tests/test_gate1_qrf_candidate5a.py (seed-0 reproduction without a populace-fit gate, determinism / panel-pin / anchor / nearest-age-tie tests, and always-runnable internal-consistency tests). All prior tests stay green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
The fifth pre-registered gate-1 run, and the first non-generative candidate: deterministic donor matching + age-indexed whole-career splicing, implemented literally from the frozen candidate-5a registration (issue #42 comment 4891949761). One shot on the locked gate; publishes the failure exactly as computed. VERDICT: gate_1_pass=False (geometry 0/5, battery 0/5). Geometry fails only on c2st_auc, on both locked views, all five seeds (pairs 0.590-0.612 vs 0.53; runs 0.605-0.628 vs 0.54); every other geometry metric passes. Battery fails 5/5 on mobility_diagonal (0.665 vs 0.604+/-0.05), exit_rate (0.227 vs 0.299+/-0.05) and its identity zero_persistence, 4/5 on mean_spell_length, and partially on the autocorr ladder overshoot; entry_rate passes. Realized ladder 0.779/0.704/0.616 (2/4/10yr) -- the closest long-horizon autocorrelation of any candidate, but over all three bands. Deterministic: no RNG, no model fit, no populace-fit; runs under the repo .venv. The gate seed enters only through the person-disjoint 0.2 split. The protocol machinery (filter-first load, split, two locked views, panel_scorecard, battery vs committed battery_reference with locked definitions, thresholds from gates.yaml at runtime, seed-level >=4/5 conjunction on both blocks, battery-reference bit-exact precheck) is imported byte-for-byte from the merged baseline runner (#40). To let that machinery import under .venv, the baseline's populace.fit import is made lazy (moved into the two fit functions); no gated logic changes and the baseline run path is unchanged under .venv-gate. Adds scripts/run_gate1_candidate5a.py, runs/gate1_splice_v1.json (same schema; spec_registration = the candidate-5a comment URL; reported-not- gated diagnostics: age-window widening distribution, nearest-age fallback rate, scaling-clip rate, donor reuse distribution), and tests/test_gate1_qrf_candidate5a.py (seed-0 reproduction without a populace-fit gate, determinism / panel-pin / anchor / nearest-age-tie tests, and always-runnable internal-consistency tests). All prior tests stay green. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
The sixth pre-registered gate-1 run. Candidate 5a' (segment splicing) is registered, frozen before the run, in issue #42's candidate-5a' comment; every rule -- segmentation, boundary, period-indexed match, fallback cascade, per-segment scaling -- is pinned there and implemented literally. One shot on the locked gate. Verdict: FAIL (gate_1_pass=false). Geometry passes 0/5 seeds, battery passes 5/5. This is the first candidate to clear the battery: segments from multiple donors, spliced by calendar period and level-adjusted per segment at each boundary, pull every locked battery statistic (all three autocorrelation rungs, mobility, exit, mean spell, entry, zero persistence) inside its band on every seed -- the block the single-donor 5a (#50) failed 0/5. Geometry still fails, but the failure is isolated to the omnibus C2ST on both views (pairs 0.547 > 0.53; runs 0.567 > 0.54, seed means); energy distance, PRDC coverage, and the whole tail block pass 5/5. The spliced panel is closer to the held-out data than any prior candidate, but the classifier still separates it. Protocol machinery -- filter-first load, person-disjoint 0.2 split per seed, both locked views, panel_scorecard, battery vs the committed battery_reference with locked definitions, gates.yaml thresholds at runtime, the >=4/5 seed-level conjunction, and the battery-reference bit-exact precheck -- is imported byte-for-byte from the baseline runner (#40), identical to every prior run. The battery reference reproduced exactly to float precision before scoring. Only the generation (segmentation + period-indexed splicing) is local, and it is fully deterministic: no RNG, no model fit, no populace-fit; the gate seed enters only through the split. Runs in the repo .venv. Reported-not-gated splice diagnostics (in the artifact, ~41,600 segments across five seeds): segments/person mean 1.86; segment-length mean 2.52; age-window widening 0 on every seed; segment shortening 0 (0 unmatched one-period segments); scaling-clip rate 0.00012 over segments; distinct donors/person mean 1.44 (max 4), up to 35 holdouts per donor; boundary match error p50 = 0.0 on every seed. Deliverables: - scripts/run_gate1_candidate5a2.py -- deterministic runner; the registered rules exactly; protocol machinery imported from #40. - runs/gate1_splice_v2.json -- schema gate1_splice.v2; spec_registration = the candidate-5a' comment URL; the diagnostics above and the bit-exact battery_reference_reproduction. - tests/test_gate1_qrf_candidate5a2.py -- seed-0 reproduction (PSID skipif, no populace-fit gate), synthetic-pool tests for segmentation / boundary / scaling-clip / the widen-then-shorten cascade / donor-zero copying, and always-runnable internal-consistency tests against the committed artifact and locked gates.yaml. Full suite green in the repo .venv (189 passed, 4 skipped -- the skips are the prior candidates' populace-fit reproduction tests). ruff clean; black -l 79 clean. Refs #42, #40, #43, #44, #48, #50. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
The sixth pre-registered gate-1 run. Candidate 5a' (segment splicing) is registered, frozen before the run, in issue #42's candidate-5a' comment; every rule -- segmentation, boundary, period-indexed match, fallback cascade, per-segment scaling -- is pinned there and implemented literally. One shot on the locked gate. Verdict: FAIL (gate_1_pass=false). Geometry passes 0/5 seeds, battery passes 5/5. This is the first candidate to clear the battery: segments from multiple donors, spliced by calendar period and level-adjusted per segment at each boundary, pull every locked battery statistic (all three autocorrelation rungs, mobility, exit, mean spell, entry, zero persistence) inside its band on every seed -- the block the single-donor 5a (#50) failed 0/5. Geometry still fails, but the failure is isolated to the omnibus C2ST on both views (pairs 0.547 > 0.53; runs 0.567 > 0.54, seed means); energy distance, PRDC coverage, and the whole tail block pass 5/5. The spliced panel is closer to the held-out data than any prior candidate, but the classifier still separates it. Protocol machinery -- filter-first load, person-disjoint 0.2 split per seed, both locked views, panel_scorecard, battery vs the committed battery_reference with locked definitions, gates.yaml thresholds at runtime, the >=4/5 seed-level conjunction, and the battery-reference bit-exact precheck -- is imported byte-for-byte from the baseline runner (#40), identical to every prior run. The battery reference reproduced exactly to float precision before scoring. Only the generation (segmentation + period-indexed splicing) is local, and it is fully deterministic: no RNG, no model fit, no populace-fit; the gate seed enters only through the split. Runs in the repo .venv. Reported-not-gated splice diagnostics (in the artifact, ~41,600 segments across five seeds): segments/person mean 1.86; segment-length mean 2.52; age-window widening 0 on every seed; segment shortening 0 (0 unmatched one-period segments); scaling-clip rate 0.00012 over segments; distinct donors/person mean 1.44 (max 4), up to 35 holdouts per donor; boundary match error p50 = 0.0 on every seed. Deliverables: - scripts/run_gate1_candidate5a2.py -- deterministic runner; the registered rules exactly; protocol machinery imported from #40. - runs/gate1_splice_v2.json -- schema gate1_splice.v2; spec_registration = the candidate-5a' comment URL; the diagnostics above and the bit-exact battery_reference_reproduction. - tests/test_gate1_qrf_candidate5a2.py -- seed-0 reproduction (PSID skipif, no populace-fit gate), synthetic-pool tests for segmentation / boundary / scaling-clip / the widen-then-shorten cascade / donor-zero copying, and always-runnable internal-consistency tests against the committed artifact and locked gates.yaml. Full suite green in the repo .venv (189 passed, 4 skipped -- the skips are the prior candidates' populace-fit reproduction tests). ruff clean; black -l 79 clean. Refs #42, #40, #43, #44, #48, #50. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 6, 2026
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
…locks) (#55) The ninth pre-registered gate-1 run. Replaces candidate 6's discretized rank kernel with continuous empirical conditional draws and deepens the conditioning memory: a k-nearest-neighbor conditional rank bootstrap over train transition records, matched on the next two generated-or-real ranks (v1, v2) and the person's continuous anchor rank a. Frozen spec registered before the run in issue #42 (issuecomment-4896132094); implemented literally, no tuning. Mechanics (all constants fixed a priori at registration): - Rank machinery (cells, Qhat_pos/rhat, continuous anchor rank u_A) reused byte-for-byte from candidate 5b; protocol machinery imported from the baseline runner; participation gate is candidate 2's backward regime gate. - Donor pools per seed from train positives: pairs (u_prev, u_next) -- candidate 6's kernel pairs, verified bit-identical (64,603 seed 0) -- triples (u_prev, u_next, u_next2) where the next-later observed period is also positive, and re-entry pairs (candidate 6's, 4,994 seed 0). Records pinned in a stable (person_id, period) order fixing the k-NN tie-break. - Conditional draw: triples when v2 exists else pairs; distance |u_next - v1| + 0.5|u_next2 - v2| (triples) + 0.25|u_A - a|; k=25 nearest; one record drawn with probability proportional to its weight; generated u_prev is that record's u_prev exactly (no binning/smoothing/jitter). Earnings = Qhat_pos of the target cell at u_prev. Zero crossings use the re-entry pool matched on |u_A - a| alone. Verdict: gate_1_pass = False (geometry 2/5, battery 2/5; needs >=4/5 both). The deepened memory is a real improvement over candidate 6 (which failed 0/5 both) but does not clear the conjunction. - Geometry: the only failing metric is the runs-view (window-3) c2st_auc, failing seeds 0/2/4 (0.548/0.546/0.549 vs 0.54) and passing 1/3 (0.539/0.532). The pairs-view c2st passes on all five seeds (0.516-0.529 <= 0.53); every other geometry threshold passes everywhere. - Battery: the only failing metric is the 10-year autocorrelation, failing seeds 2/3/4 (0.445/0.442/0.465; deviations 0.094/0.097/0.074 vs tolerance 0.07) and passing 0/1 (0.470/0.473). This is the registered risk: two-step-plus-anchor memory does not carry the full permanent share on 3/5 seeds. Every other battery tolerance passes on all five seeds. Determinism: battery_reference reproduces bit-exact before scoring; the live seed-0 reproduction test passes in the gate venv; the run reproduces from the seeds alone. Reported-not-gated diagnostics per the registration (neighbor distances, triple/pair share, donor reuse, drawn corner mass by anchor quintile, clamped share) are carried in the artifact. Deliverables on this branch: scripts/run_gate1_candidate7.py, runs/gate1_rank_knn_v1.json (schema gate1_rank_knn.v1, spec_registration = the candidate-7 comment), tests/test_gate1_qrf_candidate7.py. Full pytest green (249 passed, 7 skipped); ruff clean; black -l 79 clean. Refs issue #42, forensics #54, and the eight prior run PRs (#40, #43, #44, #48, #50, #51, #52, #53). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
…pace (#56) * Gate-1 candidate 7: k-NN conditional rank bootstrap (fails 2/5 both blocks) The ninth pre-registered gate-1 run. Replaces candidate 6's discretized rank kernel with continuous empirical conditional draws and deepens the conditioning memory: a k-nearest-neighbor conditional rank bootstrap over train transition records, matched on the next two generated-or-real ranks (v1, v2) and the person's continuous anchor rank a. Frozen spec registered before the run in issue #42 (issuecomment-4896132094); implemented literally, no tuning. Mechanics (all constants fixed a priori at registration): - Rank machinery (cells, Qhat_pos/rhat, continuous anchor rank u_A) reused byte-for-byte from candidate 5b; protocol machinery imported from the baseline runner; participation gate is candidate 2's backward regime gate. - Donor pools per seed from train positives: pairs (u_prev, u_next) -- candidate 6's kernel pairs, verified bit-identical (64,603 seed 0) -- triples (u_prev, u_next, u_next2) where the next-later observed period is also positive, and re-entry pairs (candidate 6's, 4,994 seed 0). Records pinned in a stable (person_id, period) order fixing the k-NN tie-break. - Conditional draw: triples when v2 exists else pairs; distance |u_next - v1| + 0.5|u_next2 - v2| (triples) + 0.25|u_A - a|; k=25 nearest; one record drawn with probability proportional to its weight; generated u_prev is that record's u_prev exactly (no binning/smoothing/jitter). Earnings = Qhat_pos of the target cell at u_prev. Zero crossings use the re-entry pool matched on |u_A - a| alone. Verdict: gate_1_pass = False (geometry 2/5, battery 2/5; needs >=4/5 both). The deepened memory is a real improvement over candidate 6 (which failed 0/5 both) but does not clear the conjunction. - Geometry: the only failing metric is the runs-view (window-3) c2st_auc, failing seeds 0/2/4 (0.548/0.546/0.549 vs 0.54) and passing 1/3 (0.539/0.532). The pairs-view c2st passes on all five seeds (0.516-0.529 <= 0.53); every other geometry threshold passes everywhere. - Battery: the only failing metric is the 10-year autocorrelation, failing seeds 2/3/4 (0.445/0.442/0.465; deviations 0.094/0.097/0.074 vs tolerance 0.07) and passing 0/1 (0.470/0.473). This is the registered risk: two-step-plus-anchor memory does not carry the full permanent share on 3/5 seeds. Every other battery tolerance passes on all five seeds. Determinism: battery_reference reproduces bit-exact before scoring; the live seed-0 reproduction test passes in the gate venv; the run reproduces from the seeds alone. Reported-not-gated diagnostics per the registration (neighbor distances, triple/pair share, donor reuse, drawn corner mass by anchor quintile, clamped share) are carried in the artifact. Deliverables on this branch: scripts/run_gate1_candidate7.py, runs/gate1_rank_knn_v1.json (schema gate1_rank_knn.v1, spec_registration = the candidate-7 comment), tests/test_gate1_qrf_candidate7.py. Full pytest green (249 passed, 7 skipped); ruff clean; black -l 79 clean. Refs issue #42, forensics #54, and the eight prior run PRs (#40, #43, #44, #48, #50, #51, #52, #53). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Downstream relevance of candidate 7: what the classifier residual costs in benefit space REPORTED, NOT GATED. Reads no gate, changes no gate. Translates the candidate-7 population-view classifier residual into the downstream benefit-magnitude space a Social Security analysis consumes, as evidence for whether a FUTURE public gate amendment (which would need its own referee round) is warranted. gates.yaml and every committed gate artifact are untouched. The functional is a STATUTE-SHAPED PROXY, not the full 42 USC 415(b) AIME: the filtered panel's careers are partial (biennial PSID, prime age 25-59, 1998-2022), so a faithful highest-35 AIME cannot be formed. The proxy caps each positive-earnings year at its wage base, indexes to 2022 by the NAWI ratio, averages the top min(10, n_pos) indexed years over (count * 12 * 2), and runs the result through the exact 2022-eligibility 415(a)/415(g) PIA formula. It is monotone in lifetime earnings; the constant scale cancels in every real-vs-candidate comparison. Every artifact and doc says so. Per gate seed 0-4, candidate 7 is regenerated deterministically over the holdout via the merged candidate-7 machinery (filter-first load, locked person-disjoint 0.2 split, train marginals/donor pools/participation gate, backward k-NN chain) -- reproducing the committed candidate-7 artifact's seed-0 diagnostics to float precision, so the histories pushed through the proxy are exactly the ones the gate scored. Both real holdout and candidate (same persons, same rows, only earnings differ; anchor held real) go through the proxy, weighted by each person's anchor-period weight. Gaps are anchored to a real-vs-real noise floor at the same scale: the ctx20 construction (fraction=0.4 seed=1000+s, then fraction=0.5 seed=s) on the seed's TRAIN split. Findings (pooled over 5 seeds; candidate-vs-real / real-vs-real noise): - Overall shape holds: KS 0.025 (within the 0.028 noise floor); mean gap +1.85% and median +1.02% (above the tight sub-0.5% real-vs-real floor but well inside the paper's +/-5% AIME-percentile criterion). - Deciles d2-d9 within +/-5% (mostly under 2%); the bottom decile d1 is +32.6% vs a +4.1% noise floor -- a near-zero-denominator artifact (bottom PIA-proxy ~$290-500/mo, so ~$80-145 absolute gaps read as huge percents), not a wholesale divergence. - Person-level (a bootstrap, not a predictor): weighted MAE $315/mo, RMSE $493/mo; only 26.8% of persons within 5% and 40.8% within 10% of their real PIA-proxy. It matches the distribution, not who-is-where. - Concentration: the residual sits in the zero-anchor group (Q0: mean +9.3%, median +22.9%, KS 0.097, 4.9% within 5%) -- the low/no-attachment workers the k-NN bootstrap conditions weakest and whom the progressive PIA formula weights most. Positive-earner quintiles Q1-Q4 are within a couple percent. Deliverables: - scripts/build_downstream_relevance.py: deterministic; the pinned functional; oracle parameters loaded once with the pe-us revision (bf71be3b) recorded. - runs/downstream_relevance_c7_v1.json: per-seed + pooled measurements, the noise-anchor rows, the pe-us revision, the candidate-7 artifact sha256 reference, reported_not_gated=true and a one-line purpose. - tests/test_downstream_relevance.py: always-runnable internal-consistency (gaps recompute from stored per-side statistics; schema; weighted-stat helpers) + a seed-0 reproduction pin (skipif PSID, importorskip populace.fit) that passes live in the gate venv. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Jul 6, 2026
…cks) (#58) The tenth pre-registered gate-1 run, and the last planned candidate iteration before the governance track resolves. Candidate 7's k-NN conditional rank bootstrap VERBATIM with exactly two registered substitutions, both conditioning refinements with no new tuned constant. Frozen spec registered before the run in issue #42 (issuecomment-4897723604); implemented literally, no tuning. Substitution 1 (long memory): every train donor record carries u_w = Phi(what / sigma_hat_w), the donor person's correlated-noise-shrunk permanent rank from candidate 3's stage-1 decomposition APPLIED TO THE Z-PANEL (z = Phi^-1(rank) of positive observations; the same rank map that forms u_prev/u_next). The k-NN third term becomes |u_w(donor) - u_A(target)| at candidate 7's 0.25 weight, upgrading the donor side from a single noisy anchor draw to the shrunk full-career permanent estimate. The target side keeps u_A. Substitution 2 (attachment-aware zero conditioning): for zero-anchor holdout persons (u_A = p0/2 identically) every k-NN distance replaces the third term with |d age|/40 + |d n_observed_periods|/13 (scales pinned as the range widths -- age over the 25-59 filter, the observed-period count over the 13 biennial reference years -- not tuned), and the donor pool is restricted to train records whose person's own anchor earnings are zero. Everything else -- donor pools, k=25, the 1/0.5 lag weights, the weighted single-record draw, no smoothing/jitter, the re-entry pools, the regime gate, the rank machinery, the gap rule, the substream seeding -- is byte-identical to candidate 7. Protocol machinery imported from the baseline runner (PR #40); rank machinery / participation gate from candidate 5b (PR #52); the k-NN draw and anchor quintiles from candidate 7 (PR #55); the u_w decomposition from candidate 3 (PR #44); the reported benefit-space functional from PR #56. Scored under the CURRENT locked gate; the artifact additionally REPORTS the proposed benefit-space block (PIA-proxy gaps incl. Q0) so this run carries evidence for both standards. VERDICT: gate_1_pass = False (geometry 0/5, battery 0/5). Substitution 1 overshot persistence rather than repairing it. Candidate 7 undershot the 10-year autocorrelation (mean 0.459, band 0.539 +/- 0.07); candidate 8 overshoots it (mean 0.670) and now overshoots ALL THREE autocorrelation lags -- 2yr 0.791 (dev 0.053-0.071), 4yr 0.733 (dev 0.066-0.085), 10yr 0.670 (dev 0.110-0.145) -- so the battery fails 5/5. Mobility diagonal (0.61, within 0.05) still passes. Geometry fails 5/5: the runs-view c2st (mean 0.5495) misses 0.54 on every seed; pairs-view c2st (mean 0.5307) clears 0.53 on seeds 2-4 only. The Q0 fix did not work. The zero-anchor subgroup's PIA-proxy overstatement did not shrink -- Q0 mean gap +12.2% (candidate 7 +9.3%), Q0 median +24.0% (c7 +22.9%), Q0 KS 0.092 (c7 0.097). Overall benefit space also degraded: the persistence overshoot flipped the pooled mean gap to -2.1% (c7 +1.85%) and worsened the KS to 0.040 (c7 0.025). Reported-not-gated per seed: the u_w decomposition (rho 0.74-0.78, sigma_hat_w ~0.72, permanent share ~0.55; u_w spans [0.002, 1.0], median ~0.45), the Q0 pool sizes (~6,400 pairs / ~4,400 triples / ~2,950 re-entry; Q0 draws ~11-14% of positive draws), the neighbor-distance distribution, usage shares, corner masses, and the full PIA-proxy benefit-space block. Runner deterministic; seed-0 reproduction test run live in .venv-gate (matches the committed artifact to float precision). Full pytest green in the repo .venv (281 passed, 12 skipped). Battery-reference reproduced to float precision before scoring. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Verdict: gate-1 FAILS
The first pre-registered model run of populace-dynamics. Scores the locked baseline earnings process — populace-fit's regime-gated chained weighted QRF, run as a one-step backward biennial backcast — against the gate-1 thresholds locked in
gates.yaml(ratified in #33 / #39, commiteaa7c47). The protocol is read fromgates.yamlat runtime and implemented literally: no threshold is hardcoded and no model choice is tuned against holdout scores.Geometry passes 0/5 seeds; the battery passes 0/5 seeds (gate rule: ≥4/5 on each). This is the scientifically expected outcome for a one-step chained baseline — the naive Markov backcast cannot reproduce the real earnings process's long-horizon persistence, exactly the failure mode the lock's own prose predicts for a chained model.
Per-seed conjunction
What fails (every seed)
The pairs view (window-2) passes all six locked thresholds on all five seeds — as the lock notes, a chained one-step candidate matches the pairs view by construction. The failures are concentrated exactly where persistence understatement shows:
c2st_auc(locked ≤ 0.54)autocorr_log_4yr(ref 0.657 ± 0.06)autocorr_log_10yr(ref 0.539 ± 0.07)c2st_auc: 0.553–0.566 vs the locked ≤ 0.54. The window-3 view sees the two-consecutive-transition persistence understatement that the window-2 pairs view cannot.autocorr_log_4yr(2 chained steps): 0.557–0.591 vs reference 0.657, tolerance 0.06.autocorr_log_10yr(5 chained steps): 0.309–0.368 vs reference 0.539, tolerance 0.07 — the chain decays autocorrelation far faster than the real process.Everything else passes on all seeds: pairs-view geometry (c2st ≤ 0.520, coverage ≥ 0.949, energy, both tail-ratio bands, w1/sd), the 2-year autocorrelation, the mobility diagonal, zero persistence, entry/exit rates, and mean spell length.
Battery-reference reproduction (pre-flight)
All eight committed
battery_referencevalues inruns/noise_floor_psid_family_9822.jsonreproduce to float precision on the full filtered panel (126,867 person-periods, 22,300 persons), proving the battery code path matches the committed definitions before any candidate is scored:0.730123510230560/0.657166897978905/0.5388794272193180.604051920570276(6 diagonal cells: five weighted quintile bins + zero bin)Baseline design (fixed by the feature author, implemented as stated)
populace.fit.qrf.RegimeGatedQRFat DEFAULT hyperparameters (100 trees,zero_atol=1e-6,max_samples_leaf=None), plain-table front door (explicit weight column), seeded from the gate seeds.t-2, predictors = (earnings att, age att-2),sample_weight= the pair's earlier (t-2) weight; fit on the 80% complement's adjacent 2-year pairs. The target is zero-inflated positive; the regime gate handles the zeros.Protocol
Filter first (age 25–59, reference years 1998–2022, positive weights), then per seed 0–4
split_panel_by_person(panel, "person_id", fraction=0.2, seed=s)— the drawn 20% is the holdout, the complement trains a fresh model. Geometry viapanel_scorecard(candidate, holdout, view, seed=s)on both locked views (psid_family_earnings_pairswindow-2,psid_family_earnings_runswindow-3); battery on the candidate panel vs the committed reference. Seed-level conjunction exactly as locked.Deliverables
scripts/run_gate1_baseline.py— deterministic runner (fit, generation, scoring, artifact write).runs/gate1_qrf_baseline_v1.json— evidence artifact: per-seed per-view geometry scores vs locked thresholds with per-metric pass/fail, per-seed battery values vs references/tolerances with pass/fail, the seed-conjunction table, the gate verdict, model description, revision pins (populace-dynamicseaa7c47, populace2c93936, schemagate1_qrf_baseline.v1), and per-seed n_persons/n_windows.tests/test_gate1_qrf_baseline.py— a seed-0 reproduction test (skipif PSID absent) pinning the artifact to float precision (1e-12), and always-runnable internal-consistency tests that recompute every reported pass/fail from its own stored score vs stored threshold, check stored thresholds againstgates.yaml, and recompute the verdict from the seed table.Determinism & CI
black -l 79andruff checkclean repo-wide. In a CI-exact environment (pip install -e ".[dev]", no PSID data / no external engine), the full suite is 97 passed, 24 skipped, 0 failed — the reproduction test and other data-gated tests skip, and the always-runnable consistency tests pass.Locked gate: #33 (lock) / #39 (ratification flip). Draft — do not merge.
🤖 Generated with Claude Code