Repository navigation
Add Axiom graph adapter surfaces and simulate.rules_by_ref@1 (NZ v0, G1) - #1118
Merged
Merged
Conversation
Salvage the live parts of #821's adapter onto main's axiom.py and add what graph nodes need to run the real Axiom engine (NZ graph plan, package G1): - NZ_SCHEMA (persons in households and families) and NZ_NESTING. With AxiomEngine(nesting=...), a family split across two households is refused from the person memberships alone, whatever the weights. #821's explicit {group}_{parent}_id relation-column check is ported; a contract-required relation column is enforced at export only. - AxiomPeriod(start, end, kind) and periods={label: AxiomPeriod}: "2026-27" resolves to explicit tax_year bounds, and an unmapped label fails closed. - output_dtypes="graph": judgments -> int64 codes, integers -> int64, decimals -> float64, bool -> bool, all lossless; text and date outputs are refused before the engine runs. graph_dtype() names the Owned dtype token. The default ("native") is unchanged, so Belgian behaviour is unchanged. - axiom_engine_ref(): canonical JSON of the engine commit, wheel SHA-256, RuleSpec commit, module path and SHA-256, the whole-root digest (rulespec_tree_digest, the graph's directory-identity formula), arithmetic, output dtypes, schema, entity names, period map and nesting. The reference pins the adapter: it refuses an adapter that already compiled, and every later compile or reference refuses a root whose digest moved. A git checkout root must hold exactly the declared commit (no modified, untracked or ignored files); a root with symlinks is refused. - assert_no_relations(engine, entity) names the module path when a dense program declares relations. - New microcosm.frame.rules_kernels.SimulateRulesByRefKernel (simulate.rules_by_ref@1): {engine_ref: RulesEngine}, one SimulateRulesKernel per binding by composition, so each node keeps simulate.rules@1's params contract, outputs check, all-rows rule and receipt. Its implementation hash binds rules_kernels.py, kernels.py, the frame bundle/rules/schema modules and each distinct adapter class, not the set of refs. kernels.py is untouched (parity pin). Invariants (Hypothesis property tests): - A family nests in exactly one household (refused iff some family spans households). - Only households carry explicit weights in an NZ export (any explicit person or family weight blocks the write under the NZ contract; families resolve their household's weight). - An unmapped period label fails closed (resolves iff mapped). - Graph-typed judgments are lossless (codes -1/0/1 round-trip bit-for-bit). - engine_ref moves iff a pinned byte moves (relocation-invariant; any one-byte edit moves it). Differential tests: rulespec_tree_digest vs microcosm.graph.keys (_directory_identity and source_content_key); simulate.rules_by_ref@1 vs simulate.rules@1 on kernel contexts and in two-engine run_graph runs. Not ported (salvage note): #821's Decimal-object input path (_checked_decimal_array) and its Decimal HDF write path (fixed-format tables for Decimal columns). Graph columns cannot hold object dtype, so they stay on branch codex/nz-transport-microcosm (9f7dead) for a later lane. Coordination: drafts #826 (feature/axiom-relation-bindings, 952952a) and #822 (feat/axiom-concept-coverage-be, e6d3c92) also edit axiom.py. Both already conflict with main there (2 hunks each). With this change, merge-tree shows 5 and 3 hunks, all additive (imports, __all__, docstring, the period line in materialize, appended helpers); no new conflicted files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apply findings 1, 2, 3 and 5 of the independent review of 105c062: - _require_clean_checkout now refuses any tracked file that `git ls-files -v` tags S (skip-worktree) or lowercase (assume-unchanged). git status reports no edit to such a file, so an edited, flagged file used to pass as a clean checkout at the declared commit. The check runs before the HEAD comparison and refuses a flagged file even when it is unedited. - AxiomEngine._require_pinned_tree refuses a symbolic link under the root before re-hashing it. The tree digest does not descend into a linked directory, so a directory link added after axiom_engine_ref left the pinned digest unchanged, and later compiles went ahead. - The axiom_engine_ref docstring now says the engine commit and wheel SHA-256 are pins the caller declares. They are recorded as given and not read from the installed engine, and the directory digest is the authority. Binding the installed engine is left for a later lane. - A new test checks that SimulateRulesByRefKernel's implementation hash is the same for all six binding orders of adapter classes from three modules. The hash must equal source_hash over the classes in (module, qualname) order. The test kills the review's surviving -id(cls) sort-key mutant and an unsorted insertion-order mutant; every earlier test let both through. New tests: a hidden-edit refusal for each flag, an acceptance once each flag is cleared, and a refusal of a symlink added after the reference. All five fail on 105c062 with "DID NOT RAISE". Findings 4, 6 and 7 are outside this change: 4 lands with G2's export contract, 6 is a separate docstring nit (native text and date outputs are arrays, not lists), and 7 is the missing CI engine job. This narrows the PR description's checkout claim to: "A git checkout root must be clean and at the declared commit: no modified, untracked or ignored files, and no tracked file flagged skip-worktree or assume-unchanged (git status hides edits to those). A root holding a symbolic link is refused when the reference is made and on every later compile." The engine pins are described as "the declared engine commit and wheel SHA-256 (recorded as given, not read from the installed engine)". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Merged by the NZ hub (session local_e407a527) at 065d8eb with --merge. Gates: |
This was referenced Oct 7, 2026
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.
Salvage the live parts of #821's adapter onto main's axiom.py and add what
graph nodes need to run the real Axiom engine (NZ graph plan, package G1):
AxiomEngine(nesting=...), a family split across two households is refused
from the person memberships alone, whatever the weights. Add NZ transport scaffold and real-Axiom Frame bridge #821's explicit
{group}_{parent}_id relation-column check is ported; a contract-required
relation column is enforced at export only.
resolves to explicit tax_year bounds, and an unmapped label fails closed.
decimals -> float64, bool -> bool, all lossless; text and date outputs are
refused before the engine runs. graph_dtype() names the Owned dtype token.
The default ("native") is unchanged, so Belgian behaviour is unchanged.
RuleSpec commit, module path and SHA-256, the whole-root digest
(rulespec_tree_digest, the graph's directory-identity formula), arithmetic,
output dtypes, schema, entity names, period map and nesting. The reference
pins the adapter: it refuses an adapter that already compiled, and every
later compile or reference refuses a root whose digest moved. A git
checkout root must hold exactly the declared commit (no modified,
untracked or ignored files); a root with symlinks is refused.
program declares relations.
(simulate.rules_by_ref@1): {engine_ref: RulesEngine}, one
SimulateRulesKernel per binding by composition, so each node keeps
simulate.rules@1's params contract, outputs check, all-rows rule and
receipt. Its implementation hash binds rules_kernels.py, kernels.py, the
frame bundle/rules/schema modules and each distinct adapter class, not the
set of refs. kernels.py is untouched (parity pin).
Invariants (Hypothesis property tests):
households).
person or family weight blocks the write under the NZ contract; families
resolve their household's weight).
one-byte edit moves it).
Differential tests: rulespec_tree_digest vs microcosm.graph.keys
(_directory_identity and source_content_key); simulate.rules_by_ref@1 vs
simulate.rules@1 on kernel contexts and in two-engine run_graph runs.
Not ported (salvage note): #821's Decimal-object input path
(_checked_decimal_array) and its Decimal HDF write path (fixed-format
tables for Decimal columns). Graph columns cannot hold object dtype, so they
stay on branch codex/nz-transport-microcosm (9f7dead) for a later lane.
Coordination: drafts #826 (feature/axiom-relation-bindings, 952952a) and
#822 (feat/axiom-concept-coverage-be, e6d3c92) also edit axiom.py. Both
already conflict with main there (2 hunks each). With this change, merge-tree
shows 5 and 3 hunks, all additive (imports, all, docstring, the period
line in materialize, appended helpers); no new conflicted files.
Invariants, acceptance and tests (from the build lane report; independent review pending)
Tests run
POPULACE_RULESPEC_BEpointing at a local rulespec-be checkout, 5 frame files: 203 passed, 1 skipped. The skip is the "engine absent" test. All Belgian adapter tests pass, including the pilot slice.ruff check .is clean,ruff format --checkis clean on the 4 touched files, andtools/ci_test_plan.py verifypasses. A localmicrocosm-framewheel build matches the source tree and includesrules_kernels.py.Every pytest run used
-p no:cacheprovider --basetemp=.hub-scratch/pytest -o tmp_path_retention_policy=failed. I deleted.hub-scratch,.hypothesisand.ruff_cacheafterwards. The workspace.venv(857 MB, git-ignored) is still there.The local engine was the checkout's Python package at
2840b57plus a native library built on 6 Sep for CPython 3.14. It is not the MC1 pin. It needed a non-free-threaded 3.14 scratch venv, because the workspace venv is free-threaded 3.14t and cannot load it.Shared files and owners
packages/microcosm-frame/src/microcosm/frame/adapters/axiom.pyis shared. Open drafts Authenticate Axiom relation materialization #826 and Add Axiom input concept-coverage diagnostics #822 also edit it; their sessions should check the merge. The parts carried over from Add NZ transport scaffold and real-Axiom Frame bridge #821 replace Add NZ transport scaffold and real-Axiom Frame bridge #821's adapter changes.frame/rules_kernels.py.frame/kernels.pyis unchanged, so its pinned hash still holds.Part of the Microcosm NZ v0 graph plan (Max ruling d962). Built by the NZ hub on an Opus build lane; the hub verified scope (no frozen graph files, uk_runtime/us_runtime or frame/kernels.py touched) before committing.
🤖 Generated with Claude Code