Skip to content

Implement amendments 11-13: entrants, partitioned mass, declared tolerance - #851

Open
MaxGhenis wants to merge 4 commits into
graph-amendments-11-13from
graph-amendments-impl
Open

Implement amendments 11-13: entrants, partitioned mass, declared tolerance#851
MaxGhenis wants to merge 4 commits into
graph-amendments-11-13from
graph-amendments-impl

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Stacked on #847 (retarget to main once it merges). The executor semantics for interface amendments 11-13, built by a sol lane against the red acceptance tests B6, C5, D6 and flipped with tools/graph_acceptance_flip.py.

  • B6 entrants: an EXPAND node with entrants=True accepts null lineage; entrant rows are built from the kernel's materialized columns (every carried column required, dtype-checked), memberships must name incumbent or entrant groups, the lineage receipt records [new_id, null], and cached replay restores the null. Entrant persons remain fail-closed because the frozen KernelResult has no channel for a new person's mandatory stratum; amendment 14 (KernelResult.strata, charter row B7) follows on Interface amendments 11-13: entrants, mass partition, declared tolerance #847 and a further flip lands here.
  • C5 tolerance: recorded in every receipt, resolved for every declared input into KernelContext.tolerances (a rewrite reads its incumbent's owner), bound into the producer's key so a changed tolerance invalidates readers, carried through manifest save/load, shown in view/explain.
  • D6 partitioned mass: accounted per (partition, stratum) when Graph.mass_partition is set; conserve enforced per partition and the rejection names the partition value; receipt carries a nested partition block beside the flat fields; kernel-declared accounting validated to the same shape.
  • fit.qrf@1 measured: the H1 fixture regenerated on arm64 and on x86_64 under Rosetta differs by zero cells (max ULP 0), so the declared bound is Tolerance(ulps=1), recorded in the constant's comment; only pins.json moved.

Lane verification (verbatim in the lane report): graph suite 207 passed in 573.09s, cross-package kernels and country graph tests 29 passed, H1-H3 3 passed, ruff, ci_test_groups --verify, graph_acceptance_burndown --verify --baseline origin/main total 0. An independent rerun is in progress here and a sol review follows before merge.

🤖 Generated with Claude Code

…rance (B6, C5, D6 green)

Executor and population semantics for the three interface amendments,
built by a sol lane (20260902-101550-impl-11-13) against the red
acceptance tests and flipped with tools/graph_acceptance_flip.py:

- B6: an EXPAND node with entrants=True accepts null lineage; entrant
  rows are built from the kernel's materialized columns (every carried
  column required, dtype-checked), memberships must name incumbent or
  entrant groups, the lineage receipt records [new_id, null], and cached
  replay restores the null. Entrant persons stay fail-closed for now:
  KernelResult has no channel for their stratum (amendment 14 follows).
