Skip to content

Add AS entitlement bridges, take-up gaps and scenario bands (NZ graph G7) - #1181

Merged
MaxGhenis merged 5 commits into
mainfrom
transport/as-entitlement-gap
Oct 10, 2026
Merged

MaxGhenis merged 5 commits into
mainfrom
transport/as-entitlement-gap

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

G7 of the Microcosm NZ graph plan (Max's d962): the Accommodation Supplement chain, built on G6's skeleton (#1161, merged) through its extension point. Under the hub's G6/G7 split amendment, G7 owns the scenario- and gap-dependent properties.

What it adds

  • simulate.counterfactual@1 and simulate.solve_zero@1 in packages/microcosm-frame/src/microcosm/frame/rules_kernels.py. Both take an {engine_ref: RulesEngine} mapping, so the base rate can read more than one module (R15), and both use only the RulesEngine protocol. solve_zero is vectorised per-row bisection with a fixed iteration count and a declared tolerance, so it is deterministic. It requires independent, non-increasing row residuals; coupled systems are explicitly not supported. It evaluates the returned answers and refuses any residual that is positive beyond the tolerance, and it reports its fixed evaluation count (iterations + 3). Implementation identity binds the code and adapter classes; selected spec values and their resource digests go in node params.

  • takeup.gap@1 and takeup.bands@1 in build/transport/takeup_kernels.py. The gap compiles declared references, then computes E, the annualised weighted selected measure (dollars for expenditure references, counts for count references), the published comparator A, and E − A exactly. Bands keep min, central and max per table, and each bound names the scenario that set it.

  • build/transport/entitlement.py: the AS chain as a spec-declared TransportExtension. It covers the bridges, the AS rules node, scenarios S0–S5, variants V1–V3, grouped and count gaps, bands and a WFF tripwire. An optional entitlement_graph spec resource installs it, and its resource shape is documented in docs/transport-entitlement.md.

  • One change to G6's extension guard, which reviewers should check. An extension may now add typed artifact edges (TransportExtension.package_inputs) to the skeleton's terminal transport.package@1 node, so the final receipt can carry gaps and bands. Each condition is enforced in compose.py:

    • the target must be a skeleton package node with no successors;
    • the edges must come from extension nodes;
    • aliases must be new and distinct;
    • the post-composition check accepts exactly those extra predecessors.

    Every other skeleton node's predecessor set stays fixed. Plan §2.3 has bands feeding nz.package, and the amendment expects nz.package to miss when S1 changes.

  • tools/transport_bridge_differential.py: a hub-run driver for small-case and sampled-unit differentials against the axiom-oracles Treasury IncomeExplorer cases. Before preparing anything it refuses ambiguous cases: empty or duplicate call IDs, two calls writing one output, and comparisons naming a missing or ambiguous call. It also refuses missing or invalid oracle values and tolerances. Oracle pointers follow RFC 6901, with canonical non-negative array indices and bounds checks. Without the engine it writes a skipped receipt. Assembling golden-08 itself is unresolved, pending the approved case. The committed bridge declaration (build/nz/as_rate_bridge.json) recovers the threshold and slope from three evaluations rather than a zero solve, and the driver cannot yet express that composition. No real-engine result is claimed in this PR.

Invariants (Hypothesis property tests on an engine-free toy graph with invented engines)

  • 0 ≤ AS ≤ the unit's area maximum.
  • AS = 0 when cash assets exceed the limit or an exclusion applies.
  • For non-beneficiaries, AS is non-increasing in income, and non-decreasing in qualifying costs below the cap.
  • Weighted total = Σ family weight × annualised AS.
  • Gap = E − A exactly.
  • Bands are ordered low ≤ S0 ≤ high, and each bound names its scenario.
  • Determinism.
  • Locality, from the amendment:
    • A3: S1's knob misses exactly nz.scn.S1.*, nz.as.bands and nz.package.
    • A6: hold-out fact bytes miss only the gap, validation, bands and package nodes.
    • C2: adding a scenario re-keys only bands and package.
  • Differentials: the bridges and AS graph match direct toy-engine calls; counterfactual matches direct engine evaluation.

Not in this PR (activation, G8 and D1)

  • No NZ rates, thresholds or spec values are added, and the real NZ spec still refuses.
  • Real NZS/VP base-rate correctness needs the hub's approved bridge data.
  • The real WFF tripwire stays parked until its input encoding, three chained module bindings and Child-rule treatment are approved.
  • The target compiler has no aging-index parameter, so calibration variants use explicit target-reference resources.

Tests

Run by the hub at b2c8e38, one file at a time: test_transport_bridge_differential.py 37, test_counterfactual_kernels.py 27, test_transport_graph.py 15, test_transport_takeup_kernels.py 22, test_transport_entitlement_graph.py 23, test_transport_composed_graph.py 137, test_transport_column_kernels.py 29. All passed. The fix lane also ran test_transport_registry.py (31), the spec-only test (8) and test_ci_integration_job.py (9), for 338 in total. Every one of its 84 new or changed cases fails on 8ac9b1f or under a named mutant. tools/ci_test_plan.py verify, ruff check and format, and git diff --check pass.

Review

Part of Microcosm NZ v0 (d962), package G7. Built on a GPT-6.1 Sol Subfleet lane; verified, committed and opened by the NZ hub.

🤖 Generated with Claude Code

MaxGhenis and others added 5 commits October 9, 2026 23:19
Register counterfactual and fixed vector-bisection kernels against one prepared
engine map. Compose spec-declared entitlement scenarios, independent calibration
variants, held-out comparisons and labelled bands into the final receipt.

Keep calibration independent of AS and hold-out inputs, bind scenario knobs
separately, and preserve every skeleton predecessor set except explicit final
receipt artifact edges. Cover AS bounds, exclusions, monotonicity, weighted
totals, exact gaps, deterministic labelled bands and cache locality with
engine-free properties and differentials. Leave real activation and receipts
to the hub; include a local golden-08/sample differential driver.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1180 had not landed when the round-1 fix lane ran, so G7 merges its
branch directly; once #1180 merges to main, later merges of main are
trivial. The one conflict, packages/microcosm-build/src/microcosm/build/
transport/compose.py, is resolved with the fix lane's tested version: it
keeps #1180's preflight (shared resource-selection resolver, malformed
names, receipt-contract validator, references, age, pins, null knobs) and
adds G7's entitlement/scenario selections and the terminal-package
exception. That resolution also carries the lane's finding-5 change
(activation reads only rows the entitlement factory instantiates), since
both edit the same function. The rest of the lane's fixes follow in the
next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Validate differential call identities, output ownership, comparisons and
canonical oracle pointers before registry preparation. Verify returned
row-independent bisection answers with a fixed final engine evaluation.

Resolve G6/G7 activation intent using the entitlement factory's selected rows
and shared resource preflight. Correct the golden-08 and deferred-law claims.
Preserve origin/main and transport/g6-review-nits changes in the prepared tree.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Main's only new commit is #1180's merge, whose content this branch already
carries (merged from its branch in 1679bf3); the tree is unchanged. This
merge gives GitHub a single merge base again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 2fc2e70 into main Oct 10, 2026
10 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Merged by the NZ hub (session local_e407a527) at 809d138 with --merge. Gates: gh pr checks exit 0; MERGEABLE; not draft; no CHANGES_REQUESTED review. Reviewed head: 809d138. Independent review chain: r1 (GPT-6.1 Sol at 8ac9b1f) REQUEST_CHANGES on two blockers (duplicate differential call IDs could give a false pass; solve_zero could return a positive residual on coupled rows) plus four findings (jobs/review-microcosm-1181/REPORT-r1.md). Fixes b2c8e38 (GPT-6.1 Sol lane; merges of main and #1180's branch recorded by the hub, final tree equal to the lane's tested tree). r2 (GPT-6.1 Sol at b2c8e38) APPROVE_WITH_NITS, Needs Max: no (REPORT-r2.md): 338 tests, 111/111 new or changed cases killed by mutants, both blockers verified fixed, #1180 preflight and the narrow package exception intact. Head 809d138 is a no-op merge of main after #1180 landed: its tree is identical to the reviewed b2c8e38. Non-blocking nits (gap kernel identity should bind numerical library versions; a two-example monotonicity property can run vacuously) go to a follow-up PR. All 10 checks green, MERGEABLE/CLEAN, no CHANGES_REQUESTED.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant