Skip to content

Interface amendments 11-13: entrants, mass partition, declared tolerance - #847

Open
MaxGhenis wants to merge 6 commits into
mainfrom
graph-amendments-11-13
Open

Interface amendments 11-13: entrants, mass partition, declared tolerance#847
MaxGhenis wants to merge 6 commits into
mainfrom
graph-amendments-11-13

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Max ruled go (2026-09-02) on the two dynamics decisions recorded in microcosm-dynamics#412: person_period as an entity produced by an EXPAND node with lineage to the person, and period household weights as a REWEIGHT node that owns them. This PR makes the three interface amendments those decisions need, under the charter's ceremony (docs/graph-acceptance.md, "Interface freeze"; lock re-recorded).

Amendments

  1. Entrants are declared. Node.entrants=True (EXPAND only) lets a kernel add rows that copy no base row: null lineage, every carried column materialized by the kernel, recorded as entrants, and mass='conserve' refused at declaration. Consumer: the dynamics scheduled-entries seam (immigrant cohorts).
  2. Mass is partitioned. Graph.mass_partition=(entity, column) partitions mass accounting per stratum within each partition value; every CREATE node must declare the column with a dtype in PARTITION_DTYPES. Normative: folded into every structural node's key.
  3. Tolerance is declared. Tolerance(rtol, atol, ulps); Capabilities.tolerance is required for tolerance_bound kernels and forbidden for bitwise ones; KernelContext.tolerances hands each reader the declared tolerance of every input cell's owner. Raised by the H2 finding that root weights differ by one ulp between arm64 and x86.

Also: D2 clarified per #844 (mass is weighted person mass per stratum; a composition-changing expansion declares its change with a receipt stating the invariant it does hold), and three new charter rows B6, C5, D6.

What is in this PR

  • decl.py, kernel.py (frozen; amended and re-locked), serialize.py, keys.py, exports. A declaration without the new fields serializes byte for byte as before, so every pinned graph JSON still loads; fit.qrf@1 declares a provisional Tolerance(rtol=1e-6) pending measurement across arm64 and x86_64, which moved its implementation hash (H1 pins regenerated).
  • Declaration- and protocol-level tests (green): test_graph_decl.py, test_graph_kernel_contract.py.
  • The three charter properties committed red (xfail(strict=True)) by the acceptance lane, with the toy machinery they need; each fails at the absent feature (evidence in the lane report). The executor semantics land in the next PR, which flips them.
  • tools/graph_acceptance_burndown.py: a marker on a property the baseline charter never listed is a new red, not a re-red (unit-tested both ways). The suite pins report 3 red until the flip.

Verified: packages/microcosm-graph (203 passed, 3 xfailed), fit/calibrate/frame kernel tests, test_uk_graph.py, test_us_graph.py, ruff, tools/ci_test_groups.py --verify, tools/graph_acceptance_burndown.py --verify --baseline origin/main.

Refs #836, #844, microcosm-dynamics#412.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits September 2, 2026 09:24
- decl.py: Node.entrants (EXPAND only; cannot conserve mass) and
  Graph.mass_partition (an (entity, column) every CREATE node declares
  with a partition dtype; normative, folded into structural node keys).
- kernel.py: Tolerance(rtol, atol, ulps); Capabilities.tolerance is
  required for tolerance_bound kernels and forbidden for bitwise ones;
  KernelContext.tolerances hands readers their inputs' owners' bounds.
- serialize.py and keys.py carry the new fields; older JSON still loads.
- fit.qrf@1 declares a provisional Tolerance(rtol=1e-6) pending
  measurement across arm64 and x86_64.
- Charter: amendments 11-13, D2 clarified (weighted person mass per
  stratum; composition-changing expansions declare), rows B6, C5, D6.
- Lock re-recorded; B2's KernelContext field pin gains tolerances.

Max ruled go on the two dynamics decisions (microcosm-dynamics#412);
the B6/C5/D6 acceptance tests follow from the acceptance lane.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…count 44 properties

graph_to_json emits mass_partition only when declared, so every pinned
graph JSON still round-trips unchanged. fit.qrf@1's implementation hash
moved with its declared tolerance; the H1 pins are regenerated. The
explorer test counts the charter's 44 properties.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o the charter

The acceptance lane (sol, 20260902-092431-acceptance-11-13) added the
three strict-xfail tests and the toy machinery they need: a toy EXPAND
kernel with declared entrants, a tolerance-bound producer and a gate
that reads context.tolerances, and a partitioned toy source. Each fails
today at the absent feature, not before it (evidence in the lane report).

tools/graph_acceptance_burndown.py now treats a marker on a property the
baseline charter never listed as a new red rather than a re-red, with a
unit test for both directions. The suite pins report 3 red until the
implementation lane flips them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits September 2, 2026 12:19
Implementing amendment 11 showed the frozen KernelResult had no channel
for a new person's mandatory stratum, so entrant persons were fail-closed
while immigrant cohorts are persons. KernelResult.strata (EXPAND kernels
on an entrants=True node) names every entrant person's stratum by id;
the executor requires exactly the entrant persons there. Charter row B7
is committed red with a toy kernel that admits one entrant person into
an incumbent household; it fails today at the executor's null-lineage
refusal. Lock re-recorded; suite pins count 45 properties, 4 red.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ance

The #851 review showed a string spelling an enum member passed as the
member, so a kernel could claim tolerance_bound without a bound. Every
Capabilities field is now checked at construction (enums by type,
consumes_se a boolean, dependencies a tuple of names) and
KernelRegistry.register refuses a look-alike. Lock re-recorded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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