Repository navigation
UK bus fares: impute local-bus journeys from the NTS microdata and price them at the published yield (#930) - #954
Conversation
fcb005c to
b0a1c0f
Compare
|
Review at The structure is what #930 asked for and the pieces I could recompute hold. The feed pin is chronicle #275's merge commit, no committed target moves, the three vendored resources and the NTS0705a quintile selection are declared with real consumers. The stage is registered in lockstep with a regime-gated QRF on identity-keyed uniforms, band means by series and residence group, and a declared published-shares fallback. Every England pricing factor recomputes from the vendored rows: London boardings per resident trip 2.369 and yield £1.018 (fare per trip £2.41, concessionary share 0.273); outside London 1.125 and £1.555 (£1.75, 0.281), matching the receipts, and the NTS0303 rates equal the NTS0705a all-income rates exactly. The Should-fix1. The Northern Ireland eligibility rule is wrong in law. 2. The body says "draft until the licensed NTS tabs land" but the PR is not draft, and it promises spine-t, the twin diff, the E6 bounds and the calibration round "in this PR". Either mark it draft or split the licensed measurement out; otherwise the review target keeps moving, and the changelog fragments describe a finished feature. 3. Nothing tests the zero placeholder pins, and one path skips them. "Refused at runtime" is the generic size-then-sha mismatch in 4. Trivial. Questions for María
NitsReceipts Part D still says 32 declared / 30 on the fixture with the pre-rebase oracle where Part A says 33 / 31. Scotland's under-22 rule has no floor, so under-fives are eligible there alone while the basis text says the yield absorbs them; immaterial. Could not verifyThe licensed Part E measurement and sidecar sizes, the DfI series composition, and Nothing blocks on the code that ran. 1 is a factual error about the law; 2 is the state of the PR; the tautology question is María's and this PR is the right place to settle it. |
62221e0 to
99d1770
Compare
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Second pass at 99d1770e (16 commits on main 35e10f02, which is also the merge base). Local, without the tapes or the feed: ruff check/format clean on the 42 changed files; coverage-manifest --check current; ci_test_groups.py --verify ok; spec-engine coverage 42,162/42,162; duplicate-key scan over every uk/*.json and the H2 fixture clean; pytest over the 24 stage/pricing/support/gate/schema/graph/parity/vendoring/feed/contract suites 708 passed / 12 skipped / 0 failed. CI: 5 lanes green, 18 still queued or running at post time.
The new work is solid. C10's real SN 5340 pins are committed and asserted non-zero; C12 retires the ETB rake cleanly (no dangling rake_to_vendored_facts reference, the bus_support_pricing gate recomputes at 1e-9, the priced column carries no terminal bound); C13's output-order fix was a genuine column-order bug caught by the parity identity; the rebase declares nts_bus_travel's mass receipt with its coverage reason and the fixture stands at 31 stages. The support side is no longer tautological: with the rake gone the design-weight ratios are 0.95 / 1.16 / 1.62 against the still-bound targets, and the fares framing ("composition check, never a level the stage set") is recorded in sources.yaml:1860 and the changelog.
Requesting changes on one item from round one that has not moved, plus the stale text.
- Northern Ireland eligibility is still 65.
sources.yaml:1384min_age: 65, basis text:1354, receipts:111and:149("the 65+ SmartPass series, so half-fare 60–64 boardings are not deducted"), the test pin, and the body's stage bullet are all unchanged, and neither rulings list mentions it. nidirect: the 60+ SmartPass gives free travel on all Translink scheduled services within Northern Ireland from age 60; the 65+ pass adds all-Ireland travel and nothing else. There is no half-fare tier. Since C13,bus_pass_eligiblealso gates the fare-cap bite, so NI 60–64s are now both fare-priced and counted as cap-eligible. Either set 60 (with test, basis, receipts and body moving) or record a ruling that says why 65 stands. - Stale text. Body "Verification": "Licensed measurement pending (Part E of the receipts)" and "Rebased over #939 (main
ce76b358)" while the tree is on #971 and Parts E–J exist; heading "Parts E–G" but bullets cite H and J. Receipts Part D still reads as current::103"32 declared / 30 on the fixture" (Part A says 33/31),:117zero placeholder pins,:125"thebus_subsidy_spendingrake stays", and:128citesuk_runtime/bus_support_per_journey.py, which is not in the tree. Mark Part D superseded or edit it. - The headline calibration line is spine-t's, not this tree's. Part J says the battery on spine-t3 blocks at
uk_target_fiton the stale self-employment deferral (+24.2 %, deferral approved 2026-09-18, expires 2026-10-16), and no H5 is written. The body discloses this two paragraphs later, but "all six terminal gates pass" reads as the tree's state on a fast pass. Lead with the block and the ruling it needs.
Smaller. Scotland under-22 and London under-18 rules still have no floor. dft_bus_journeys.json still lists lcfs_consumption as a consumer. Schema size_bytes is an unbounded number (no runtime refusal test for a zero pin; acceptable now that the real pins are asserted). The C13 order fix is covered only by the parity identity, not a unit assertion on column order. test_acceptance_h_parity.py:283 comment says 30 spine stages against an assertion of 31.
Merge picture. Conflicts with #979 (e01c6846) in eight files: the coverage manifest, contract.py and its test, the H2 fixture, and four test files. Whichever lands second re-pins; the fixture needs regenerating over the union.
Ready to approve once 1 and 2 are settled.
…e is 60, under-5s ride free everywhere, stale text retired (#930) The 60+ SmartPass gives free travel on all Translink scheduled services within Northern Ireland from age 60; the 65+ pass adds all-Ireland travel and nothing else, and there is no half-fare tier. The rule is 60, the basis text, the tests, the changelog and the receipts move with it, and the DfI series is described as what it is: the full-fare-concession travel status, the count of free-travel boardings across every concession, not an age series. Under-5s are declared free everywhere (the London and Scotland under-age rules already covered them), so the same law applies in every area instead of being absorbed in three. Also: the receipts' Part D is marked superseded and its stale sentences corrected; the PR body leads with the terminal-battery block and the ruling it needs; the parity test's comment counts 31 stages; the person column order is asserted in the end-to-end test; a zero placeholder pin has a refusal test; dft_bus_journeys.json no longer names the lcfs module as a consumer. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for the second pass. Addressed at 1. Northern Ireland eligibility. You are right, and the round-one item should not have slipped. The rule is 60 ( 2. Stale text. Part D is marked superseded with the four sentences you listed corrected in place (the stage count, the placeholder pins, the rake, the module name); the body's licensed section is now "Parts E–K", the verification paragraph says rebased over #939, #967 and #971 on 3. The headline. The body's licensed section now opens with the state of this tree: the calibration on spine-t4 solves with every bus row on target, its terminal battery blocks on the stale self-employment deferral (María's ruling), no H5 is written, and the "six terminal gates pass" line is labelled as spine-t's, the pre-rebase build. Smaller. Scotland's and London's under-age rules keep no floor because under-5s are now declared free everywhere, so the floor would only re-price them; Merge picture. Noted in the body: whichever of #979 and this lands second re-pins the digests and regenerates the fixture over the union. On your round-one framing question, "level injected from the receipts, composition free" is the honest description of the fares and the body now uses it; the support side stopped being a tautology on 2026-09-23 when María ruled the rake retired. |
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Third pass at f9aa757d (two commits since 99d1770e; main 35e10f02 is still the base). Local, without the tapes or the feed: ruff check/format clean on the 40 changed files; ci_test_groups.py --verify ok; coverage-manifest --check current; merge-tree against main clean; pytest over the stage, pricing, stage-health, spine, source-stages, country-spec, contract-pin, data-contract and H2 parity suites: all passed (summary line not flushed; no F markers). CI: 2 lanes green, 11 queued or running at post time (GitHub's queue is slow today), none failed.
Everything from round two is closed.
- Northern Ireland at 60, with the basis text now stating the 60+ SmartPass rule and the 65+ pass's all-Ireland scope correctly (
sources.yaml:1354, 1381), the test pinning 60, and the changelog saying 60+. Making under-5s free in every area (max_age_exclusive: 5on England outside London, Wales and Northern Ireland) is the right uniform rule, and the DfI series is now described as the full-fare-concession travel status rather than a 65+ series. Part K carries the twin effect: Northern Ireland eligible 888 → 1,417 of 3,945, its fares 1.76 → 1.57 of the Translink receipts, England outside London 1.12 → 1.06 on fares and 0.95 → 1.00 on priced support, London and Scotland unchanged. That is what the eligibility change should do and nothing else moved. - Stale text. Part D is headed superseded with the four sentences corrected in place; the body's licensed section is "Parts E–K", the verification paragraph names the three rebases on
35e10f02, and "pending" is gone. The dead module name survives only as history ("since renamedbus_support_pricing.py"), which is fine. - Headline. The licensed section now opens with the state of this tree: spine-t4 solves with every bus row on target and its battery blocks on the stale self-employment deferral, no H5 written; the "six terminal gates pass" line is labelled spine-t.
Smaller items landed: dft_bus_journeys.json no longer names the lcfs module, test_read_pinned_tab_refuses_a_zero_placeholder_pin exists, the end-to-end test asserts person column order against the declared outputs, the parity comment says 31. Keeping the Scotland and London under-age rules floorless is right now that under-5s are declared free everywhere.
One nit, not blocking: changelog.d/930-nts-bus-travel-stage.added.md still says "the artifact pins are placeholders refused at runtime until the licensed tabs land" and "(30 stages)"; the pins are real and the fixture has 31.
Merge picture is as the body says: eight conflicts with #979 (e01c6846) on the coverage manifest, contract digests, the H2 fixture and four test files; whichever lands second re-pins and regenerates the fixture over the union. The battery block on the stale deferral is María's ruling and sits outside this PR.
Approving. Merge on green CI, after settling the order with #979.
…rip-rate and car-availability facts (#930 C2+C3) chronicle#274 landed as PolicyEngine/chronicle PR #275 (78466057): DfT BUS01 passenger journeys by area with the BUS01c concessionary split, the BUS05i operating-revenue and support components, NTS0303/NTS0601 trip rates by mode and age band, and the DfI full-fare concession journeys (277,183 rows, chronicle.consumer_fact.v3). No existing reference moves by value or period; the membership, census and validation-level surfaces move by their feed label only (631 active / 7 deferred / 8 signed out national; 20,885 active local; the parity receipts are byte-identical). Every vendored resource is regenerated with the new feed identity. Three are new: dft_bus_journeys.json (journeys and concessionary journeys for England, London, England outside London, the metropolitan split and the nine regions, FY2023-25; the seven BUS05i components; ONS mid-year population of the four countries and the nine English regions), nts_trip_rates.json and nts_car_availability.json; devolved_bus_finance.json gains the DfI concession journeys. The NTS0705a selection is pinned to its income-quintile groupby because the new NTS packages reuse the trip-rate concepts (it had grown from 24 to 84 rows). The new resources are declared in the country package and the frozen resource lists; their consumers are planned until the pricing and stage commits name them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…y, and read the per-target weight-stretch anatomy from them (#930 C1) A national calibration attempt the terminal battery blocks wrote no staging H5 and no weight vector, so the per-target anatomy (how much of a target's fitted mass sits on households the solver stretched) could not be read: the #890 acceptance line on England bus fares was never re-measured (receipts Part N). The seam now writes the solve's CSR matrix, row names, target vector, design and final household weights and household ids beside the diagnostics, before the battery runs, as non-release sidecars with a manifest of digests; the H5 posture is unchanged. tools/diagnose_uk_target_support.py decomposes any compiled row from them: target, design and final aggregates, carrier count, top-1/top-5 shares, the carrier weight-ratio distribution, the share of final mass on households stretched beyond declared multiples of design (3x and 5x by default) beside the frame-wide share above the same multiple, and the near-cap fraction; the recomputed final estimates are verified against the attempt's diagnostics so another attempt's sidecars are refused. Ported from the US target-support tool's decomposition with the stretched-mass buckets added. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nditional schema keys, per-sweep IPF residuals, the walk documented, receipts attributions (#930 C0) The should-fixes, questions and nits of the approving review on PR #927 (three minutes before merge) were never addressed. Declarations: the lcfs stage notes and their packaged mirror no longer say the FY2024-25 Ofgem pricing sets the energy columns' level (the NEED 2024 shape at the DESNZ level and the QEP average prices paid do); the price_domestic_energy schema branch requires the connection keys whenever gas_connected is published_meter_share (the file's first if/then, refused at validation rather than in the stage); the regions the crosswalk maps to no subnational area are declared as connection_fallback_regions (Northern Ireland) and refused if they differ from the crosswalk, so the fallback is no longer inferred from a None. Receipts of convergence: iterative_proportional_fit records the cross-margin residual after every sweep (raking_sweep_residuals), the energy rake receipt carries it per fuel (sweep_residuals), and the energy_rake gate note states the tolerance governance (a rule above the observed maxima; a converged residual above it is a new ruling, never a silent re-pin) and the connection-cap rule (declared, waived only for a receipted shortfall). The gas-connection walk is documented as the greedy weight-fitting walk it is and tested on unequal weights through its skip and nearest-skipped branches; the evidence_absent_blocks plus synthetic_smoke seam is tested (an absent receipt blocks the smoke, a failed population fact check does not). Receipts Parts R and S credit the UK spec-digest move to the rebased 713b506 (run labels untouched); Part T records that ONS 04.5.3 and 04.5.4 (about GBP 1.57bn) are vendored and unbound and that María confirmed the 04.5 sign-out on 2026-09-17. The merged PR body carries the rebased hashes. The H2 fixture, the coverage manifest and the gate-battery and certification-part digests are regenerated and re-pinned. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…the published yield, fence the support rake (#930 C4–C7) C4+C5, the stage: a person-grain `nts_bus_travel` stage between `was_wealth` and `lcfs_consumption` reads the NTS Household, Individual and Trip tabs (UKDS SN 5340, EUL; artifact pins are placeholders refused at runtime until the licensed tabs land) through a declared codebook, fits one regime-gated QRF on the frequency-of-use band, assigns the diary's band means per series (bus in London, other local bus) and residence group, and emits the statutory concessionary eligibility per area. Gates: a support clip and a `bus_travel_facts` population fact check against the vendored NTS0313 and NTS0303 rows; NTS0205 car availability is a receipt line. Graph, kernel registry, spine tool, coverage manifest, export surface, contract scope and the H2 fixture (synthetic NTS tabs, 30 stages) carry the stage. C6, the pricing: `assign_bus_use_incidence` and the fare cells of `rake_to_vendored_facts` leave the lcfs declaration; `price_bus_journeys` sets `bus_fare_spending` as the household's non-eligible persons' trips times boardings per resident trip (BUS01 over NTS0705a times ONS population) times the yield per fare-paying boarding (BUS05ai receipts over journeys less concessionary journeys) per area, Scotland and Northern Ireland from their own receipts with England's rate as the declared proxy, Wales unpriced (raw draw, clipped). The chain still conditions on the raw draw. A `bus_pricing` gate recomputes every factor from the vendored rows. C7, the support side: the ETB `bus_subsidy_spending` rake stays and gains a `fact_rake` gate (every cell recomputed through the stage's own declaration, totals after the rake checked, the NI cell jointly over bus and rail, a skipped cell fails closed); `record_support_per_journey` records the value-side alternative beside the raked total, never applied. Digests re-pinned; `ci_test_groups --verify` ok. One commit for the four chunks: their derived surfaces (fixture, coverage manifest, digests, pins) interleave, so intermediate commits would not each have been green. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#939 (#930) Main's #939 re-pinned the feed to chronicle c5e5bf8 (the HMRC CGT tables); this branch's pin, 78466057, is its descendant, so the rebase keeps the newer pin and regenerates every surface on it over the merged register: the vendored resources (main's two CGT resources now carry the 78466057 identity beside the three bus resources), the national references and membership, the local census and references, the signed compile-parity receipts, the H2 fixture (31 stages: #725's asset-type stage and #930's nts_bus_travel), the release-input coverage manifest and the gate-battery and certification-part digests. The stage-count pins both sides had bumped to the same number move once more (31 graph stages, 33 declared). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…deposited lookup tables (#930 C10) The licensed National Travel Survey extract (UKDS SN 5340, 19th edition, November 2025) is on disk: the Household, Individual and Trip tabs are pinned by size and digest and verified at runtime, and the declared codebook is checked against the deposited lookup tables and the data extract user guide. Three corrections came out of that check. The frequency-of-use question is OrdBus2Freq_B01ID (ten codes since 2019; the declared LocalBusFreq_B01ID never existed and OrdBusFreq_B01ID ended in 2018); its codes fold onto the seven NTS0313 bands, code -9 (not applicable, proxy responses) is declared a non-user because the published 2024 shares reproduce only with those persons in the base (0.526 without them, 0.505 with them, published 0.505), and -8 is dropped and receipted. Age_B01ID carries 21 bands, so the codebook maps each code to its lower age before the declared edges band donor and recipient alike; the earlier one-to-one assumption would have misaligned the QRF predictor. The trip weight is W5, which already carries the diary household weight W2, so a person's counted trips are divided by W2 before the W2-weighted mean (the user guide's 52.14 x sum(JJXSC x W5) / sum(W2)); W5xHH is only the within-household factor. Interview-only households (W2 = 0) leave the donor and are receipted. The disclosure-safe E6 bounds for the stage's band and trip columns (uk/nts_bus_travel_support_bounds.json, outward-rounded from the pinned tabs) join the terminal uk_support gate; the H2 fixture's synthetic tabs follow the verified codebook; the coverage manifest and the gate digests are regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…k, spine-t against its main twin, and the national calibration with the stretch anatomy (#930 C11) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ourneys at the published support per boarding (#930 C12) María's ruling of 2026-09-23: raking retires with the imputation. The ETB stage no longer rakes bus_subsidy_spending to the published net support per area; a declared price_bus_support step sets each household's support from its persons' boardings (the nts_bus_travel trips times the fare pricing's boardings per resident trip) at the published support per boarding: the concessionary travel reimbursement per concessionary boarding for eligible persons plus the rest of the net support per boarding for every boarding, for London and England outside London (DfT BUS05bi and BUS01) and Scotland (Scottish Transport Statistics components and journeys). Wales (no published boardings) and Northern Ireland (the NITHC accounts carry bus and rail jointly) keep the chain's raw draw clipped to donor support, as Wales fares do; the support clip no longer exempts the column. The published totals stay bound as calibration targets and now measure the priced quantity instead of a level the stage set. The rake_to_vendored_facts operation kind, uk_runtime/fact_raking.py and the fact_rake stage-health check leave with their last consumer; the uk_stage_etb_services_support_pricing gate recomputes every area's components and per-boarding rates from the vendored rows. The register's two resources name the pricing module; fixture, coverage manifest and digests regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he support-clip exemption and pin its zero allowances (#930 C12) The support_clip gate for etb_services still exempted bus_subsidy_spending from the #890 rake days; the spine-t2 build blocked on it. The column is clipped to donor support like education and rail before the pricing step overrides it outside Wales and Northern Ireland, at the same clean-baseline allowance of zero clipped rows. Digests re-pinned. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…old-mass receipt, surfaces regenerated, receipts Part H (#930) Main's #967 has every source stage declare and record a mass-conservation receipt the terminal family gate checks by reason; the NTS stage now does too. The coverage manifest, the H2 fixture and the gate digests are regenerated on the rebased tree; the ETB test that monkeypatched the retired support rake patches the pricing step instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…erson's fare-paying boardings (#930 C13) María's ask of 2026-09-23, after the fare-cap question: the boardings a per-journey cap binds on. Two more pinned SN 5340 artifacts (the Stage table, a boarding per row with the cost paid at the point of use and the held ticket used; the Ticket table, the season tickets and passes held, concessionary codes 7 to 11). Every diary bus boarding is classed as paid at the point of use, a season ticket or pass, a concessionary pass, free with no ticket, or unknown; per series, residence group and band the share of point-of-use boardings among fare-paying ones is assigned to each person as local_bus_single_fare_share (trips-weighted across the two series). The fare paid per boarding by residence group and survey year, the boarding-class shares and the NTS boardings per bus trip are receipted; nothing derived from the licensed rows is committed. The column joins the export surface and the stage's E6 support bounds (0 to 1); the spine tool takes --nts-stage-tab and --nts-ticket-tab; the graph sources, the H2 fixture (synthetic stages and tickets), the coverage manifest and the gate digests follow. policyengine-uk#1871 carries the parameter side. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he spine-t3 calibration in the receipts (#930 Parts H–J) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…output order the graph's cells use (#930 C13) The H2 parity test caught the stage emitting the two columns in the other order; the fixture is regenerated and the receipts note that spine-t3 was built one commit earlier with the columns swapped, values unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e is 60, under-5s ride free everywhere, stale text retired (#930) The 60+ SmartPass gives free travel on all Translink scheduled services within Northern Ireland from age 60; the 65+ pass adds all-Ireland travel and nothing else, and there is no half-fare tier. The rule is 60, the basis text, the tests, the changelog and the receipts move with it, and the DfI series is described as what it is: the full-fare-concession travel status, the count of free-travel boardings across every concession, not an age series. Under-5s are declared free everywhere (the London and Scotland under-age rules already covered them), so the same law applies in every area instead of being absorbed in three. Also: the receipts' Part D is marked superseded and its stale sentences corrected; the PR body leads with the terminal-battery block and the ruling it needs; the parity test's comment counts 31 stages; the person column order is asserted in the end-to-end test; a zero placeholder pin has a refusal test; dft_bus_journeys.json no longer names the lcfs module as a consumer. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he round-two eligibility change (#930) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… digests re-pinned over the union, receipts Part L (#930) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
f9aa757 to
b4f8f79
Compare
…ahid's third-pass nit, #930) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ure and coverage regenerated, digests re-pinned Main's #954 (nts_bus_travel) landed on the 7846605 feed; this lane pins 5324aa2, which descends from it (PolicyEngine/chronicle#282 and #284 on top of #275), so the pin stays and the union is regenerated at it: the three resources #954 vendored at 7846605 (dft_bus_journeys, nts_trip_rates, nts_car_availability) and the two whose selections #954 changed (devolved_bus_finance, nts_bus_use_frequency) re-vendored from the pinned artifact (rows as published; identity blocks move), the national and local references and membership regenerated (byte-identical: 1,124 and 20,885 active), the local census unchanged, the three compile-parity receipts unchanged; the stage manifest projection verified on the 35-stage roster, the H2 parity fixture rebuilt on 33 spine stages, the release-input coverage manifest regenerated, and the gate-battery and certification-part digests re-pinned in the data-contract mirrors. Engine: the workspace pin policyengine-uk 2.100.0 reproduces every compiled value of 2.98.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ure and coverage regenerated, digests re-pinned Main's #954 (nts_bus_travel) landed on the 7846605 feed; this lane pins 5324aa2, which descends from it (PolicyEngine/chronicle#282 and #284 on top of #275), so the pin stays and the union is regenerated at it: the three resources #954 vendored at 7846605 (dft_bus_journeys, nts_trip_rates, nts_car_availability) and the two whose selections #954 changed (devolved_bus_finance, nts_bus_use_frequency) re-vendored from the pinned artifact (rows as published; identity blocks move), the national and local references and membership regenerated (byte-identical: 1,124 and 20,885 active), the local census unchanged, the three compile-parity receipts unchanged; the stage manifest projection verified on the 35-stage roster, the H2 parity fixture rebuilt on 33 spine stages, the release-input coverage manifest regenerated, and the gate-battery and certification-part digests re-pinned in the data-contract mirrors. Engine: the workspace pin policyengine-uk 2.100.0 reproduces every compiled value of 2.98.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings in the 19 main merges since 6442030: the Route A remediation stack (#1016, #1018, #1017, #1025, #1024, #1028), #1029, #1005, #1008, #1004, #992, #1031, #1015, #1033, #994, #954, #966, #1006 and #1010. Eight conflicted paths, each recorded in docs/native-integration-20260923.md: - test.yml keeps the native sharded matrix (main's --durations=25 is already in every native pytest call); - the us_runtime facade stays lazy and gains main's three fiscal-target exclusion exports (the parent union, 920 names; the facade-union test is re-pinned to that union's digest); - reform_validation.py keeps main's _released_engine_state and the native explicit-constructor default_simulate_factory; - build_us_fiscal_refresh_release.py carries the native explicit consumer seams (formula metadata, dataset and microsimulation constructors, SPM selection) onto main's household-batched post-export scorer and batched base materialization; omitted seams keep main's exact calls, and _main supplies none. Three native test files that addressed the removed frame-based factory now address the scorer with the same assertions; - identity pins observed on the merged tree: five EXPECTED_HASHES entries, the regenerated F0 coverage report (42,239/42,239 fields, 41/41 checks), the US spec identity 2dfa51b8... and the loader golden f2047cb9... tools/generate_us_bundle_from_constants.py --check, tools/ci_test_groups.py --verify, the CI matrix contract and ruff pass. The fiscal consumer, formula-metadata, shared target/solve and calibration-attachment files pass; the rest of the fiscal battery and the known pre-existing failures are follow-up work on this branch. No actual-data native run, release certification or publication. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closes #930. Follow-up to #927 (#890): the structural fix María ruled on 2026-09-15 for the rake-then-bind bus fares. Plan of record and rulings in the receipts (
experiments/930-nts-bus-journeys-receipts.md).The licensed NTS tabs are pinned (UKDS SN 5340, 19th edition, End User Licence) and the stage's codebook is verified against the deposited lookup tables and the data extract user guide (three corrections: the frequency question is
OrdBus2Freq_B01ID,Age_B01ID's 21 bands map to lower ages before the declared edges, and the trip weight isW5divided by W2). The licensed twins (spine-t against a main control, then each change against its predecessor), the stage receipts, the E6 bounds and the calibration rounds are in the receipts (Parts E–K).What changes
7846605(PolicyEngine/chronicle#274→ chronicle PR Carry the full geography ladder from census block: county, place, state leg districts, metro/CBSA as spine columns #275): BUS01 journeys and concessionary journeys by area, the nine BUS05i revenue components, NTS0303/NTS0601 trip rates, NTS0205 car availability, the DfI concession journeys. Three new vendored resources, the NTS0705a selection pinned to its income-quintile breakdown; no committed target moves.nts_bus_travel, a person-grain stage betweenwas_wealthandlcfs_consumption: one regime-gated QRF on the NTS frequency-of-use band, trips assigned from the diary's band means by series (bus in London, other local bus) and residence group, the statutory concessionary eligibility per area (England outside London 66+, London under 18 or 60+, Scotland under 22 or 60+, Wales 60+, Northern Ireland 60+, under-5s free everywhere). Two stage gates; NTS0205 car availability as a receipt line; a published-shares fallback if the extract lacks the frequency column.bus_fare_spendingpriced, not raked: the Bind DfT, HMRC, DESNZ, Ofgem and ORR facts for bus fares, road fuel, domestic energy and rail support (#790 ruling: bind facts and calibrate) #890 incidence draw and fare rake leave the lcfs declaration;price_bus_journeyssets the column as the household's non-eligible persons' trips × boardings per resident trip (BUS01 over NTS0705a × ONS population) × yield per fare-paying boarding (BUS05ai receipts over journeys less concessionary), per area; Scotland and Northern Ireland from their own receipts and journeys with England's trip rate as the declared proxy; Wales keeps the clipped raw draw. The chain still conditions on the raw draw, so every other LCFS column is byte-identical. Abus_pricinggate recomputes every factor from the vendored rows.bus_subsidy_spendingrake retires too (María's ruling, 2026-09-23).price_bus_supportsets each household's support from its persons' boardings at the published support per boarding (concessionary reimbursement per concessionary boarding for eligible persons plus the rest of the net support per boarding for every boarding) for London, England outside London and Scotland; Wales (no published boardings) and Northern Ireland (bus and rail jointly in the NITHC accounts) keep the clipped raw draw. Therake_to_vendored_factskind and its module leave with their last consumer; abus_support_pricinggate recomputes every area's factors from the vendored rows.local_bus_single_fare_share, the share of their fare-paying boardings paid at the point of use rather than on a season ticket or pass, the boardings a per-journey fare cap binds on; the fare paid per boarding by area and year (2022 pre-cap, 2023–24 capped), the boarding-class shares and the NTS boardings per trip are receipted. The parameter side is policyengine-uk#1871 (with Vahid's #1869).tools/diagnose_uk_target_support.pyreads the mass on households stretched beyond 3x and 5x per target.Licensed measurement (Parts E–K of the receipts)
State of this tree first. The national calibration on the final tree (spine-t4, Part K) solves with every bus row on target, but its terminal battery blocks on a row this PR does not touch: María's signed v20 deferral of the HMRC self-employment 20–30k band (approved 2026-09-18, expiring 2026-10-16) is stale here because the row solves to +24.6 %, inside the 25 % fence, and the target-fit gate refuses stale deferrals by design. No H5 is written from this tree until that deferral comes off, on her ruling; the readings below come from the pre-battery sidecars. The "all six terminal gates pass" line further down is spine-t's, the pre-rebase build on the register without that deferral.
bus_fare_spending), two thecolumn_orderstructural surface adjudicated as in UK spine: relationship-to-head frame column, so the ONS household-composition split is measurable #791; Wales rows byte-equal; weights and every other column byte-equal.bus_subsidy_spendingeverywhere, rail support on the 679 Northern Ireland rows the retired joint cell used to scale, nothing else.Verification
Rebased over #939, #967, #971 and #979 (main
43ca60f6): the feed pin78466057is the descendant of #939'sc5e5bf8, so the branch keeps its pin and regenerates every surface on it over the merged register; the national target references are byte-identical to main's; the H2 fixture carries 32 stages (#725's asset-type stage, #970's incidence anchor andnts_bus_travel), 34 declared, every stage recording the household-mass receipt #967 requires. The #979 rebase conflicted only on the regenerated surfaces (coverage manifest, contract digests, fixture) and on four test files' additions; both sides' additions are kept, the surfaces regenerated and the digests re-pinned over the union. #970's incidence anchor runs after the three bus stages, so the stage receipts in Parts E–K are unchanged by it; only the terminal weights and the calibration would move, and the rebased tree is not rebuilt here.Unit suites for the stage, pricing, support pricing, gates, schema, graph, spine tool, source stages, vendoring, feed, contract pins and the H2 parity fixture green locally;
tools/ci_test_groups.py --verifyok; ruff clean on the repo.Rulings recorded
Chronicle facts first; per fare-paying boarding with a declared boardings-per-trip translation; statutory age eligibility at zero fare (Northern Ireland at 60 and under-5s everywhere since Vahid's second pass); Wales unpriced; the 04.5 sign-out stands; the support rake retires (2026-09-23). Open at review: pooled 2022–2024 donor vintage; vehicle shares as a receipt line; the devolved proxy region for Scotland and Northern Ireland.
Out of scope
The engine-side
bus_usagequantity (policyengine-uk issue drafted), the dense solve, the QRF drift issue, rail support value-side treatment, local-grain journeys.🤖 Generated with Claude Code