Port the post-freeze childcare / Tax-Free Childcare inputs and targets, re-pin the Chronicle feed, and activate the DfT bus targets (#834, #789) - #874
Draft
juaristi22 wants to merge 35 commits into
Draft
Conversation
chronicle#143 consumer side: microcosm must accept both ledger-era and chronicle-era Chronicle schema ids and hash domains before Chronicle flips emit. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… dual-read Chronicle (formerly Ledger) introduces chronicle-era hash domains and chronicle-named schema ids for newly emitted rows at a declared cutover; ledger-era ids stay valid history forever (PolicyEngine/chronicle#143). Microcosm is a consumer, so it must accept both eras before Chronicle flips emit. microcosm.build.chronicle_epoch is the single place that knows which identity belongs to which era. Epoch detection is structural — the namespace segment of a key's domain — rather than a lookup in a frozen list of domain strings, so a chronicle-era family whose version number the spec has not yet declared still resolves, and no validator hard-codes one epoch. Fact keys stay opaque: Microcosm never recomputes a Chronicle digest, so comparison stays exact string equality and only the 'is this a Chronicle key?' question goes dual-era. The consumer-artifact loader now tests manifest schema_version for membership in both eras instead of equality with one, validates a per-row schema id when a feed carries one (Chronicle-published rows never have), and records the observed id, its epoch, and the feed's fact-key epochs in provenance() so a release manifest witnesses which era actually resolved its targets. microcosm.build.chronicle_env is the dual-read window for the operational env names: CHRONICLE_URL/KEY/API_KEY/EXPORT_KEY preferred, POPULACE_LEDGER_* still honored with one DeprecationWarning per process per name. LEDGER_HMRC_BANDS, LEDGER_ONS_*_BANDS and LEDGER_US_SOURCE_COVERAGE_CONTRACT_COMMIT only look like env vars to a grep — they are data constants, so they take chronicle-era aliases instead. Nothing renames on disk: emitted ids, diagnostic field names, populace_* key namespaces, goldens and fixtures stay frozen at v1 (microcosm#639). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Covers the epoch module itself, the loader under each schema id, a mixed-epoch feed straddling the cutover, mixed-epoch target compilation and a chronicle-era reference pin, and the two producer surfaces: the minted US trade artifact declares the ledger-era id but loads under either, and the congressional-district vintage translation mints byte-identical microcosm.derived_fact keys whether its source rows are ledger-era or chronicle-era — otherwise cutover day would silently re-identify every derived fact a target is pinned to. Also documents the env dual-read in logbook/README.md and adds the towncrier fragment. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Dual acceptance must widen what loads and narrow nothing. The loader as committed added a per-row schema_version check that rejected any id outside the two chronicle#143 names — a validation main never performed, on a field main never read. Real feeds do not honor that set. The pinned US fiscal-refresh feed consumer_facts_buildn_v9_4.jsonl, which the release path loads through this loader, declares 'arch.consumer_fact.v1' on 37,006 of its first 200,000 rows and 'ledger.consumer_fact.v1' on 399 of them; test_uk_firm_generation builds the same arch-namespace rows. The check therefore failed the build closed on its own pinned input, and PR CI could not see it: the feed is gated data outside PR CI. Verified by loading an arch-namespace row through load_ledger_consumer_artifact — ValueError before, loads after. The id is now carried and reported through fact_schema_versions, which provenance records beside the artifact schema id and the fact-key epochs, so a release manifest still witnesses exactly which producers wrote its rows. Epoch witnessing was also reading only the four key fields targets resolve a fact by. Published rows carry nine, plus two key lists: the captured UK feed fixture has observed_measure_key, source_release_key, source_series_key, universe_constraint_set_key and lineage.source_row_keys as well. Chronicle moves families independently — the spec declares v3 only for the aggregate and semantic families — so a straddling row with a ledger-era aggregate key and a chronicle-era source-release key was witnessed as pure ledger-era. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…scribe The map documented six families and said it recorded what this repo's feeds carry. The captured UK feed fixture carries ten, and the pinned US feed carries eleven: observed_measure, source_release, source_series, universe_constraint_set and source_row were all missing. Nothing consults the map at runtime, which is precisely how such a list rots, so a test now pins it to the fixture. The completed map also shows why detection cannot be a lookup in it: the observed version numbers differ by family, with fact and source_cell at v1 where the rest are at v2. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
POPULACE_LEDGER_URL/_KEY/_API_KEY/_EXPORT_KEY are Logbook store credentials (microcosm#632), not Chronicle fact-store ones. Naming the preferred spellings CHRONICLE_* would recreate the exact collision microcosm#632 renamed Ledger away from. Per PR #849 review: rename chronicle_env.py to logbook_env.py, its symbols to LOGBOOK_*/logbook_env*, and every caller (logbook.py, tools/logbook.py, build/__init__.py exports, and the two module-path comments in firm_generation.py/source_coverage.py that named the old module). Legacy POPULACE_LEDGER_* names and the once-per-process DeprecationWarning behavior are unchanged; the warning text now cites microcosm#632 instead of chronicle#143. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The changelog fragment, logbook/README.md, and the branch journal all described CHRONICLE_URL/CHRONICLE_KEY and the env dual-read window as part of the chronicle#143 epoch migration. It is a separate Logbook naming cleanup (microcosm#632) riding along on this branch: split the changelog sentence into its own paragraph, update the README's live-store section to LOGBOOK_URL/LOGBOOK_KEY, and append a dated correction note to the journal recording why and what changed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
logbook_env's import in build/__init__.py sorted alphabetically after the rename, and tools/logbook.py's two dual-read imports needed reordering and reformatting to match. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…-*.md only Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The findings turn on which schema ids Chronicle actually emits, so the identities are recorded here with the file and line they were read from on chronicle origin/main rather than restated from the PR body. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…istry
The accepted set was {policyengine_ledger.consumer_artifact.v1,
policyengine_chronicle.consumer_artifact.v2}, which is one generation off at
both ends. Chronicle's main emits policyengine_ledger.consumer_artifact.v2
today (policyengine_chronicle/consumer.py:30, README line 299), so the loader
rejected every artifact Chronicle currently publishes, and the chronicle-era
successor of that id is .v3, not .v2. The v1 spelling is Microcosm's own
minted artifact and stays accepted as the history it is.
Epoch now comes from a declaration keyed by (namespace, family, version)
rather than from the namespace segment of the key. Reading the namespace told
us where a key claimed to come from, not that Chronicle issued it, so
chronicle.source_cell.v3 and chronicle.anything.vN were being witnessed as
Chronicle-issued identity. The ledger-era half of the table is transcribed
from Chronicle's own hash-domain constants; the chronicle-era half is each
one's successor under the rename rule, which puts source_cell at v2 where
aggregate_fact is at v3. An undeclared spelling in a Chronicle namespace is
reported as 'undeclared' in provenance, with the domain named, instead of
being folded into an era nobody declared it for.
The membership predicates are total over JSON. A manifest whose schema_version
is a list or an object raised TypeError out of a frozenset membership test,
bypassing the loader's own unsupported-schema message.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The per-module delenv lists named POPULACE_LEDGER_* only, because they were
written before the LOGBOOK_* spelling existed. A shell exporting the
preferred names — a developer who just ran an export, a runner where the
variables are set for a later job — walked straight past them:
logbook._remote_config() returns ('https://example.invalid', 'x', 'x') under
LOGBOOK_URL/LOGBOOK_KEY alone, and the append path would then POST to it.
The store is append-only, so a row that lands cannot be retracted.
An autouse conftest fixture now clears both generations of every variable in
the dual-read window, taken from the window itself so a variable added there
cannot leave a hole here, plus POPULACE_LOGBOOK_PREV_ROW_DIGEST. The second,
independent guard replaces the Logbook urlopen with one that raises —
on every module currently holding it, since tools/logbook.py binds the name
at import, and on the opener it delegates to, which closes the path for any
importer this does not find. allow_logbook_network restores the real
callables for a test that means it; nothing in the suite asks for it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…t alias microcosm.build re-exported the reader function logbook_env under the same name as its module. 'import a.b as c' returns the attribute when the package has one, so 'import microcosm.build.logbook_env as env' handed back the function and every env.LOGBOOK_URL_ENV after it raised AttributeError. The barrel now re-exports only logbook_env_names, which collides with nothing; the function is imported from its own module, as logbook.py and tools/logbook.py already do. CHRONICLE_US_SOURCE_COVERAGE_CONTRACT_COMMIT was added beside the ledger-era pin but never re-exported, so it was importable from source_coverage and not from the us_runtime barrel its sibling reaches — an alias only half the callers could use. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
_ledger_provenance rebuilt the block from the artifact field by field, which is how it came to record facts_sha256, fact_row_count and manifest_sha256 but not schema_epoch, fact_key_epochs or fact_schema_versions. The loader had already worked out which era resolved the targets; the UK run reported only the hashes, so a signed diagnostics file could not say whether a cutover-window feed had straddled the rename. It now delegates to LedgerConsumerArtifact.provenance() and keeps only the manifest sub-block UK-shaped, because that one feeds the run's identity digest and is deliberately narrow. A stand-in without the shared method still records what it carries rather than fabricating the rest. Coverage is a real mixed-epoch artifact through run_uk_calibration: a Chronicle-main manifest id over ledger-era and chronicle-era rows plus one undeclared Chronicle-namespace key, asserted in the build record and in the diagnostics 'build' block. The delegation itself is pinned as a property — every shared field reaches the UK block — rather than as a list that would go stale the next time the shared block grows. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
'logbook export --remote --help' named POPULACE_LEDGER_URL alone, so an operator configuring from the help text set up the exact spelling the dual-read window exists to retire, then got a deprecation warning for following the instructions. The preferred LOGBOOK_* names come first and the ledger-era ones are named as the fallback they are, since an operator whose environment predates the rename still has to recognise what is being asked for. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The lane journal is history once written, but four of its claims read as current design and are now wrong: the two-id accepted set, the uniform v2-to-v3 domain bump, CHRONICLE_* env names, and structural epoch detection. Each is annotated in place with the correction and its date so the file cannot mislead a later reader, and the changelog fragments now describe the behavior that is actually on the branch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Both said chronicle#143 declares the v3 spelling for exactly two fact families, which the issue does not: it lists 'dual-hash window or v3 domains' as open options. The import_entry_facts header also named the chronicle-era artifact id as .v2 and did not say which of the ledger-era ids this module emits, which is the distinction the whole finding turned on. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Both microcosm-build suites are outcome-identical, which is the guarantee the Logbook isolation finding asked for. The two red tests are recorded with the evidence that they reproduce at origin/main, because the earlier lane reported this suite as all green and on a machine holding the pinned feed it is not. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
policyengine-uk 2.93.0 adds the person-level tax_free_childcare_spend_routed_share input and 2.92.2 applies the Tax-Free Childcare rate to the gross payment; the port of uk-data #473/#474 needs both. 2.94.0 is the release the free-childcare dashboard was measured on. The frame and data shards' uk extras had drifted back to >=2.88 after #811; all three shards now agree on >=2.93. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tract they compile against (#834, #789 I0) The committed national surface was generated on a Chronicle feed (226358e7, 107,550 rows) the local census no longer pinned (33ca98a, 108,112 rows); on the pinned feed 19 references failed to compile and the calibration runner refused to run. Both surfaces now pin one feed built from Chronicle main 6fb700e (128,717 rows, facts 6ae49d7d…, manifest dcda51d6…, artifact schema v2), and the runner refuses any other feed unless --allow-unpinned-feed is passed and recorded. What the re-pin surfaced and how the contract answers it: - The #239 UC crosses share source_concept and groupby_dimension with the base family-type and number-of-children tables; the composition rows now pin their exact dimension key set, and the generator no longer reads a `dimensions` list as a sum trigger. - The caseload row keeps binding DWP UC deductions statistics Table 1 (measure total_units, month groupby): its April–December 2025 calendar-year average is 6,758,889, the value #735 recorded; the Stat-Xplore family-type sum runs 1.45% above it (chronicle#247 asks for the cube's Total row). - The CGT totals pin Table 1; Table 5's UK rows carry the same concepts. - Every dwp_universal_credit row is a calendar-year average (one temporal basis): the 100 payment-band rows move from the May-2025 snapshot to the 2025 mean, and the Scotland youngest-child row is re-bound at benefit-unit grain. - ons.population.scotland_households_3plus_children is signed out (its selector reaches person-level mid-year population rows; #736). - The local private-rent deferral private_rent_pipr_after_target_period is stale since #231 extended PIPR to 2023–2026: the 314 rows bind the 2025 calendar-year average (12 members each). Local active references 19,618 -> 19,932. - The nine scotgov council-tax bands restore themselves (#231's measure-id fix). Regenerated with the repository tools: national and local references and membership, the local census and validation levels, both compile-parity receipts, the feed-row fixture. A hermetic test regenerates the surfaces from the pinned identity and skips only when the feed is absent. docs/uk-chronicle-feed-repin.md records the procedure. Codex implemented increment I0 of the #834 plan under the approved-plan protocol; reviewed section by section, source_repo restored to the canonical PolicyEngine/chronicle, census regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…us targets (#834, #789) Lane A (D1–D6): a generic `assign_period_constant` source operation gives `frs_person_draws` the HMRC-derived `tax_free_childcare_spend_routed_share` from a new `stochastic` entry of the take-up contract at the build year (2024-04-01 → 0.593; 2017–2025 series from the March-2026 account-activity ODS, Chronicle package and sha pinned), with the stage's node key folding the contract sha, a build-year lockstep check against the installed engine, the degenerate-column and swap-register entries, and the H2 fixture regenerated. The contract's TFC citation is corrected, the targeted rationale added, and the extended-hours distribution moved to `frozen_by_adjudication`. The childcare fitter is rewritten: targets compiled from the contract and the pinned feed, four rates, hours frozen, identity-keyed draws, `--eps` recorded in the receipt. Lane B (D8–D13): five childcare rows declared once and resolved by period (`hmrc.tfc.*` at fiscal-year government/person grain; the three DfE rows with the `sum` cardinality guard, the `difference` operation and the observation basis), the two England bus rows active at household grain and the London, outside-London and UK rows declared with model-side filters but signed on the new `target_reference_signed_exclusions.json`; national references, membership, local references and the compile-parity receipts regenerated on feed `6ae49d7d…` (415 active / 7 no fact / 8 signed). Publisher fixtures for the tests are Chronicle rows (`uk_bus05i_fy2025.json`), never hand-copied. Two I0 defects fixed here: `dwp.uc.scotland_households_child_under_1` keeps its household-grain binding (the measure provider has no categorical household-to-benefit-unit broadcast, so the benefit-unit re-bind refused at calibration), and the held London / outside-London bus rows carry their region filters. Receipts: `experiments/834-childcare-tfc-receipts.md` Parts C–E (L2 column twin, L3 round trip, L5 fit diagnosis, bus re-measurement, both-basis table). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd land the extended and universal rates (#834 L5) The fitter no longer draws. The build keys each take-up flag on the spine's int64 benunit id at the frs_take_up stage and later stages clone and re-key rows, so no re-drawn realisation can sit on the persisted one (re-hashing the final ids agrees with the persisted universal flag on 66% of rows, chance being 51%), and the draw objective was a step function whose finite-difference step flipped no unit on the targeted row's ~157-child base. Two engine runs with the flags forced on (extended on, then off) now give each row's weighted per-row contributions; each target's expectation is linear in its own rate and bilinear with the extended rate through the engine's mutual exclusions (targeted and universal need a family that is not extended-eligible). The objective is smooth, exact for the build, and the receipt reports each row's ceiling at a take-up of one. Unit test pins the bilinear form; `--eps` is recorded in the receipt. Fitted on the L2 column twin at the 2024 base year (Jan-2025 vintage override on the extended row, routed share 0.593 from the contract, hours frozen): extended 0.812 → 0.6054 and universal 0.563 → 0.4539 land as 2024-04-06 entries with a `fitting_receipt`. `tax_free_childcare` (0.997, at its ceiling: with spend routed the two HMRC rows conflict) and `targeted_childcare` (1.0, the eligible base reaches 0.85 of the count) are held at 0.88 / 0.597 for adjudication (plan A22/A23); a rate of 1.0 would also make the persisted flag constant. Receipts Part C L5 carry the three fits, the probes and the rebuilt twin's magnitudes; the swap register signs the two moved flags as `childcare-take-up-refit-834`; the H2 graph parity fixture is regenerated (the take-up stages' node keys fold the contract sha) and the contract test's pinned rates follow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Run 1 is the weighting-sensitivity receipt (per-target uniform weights); run 2 the family-equal composition, equal to L4-pre to the second decimal with the seven new rows binding within 0.5%; run 4 reproduces it on a payload-identical rebuild with the seam supplying the exclusion clock, so the ported target-fit register renders its verdict: the four UC with-children cells defer, OBR CGT and the two state-pension bands fail unsigned, the private-pension band entry reads stale. The runner's --build-record-json is the seam's own output; the note records how run 2 overwrote the twin's spine sidecar and why the twin was rebuilt. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…w reference fields in monetary-binding receipts (#834) The live-tree guard refuses the incumbent package name: the signed target-reference exclusions register now cites uk-data#230 and the uk-data PR as every other live file does. The monetary binding's activated-reference receipt is an exact key set; LedgerTargetReference gained value_operands and expected_member_count for the multi-member childcare rows, so the receipt contract and its hermetic fixture carry them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
# Conflicts: # out.md # packages/microcosm-build/tests/conftest.py
María ruled A21 as option 1 on 2026-09-05: the facts stay bound as published and obr.capital_gains_tax@2025 is signed on the publication stack's register under microcosm#875 (window to 2026-10-05). Run 5 reproduces run 4 and the battery now defers five cells; the two state-pension bands and the stale private-pension band entry remain the stack's open questions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…fix (#834) The membership report embeds the signed-exclusion rationale, so the citation fix in the register moved its digest; the references themselves are byte-identical. The packaged-report test carries the uk-data wording. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dentity (#834) Main's #871 attests the workspace lock; this branch's policyengine-uk floor bump (>=2.93, lock 2.94.0) changed uv.lock, so the merged tree's digest is approved. No derived identity moved: the spec-engine identity, legacy adapter, re-emission, field-usage and inventory-coverage suites pass on the approved digest without a re-pin. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…834) The provenance receipt read policyengine-uk's version unconditionally, so the hermetic determinism test with an injected runner failed in CI's no-engine lanes (fast spine-uk, wheels) while every engine lane passed. The version is recorded as absent when the distribution is missing; a real fit still needs the engine for its basis runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Closes #834 and #789 (WS-E of #145, epic #665). Plan:
repos/uk-834-childcare-tfc-port-plan.md(approved 2026-09-04, re-based on main96faa5d5); Codex implemented increments I0–I2 under the approved-plan protocol (deviations listed below), followed by the licensed lane (L0–L5) whose receipts are inexperiments/834-childcare-tfc-receipts.md. Stacked on #849 (A11: the v2/v3 artifact loader this feed needs): #849's 22 commits ride in this diff until it merges, after which this branch rebases and the diff is #834's own. Base ismainso CI runs on the merge ref. Draft — María reviews everything at the end; never merge without her go.What the issue asked for, re-measured against main
tax_free_childcare_spend_routed_share(uk-data #472)assign_period_constantop infrs_person_draws, reading a newstochasticentry oftake_up_contract.jsonat the build year (2024-04-01 → 0.593; series 2017–2025 from HMRC's account-activity ODS, Chronicle package pinned by sha). Engine floor ≥2.93, lock 2.94.0.hmrc.tfc.government_top_up,hmrc.tfc.children_with_used_accounts,dfe.funded_childcare.working_parent_children_2_to_4,dfe.funded_childcare.early_learning_2_year_olds,dfe.funded_childcare.universal_only_children— declared once, resolved by period (Part E): the issue's five numbers at 2024, the FY2025-26 / Jan-2025 counterparts at the 2025 calibration year.dft.bus_fare_receipts.englandanddft.bus_net_support.englandactive at household grain; London / outside-London / UK rows declared with model-side filters and signed-excluded until the regional measure lands (target_reference_signed_exclusions.json).226358e7feed (v1 schema); 12 references broken on the current feed.6fb700e(128 717 rows, facts sha6ae49d7d…, manifest shadcda51d6…, v2 schema via #849); contract repaired by declaration only (Part A / plan §5c).Contract repairs carried by the re-pin (I0)
The previous feed pin (
226358e7, schema v1) broke 12 references on the current Chronicle main and moved 101 values. The repair is declaration-only: UC household rows re-bound to thedwp.uc_householdsfamily-type/children/youngest-child series withdimensions(exact key set) +dimension_values(subset) selectors and 2025 calendar-year averages (April–December, the months the feed carries); the caseload row keeps DWP deductions Table 1total_unitswith a tightened selector (A16; chronicle#247 filed for the Stat-Xplore family-type Total row); the two CGT totals bound to Table 1'sTotalline (Table 5 duplicates excluded bysource_measure_id); the stale PIPR deferral retired and the available local rent rows activated on the same temporal basis (A18); the runner now requires--ledger-manifest-sha256and refuses a feed that is not the committed pin unless--allow-unpinned-feedis recorded. One I0 defect surfaced by the L4-pre calibration is fixed in this PR's second commit: the Scotland youngest-child row keeps its household-grain binding (the measure provider has no categorical household-to-benefit-unit broadcast). Receipts Part A;docs/uk-chronicle-feed-repin.md.Surfaces moved
Lane A:
assign_period_constantoperation kind (schema branch, allow-list,sources.yaml+ byte-lockstepsource_stages.json);frs_person_drawsartifact pin of the take-up contract (its sha folds into the node key) and build-year lockstep check;take_up_contract.json(newstochasticentry; hours entryfrozen_by_adjudication; fourprogramsentries with corrected citations, two re-fitted withfitting_receipt); loader validation ofentity; H2 parity fixture regenerated (twice: the column, then the contract sha); coverage manifest;degenerate_reviewed_exclusions.json(+1);spine_swap_signed_differences.json(net-new column; re-fitmechanism_changewith L5 magnitudes); contract digests; roster pins. Lane B:uk_population_targets.json(+7 active rows, +6 signed-held bus rows, Scotland row grain);differencevalue operation withvalue_operands;expected_member_countcardinality guard;observation_basis;entity_name/period_type/period_value/layout_groupby_value_idselector keys;target_reference_signed_exclusions.json(new register, declared in the country package); regenerated national/local references, membership and compile-parity receipts (415 active / 7 no fact / 8 signed on feed6ae49d7d…); test fixtures from Chronicle rows only (uk_bus05i_fy2025.json, feed rows appended). Fitter:tools/fit_uk_childcare_takeup.pyrewritten (tool version 3). Engine:policyengine-uk>=2.93, lock 2.94.0.Deviations from the plan
frs_take_upstage and later stages clone and re-key rows, so no re-drawn realisation can sit on the persisted one (66% flag agreement re-hashing final ids; chance 51%), and the draw objective is a step function whose 1e-2 finite-difference step flipped no unit on the targeted row's 157-child base (first fit left it untouched). The fitter now takes two engine runs with the flags forced on and fits each row's expectation (linear in its own rate, bilinear with the extended rate through the engine's mutual exclusions): smooth, exact for the build, ceilings reported. Plan A24; receipts Part C L5.Verification
test_contract.py, the graph package incl.test_h2_uk_spine_parity), JUnit-counted from this branch's venv with policyengine-uk 2.94.0: 2 893 tests, 2 failures, 27 skipped — the two failures are the documented licensed-cache regeneration tests (test_cached_reference_regeneration…,test_cached_candidate_regeneration…: committed evidence minted under 2.89.0 vs the installed engine, Make the UK eFRS parity re-pin one reviewed command; hold every identity mirror in lockstep (companion to #747) #749's lane), failing on main the same way. Post-port targeted set 468 passed / 1 skipped. After the L5 landing: graph package + digest-sensitive set 463 tests, the same single licensed-cache failure.ruff checkclean on every touched file;tools/ci_test_groups.py --verifyok;tools/build_uk_release_input_coverage_manifest.py --checkok. CI is authoritative. Mergedmainc1b83241(Portable authenticated worker identity: semantic identity plus audit-only aliases for the primary-QRF worker binding (fixes #863) #871, portable worker identity) on 2026-09-05: two conflicts (a root journal kept at main's version; the build tests' conftest keeps both Accept chronicle-era Chronicle artifact schema ids and fact-key domains; CHRONICLE_* env names (chronicle#143 consumer side) #849's Logbook isolation and Portable authenticated worker identity: semantic identity plus audit-only aliases for the primary-QRF worker binding (fixes #863) #871's worker-identity priming), the primary-QRF worker identity's approveduv.lockdigest moved to the merged tree's (this branch's engine floor bump changed the lock) with no derived identity re-pin needed (spec-engine identity, legacy adapter, re-emission, field-usage and inventory-coverage suites green), and the national membership report regenerated after theuk-datacitation fix. Post-merge set: 1 027 tests on the identity, pin, UK contract, graph and data-contract files with only the documented licensed-cache failure. Full-tree funnel on the L5 tree (every shard's tests, 8 233 tests): 19 failures — 13 US tests that needpolicyengine-us(this venv carries the uk extra only; the same files fail on a cleanorigin/maincheckout in the same venv), the same two licensed-cache tests, and four of mine, fixed in the last commit: the live-tree guard found the incumbent package name in the new signed-exclusions register (nowuk-data#230), and the monetary-binding receipt contract needed the two new reference fields (value_operands,expected_member_count) —test_monetary_targetsand the calibrate shard's monetary tests green after the fix.uk-publication-stack-834(ca050866,8c8f60d9,9b71e0f8,9ab60650— register port, required artifact, seam clock, signed CGT deferral — on this branch's head): the register port's 406-test set green (pins, spec bundles, source stages, terminal gates, battery bindings, gate battery, release certification,test_contract.py).Licensed lane (receipts Parts B–D; raw JSON licensed-side)
uk-publication-stack-834): on the rebuilt twin,family_equalas L4-pre: loss 0.352 → 0.0235, 90.0% of 371 targets within 10%, ESS 5 868. The seven new rows all fit within 0.5% (targeted from 0.77× at design weights to 0.997). The pre-existing surface is where L4-pre left it to the second decimal: the same sevenuk_target_fitbreaches (OBR CGT +44.2% — A21; the four UC with-children cells −29…−39% signed on the stack's register to 2026-09-30; the two state-pension SPI bands +35% / +25%), UC caseload −13.4%. The port neither helps nor harms the Port UK compact source stages and 2024-25 refresh from uk-data #145 residuals. Terminal battery with the ported register (run 5, after María's A21 ruling): the four UC with-children cells and OBR CGT (+44.2%, signed 2026-09-05 → 2026-10-05 under UK CGT: translate the 2024-25 gains outturn to the 2025 calibration year (forestalling year; OBR CGT +44.2% signed on the stack register) #875, the 2024-25 → 2025 translation of the forestalling-year gains) defer under their in-force entries;uk_target_fitstill fails on the two state-pension SPI bands (+34.6% / +25.3%) and reports the private-pension 100–150k deferral stale (+24.7%, back inside the bound). Those are the stack's open register questions, not Port post-freeze UK childcare/TFC spine inputs and calibration contract #834 rows.UK-specificity note
The routed share, the DfE/HMRC taxonomies and the DfT geographies are UK;
assign_period_constant,difference,expected_member_countandobservation_basisare generic surface machinery.Not in this PR
The publication-stack target-fit register itself, including the new CGT entry (lives on
uk-publication-stack-834, the composition branch, not for merge on its own); the #875 translation; the expected-count objective's extension to the fourwould_claim_*build draws (they stay identity-keyed by design); pointer comments on #789/#790 and closing #153 (each on María's go); the London / outside-London bus measure (#790's gradient); chronicle#247 (Stat-Xplore Total row); the CGT year (A21).🤖 Generated with Claude Code