- C5: capabilities.tolerance is recorded in every receipt, resolved for
  every declared input into KernelContext.tolerances (rewrites read the
  incumbent's owner), bound into the producer's key so a changed
  tolerance invalidates readers, and carried through manifest save/load.
- D6: mass is accounted per (partition, stratum) when Graph.mass_partition
  is set; conserve is enforced per partition and names the partition
  value; the receipt carries a nested partition block beside the flat
  fields; kernel-declared accounting is validated to the same shape.
- fit.qrf@1: the H1 fixture regenerated on arm64 and on x86_64 under
  Rosetta differs by zero cells, so the declared bound is Tolerance(ulps=1)
  with the measurement in the constant's comment; only pins.json moved.

Suite: 207 passed, 0 xfailed; H1-H3 byte-exact; burndown total 0.

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

Copy link
Copy Markdown
Contributor Author

Sol review (read-only pass over d048b68, full text in the lane report) plus my rulings as the graph owner. Changes requested; a fix lane follows once the B7 leg lands, so the two do not collide in population.py/executor.py.

Must fix before merge

  1. EXPAND overlays can overwrite validated entity ids. _expand_cells accepts an entity's id column as an overlay coordinate; a kernel can then replace lineage-derived ids after validation, the receipt says one thing and the frame another, and warm replay rejects what cold execution accepted. Fix: refuse any expand_cells coordinate equal to its entity's id column (memberships stay legal), and after all overlays assert the final id index equals target_ids[entity].
  2. B6 entrants and D6 partitions cannot compose. Entrant validation demands a downstream materialized_expand_outputs claimant for every carried column, the partition column included, while _apply_result rejects every ordinary owner of the partition coordinate. Ruling: an EXPAND-materialized partition value is structural. The overlay supplies it, it needs no downstream claimant, and ordinary nodes still cannot own the partition coordinate. Add the composed test (entrant with a partition).
  3. The node key carries tolerance but not the rest of the kernel contract. QRF_PARAM_KERNEL and QRF_EXECUTOR_KERNEL share ref, implementation hash, and tolerance and differ only in seed_source, so a PARAM-produced artifact can hit under the EXECUTOR instance. Ruling: the key takes a canonical projection of the whole Capabilities (every field), not tolerance alone; a cache load also compares the stored capabilities as defense in depth. Tolerance does not go into implementation_hash, whose frozen meaning is source bytes plus dependency versions. Add a shared-store PARAM-then-EXECUTOR regression test.
  4. Implicit rewrite incumbents are missing from KernelContext.tolerances. _project_context projects a rewrite incumbent even when it is not in Node.inputs; resolve tolerances over the union of explicit inputs and rewrite outputs, incumbents against input_version as the compiler and keys do.
  5. Capabilities accepted look-alikes. Fixed on the interface side in Interface amendments 11-13: entrants, mass partition, declared tolerance #847 (head after 602c0f8): every field is validated at construction and KernelRegistry.register requires a genuine Capabilities instance. Merge Interface amendments 11-13: entrants, mass partition, declared tolerance #847's head into the fix branch.
  6. A row-masked claimant can satisfy the entrant materialization bridge. The bridge checks coordinate, non-rewrite status, dtype, but not Owned.rows; require ROWS_ALL for bridge claims (or prove every entrant id sits inside the mask) and add the negative test.
  7. RunManifest.population() mutates a returned frame's __class__ to add entity-name accessors. Ruling: no class mutation. population() returns one type; if entity attribute access is wanted it is a documented API, not a shim.

Follow-ups (same lane if cheap)

  • Reword the fit.qrf@1 tolerance comment: a provisional one-ULP acceptance budget measured on one 12-output fixture (arm64 versus x86_64 under Rosetta, bit-identical), not an established forest-wide bound. Re-pin the implementation hash afterwards.
  • An unpartitioned graph silently accepts a bogus receipt["mass"]["partition"] block; reject it when mass_partition is unset.
  • Normalize -0.0 to 0.0 in rtol/atol before keying.
  • Person entrants: amendment 14 (KernelResult.strata, charter B7) is on Interface amendments 11-13: entrants, mass partition, declared tolerance #847; the B7 leg is in flight and lands here.
  • Regression coverage: the PR removes three markers and adjusts counts but adds no defensive tests; each finding above lands with its own unit test (test_graph_population.py, test_graph_executor.py, test_graph_keys.py).

Verified by the review under a read-only sandbox: focused population/declaration/kernel/key tests 52 passed; kernel and country graph tests 29 passed; ruff clean; ci_test_groups --verify ok; burndown total 0 against origin/main. My own rerun in the lane's worktree: graph suite 207 passed, cross-package 29 passed.

🤖 Generated with Claude Code

MaxGhenis added a commit that referenced this pull request Sep 2, 2026
…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>
MaxGhenis and others added 3 commits September 2, 2026 13:41
# Conflicts:
#	packages/microcosm-graph/tests/test_graph_acceptance_burndown.py
#	packages/microcosm-graph/tests/test_graph_explain.py
…green)

Built by a sol lane (20260902-121951-impl-b7) against the red B7 test
and folded here with the current interface head (Capabilities
validation). An entrants=True EXPAND that adds person rows supplies
KernelResult.strata for exactly the null-lineage person targets; missing
entrants, incumbent or copied ids, unknown, duplicate or null ids, a
mismatched id dtype, or strata outside that context reject the named
node. Copied persons inherit their source stratum; entrant persons take
their declared label, which may introduce a new stratum; membership
materialization keeps them in total and per-stratum mass. Cached replay
attests the full person stratum vector against an ordered
receipt["entrant_strata"] of [person_id, label] pairs (bytes labels in
a tagged hex form). The sanctioned flip removed only B7's marker; suite
pins report 45 properties, zero red.

Verified here: 252 tests across the graph shard, kernel packages, and
both country graph suites; ruff; partition and burndown verifiers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Built by a sol lane (20260902-134618-fix-851, one commit per finding,
squashed here without its journals) and verified independently: 262
tests across the graph shard, kernel packages, and both country graph
suites; ruff; burndown total 0 against origin/main.

- EXPAND overlays may not name an entity's id column; final id indexes
  are asserted against lineage cold and warm.
- An entrant's partition value is structural: the EXPAND overlay
  supplies it with no downstream claimant, while ordinary nodes still
  cannot own the partition coordinate (composed entrant-with-partition
  test).
- Cache identity binds the full canonical Capabilities projection, not
  tolerance alone; a cache load misses when the stored capabilities
  disagree; PARAM- and EXECUTOR-seeded fit.qrf no longer share entries;
  tolerance stays outside implementation_hash; signed zeros key
  identically.
- KernelContext.tolerances covers rewrite incumbents, resolved against
  the input version as the compiler and keys do.
- Entrant materialization bridge claims require ROWS_ALL.
- RunManifest.population() returns one documented PopulationView type;
  no __class__ mutation.
- fit.qrf's tolerance comment states the provisional one-ULP budget
  honestly; pins regenerated. A bogus partition receipt block is
  rejected on unpartitioned graphs.

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

Copy link
Copy Markdown
Contributor Author

All seven rulings from the review are implemented at 7a8ecbe with a regression test each (details in the fix-lane report; squashed onto this branch after independent verification: 262 tests, ruff, burndown clean). The B7 leg (amendment 14, entrant person strata) landed in the previous commit. CI is the remaining gate.

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