Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/axiom-concept-coverage.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an optional real-Axiom input inventory and a shared, closed concept-coverage diagnostic that preserves unknown metadata, requires explicit evidence bindings, and cannot certify a population schema.
117 changes: 117 additions & 0 deletions docs/axiom-concept-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Axiom input concept-coverage diagnostic

This is a **diagnostic, not a population schema, calibration plan, or
certification gate**. It makes unavailable contracts visible before a population
build tries to use them. It introduces no country-specific Python operator and
does not change Chronicle source facts.

The generic `InputInventoryProvider` protocol is optional; it does not expand the
required `RulesEngine` protocol. `AxiomEngine.input_inventory()` compiles a fresh
program through the real Axiom dense runtime and records root-input names per
mapped entity, canonical request addresses, and accepted aliases. It excludes
derived outputs. A relation-bearing module fails closed because this adapter
does not yet wire related-entity batches. Its scope is the mapped root entities
and all versions in the module, not every Belgian policy or a selected output's
minimal dependency closure.

`entity` records the operational frame table; `engine_entity` records its dense
root. These are not evidence for a source publisher's statistical entity or
universe. Input `dtype`, `unit`, `period`, `definition`, semantic `concept_id`, and
`required` remain null where the runtime does not supply them. In particular,
being a root input does not establish that an input is mandatory in every case.
Some runtime inputs are configuration or externally supplied derived quantities,
not observed microdata: the Belgian pilot includes communal/agglomeration tax
rates, a supplied tax amount, and a tax-base flag. This inventory does not decide
which fields to store, derive, impute, or supply as configuration.
The complete typed-input contract remains
[axiom-rules-engine#62](https://github.com/TheAxiomFoundation/axiom-rules-engine/issues/62).

## Run it

Install the real Axiom Python wrapper and native dense extension into the local
environment, then pass explicit absolute canonical `rulespec-<country>` roots:

```bash
uv run --no-sync python tools/inventory_axiom_concepts.py \
--module /path/to/rulespec-be/be/statutes/income_tax/individual/pilot_worker_oracle_pipeline.yaml \
--rulespec-root /path/to/rulespec-be \
--group-entity household
```

The command prints a closed v1 JSON manifest. It does not open a microdata file,
materialize taxes, infer metadata from spelling, or create semantic matches by
column name. Missing Axiom software is an error, never a fallback evaluator.

## Evidence and dataset assessment

`microcosm.build.concept_coverage.build_concept_coverage` also accepts an optional
Frame, explicit `column_bindings`, and consumer-authored `fact_bindings`.
Its string-only manifest refuses non-string Frame column labels rather than
coercing distinct labels into apparent matches.

- No Frame: `not_supplied`; every input column status is `unassessed`.
- Frame but no explicit binding: still `unassessed`, even if names match.
- Explicit binding plus Frame: `present` or `absent` according to column names.
Values, distributions, missingness, units, and observed/imputed origin are not
assessed. The schema digest fingerprints column names, **not dataset content**.
- Extra columns remain permitted. Demography, wealth, predictors, future reforms,
and presently unencoded concepts need not be current-law inputs to belong in
the population.

Every binding pins both the Frame entity and the native engine entity, along
with the runtime slot and canonical address, plus the inventory's
engine/module/root fingerprints. A binding cannot move between native root
entities even when files and request addresses are unchanged. Stale pins fail; non-canonical
aliases must be replaced by the catalog's canonical address. Conflicting target
concepts on one runtime slot fail instead of merging.

Every fact binding independently records source concept, fact ID, source artifact
digest/vintage, target concept/legal vintage, both statistical scopes, a declared
transformation, and evidence (URI, digest, locator, claim). The scopes include
statistic, entity, universe, unit, geography, period, stock/flow classification,
stock reference date, and income-year versus assessment-year accounting basis.
Entity and universe definitions require document pins for non-unresolved
assertions. An asserted exact match requires equal complete statistical scope
and an identity transformation. Names do not create bindings.

The builder preserves `asserted_relationship` separately from
`effective_relationship`. Missing target semantics produce effective
`unresolved` with reason `target_semantics_unavailable`, never a proxy invented
from ignorance. Even with future complete metadata, v0 emits unresolved with
`semantic_equivalence_unverified`: it does not fetch documents or adjudicate
legal/statistical equivalence. Authoring an exact/proxy assertion does not change
engine metadata, create a coverage score, or promote a certification flag.

## Provenance and limits

The manifest fingerprints the entry module, every YAML file plus toolchain pin
in each explicit RuleSpec root, actual imported wrapper/native files, adapter,
and diagnostic builder. Relative paths and bytes determine tree fingerprints;
relocating an identical root does not change identity. Compilation uses a fresh
adapter, and changes between before/after fingerprints abort discovery. Keep
the source checkouts quiescent during the run, as the Axiom loader requires.

Per-entity discovery records complete enumeration and its runtime input count,
or `no_derived_program` with a null count. The latter is not successful zero-input
enumeration. Missing discovery, unsupported relations, failed compilation, or
inconsistent counts refuse an artifact. The Belgian pilot enumerates seven
Person inputs; it has no Household program. `blocking_gaps` exposes unavailable
metadata, unassessed dataset columns, and unresolved evidence without claiming
that this module is all of Belgian law.

Inputs sort by canonical address, entity, and slot. The content hash uses
`microcosm-json-v1`: sorted JSON object keys, UTF-8, no NaN, compact separators,
and exclusion of `content_sha256` itself. Runtime versions and platform are
informational context. This diagnostic is unsigned; do not use a corpus release
key to sign it.

These are reproducibility fingerprints, not signed source authenticity or
release certification. They neither establish the native binary's source-build
attestation nor replace the corpus's signature chain. PR CI tests synthetic
contract fixtures; it does not certify a population or publish any artifact.

Belgium is the first inventory example, not the first proven cross-constellation
concordance. The [pilot snapshot](evidence/be-concept-coverage/README.md) records
the exact runtime/source pins and the separate scoped target-inventory audit.
No evidence bindings or dataset are supplied in that snapshot. Linking concepts
exposes missing evidence; it does not manufacture it.
66 changes: 66 additions & 0 deletions docs/evidence/be-concept-coverage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Belgian pilot input inventory snapshot

Generated on 2026-08-29 by the shared diagnostic tool, using the real Axiom dense
compiler. [pilot-inputs.json](pilot-inputs.json) contains seven Person inputs,
their runtime-provided canonical addresses, and six unknown metadata fields per
input. It supplies **no dataset and no evidence bindings**. Household compilation
reports `no_derived_program` and a null count, not successful zero enumeration.
It is not a complete Belgian-law inventory or a certified population schema.

The two identical runs produced content digest
`8b6c379afbf21e590c259722207ea07e41043be6ef335b6f77fed9a49b553086`.
The manifest fingerprints the actual adapter/builder files, installed engine
wrapper/native package, RuleSpec entry module, and canonical root YAML/toolchain.
The producer-code digests identify the files used for this dated snapshot, not
an attestation of any published release.

## Source and build pins

- Microcosm base: `ba73e2f43c6f1dcb3533faeab26ecc18260bd712`.
- Axiom source: `bb4b5684870547756078a62f1866a77c5b56f7f3`.
- RuleSpec-BE source: `b105e2b3a3086ddd2de447d58a9b951346870dd1`.
- Entry module: `be/statutes/income_tax/individual/pilot_worker_oracle_pipeline.yaml`.
- Native wheel: `axiom_rules_engine_dense-0.1.0-cp314-cp314-macosx_11_0_arm64.whl`,
SHA-256 `7928e395942ae071054197891a656f4744864e57c07554a9d0bf7d6635fe0f90`.
- Effective native Cargo lock SHA-256:
`e40add4c7ddeb39fa0005f379abc438bf9d2d927ac4570e8f6bf45d671a9e1b2`.

The pinned source's extension lock was stale: its local path dependency named
engine version 0.1.0 while the source crate declared 0.2.2. The initial `--locked`
build refused. `maturin build --release --offline` changed that one local-crate
version entry; no external dependency version changed. The wrapper/native
distribution labels remain 0.1.0, so they must not substitute for the file
fingerprints. The manifest leaves the unexposed runtime core version null.

Build/runtime outputs live outside tracked source. This snapshot is unsigned
diagnostic evidence, not an attested binary build or signed-corpus release.

## Reproduction

Install the pinned wrapper and built native wheel into a Python 3.14 environment
containing these Microcosm sources. The exact command surface is:

```bash
uv run --no-sync python tools/inventory_axiom_concepts.py \
--module /absolute/path/rulespec-be/be/statutes/income_tax/individual/pilot_worker_oracle_pipeline.yaml \
--rulespec-root /absolute/path/rulespec-be \
--group-entity household
```

The Work Bonus input's canonical owner is its imported `work_bonus` module, not
the pilot entry module. The other six addresses belong to the pilot module.
Those addresses came from the runtime catalog, not string construction. Runtime
inputs include configuration rates and supplied derived quantities as well as
remuneration; this diagnostic does not require every input to be observed data.

## Separate target-inventory observation

The local pilot artifact `microcosm_be_v051_chronicle_targets.json`, SHA-256
`250051e7c3e50a4aee5181857c72d78f4ec38c365ff7dd1fb6c00ae6def7c227`,
declares 956 targets and 91 validations. The session's scoped inventory audit
found no wealth-stock targets. A reproducible name-screen returned no target
names containing `wealth`, `net_worth`, `asset`, `mortgage`, `debt`, or `hfcs`.
This is an audit of that specific artifact, not a classification engine or a
claim that Belgian publishers lack wealth statistics. The input diagnostic does
not ingest or republish that target file, and no source-to-input equivalence is
asserted here. Income and saving flows do not establish wealth-stock coverage.
Loading
Loading