Skip to content

M6 engine: wave-loop composition per verified design (build only)#173

Merged
MaxGhenis merged 6 commits into
masterfrom
m6-engine
Jul 13, 2026
Merged

M6 engine: wave-loop composition per verified design (build only)#173
MaxGhenis merged 6 commits into
masterfrom
m6-engine

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Status: build complete — design blockers resolved

This remains a build-only draft. The forward-earnings blockers are resolved by design amendments #175 (§2.7) and #178 (§2.7.6), and this branch now implements the pinned law with no remaining stochastic-law choices.

No M6 temporal-holdout scored run was executed. The branch does not change gates.yaml, create or modify a runs/ artifact, or modify a frozen file under src/populace_dynamics/models/.

Forward earnings implementation

  • Fits the biennial forward conditional-rank chain on pooled positive-weight PSID rows aged 25–64 and dated no later than 2014.
  • Uses the pinned eight five-year age bins, pooled NAWI-normalized CellMarginal grids, and the exact fit-population inverse for re-ranking carried generated levels.
  • Projects I_proj with ln(NAWI) ~ year over 2005–2014 only; the scored path never reads the frame's realized post-2014 nawi column.
  • Implements deterministic odd-year carry and even-year participation/donor/re-entry draws using seed_from_generator and SeedSequence([seed, code]) substreams 1/2/3.
  • Carries gen_earn_w2 and gen_earn_w4 through the frame, giving the 2016 pair ramp, the full 2018 triple memory, and continued biennial memory thereafter.
  • Makes the refitted generator the bundle default while preserving the explicit external CertifiedEngineInputs.earnings override.

Module map

Module Responsibility
engine/forward_earnings.py Leakage-safe ≤2014 fit, projected wage index, normalized age marginals, forward donor pools, rank↔level law, parity branch, and generated-lag conditioning
engine/refit.py Single-cutoff refits, forward-earnings bundle/provenance, immutable registry hashes, interview-calendar filtering, and external-vintage checks
engine/assembly.py Fitted-object assembly, default/override earnings binding, initial earnings-state materialization, and cross-step state injection
engine/loop.py Ordered annual steps 1–8, initialized period-zero frame, stable person ordinals, and projection-wide synthetic IDs
engine/steps.py Mortality, aging/calendar rollover, fertility/roster, earnings application and lag rotation, and claiming adapters
engine/rng.py Draw/period/module/person RNG registry and the generator-to-seed bridge
engine/marital.py Candidate-16 injected-generator port, authoritative marital state, gate-2c modifier view, and maternal births
engine/composition.py Candidate-9 injected-state port and full-channel synthetic re-certification check
engine/disability.py M4 realized-support reproduction with injected period generators, fixed weights, and DI conversion
engine/support.py Fixed realized-2014 weights, symmetric gated presence conditioning, and separate forward-support mode
engine/__init__.py Public engine surface, including ForwardEarningsGenerator and fit_forward_earnings

Validation

  • Forward-earnings synthetic unit tests: 12 passed.
  • Full M6 engine synthetic suite: 63 passed.
  • Full always-runnable suite: 1,774 passed, 41 skipped, 956 deselected (43 pre-existing sklearn convergence warnings).
  • Full collection: 2,771 tests — unit 330, artifact 965, integration_psid 800, reproduction_legacy 520, oracle_policyengine 156.
  • Tier-policy full-collection check: 1 passed, 2,770 deselected.
  • Repo-wide Black (-l 79) and Ruff: clean.
  • gates.yaml has no branch delta from current origin/master; the newly ratified locked gate_m6 block is inherited unchanged from master.

The earlier candidate-9 injected-state re-certification remains green at the pre-named 3-sigma margin. No threshold was loosened and no M6 gate cell was scored against holdout truth.

Compose the verified annual loop, injected marital and household state, cutoff refits, fixed-weight support, and reproduction-mode disability coverage.

Co-Authored-By: Codex gpt-5.6-sol <noreply@openai.com>
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
social-security-model Ready Ready Preview, Comment Jul 13, 2026 8:24pm

Request Review

Resolve the tier manifest against the amendment-2 test additions and recount the full merged suite.

