Repository navigation
Draw SPI-channel incomes at the FRS twin's conditional rank (#840) - #1256
Conversation
c392a16 to
815fc84
Compare
815fc84 to
3205a17
Compare
|
@juaristi22 review of this PR's own diff against #1200's merge ( Verdict: the method is sound and the tests really exercise it, but the committed receipts carry exact FRS source counts that need to come out before merge, and the "same formula" bridge claim does not match the code for two of the four predictors. Findings
What I checked
🤖 Generated with Claude Code |
|
Twins on the #1200 base (receipts note section R1f; shares and weighted totals, the record counts stay with the raw receipts beside the builds). Control:
Paired against their own twins, the copies earn when the twin earns (0.587 against 0.583; control 0.743) and report benefits at the twins' shares (UC 0.111 against 0.107; control 0.062). Per unit through the engine, lone parents land on their twins (screened 0.648 against 0.646, receiving 0.575 against 0.581); childless units and couples with children pass the screen 17 to 43 % more often than their twins, the tape's low-pay tail among earners (R1c), unchanged from the control. At design weights SPI Universal Credit moves from £17.9bn to £36.4bn against £35.9bn on FRS rows; SPI income tax +8.5 %. FRS rows move only through frame-level stages after stage 17: the CGT lane ( |
|
@vahid-ahmadi thank you for the close read. Addressed in 9da1fe7; item by item:
The fit kernel's parity pins are re-recorded for the new accessor. Tests: the graph, fit and targeted engine-free files and the engine-side SPI files pass locally; CI is on the PR. |
Review round on #1256 (Vahid, 13 October): - The committed receipts carry shares and weighted totals only; record counts stay with the raw receipts beside the builds (the PR body and comment follow). - The bridge wording says what the code does: main_source and has_pay from the leaf formulas on both sides, has_trade and at_or_over_spa from the tape's indicator codes (the leaves serving a composite record without codes) and the twin's trade leaf or status and age. The receipt reports the codes against the leaves both ways, and the validation test holds records whose codes disagree with their leaves. - The main-source agreement cited everywhere is the stage receipt on the full tape with the stage's preparation (0.969); the earlier figure came from an exploratory raw-column script, and the note says so. - cross_fit_transport takes the fold count the training rows used and the training rows' identities: it refuses a recipient whose fold differs from its twin's, a single fold or an empty complement unless the caller allows in-sample location (the spine passes the transform's sampled_rung, so a full build fails closed), and folds that disagree on a target's sign classes. The stage refuses a person table without person_source_id and a located target whose reference sign classes differ from the tape forest's (FittedRegimeGatedQRF.sign_classes, with its fit-package test). A positive-row count under the group floor is withheld in the stage evidence. - The manifest, the docs and the changelog note the chain-conditioning difference between the two forests (the follow-up to measure), the State Pension-only case of the no-record rule and that stacked copies share every stage-1 draw; the changelog is two sentences. - Regenerated: the source_stages mirror, the coverage manifest, the spec loader's golden hash and the fit.qrf parity pins (arm64/darwin/py3.14, the two linux keys derived). Tests: graph package 756 passed; fit QRF 37 passed; the targeted engine-free UK and shared files 1,263 passed; engine-side SPI and release-coverage files 72 passed; ci_test_plan verify, ruff and git diff --check clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@juaristi22 round 2, on Needs changes before merge: CI is red for three reasons the PR causes, one table of exact counts is still in the receipts note, and the earlier commits on the branch still carry the counts, so the branch needs rewriting. Round-1 points
New findings
What I checked
🤖 Generated with Claude Code |
|
@vahid-ahmadi round 2 addressed. The branch is rewritten: two commits on the current Round-1 residuals
New findings
One more thing the rebase surfaced and I fixed: the recipient flag was written before the stage's other new columns, so the legacy oracle and the graph disagreed on person column order (H2 parity); it is now the stage's last new column, and H2 passes. Tests on the final tree: the full engine-free, engine-uk and engine-us suites locally, plus the graph package, the fit QRF file and the targeted files; |
9da1fe7 to
8cea07f
Compare
|
@juaristi22 round 3, on Fine once the US spec-hash pin in Round-2 points
New findings
What I checked
🤖 Generated with Claude Code |
8cea07f to
c09e6f7
Compare
|
@vahid-ahmadi round 3 addressed; the branch is re-recorded as the same two commits (7ba544e the change, c09e6f7 the note), force-pushed.
Thank you for the mutation checks and the base/head bitwise comparison of the QRF draws; that is the confirmation the parity re-pins needed. |
Stage 17 (hmrc_spi_income_spine) drew every SPI-channel claimant's and partner's income leaves from the SPI tape conditioned on age, gender and region only, at the model's random numbers. The FRS twin's own incomes, and the relation between family composition and income they carry, were discarded: half the lone-parent UC mass sat on SPI copies drawn as taxpayers, SPI lone parents passed the award screen at about half the FRS rate, and SPI employment status disagreed with the drawn income (uk-data#529). Bridge predictors. The tape forest now conditions on four facts about a record's income that the tape and the twin each carry: main_source (the largest of pay, pension and trade) and has_pay from the same leaf formulas on both sides; has_trade and at_or_over_spa from the tape's published indicator codes (SEINC_NUM, SPA; the leaf formulas serve a composite record without codes) and, on the twin, its trade leaf or self-employed status and its age against State Pension age. The read requires the three code columns and refuses unknown codes by name; the published MAINSRCE code validates the leaf-defined main source (0.969 of the classified weight on the full 2022-23 tape with the stage's preparation; floor 0.95) and the receipt reports each indicator code against its leaf both ways. Twin-conditional draw. Reference forests fitted on the FRS base claimants and partners with the same predictors and chain order locate each twin's observed leaves (FittedRegimeGatedQRF.conditional_uniforms, a Rosenblatt transform: the sign uniform in the gate's cumulative class probabilities, the quantile on the sign's magnitude forest through the new _Forest.quantile_positions, the inverse of its draw), and the tape forest draws at those uniforms through predict_from_uniforms. The reference is cross-fitted in five folds keyed on the predictor cell, so the forest locating a copy never saw its twin (an in-sample forest holds the row's own value as an atom that took a median 0.23 to 0.74 of the conditional's mass under the weighted bootstrap and kept under half of the twin's rank). Leaves without an FRS analogue, and the placements inside a class or a flat stretch, take uniforms keyed on person_source_id, so stage 1 consumes no model random stream. A full build refuses a reference the cells cannot cross-fit (only a sampled rung or a synthetic fixture may locate in-sample, and its receipt says so), a recipient whose fold differs from its twin's, a frame without person_source_id, and a located target whose reference sign classes differ from the tape forest's (FittedRegimeGatedQRF.sign_classes). No-record rule. A twin with no taxable income (no pay, trade or pension, and at most £1,000 of taxable interest, dividends, property and miscellaneous income together) has no tax record for the tape to condition on; its copy keeps the twin's values at stage 1 and stage 2. Reserved band carriers are always drawn. Stage 2, the band-donor resample, the uprating and the SPA guard are unchanged. Integration with #1145 and #1200. The restricted finance costs leaf reaches the FRS rows only at property_components, so it takes identity-keyed uniforms. The stage writes person_is_spi_income_recipient, True exactly for the rows it drew, as its last new column; the landlord stage reads it to tell tape-concept rows from FRS-concept ones (its graph node declares the read, with a test that the declaration covers the stage's inputs), so an undrawn copy keeps its twin's property income on the FRS concept. The UC gainful self-employment refresh on drawn rows takes the root's whole rule, undrawn copies keep their twin's flag, and the evidence counts the rows each route flags. Surfaces. The manifest declares the bridge, the recipient income rule, the draw, the reference model and the identity uniforms; spi_spine pins them with drift asserts; the stage evidence carries the bridge-validation receipt and the per-target transport receipt (analogue, FRS regime and sign classes, uniform source, Kolmogorov distance from uniform overall and by main source; a positive-row count under the group floor is withheld, and the counts stay with the build). Regenerated: the schema, the source_stages mirror, the coverage manifest, the UK spine parity fixture, the spec loader's golden hash, the fit.qrf parity pins, the US spec-engine inventory digests, coverage report and the multispine pool tool's spec-hash pin (the fit kernel's source hash moved), and the gate-battery vintage and release_cut pins in the data contract (the terminal-gate allow-list gained the flag). Tests: fit (round trip, uniformity, two-population transport, zero-class carry, chunked equality, sign classes, refusals); engine-free UK (bridge and code refusal with disagreeing codes, no-record rule, analogue map, transport, cell folds, cross-fit hold-out, in-sample and twin-fold and sign-class refusals, spine drift pins, graph reads); engine-side UK (identity-keyed rewrites, fit records, the recipient flag and the refresh receipt). The engine-free, engine-uk and engine-us job lists passed locally before the final rebase onto main; the parity, pin and targeted files after it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
experiments/840-spi-draw-receipts.md: the tape receipts (R0), the spine twins at design weights on the pre-rebase base (R1a to R1e: stage evidence, the award screen and reporters by channel, rank fidelity and the in-sample atom behind the cross-fit, the rebuilt treatment, and the downstream moves by mechanism) and the twins on #1200's base (R1f). Shares and weighted totals only; record counts stay with the raw receipts beside the builds (CD137 cl. 8 / CD171 5.2.1). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
c09e6f7 to
0bb3018
Compare
|
Rebased onto |
The rebase onto main 121fd4d (#1256, #1279) settled the generated files with main's side. Regenerated on the rebased tree: the gate battery digests (main's export allow-list line beside this branch's), the coverage manifest's source digests and the H2 fixture, whose synthetic CGT asset-type facts follow the locked engine. The rendered stages are unchanged. uv.lock merged cleanly (microcosm-emitter 0.2.1 from PyPI beside policyengine-uk 2.130.1), and the lock commits pin its new digest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draw SPI-channel incomes at the FRS twin's conditional rank (#840)
Closes #840. Ticks the two #1095 items below (uk-data#529 and the SPI-row
half of UC gainful self-employment). On
mainsince #1200 merged.What changed
Stage 17 (
hmrc_spi_income_spine) drew every SPI-channel claimant's andpartner's income leaves from the SPI tape conditioned on age, gender and
region only, at the model's random numbers; the FRS twin's incomes and the
composition-income relation they carry were discarded.
a record's income that the tape and the twin each carry:
main_source(thelargest of pay, pension and trade) and
has_payfrom the same leaf formulason both sides;
has_tradeandat_or_over_spafrom the tape's publishedindicator codes (SEINC_NUM, SPA; the leaf formulas serve only a composite
record without codes) and, on the twin, its trade leaf or self-employed
status and its age against State Pension age. The published MAINSRCE code
validates the leaf-defined main source (0.969 of the classified weight on
the full 2022-23 tape with the stage's preparation; floor 0.95) and the
receipt reports each indicator code against its leaf both ways. The read
requires the three code columns and refuses unknown codes by name.
pension, and at most £1,000 of taxable interest, dividends, property and
miscellaneous income together) has no tax record for the tape to condition
on; its copy keeps the twin's values at stage 1 and stage 2. Reserved band
carriers are always drawn. The £1,000 boundary is a declared modelling
choice in the manifest.
claimants and partners with the same predictors and chain order locate each
twin's observed leaves (
FittedRegimeGatedQRF.conditional_uniforms: thesign uniform in the gate's cumulative class probabilities, the quantile on
the sign's magnitude forest through the new
_Forest.quantile_positions,chained on the twin's observed earlier leaves); the tape forest draws at
those uniforms through
predict_from_uniforms.the predictor cells cannot cross-fit (only a sampled rung or a synthetic
fixture may locate in-sample, and its receipt says so), a recipient whose
fold differs from its twin's, a frame without
person_source_id, and areference whose sign classes differ from the tape forest's on a located
target. The reference locates a leaf given the twin's earlier analogue
leaves while the tape forest draws it given every earlier output, the
identity-uniform leaves included; moving the analogue targets ahead of
them in the chain is a follow-up to measure.
row's own value as an atom (median 0.23 to 0.74 of the conditional's mass
under the weighted bootstrap) and kept under half of the twin's rank, so
the reference is cross-fitted in five folds keyed on the predictor cell: the
forest locating a copy never saw its twin, and one forest locates a whole
cell. Within-cell rank fidelity of the located quantile rises to 0.72-0.99.
placements inside a class or a flat stretch take
stable_identity_uniforms(person_source_id, seed, salt="spi_stage1:<target>:<part>");stage 1 consumes no model random stream, and a draw depends on the twin and
the identity alone. Stage 2 keeps its
seed + 1stream; the band-donorresample, the uprating and the SPA guard are unchanged.
(
property_finance_costs, the last stage-1 target) reaches the FRS rows onlyat
property_components, after this stage, so it takes identity-keyeduniforms. The stage flags the rows it drew (
person_is_spi_income_recipient,typed in the graph and allow-listed beside the band-carrier flag) and
property_componentsreads the flag to tell tape-concept rows fromFRS-concept ones, so an undrawn copy keeps its twin's property income on the
FRS concept with the sublet split and the imputed finance costs its twin
gets. The UC gainful self-employment refresh on drawn rows takes the root's
whole rule (the self-employed main job as well as the earnings route), with
a receipt of the rows each route flags; undrawn copies keep their twin's flag.
the draw, the reference model (seed + 3, five folds, fold key) and the
identity uniforms;
spi_spinepins them with drift asserts; the stageevidence carries the bridge-validation receipt and the per-target transport
receipt (analogue, FRS regime, uniform source, Kolmogorov distance from
uniform overall and by main source, per-fold counts). Schema,
source_stages.json, the coverage manifest, the UK spine parity fixture andthe
fit.qrfparity pins are regenerated. FRS rows are byte-unchanged atthe stage.
Measured on the licensed spine twins (design weights, aggregates only)
Full receipts in
experiments/840-spi-draw-receipts.md; the note carriesshares and weighted totals, and record counts stay with the raw receipts
beside the builds. The headline is R1f, the twins measured on #1200's head
(
a50ffba5e, whichmaincarries; the branch now sits onmainafter#1260): control that base, treatment this branch.
Paired against their own twins, the copies earn when the twin earns (0.587
against 0.583; before 0.743) and report benefits at the twins' shares (UC
0.111 against 0.107; before 0.062). Lone parents land on their twins through
the engine (screened 0.648 against 0.646). All 37 spine gates pass; the HMRC
band replay stays
reviewed_exclusions_only.Downstream (R1e, R1f): FRS rows move only through the frame-level stages
after stage 17 (the CGT lane, the landlord stage's profit ranking, the energy
and fuel rakes, the salary-sacrifice conversion rate, the CGT mass moves, the
take-up residual draws). To hold in view: childless units and couples with
children pass the screen 17-43 % more often than their twins (the tape's
low-pay tail among earners, the annual tax-record concept, unchanged from
before); the investment leaves and the WAS wealth draws rise 10-50 % on SPI
rows as the tape conditionals given the bridge replace the cell marginal, and
the CGT lane moves part of the FRS channel's gains to SPI rows at design
weights; the stage-2 disability and carer over-imputation on drawn copies is
a pre-existing residual.
#1095 items
trade by employment status on SPI rows now match the FRS rows.
(
has_tradeconditions the draw); undrawn copies keep the twin's flag.Tests
microcosm-fit (round trip, uniformity, two-population transport, zero-class
carry, chunked equality, refusals); engine-free UK (bridge, code refusal,
no-record rule, analogue map, transport, cell folds, cross-fit hold-out,
spine drift pins, spec loader golden hash); engine-side UK (identity-keyed
rewrites, three fit records). The engine-free, engine-uk and engine-us job lists ran
locally before the final rebase onto
main(#1242), the parity, pin andtargeted files after it;
tools/ci_test_plan.py verify,ruff check,git diff --check.🤖 Generated with Claude Code