Skip to content

Bridge projected earnings histories into actual Axiom AIME/PIA execution - #450

Merged
MaxGhenis merged 3 commits into
masterfrom
dynamics-axiom-benefit-bridge-20260922
Sep 23, 2026
Merged

MaxGhenis merged 3 commits into
masterfrom
dynamics-axiom-benefit-bridge-20260922

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

First integrated earnings-to-benefit chain: projected Dynamics cohort histories go through the actual Axiom rules engine to AIME (and ordinary PIA where the candidate covers the cohort). Stacked on #449.

src/populace_dynamics/axiom_benefit_bridge.py builds lifetime requests in the retained SSA Case A runner's format. It runs the pinned axiom-rules-engine run-lifetime binary (engine commit 49f2225) against pinned compiled RuleSpec artifacts and parses the typed response. It does no benefit arithmetic itself: indexing, computation-year selection, averaging and the PIA formula all run inside the engine. Every result records the engine binary, artifact and rule-module SHA-256s, request and stdout digests, and the fact that the rule candidates are unaccepted.

Calibration

SSA's published 2026 Case A and Case B, rebuilt through the bridge, produce requests and engine output byte-identical to the retained runs: Case A AIME $5,825 and PIA $2,609.80, Case B AIME $11,463. These are the same two published cases the earlier runners matched, so this adds no new benchmark.

Refusals instead of guesses

The bridge raises a refusal listing the years involved for:

  • missing history years, a missing birth year, or unpublished wage indexes;
  • amounts above the taxable maximum;
  • rows before birth;
  • an indexing year other than the year of attaining 62 minus 2, or attaining 62 before 1979 (both added in review).

Pre-projection history enters only as an explicit caller-supplied history whose synthetic flag appears on every row. Projected labor income becomes covered earnings only under an explicit caller declaration. The float-to-decimal conversion is an explicit, recorded choice, because the engine rejects exact decimal expansions of fractional floats.

Run on the r3 fixture (12 invented people)

With nothing added, all 12 are refused, with reasons recorded (missing pre-2014 and post-2022 years, unpublished future wage indexes). With explicit synthetic zero rows for pre-2014 years, the engine computes AIME for two people per entitlement scenario. These exercise the transport only; they are not estimates. Evidence: microcosm-launch-evidence/dynasim-parity-20260909/axiom-benefit-bridge-20260922/RESULTS.md.

Review

An independent Opus reviewer rebuilt the Case A/B requests outside the test suite and diffed them. It ran the real-engine integration tests, which executed rather than skipped, and fixed four defects in 8caf372f, each with a regression test: the indexing-year check, rows before birth, and two provenance and refusal gaps. Bridge tests and the birth-evidence identity tests pass, and ruff is clean.

Not included

This PR adds no COLA, claiming adjustment, eligibility, payment, survivor benefit, benefit trajectory, or DYNASIM comparison. The Axiom candidates remain unaccepted until the encoder closure runs (blocked on a protected install and Codex quota).

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits September 22, 2026 14:33
Add populace_dynamics.axiom_benefit_bridge, an opt-in transport from
retained cohort histories to the real axiom-rules-engine `run-lifetime`
binary. It builds lifetime-request/v2 requests in the retained SSA Case A
runner's format, runs the pinned engine (commit 49f2225, the binary that
reproduced Case A) as a subprocess against pinned compiled artifacts,
parses and validates the typed response, and returns per-person results
carrying provenance: engine, artifact and candidate-module SHA-256s,
request and stdout digests, selected rule versions, and the fact that the
RuleSpec candidates are unaccepted. The bridge performs no benefit
arithmetic; indexing, top-N selection, averaging and the PIA formula run
inside the engine.

The bridge refuses rather than guesses:
- every elapsed-window year through the year before entitlement must be
  supplied; gaps raise BenefitBridgeRefusal listing the years (a leading
  gap may be accepted only by an exact, recorded acknowledgement);
- pre-2014 years come only from an explicit CallerSuppliedHistory whose
  synthetic flag travels onto every row; otherwise the gap is recorded;
- projected labor income is used as creditable earnings only under an
  explicit ProjectedAmountDeclaration matching the history's unit;
- missing birth years, wage-index years, contribution-base checks, and
  mortality removal before entitlement all refuse;
- the PIA output is requested only for the candidate's 2026
  first-eligibility cohort; other people get AIME from the AIME-only
  artifact compiled from the same 415(b) module.
The engine parses decimals with rust_decimal's from_str_exact, which
rejects exact expansions of most fractional binary64 values, so the
binary64-to-decimal encoding is an explicit caller choice recorded per row.

Tests: fake-engine unit tests for request construction, refusals,
response validation, binding tampering and the subprocess path, plus
cohort tests on invented people produced by actual engine steps.
Integration tests (skipped without the engine) rebuild SSA's published
Case A and Case B requests byte-for-byte through the bridge and reproduce
AIME $5,825 / PIA $2,609.80 and AIME $11,463 with identical stdout.

Register the module in POST_REVIEW_SOURCE_EXCLUSIONS, its pinned tuple and
the reachability guard. Remove a byte-identical duplicate of
test_source_reachability_includes_implicit_package_initializers left by the
stack reconciliation (ruff F811; the second copy already shadowed the
first, so collection is unchanged). Tier manifest recollected: unit 2,246,
artifact 2,672, integration_psid 848, reproduction_legacy 520,
oracle_policyengine 159; total 6,445.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Independent review of ef53849 found four defects; each now has a
regression test.

- OrdinaryRetirementDeterminations accepted any indexing year before
  entitlement. Under the bridge's scoped assumptions (no disability, no
  death before entitlement) 42 USC 415(b)(3)(A)(ii)(I) with
  415(a)(3)(B)(i) fixes it at the year of attaining 62 minus 2. On the
  real pinned engine, INVENTED flat earnings for a 1953 birth year
  entitled in 2023 gave AIME 5,806 when indexed to 2013 and 7,835 when
  indexed to 2021, with no refusal. The constructor now refuses any
  other indexing year, an age-21 year other than birth year + 21 (or + 20
  for a January 1 birth, per the retained POMS RS 00615.015 extract), and
  attaining 62 before 1979 (415(a)(3)(A)).
- prepare_request sent rows dated before the birth year to the engine,
  where they entered the top-N selection. It now refuses them and lists
  the years under gaps["years_before_birth"].
- execute_request ran any PreparedRequest, so a hand-built or
  dataclasses.replace-d request could document rows, determinations or
  a wage index that were not in the wire next to the wire's digest. It
  now rebuilds the request from the recorded inputs and raises
  ValueError on any divergence in wire, request, outputs or artifact role.
- AIME-only results listed the 415(a) and 2026 bend-point modules in
  provenance.module_sha256, although the AIME-only program holds only
  415(b). AxiomEngineBinding gains artifact_sources; the reviewed binding
  attributes 415(a), 415(b) and the bend points to the AIME/PIA program
  and the 415(b) source alone to the AIME-only program. Bindings without
  recorded sources keep the previous list-everything behavior.

Case A and Case B requests remain byte-identical to the retained
requests, and the real-engine tests still reproduce AIME 5,825 / PIA
2,609.80 and AIME 11,463. Re-running the r3 fixture passes with this
code gave the same status, reasons, gaps, AIME, request and stdout
digests for all 60 person outcomes; only AIME-only module attribution
changed. Tier manifest: unit 2,250; total 6,449.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
social-security-model Ready Ready Preview Sep 23, 2026 12:21am UTC

Request Review

@MaxGhenis
MaxGhenis changed the base branch from land-dynamics-stack-20260922 to master September 22, 2026 22:29
Tier manifest recollected on the merged tree: unit 2,341; total 6,540.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review September 23, 2026 01:18
@MaxGhenis
MaxGhenis merged commit 6efb58b into master Sep 23, 2026
12 checks passed
@MaxGhenis
MaxGhenis deleted the dynamics-axiom-benefit-bridge-20260922 branch September 25, 2026 23:35

This branch was successfully deployed

1 active deployment
Preview — d9eddf5e Deployed Sep 23, 2026 by vercel[bot]
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