Repository navigation
Accept a restated Ledger filter bound only where it agrees with the compiled constraint - #969
Merged
Merged
Conversation
…cept Constants only; the rule, its call sites and tests follow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A labelled Chronicle feed restates a fact's universe constraint in the Ledger's concept vocabulary (ledger_filter_us:statutes/26/62#adjusted_gross_income_lower_bound) beside the compiled metadata the US fiscal materializer slices on (agi_lower_bound). Both keys restrict the microdata, so neither can join SUPPORTED_LEDGER_FILTER_METADATA_KEYS outright: a future feed whose labelled bound disagreed with the compiled one would then be silently ignored, materializing a wider population than the published cell covers. _restated_ledger_filter_refusal accepts such a key per spec, and only when the spec also carries the constraint the materializer applies and the two select the same population — numeric equality against agi_lower_bound / agi_upper_bound including the compiler's -inf and inf ends, and mask equality against _soi_eitc_child_count_filter over the probed child counts. Anything else keeps the present refusal, extended to name the values that disagree. The same rule runs in _unsupported_soi_ledger_filters, which is consulted where a non-empty result skips the spec from SOI materialization with no error: accepting a restatement at the fatal guard while leaving it listed there would only move the spec from a refusal to a silent disappearance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A fixture of compiled US fiscal target metadata — one target per (family, target_role), four IRS SOI rows carrying an AGI band or an EITC child-count filter, and a key census covering all 32,866 compiled targets — taken from compile_us_fiscal_target_registry over the Chronicle feed #955 pins. The regression asserts no target is refused, no irs_soi target falls into the SOI slice's silent skip, and that every ledger_filter_* key the feed carries outside the supported and identity sets is noop-valued on every target, so "zero unsupported" holds for the whole registry and not only the sample. A second test replays the restated-constraint rule over the real compiled bands, since the pinned feed states its AGI band only as compiled metadata: each banded target's own lower edge is accepted and the same edge moved is refused. A third arm compiles the state-level surface from the real feed when MICROCOSM_US_CHRONICLE_FACTS points at it, and skips otherwise — the 164 MB export is on no CI lane and the compile takes order ten minutes. experiments/us-labelled-filter-support/census_compiled_ledger_filters.py is the receipt that regenerates the fixture and measures both guards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Line references rot on the next edit to a 5,000-line tool; the constructs they pointed at are reachable by name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The refusal this lane was written against does not reproduce at this head: the feed #955 pins carries its AGI band and child count as universe constraint rows and plain dimensions, and the tree's single ledger_filter_* producer stamps dimensions only, so no compiled target carries a concept-vocabulary key. All three measured surfaces refuse nothing. The report states the derivation, the counts by family and target_role, the dense float32 matrix sizes beside the historical ACS local release, and the open questions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both workflows trigger only on pull requests whose base is main, so the stacked PR gets no checks until #955 merges and it retargets. The report carries the local pytest, ci_test_groups --verify and ruff exit codes in their place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sections 1-6 of the lane report were measured before this branch merged origin/main, which is where _constraint_bound_filters lives: it stamps a fact's numeric universe constraints as ledger_filter_<variable>_bound keys, and those are the restated keys the rule here accepts. Section 5 said the premise did not reproduce; on the re-levelled head it does, so section 7 records the mechanism, the three counts (1,988 refused without the rule, 0 with it, 1,988 with both call sites reverted) and the 939 age-band refusals that are main's and survive this branch. The committed fixture predates that merge, so its key census lists none of the restated keys. It stays as the pre-merge pin it is; its description and the two tests reading it now say so, and the live-feed arm's docstring records that it now meets 1,988 real restated keys. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Re-level #969 on main now that #955 (us-chronicle-feed-repin) merged at 6710d0f. No textual conflicts; tools/build_us_fiscal_refresh_release.py and packages/microcosm-build/tests/test_us_fiscal_refresh_builder.py auto-merged (main added the committed-feed pin check and the SPM composition gate; this branch adds the restated-filter rule). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…erged Re-measured at the main-based merge b10e117 (main 6710d0f): state surface full 31,066 specs, 0 refused with the rule and 1,988 with it reverted (2,702 entries); whole registry 939 versus 3,208. The b571381 export gives the same counts as the pinned c5e5bf8 feed. Every number equals section 7; the stacked-PR and no-CI lines are historicized in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add measure_restated_filter_arms.py, which compiles the US fiscal registry through the production path for each Chronicle feed and counts _unsupported_ledger_filter_metadata refusals and _unsupported_soi_ledger_filters skips on the whole registry and the ACS local state surface (full and totals), with the restated-filter rule and with it reverted to the bare key (main's behaviour). Its output over both US exports is committed as restated_filter_arms_receipt.json (aggregate target-spec counts only, no microdata). REPORT.md section 8 now cites the receipt, and labels which earlier-section numbers it regenerates and which are records of uncommitted runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section 8 now lists the checks run at b6e0b04 (origin/main 2b85b7b merged in): the builder module against the pinned feed, the 29 other modules importing the release tool or ledger_targets, ci_test_groups --verify and ruff. The 15 failures and errors in that run were all disk exhaustion (ENOSPC) in test_us_multispine_pool_tool.py, and the affected tests pass on re-run; the report says so rather than folding them into a pass count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…onfirms its operator Max's rulings on #969 (2026-09-22). A restated us.tax.earned_income_credit_qualifying_children upper bound is no longer read as exclusive and compared: _restated_eitc_child_count_refusal refuses it outright, naming the unconfirmed operator (< or <=), whatever the spec compiles. Lower and exact restatements keep the agreement rule, and the comparison raises if any other bound side reaches it, so emptying RESTATED_EITC_CHILD_COUNT_REFUSED_SIDES cannot fall back to an exact-count comparison. Tests: the upper case leaves the acceptance test; new tests prove the refusal (both the < and <= readings, no child-count filter, the fatal guard, the SOI skip), the no-guess fallback, and that agi_{lower,upper}_usd stay refused by bare key (Q2: not added as concepts). REPORT.md section 6 gains a dated rulings block: merge (premise evidenced on main), do not add agi_*_usd, totals becomes the ACS local default in a separate PR, refuse EITC upper bounds here, and the 939 age-band refusals get their own PR. The committed receipt's reverted arm lists no qualifying-child upper-bound key on any surface of either feed, so its counts stand; the measurement was not re-run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 22, 2026
MaxGhenis
marked this pull request as ready for review
September 23, 2026 00:53
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.
Re-levelled on
mainafter #955 (us-chronicle-feed-repin) merged at6710d0f5f; base ismain. This was first opened stacked on #955.origin/mainwas merged in at6710d0f5fand again at2b85b7b22(#976) with no conflicts, and nopackages/*/srcfile differs frommain. The restated-filter counts below reproduce unchanged on themain-based tree, for both US Chronicle exports on this machine; they are now committed asexperiments/us-labelled-filter-support/restated_filter_arms_receipt.json, written byexperiments/us-labelled-filter-support/measure_restated_filter_arms.py(rule and rule-reverted arms; the reverted arm ismain's guard behaviour).REPORT.mdsection 8 cites it.2026-09-22: Max's rulings on the four open questions are applied on this head — see Rulings below. The one code change they required: a restated EITC qualifying-child upper bound is now refused outright.
What this does
A labelled Chronicle feed can restate a fact's universe constraint in the Ledger's own concept vocabulary —
ledger_filter_us:statutes/26/62#adjusted_gross_income_lower_bound— beside the compiled metadata the US fiscal materializer actually slices on (agi_lower_bound). Both keys restrict the microdata, so neither can joinSUPPORTED_LEDGER_FILTER_METADATA_KEYSoutright: a future feed whose labelled bound disagreed with the compiled one would then be silently ignored, materializing a wider population than the published cell covers. That is exactly the failure_assert_supported_ledger_filter_metadataexists to stop._restated_ledger_filter_refusalaccepts such a key per spec, and only when the spec also carries the constraint the materializer applies and the two select the same population:agi_lower_bound/agi_upper_bound, including the compiler's-inf/infends. Bound sides are judged independently; a suffix-free (exact-value) AGI restatement is refused, because the materializer applies a half-open band and no exact-value AGI filter._soi_eitc_child_count_filter, the function the SOI loop calls, evaluated through_eitc_child_count_maskover the probed counts. A lower bound of3agrees with3plusand only with it; a suffix-free key restates an exact count. An upper bound is refused outright, before any comparison, until the Ledger confirms whether it means<or<=(RESTATED_EITC_CHILD_COUNT_REFUSED_SIDES; Max's ruling, 2026-09-22). The two readings select different returns —< 1agrees with a compiled0, and so does<= 0— so neither is guessed.Anything else keeps the pre-existing refusal, extended to name the values that disagree:
Unknown
ledger_filter_*keys are untouched and still refuse under their bare name.The same rule runs in
_unsupported_soi_ledger_filters. That checker's non-empty result skips the spec from SOI materialization with no error at all, so accepting a restatement at the fatal guard while leaving it listed there would only have moved the spec from a refusal to a silent disappearance. A disagreeing restatement stays listed, and the fatal guard at the top of the same_materialize_target_framerefuses it before the loop runs, so the silent skip is unreachable for one.The premise reproduces — and why the first measurement said it did not
An earlier revision of this body reported zero unsupported keys on every surface and concluded the rule was forward-compatibility scaffolding. That measurement was correct for the tree it ran in and is now superseded. Both branches have since been re-levelled on
origin/main(18c6d39a0), and the refusal is real.The missing piece is
microcosm.build.ledger_targets._constraint_bound_filters, which postdates this stack's merge base8c44daa52— it arrived onmainwith theparameter_gated_thresholdfilter-aware work in the UK CGT lane (changelog725-filter-aware-gated-provider.changed.md). It runs inside_ledger_metadataimmediately after the dimension stamp:and promotes every
role: filteruniverse constraint with a>= > < <=operator, a finite numeric value, and a variable that is not already a dimension intoledger_filter_<variable>_lower_bound/_upper_bound. The earlier reading — "ledger_targets.py:3257is the only producer ofledger_filter_*metadata and it stampsdimensionsalone; nothing synthesises a*_lower_boundkey from a constraint row" — was true of the pre-merge tree and is precisely what stopped being true. The feed never changed; it has always stated the AGI band and the qualifying-child floor asuniverse_constraints, and those rows are now filter keys.Measured against the pinned feed, re-levelled
tools/build_us_acs_local_release.py::state_admin_specs(feed, ["snap","medicaid","soi"], soi_mode="full")over the feed #955 pins (Chroniclec5e5bf8,consumer_facts_us_c5e5bf8.jsonl, 39,158 facts), counted with the production guard functions. 31,066 state specs in every run._unsupported_ledger_filter_metadata_unsupported_soi_ledger_filtersorigin/main, no ruleThe 1,988 refused specs carry 2,702 refusal entries:
ledger_filter_us.tax.earned_income_credit_qualifying_children_lower_boundledger_filter_us:statutes/26/62#adjusted_gross_income_lower_boundledger_filter_us:statutes/26/62#adjusted_gross_income_upper_bound— the three keys this rule was written for, in the vocabulary it was written for. So this is not a forward guard: it is what keeps the ACS local state surface compiling now that #955 is on
main.State-level target counts by family and
target_roleare unchanged from the earlier compile (irs_soi|soi_fiscal_distribution30,306,irs_soi|aca_ptc_returns547,irs_soi|aca_spending60,usda_snap|snap_households51,usda_snap|snap_total51,cms_medicaid|medicaid_enrollment51), as are the measure-matrix sizings inexperiments/us-labelled-filter-support/REPORT.md§4. No selection or default changes in this PR.Adjacent and not fixed here: 939 age-band refusals
_constraint_bound_filtersalso stamps the bare vocabulary. Over the whole compiled registry (32,866 targets, not just the ACS state surface), measured againstorigin/main18c6d39a0with none of this stack applied:origin/main18c6d39a0aloneMain's 3,208 split
irs_soi|soi_fiscal_distribution2,269,census_population|population_age936,ssa|ssa_ssi_age_band_recipients3. This PR clears the 2,269. The remaining 939 areledger_filter_age_lower_bound/ledger_filter_age_upper_boundrestating theage_lower_bound/age_upper_boundthat_population_age_household_valuesalready slices on — the same pattern, one concept further out, and not a regression of this stack: it arrives with_constraint_bound_filtersand refuses onmainalone for any caller that materializes the age family. The ACS local state surface never selectscensus_populationorssa, which is why the state-surface table reads 0.Adding
agetoRESTATED_LEDGER_FILTER_CONCEPTSunder a thirdage_bandrule would be a one-rule change of the same shape, but it widens what this PR accepts beyond the surface it was reviewed against. Per Max's ruling (2026-09-22) it gets its own follow-up PR; this PR adds noageconcept.Rulings (Max, 2026-09-22)
The four questions in
REPORT.mdsection 6 are answered; the report records them in a dated block there.main(report section 7; section 8's committed receipt: 1,988 state-surface refusals with the rule reverted, which ismain's behaviour, 0 with it).agi_lower_usd/agi_upper_usd— do not add them toRESTATED_LEDGER_FILTER_CONCEPTS. The guard already refuses an unknownledger_filter_*key loudly:_restated_ledger_filter_refusalreturns the bare key for a concept it does not name (tools/build_us_fiscal_refresh_release.py:4634-4635) and_assert_supported_ledger_filter_metadataraises (:4675-4687). Newtest_legacy_agi_usd_dimensions_stay_refused_by_bare_keypins that, even where the legacy value equals the compiled edge.soi_mode="totals"becomes the ACS local default, with the AGI-band distribution opt-in. Done in a separate PR, not here; this PR still changes no default or selection."upper"from the refused set cannot silently fall back to an exact-count comparison. The receipt's counts do not change (deduced from the committed receipt, not re-measured): its reverted arm lists every otherwise-unsupported, non-noopledger_filter_*key by bare name, and on every surface of both feeds the only qualifying-child key is…_lower_bound; no…_upper_boundor…_upper_bound_inclusivekey appears, and the compile (packages/*/src) is untouched. An ad hoc scan of both feeds (not committed) agrees: their qualifying-child constraint rows use only==(3,534) and>=(1,180).Tests
test_restated_agi_bounds_pass_the_guard_only_where_they_agree— both bounds, lower only, upper only, and the-inf/infends.test_disagreeing_restated_agi_bounds_are_refused_by_value— disagreeing lower, disagreeing upper, a bound on a spec compiling no band, an exact-value restatement, and an unknown key as the untouched control; asserts the refusal text.test_restated_eitc_child_bounds_pass_the_guard_only_where_they_agree—3with3plus, exact2with2. (Its former upper1with0case now lives in the next test, as a refusal.)test_restated_eitc_child_upper_bounds_are_refused_outright(2026-09-22) — upper1with0(agrees if read<) and upper0with0(agrees if read<=) are both refused with the operator reason, as is an upper bound on a spec with no child-count filter; an exact restatement and an AGI upper bound on the same spec are still accepted; the fatal guard raises and the SOI skip keeps the key;_upper_bound_inclusivestays refused by bare key.test_restated_eitc_child_comparison_never_guesses_an_upper_reading(2026-09-22) — with the refused-sides set emptied, an upper bound raisesValueErrorrather than being compared as an exact count.test_legacy_agi_usd_dimensions_stay_refused_by_bare_key(2026-09-22) —ledger_filter_agi_{lower,upper}_usdequal to the compiled band are refused by bare name at both call sites, and the fatal guard raises.test_disagreeing_restated_eitc_child_bounds_are_refused_by_value—3with2,3with no child-count filter, a non-count value.test_restated_filters_clear_the_soi_skip_only_where_they_agree— the SOI checker clears an agreeing restatement, keeps a disagreeing one, and the fatal guard refuses the disagreement first; unknown SOI filters unchanged.test_restated_concept_rules_all_have_a_comparison— every named concept routes to an implemented rule.test_pinned_chronicle_feed_compiles_no_unsupported_ledger_filters— the compiled-metadata fixture clears both guards, and every unclassified key in its registry-wide census is noop-valued. The fixture was captured before the re-level, so its census predates_constraint_bound_filtersand lists none of the restated keys; it is kept as the pre-merge pin it is, and the fixturedescriptionand both tests reading it now say so.test_restated_bounds_track_each_compiled_band_in_the_fixture— replays the rule over real compiled bands, agreeing and perturbed.test_pinned_chronicle_feed_state_surface_compiles_no_unsupported_filters— this is now the arm that meets real restated keys. Before the re-level it passed over a feed compiling none; it now passes over 31,066 real specs of which 1,988 carry one, and reverting either call site fails it on exactly those 1,988.CI
This PR now targets
main, so both workflows (pull_request: branches: [main]) run on it. While it was based onus-chronicle-feed-repinthey triggered nothing, so it was verified locally, at the re-levelled head before #955 merged:Every test file either merge touched (45 files, both packages) also runs green on this head: 2,752 passed, 13 skipped, 0 failed across four batches, every batch exit 0. No attested spec-engine module was touched, so no identity pin moves.
At
b6e0b04cd(after mergingmain2b85b7b22), locally: the builder module against the pinned feed, 245 tests, no skips, exit 0; the 29 other modules importingtools/build_us_fiscal_refresh_release.pyorledger_targets, 1,405 passed, 13 skipped, and 11 failed plus 4 errors, all intest_us_multispine_pool_tool.pyand allOSError: [Errno 28] No space left on device(the machine's disk filled mid-run); the seven affected test functions re-run with the disk clear, 22 passed, exit 0;ci_test_groups.py --verifyok; ruff check and format clean on the changed files. Details inREPORT.mdsection 8.At
01dc806f4(the rulings commit), locally: the builder module against the pinned feed, 248 passed in 80.37s, no skips, exit 0 (the feed arm ran);ci_test_groups.py --verifyok;ruff check .clean;ruff format --checkclean on the two changed.pyfiles. The other modules importing the builder were not re-run: the change is confined to_restated_eitc_child_count_refusaland its constants, reached only through the two guards. Details inREPORT.mdsection 6, "Rulings".🤖 Generated with Claude Code