Co-Authored-By: Codex gpt-5.6-sol <noreply@openai.com>
MaxGhenis added a commit that referenced this pull request Jul 13, 2026
Address the design-referee round on #175 (comment 4959673982, MAJOR
REVISION); the forward law itself was verified code-true, the fixes are
contract/record restatements:

- finding 1 (seam contract): respec §2.7.4/§2.7.5 to PR #173's real
  EarningsGenerator.generate(frame, year, rng) -> np.ndarray seam
  (origin/m6-engine steps.py:164-169) -- per-year, called by apply_earnings
  every projection year, stateful THROUGH the frame. Name the frame columns
  read, the even/odd parity branch (biennial draw on even reference years,
  deterministic fill on odd), and the drawn-prior-2016-rank threading (recovered
  inside generate by re-ranking the carried earnings column, which
  _merge_period_columns threads forward). The forward per-year seam has no
  lookahead, so §2.7.2 annualization is corrected to a carry-forward default
  (log-linear interpolation only via batch-compute + backfill), which resolves
  the revision-1 interp-vs-carry flag; still non-scored (isolation unchanged).
- finding 2 (block draft): update docs/design/gate_m6_block_draft.yaml -- covers
  and not_certified.forward_earnings_law_not_gate1_certified now record that a
  gate_m6 PASS first-certifies the §2.7 forward law (gate_1 does NOT cover it; no
  certificate transfers), including its structural spec-selection distinct from
  the surface selection; design_pr 170->175 and design_commit re-pinned off the
  stale 1d83a22 (note added; the hash is set to this PR's design commit).
- finding 3 (u_w provenance): u_w = Phi(w-hat/sigma-hat_w) is candidate-8's
  construct (PR #58) built on candidate-3's Stage-1c decomposition; cited that
  way in §2.7 and the §10 ledger.

Docs-only; no gates.yaml edit, no floor, no test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Jul 13, 2026
…175)

* M6 design amendment: forward earnings generator spec (unblocks #173)

Add §2.7 to docs/design/m6_projection_engine.md specifying the forward
earnings generator the engine build (Sol, PR #173) correctly left external.
The certified gate-1 candidate-11 chain is a BACKWARD biennial imputation
(anchors the latest real earnings, predicts t-2 participation from later
earnings, draws earlier ranks conditional on later ranks) and cannot be
composed into the M6 forward loop without a new stochastic law.

§2.7 specifies that law:

- a biennial forward conditional-rank chain 2014->2016->2018 (scored on the
  {2016,2018} cells of §4.1), mirroring the certified conditioning structure
  reversed in time and fit <=2014 from scratch -- not an inversion of the
  backward conditional, no annual kernel for any gated cell, no marginal
  extrapolation (retiring Sol's three refused choices);
- transfers k=25, distance weights 1/0.5/0.25, lambda=0.1 (Q0-exempt), the
  u_w shrunk-permanent rank, the RegimeGatedQRF participation gate, and the
  zero-anchor full re-entry pool from candidate-11/10;
- newly chosen items (forward donor pools on <=2014 forward tuples, forward
  participation-gate fit, initial-2014 anchor, start-of-chain memory ramp)
  justified from <=2014 fit-window diagnostics only, candidate-blind with
  respect to the holdout (#42 comment 4948637741 spec-selection disclosure);
- non-scored annualization (participation carried from the prior biennial
  wave; positive level log-linear interpolated on the NAWI-indexed level)
  feeding only the seam / AIME / claiming, never a gated cell;
- certification framing: NOT gate_1-certified (different, forward law),
  first-certified by gate_m6; §4.2 refit enumeration + decision 10 updated;
- implementation contract for the engine lane: inputs, outputs, RNG stream
  slots under the F3 (module, period) tree, and the CertifiedEngineInputs
  seam interface.

Docs-only; no gates.yaml edit, no floor, no test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* M6 forward-earnings spec: match Sol's real seam + block-draft (rev)

Address the design-referee round on #175 (comment 4959673982, MAJOR
REVISION); the forward law itself was verified code-true, the fixes are
contract/record restatements:

- finding 1 (seam contract): respec §2.7.4/§2.7.5 to PR #173's real
  EarningsGenerator.generate(frame, year, rng) -> np.ndarray seam
  (origin/m6-engine steps.py:164-169) -- per-year, called by apply_earnings
  every projection year, stateful THROUGH the frame. Name the frame columns
  read, the even/odd parity branch (biennial draw on even reference years,
  deterministic fill on odd), and the drawn-prior-2016-rank threading (recovered
  inside generate by re-ranking the carried earnings column, which
  _merge_period_columns threads forward). The forward per-year seam has no
  lookahead, so §2.7.2 annualization is corrected to a carry-forward default
  (log-linear interpolation only via batch-compute + backfill), which resolves
  the revision-1 interp-vs-carry flag; still non-scored (isolation unchanged).
- finding 2 (block draft): update docs/design/gate_m6_block_draft.yaml -- covers
  and not_certified.forward_earnings_law_not_gate1_certified now record that a
  gate_m6 PASS first-certifies the §2.7 forward law (gate_1 does NOT cover it; no
  certificate transfers), including its structural spec-selection distinct from
  the surface selection; design_pr 170->175 and design_commit re-pinned off the
  stale 1d83a22 (note added; the hash is set to this PR's design commit).
- finding 3 (u_w provenance): u_w = Phi(w-hat/sigma-hat_w) is candidate-8's
  construct (PR #58) built on candidate-3's Stage-1c decomposition; cited that
  way in §2.7 and the §10 ledger.

Docs-only; no gates.yaml edit, no floor, no test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* M6 block-draft: pin design_commit to this PR amended-design commit

Set gate_m6_block_draft.yaml design_commit to d6abb16 (this PR design commit
carrying the §2.7 forward-earnings amendment), completing the finding-2 re-pin
off the stale 1d83a22. design_commit_note records the finalize-at-lock-flip
rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix earnings-carry mechanism attribution (verifier nit, comment 4959939799)

Earnings is written in-place by apply_earnings and threaded by the loop's
frame reassignment; _merge_period_columns threads the marital/disability/
household update-frames. Conclusion unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis and others added 4 commits July 13, 2026 12:09
# Conflicts:
#	tests/README-tiers.md
#	tests/tier_counts.json
# Conflicts:
#	tests/README-tiers.md
#	tests/tier_counts.json
Fit the pinned <=2014 forward conditional-rank chain on ages 25-64, project NAWI from the 2005-2014 OLS, and preserve generated biennial memory through frame state.

Wire the fitted generator as the refit-bundle default while retaining the explicit external earnings seam.

Co-Authored-By: Codex gpt-5.6-sol <noreply@openai.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Adversarial referee — round 4 (complete M6 engine build @ 8c9788d)

Verdict: MERGE-READY (build-only)

Every §2.7.6 pin, the §2.5–§2.6 injection contract, the §4.2 refit protocol, the §2.2 composition order, and the build-only discipline are implemented exactly as the ratified design (pin 4c6a0f6, through §2.7.6) specifies. I found no deviation from the pinned design. Independent probes (below), a mutation run of the negative test, the full always-runnable suite in a disposable env, and line-level comparison of every "transfers verbatim" claim against the certified candidate scripts all pass. Six non-blocking observations for the ceremony record close the report.

What I executed

  • Disposable env (uv venv + -e ".[dev]"), worktree at 8c9788d.
  • Full always-runnable suite: 1,774 passed / 41 skipped / 0 failed (17:51). Live tier collection matches the committed manifest exactly: unit 330 / artifact 965 / integration_psid 800 / reproduction_legacy 520 / oracle_policyengine 156 = 2,771.
  • black --check and ruff check clean on all 20 engine/test files.
  • CI fresh on 8c9788d (runs 29282219890/29282219517, 2026-07-13T20:23Z): build, lint, pytest 3.11 + 3.13 all pass; PR is draft + MERGEABLE.
  • Diff surface confirmed: src/populace_dynamics/engine/ + tests/ only. docs/, gates.yaml, and src/populace_dynamics/models/ are byte-identical to master (empty git diff origin/master...HEAD on all three). No runs/ additions, no artifact IO anywhere in engine/ (grep + the shipped filesystem-monkeypatch test), no scored run exists.

Probe results (independent of the shipped tests; 16/16 pass)

Parity branch (§2.7.2/§2.7.5). A counting np.random.Generator through generate: odd year consumes zero RNG calls; even year consumes exactly one integers draw (the seed_from_generator bridge; the three candidate-10 substreams are derived from it, never from the injected stream); even year ≤ 2014 raises.

Leakage fence (§2.7.6.3) — harder probe than the shipped poisoned-column test. I poisoned realized post-T* NAWI at every reachable surface simultaneously — post-2014 keys in the fit-time NAWI mapping (2015→1.0, 2016→77.7, 2017→1e12, 2018→3.14) and a realized nawi frame column (1.23e8) — then drove the per-person production seam 2015→2018 (odd carries, even draws, gen-lag rolls). All draw vectors are bit-identical to the clean run (353 positive scored draws compared). fit_projected_wage_index is exactly invariant to post-T* values. The shipped raising-frame test (test_scored_even_path_never_reads_frames_realized_nawi_column) also passes.

I_proj constants (§2.7.6.3). Recomputed OLS ln(NAWI) ~ year over [2005, 2014] from the real ss/params.py series: engine matches my independent normal-equations fit to <1e-10 relative — I_proj(2016) = 48,328.01, I_proj(2018) = 50,553.84, slope 0.022514. Realized NAWI_2016 = 48,642.15 differs from the projection, so a realized-value leak would be detectable, and the fence held. Perturbing 2004 and 2015 leaves the fit unchanged (window is exactly [2005, 2014]).

Memory ramp (§2.7.1/§2.7.6.5). Poisoning gen_earn_w4 and realized_earn_2012 at the 2016 call leaves the 2016 draws bit-identical (one-step-plus-anchor: pair pool; triple requires year ≥ 2018 in code). Inverse sanity: tripling gen_earn_w4 at 2018 changes 104/260 draws — the 2018 triple genuinely conditions on drawn-2016 + realized-2014, matching the pinned lag fill.

Exact-inverse re-rank (§2.7.6.4). On the fitted marginals, level_to_rank(rank_to_level(u)) round-trips with max |Δ| = 1.6e-14 across all 8 bins at both 2016 and 2018 (the de-index multiplies by projected(year) and the re-rank divides by normalization_index(year) = projected for post-T*, realized for ≤2014 — the exact inverse, and fit-consistent for realized lags). Corners are deterministic, replayable, and clamp into [0.001, 0.999]; a carried zero routes to the p0/Q0 regime without error.

Byte-determinism (§2.7.6.5). Two independent fits + runs on the same panel and streams produce bit-identical 2015–2018 draw vectors; draw k=1 vs k=0 differ (stream separation). The shipped substream-bridge byte-replay test also passes.

Re-cert negative — run mutated. (1) My own real-shift probe: a genuine +0.08 shift in legal_residual_state raises AssertionError naming the channel and "fuller re-ceremony required" (delta 0.088 > 3σ = 0.024); matched ensembles pass all 15 cells. (2) Mutation run: with check_candidate9_recertification's raise replaced by pass, the shipped test_targeted_recertification_fails_loudly_on_a_channel_shift fails ("DID NOT RAISE AssertionError") — the negative test is genuinely load-bearing. Mutation reverted; working tree clean.

Design-fidelity verification (line-level, against the certified objects)

  • Certified-transfer claims, checked one by one against run_gate1_candidate5b/7/8/10.py, run_gate1_candidate3.py (via c8's imports), run_inner_sweep.py, and run_gate1_baseline.py: _knn_draw (argpartition k+8 margin, per-row lexsort (distance, donor index) tie-break, inverse-CDF weighted single-record draw, no jitter) — verbatim; k=25, weights 1/0.5/0.25, λ=0.1 donor-side blend with target side always u_A, Q0 exempt (donor u_A, memory terms retained in transitions, anchor-only re-entry, full pool) — exactly candidate-10's _transition_draw/_reentry_draw semantics including the non-Q0-then-Q0 uniform order; gate draw = bit-for-bit the certified cumulative-proba/argmax/classes_ reconstruction, forward-mirrored (earnings_tm2/age_tm2earnings_tp2/age_tp2); zero-anchor gate = conditional refit on zero-anchor persons' pairs with shared-gate fallback when empty; anchor rank = rhat at own cell, zero → p0/2; CellMarginal/_plotting_positions/clamps = candidate-5b verbatim, re-keyed to the pinned pooled ≤2014 NAWI-normalized age_bin object; u_w = candidate-8-on-candidate-3 exactly (same GAMMA_LAGS, same 46-point RHO_GRID, same NNLS design, same shrinkage, Φ(perm/σ_w), missing → 0.5); pool formation = baseline's strict biennial adjacency, forward-ordered, with the triple's second lag on the earlier side (exact mirror) and draw-target-period weights.
  • Injection (§2.6, R1–R3). engine/composition.py is a faithful line-for-line port of base_simulator.py + simulator.py with only the two internal ft.simulate calls replaced by the injected step-3 result (consumed through the certified read-only mappers) and engine-supplied streams. Period-0 stream topology reproduces the certified tags byte-for-byte (0xB2B; 0xC2/0xC4/0xC3/0xC5 spawn children at the certified positions; 0xC6/0xC7; 0xC8 children 0/1/2 for the delta layer) — shipped test asserts it. The monkeypatch test proves the injected path never calls ft.simulate. The P2 byte-identity premise is enforced at assembly (pickle-sha256 of the embedded vs authoritative core). The margin check covers all four named channel sets — cohabitation (2 cells), legal-spouse-residual (4), occupancy (4), household-size (5) — at 3σ of the mean difference with no tolerance floor, and the shipped coverage test executes a real 20-draw injected-vs-internal ensemble across all 15 cells.
  • ≤T* refit (§4.2). Pure at the repository boundary (no path resolution, no artifact read/write, no gates.yaml consult — grep-verified and monkeypatch-tested). Conservative biennial boundary rule: flow rows require required_interview_year ≤ T*, derived from the interview calendar via next-wave searchsorted; the shipped test confirms a 2014 event dated by a 2015 interview is excluded from the fit. Spec-vs-fit: same CandidateSpec.sha256, new truncated-panel fit, provenance records certified_full_window_artifacts_read/written = False. External vintages (claiming supplement, mortality reference, SSA index params) are rejected if post-T* — the finding-11 freeze is structural.
  • Composition order + wiring (§2.2, §3.2, §4.4, §4.7). The loop runs the eight steps in the exact revised order with one authoritative MaritalStepResult consumed by both fertility and household composition; the 2c modifier composes at step 3 as the certified no-RNG marginal-preserving reweight (weighted-events view; states unmutated — tested; the certified RuntimeError guard on sum m·phi_cert = 1 is live). The marital core port is token-identical to the certified state machine (divorce-priority, snapshot semantics, gap-stream draws, entry-widowed and marriage-residual post-passes) with injected streams. Disability is the M4 reproduction port with byte-equality to the frozen simulate_draw at the same seed (shipped test) and per-(module, period) streams; F6 start-wave weights and §4.4 symmetric presence-conditioning are implemented with the forward mode structurally rejecting realized holdout inputs. RNG registry implements the §3.2 spawn tree rooted at SeedSequence([5200+k, GATE_M6_TAG]) with per-person addressability and ordinal stability under roster churn (tested).

Non-blocking observations (for the ceremony record)

  1. §2.7.6.5's fill-sentence vs the one-step pin. "2016 uses realized-2014 (w−2) + realized-2012 (w−4)" reads as lag-column contents; §2.7.1 and the summary-JSON pin (start_of_chain_memory_ramp_2014->2016_one_step) pin the 2016 law at one-step-plus-anchor. The engine follows the two explicit pins (2016 = pair pool; probe-verified w−4-invariant) and materializes realized_earn_2012 per the frame-schema pin as a never-conditioned start-lag (shipped test names it "unused NaN in the 2016 ramp"). Correct resolution; recorded here so the design text's internal tension is on the record.
  2. Marital core is distribution-identical, not byte-identical, to certified ft.simulate — forced by the design's own step-3/step-4 split (certified candidate-16 interleaves fertility draws on its main stream; §2.2 moves fertility to step 4 on its own module stream). Kernel, lookups, and state machine are the certified objects token-for-token; self-replay is tested. This is composition per the ratified order, not surgery on the estimated object.
  3. The real-data re-certification margin check over the gate seeds remains a §9 floors-ceremony deliverable. The build ships the machinery and executes it on synthetic 20-draw ensembles (all 15 cells pass); the ceremony must run it on the real panel before any scored run, per §2.6 item 4 / §9.
  4. fit_mortality_model's external-anchor decomposition algebraically cancels (ratio × central = PSID band rate), as its docstring discloses. Mortality is ungated (§4.10 not_certified), so this is report-only plumbing; the family-B SSA/NCHS anchor at the ceremony is where the external comparison gets teeth.
  5. EARNINGS_SPEC_REGISTRATION cites the candidate-11 registration (Candidate 2 design: latent-permanent conditioned chained QRF (research memo) #42 comment 4905323933 — verified it exists) as provenance for the transferred hyperparameters; the gate_m6 candidate itself must still be registered on Candidate 2 design: latent-permanent conditioned chained QRF (research memo) #42 before its one-shot scored run. Ceremony obligation, not a build defect.
  6. _gate_sign_draw prefers a draw_sign method when the fitted gate exposes one (test seam; the certified reconstruction is the fallback and is what production RegimeGatedQRF objects will hit today). If populace-fit ever grows a draw_sign, scored-run verification must confirm the deployed path is still the certified externally-driven draw.

Build-only discipline

Gate gate_m6 is locked and untouched (gates.yaml byte-identical to master). No scored run exists on the branch: no runs/ additions, no real-frame fixtures (all new tests are synthetic), no post-T* column on the scored path (pinned FRAME_COLUMNS selection + poison tests + my bit-identity probe). The scored ceremony (registration, real-data margin check, one-shot run through artifacts.write_new, independent pass verification) remains ahead and is correctly not pre-empted by this build.

Referee execution: worktree m6eref @ 8c9788d, disposable venv, probes + mutation run + full suite as described; working tree restored clean.

@MaxGhenis MaxGhenis marked this pull request as ready for review July 13, 2026 20:59
@MaxGhenis MaxGhenis merged commit 95a3e05 into master Jul 13, 2026
7 checks passed
MaxGhenis added a commit that referenced this pull request Jul 13, 2026
…e tier_counts.json)

origin/master advanced to 95a3e05 (PR #173, "M6 engine: wave-loop composition",
build-only) after the fixes-round-1 verification at 60f6ee5, creating a
tier_counts.json conflict (both branches edited the manifest).

Non-overlapping reconciliation:
- master changed unit 267 -> 330 (+63 M6 engine tests; artifact untouched)
- this branch changed artifact 965 -> 991 (+26 amendment-3 tests; unit untouched)
- merged manifest: unit 330, artifact 991 (other tiers unchanged)

Verified in the disposable env: per-tier collection unit 330 / artifact 991 /
integration_psid 800 / reproduction_legacy 520 / oracle_policyengine 156 (2797
total); always-runnable suite (unit or artifact) 1280 passed / 41 skipped / 0
failed, including test_tier_policy against the reconciled manifest and the new
M6 engine tests; amendment-3 module 26/26; gates.yaml byte-identical to
origin/master. The PR diff (vs the new base origin/master) remains the three
amendment-3 files only: the doc, the amendment-3 test, and tier_counts.json.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Jul 14, 2026
)

Correct §2.8.6 and the §10 preflight_2 field, which inverted the certified
earnings sign-path. They pinned pre-flight 2 to verify the draw_sign branch and
to reject the _target_models reconstruction as a "test seam" -- but today's
certified populace.fit.qrf.FittedRegimeGatedQRF exposes _target_models and no
draw_sign, so the faithful-to-spec pre-flight aborts every real run
(harness-referee finding F1, PR #185 comment 4966859161; verify_external_sign_path
raises against the real _target_models-only shape).

The corrected pin verifies the _target_models reconstruction
(forward_earnings.py:820-826, reproducing FittedRegimeGatedQRF._gate_draw on
engine-supplied uniforms -- the branch every real candidate-10 gate takes)
deploys, and rejects the draw_sign fast-path (815-819) as the test seam. This
restores the direction of engine-referee observation 6 (PR #173 comment
4962620806), which correctly labeled draw_sign the seam and the _target_models
reconstruction the certified path; the designed-abort semantics are unchanged.

Docs-only: §10 JSON revision 7 -> 8; edits no gates.yaml cell, moves no
threshold, builds no floor, writes no test.

Closes harness-referee F1.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant