Source-Bound Reproduction, Deterministic Builds, and Availability
The core Stage 0–6 results in sec. 5 use vendored inputs and
local computation. The release source repository is Institute
release source repository. Their ordinary recorders support
deterministic offline replay once the pinned environment and generated
prerequisites are prepared. The one-shot replication of sec. 10.6 is deliberately
outside that replay inventory. Its spent-population refusal and the
separate descriptive replay are explained below. The external-model
reference frame is the stated exception. Re-measuring it requires a
local Ollama server serving the named local probes. The stipulated
synthetic and in-context probes score through the hosted OpenRouter
transport, which requires an exported OPENROUTER_API_KEY
kept out of versioned artifacts. Eligible cached replies avoid repeated
generation under their recorded transport identity. Local Ollama
identity is content-bound; hosted OpenRouter identity records logical
model slugs and does not authenticate immutable serving weights. The
historical component corpora are vendored as committed count artifacts
(tbl. 20). Their upstream use
terms, including Brown’s non-commercial restriction and the Czech
artifact’s CC BY-NC-SA terms, remain in LICENSE and
THIRD_PARTY_NOTICES.md.
Availability. The versioned release source is the Institute repository’s release tag. The corresponding Zenodo deposition is unpublished. Its reserved DOI identifies the intended archive and does not yet resolve to a public record. The citation, package metadata and title page identify the same intended archive and release destination. Public source and archival availability do not establish independent reproduction. No independent reproduction outside the project is recorded in the evidence available here. A reproducibility claim becomes a result only when someone other than its authors acts on it.
Pinned environment and interpreter identity
The project pins inferactively-pymdp 1.0.4, which runs
on JAX (Bradbury et al.
2018), and is installed with uv sync --locked
from pyproject.toml and the committed uv.lock.
All project commands then address .venv/bin/python
explicitly. The quick release profile checks this base
dependency set. The full profile requires the declared
gnn-interop extra, installed with
uv sync --locked --extra gnn-interop, and a real upstream
GNN checkout selected by AILM_GNN_UPSTREAM or the validated
default discovery path. Its interoperability checks fail on missing
prerequisites instead of skipping. Returning to quick
requires uv sync --locked to restore the base set; neither
release profile modifies the environment it checks. This sidecar is not
a member of the surrounding template workspace, so uv run
can bind the template environment and a bare pytest can
select a shim; either can produce a green run against the wrong Python
or pymdp. Coverage on src/ailm is gated at 90% with branch
coverage (fail_under in pyproject.toml,
recorded into the ledger by the Stage 0 recorder so this sentence cannot
silently disagree with the gate).
Vendored corpus artifacts and their population boundaries
The historical component corpora are reduced to committed count artifacts, so core corpus evaluation and figure generation do not require downloading those corpora again. The connected GUM evaluation additionally uses a vendored raw CoNLL-U test file and a frozen document/exclusion manifest, rather than only sufficient statistics.
| Artifact | Size | sha256 (first 12) | Regenerated by | Contents |
|---|---|---|---|---|
vendor/brown_counts.json |
14 kB | 778e2b31740b |
scripts/generate_counts.py |
Letter bigram counts: 805 types over 5,856,736 tokens from the Brown corpus |
vendor/cmudict_counts.json |
978 kB | 9f0f20746086 |
scripts/generate_phoneme_counts.py |
Phone unigrams and bigrams, plus the 25,936 train and 6484 test length-matched position-aligned letter-to-phone (G2P) pairs |
vendor/brown_word_counts.json |
2082 kB | 2d10d0c6e237 |
scripts/generate_word_counts.py |
Word-level sufficient statistics for the Stage 3 word level |
vendor/ud_ewt_case_counts.json |
393 kB | 3de812c40139 |
scripts/generate_case_counts.py |
UD English EWT case counts for the Stage 4 case level |
Full provenance for every artifact, including each derivation choice
that biases the counts, is in docs/provenance/sources.md:
the text normalization applied to Brown (Francis and Kučera
1979; Bird et al.
2009), and for CMUdict (Carnegie Mellon University Speech Group,
n.d.) the use of the primary
pronunciation only, the stripping of stress digits to the canonical
39-phone inventory, the length-matching restriction, and the shipped
sorted-index interleave. That seedless word-level split is reproducible
but permits lexical-family overlap; the separately recorded
family-disjoint arm keeps each prefix family on one side and reports the
covariate cost of doing so. The accompanying
docs/reference/data_statement.md describes language
varieties, curation, filtering, sampling units, and limits on
generalization. It covers the English corpora and authored Stage 1
fixture, the exploratory Czech morphology arm, and the stipulated letter
and phone controls separately. For English EWT it distinguishes internal
document partitions of upstream dev from the upstream test
population subsequently used under the registered replication
protocol.
The connected evaluation uses
vendor/en_gum-ud-test.conllu,
data/connected_gum/protocol.json and
data/connected_gum/input_manifest.json.
scripts/record_connected_gum_claims.py authenticates the
frozen inputs, excludes the documents already inspected during bounded
development, and records paired per-document losses with its execution
binding. Replaying those same documents checks reproducibility; it does
not create another independent replication. The GUM file retains its
upstream CC BY-NC-SA 4.0 terms (Zeldes 2017). Only its raw text
comments enter inference under the normalization specified in sec. 5.1; annotation
columns remain withheld.
Reproduction order and offline, local, and hosted dependencies
tbl. 21 lists the reproduction
path from the project root. Set and export
TEMPLATE_REPO_ROOT to the existing template checkout’s path
before running the table. The render and validation commands use that
variable to change directory in a subshell. Core level verdicts are
independent of the model server. Re-measuring the external reference
frame of sec. 13,
including the stipulated controls, uses the network claim phase and
requires a local Ollama server with all registered probes available and,
for the two hosted scored-call recorders, an exported
OPENROUTER_API_KEY. A missing probe or key refuses the
comparison rather than silently shrinking its declared family.
Environment installation and count regeneration from upstream sources
may also require downloads. The committed counts support offline core
evaluation.
That network phase stores calls individually, keyed by the request, endpoint, protocol and transport-specific identity. Local Ollama calls require a server-supplied content digest or a validated content blob in a stable build manifest. Hosted OpenRouter calls instead hash requested and returned model slugs; a hash of a logical slug is not a hash of serving weights. Capped hosted runs additionally bind the selected provider and price constraints in both the exact cached payload and the run receipt, retaining raw server response and usage evidence. This documents the serving route and observed response, while provider-side weight immutability remains unverified. The synthetic and in-context recorders retain registered probe tags as run labels, but their scored calls use the hosted model named in the receipt, not distinct local weights. Replay is protocol-specific. The external benchmark can reuse eligible ordinary calls, but its repeat-agreement trials make both requests fresh. Every scored synthetic and in-context call is fresh on a publication run. The drift recorder pairs authenticated stored log-probability replies with fresh uncached observations. Re-running the phase is therefore a new measurement and can change scientific values.
The external, synthetic, and in-context recorders namespace every fresh scored call with a UTC run scope, the registered probe tag, and that call’s own position slot — every scored call’s namespace is unique within its run, because the hosted transport’s replies are not assumed deterministic — preserving older records without overwriting them. The in-context recorder authenticates the synthetic producer’s stored zero-shot replies under that producer’s scope before making its own scored calls. The drift recorder instead binds its sampled stored records and new observation pairs directly. Receipts record hit, miss, and fresh-call accounting as execution evidence; their validator reconstructs the claims from the exact declared records and rejects missing, extra, or inconsistent evidence. Source and vendored-input manifests must remain unchanged throughout recording.
Separately, the external recorder’s --verify-cache audit
re-measures a stratified sample, requires exact answer strings, and
compares log-probability candidates at aligned emitted positions under
the frozen tolerance before writing claims. Distribution-bearing rows
must retain their emitted-token identity and shared candidates; the
audit does not flatten candidates across different output contexts. Its
strata cross registered probes with ordinary and answer-distribution
requests. This compares current replies with the sampled stored replies;
it establishes neither stability of every cached call nor a guarantee
about future server behavior.
The ordinary offline inventory is the dynamically discovered
scripts/record_*_claims.py set.
scripts/record_confirmatory_replication.py deliberately
sits outside it: decision 111’s sentinel records that the held-back
population has been spent and refuses another scoring run. Ordinary
reproduction preserves that record. By contrast,
scripts/record_confirmatory_stage6_clustered_claims.py
belongs to core: decision 115 permits deterministic replay
of its separately specified estimand on the already-spent population
with frozen development fits. Its status remains descriptive; replay
supplies no new held-back replication.
| Step | Command | Produces |
|---|---|---|
| Install | uv sync --locked |
The base environment; select the declared extra above for the full profile |
| Regenerate counts | .venv/bin/python scripts/generate_counts.py,
..._heldout_stream.py, ..._phoneme_counts.py,
..._word_counts.py, ..._case_counts.py,
..._case_word_counts.py,
..._czech_case_counts.py,
..._clause_counts.py, ..._narrative_counts.py,
..._clause_word_counts.py,
..._online_genre_counts.py,
..._synthetic_counts.py,
..._synthetic_phone_counts.py,
..._clause_widened_counts.py, and
..._confirmatory_ewt_counts.py |
tbl. 20 and the remaining vendored counts, byte-identical; the last two regenerate the widened clause artifact (sec. 4.7.1) and the held-back confirmatory population |
| Re-record ordinary offline claim namespaces | .venv/bin/python scripts/orchestrate_claim_recorders.py core |
Every dynamically discovered non-network recorder except the order-sensitive formal and aggregate writers; fail-fast, with the one-shot replication excluded as described above |
| Reproduce the connected GUM comparison separately | .venv/bin/python scripts/record_connected_gum_claims.py |
The fixed locally specified population, paired document summaries
and source-bound connected_gum_ claims; also included in
ordinary core recorder discovery |
| Re-record and bind every network claim namespace | .venv/bin/python scripts/orchestrate_claim_recorders.py network |
Every recorder whose scored calls reach a model server — the local
Ollama probes and, for the stipulated synthetic and in-context probes,
the hosted OpenRouter transport with an exported
OPENROUTER_API_KEY — with its binding validated before the
next producer and an unscoped final validation; the live discovery is an
exact disjoint phase of the full recorder inventory |
| Re-record aggregate statistical claims | .venv/bin/python scripts/orchestrate_claim_recorders.py aggregate |
The multiplicity family and cluster-aware derived intervals, after all contributing measurement recorders |
| Regenerate the Lean ledger bridge | .venv/bin/python scripts/generate_lean_ledger.py (add
--check to fail on a stale file) |
formal/AILM/LedgerData.lean, byte-identically |
| Check the formal layer | Full formal-layer command below | The Lean proofs, formal/axiom_report.txt, and a
mutation control accepted only when the test observes every expected
refutation diagnostic, including the ledger-backed one |
| Re-record the formal claims | .venv/bin/python scripts/orchestrate_claim_recorders.py formal |
The formal_* entries in data/claims.json,
from the real build |
| Assign epistemic statuses | .venv/bin/python scripts/assign_claim_status.py |
A status on every ledger entry, derived from recorder ownership and registered design chronology |
| Audit every gate | .venv/bin/python scripts/audit_gates.py (add
--json for a machine-readable export) |
The eq. 12 classification,
plus tbl. 27; with
--json, also
output/reports/gate_audit.json |
| Manuscript variables | .venv/bin/python scripts/z_generate_manuscript_variables.py |
output/data/manuscript_variables.json and the resolved
manuscript tree; every mutable scientific/configuration value is
injected here before any dependent figure or render |
| Hydrate and check repository documentation | .venv/bin/python scripts/z_render_docs.py && .venv/bin/python scripts/z_render_docs.py --check |
The resolved documentation mirror, checked against authored sources and current claim values |
| Figures | MPLBACKEND=Agg .venv/bin/python scripts/generate_figures.py |
Every PNG referenced in this manuscript |
| Publish the figure registry | .venv/bin/python scripts/generate_figure_registry.py
(add --check to build and validate without writing) |
../figures/figure_registry.json, built by the
template’s own infrastructure.documentation builder from
the provenance receipt and this manuscript’s own figure captions |
| Generate and check the cover | MPLBACKEND=Agg .venv/bin/python scripts/generate_cover.py && MPLBACKEND=Agg .venv/bin/python scripts/generate_cover.py --check |
The current cover and its content-bound freshness receipt, required before rendering |
| Export the web model | .venv/bin/python scripts/export_web_model.py |
The ignored local model payload required by the clean full suite |
| Build the web page | .venv/bin/python scripts/build_web_ailm.py |
The ignored standalone local page required by the clean full suite |
| Stage 0 gate | .venv/bin/python -m pytest tests/test_stage0_gate.py -v |
Infrastructure, ledger, harness |
| Stage 1 gate | .venv/bin/python -m pytest tests/test_stage1_gate.py -v |
tbl. 9 comparators and the anti-wiring negative control |
| Stage 2 gate | .venv/bin/python -m pytest tests/test_stage2_gate.py -v |
tbl. 12, tbl. 13, the paired McNemar test |
| Stage 3 gate | .venv/bin/python -m pytest tests/test_stage3_gate.py -v |
The word-level comparators and mis-wiring controls |
| Stage 4 gate | .venv/bin/python -m pytest tests/test_stage4_gate.py -v |
Case-agreement comparators against the gold and derived oracles |
| Stage 5 gate, canonical arm | .venv/bin/python -m pytest tests/test_stage5_widened.py -v |
The widened-observation clause gate registered by decision 112 and promoted by decision 114, its resolved paired gain, its decoder-equivalence and swapped-blocks negative controls, and its detectability control |
| Stage 5 gate, retained ablation | .venv/bin/python -m pytest tests/test_stage5_gate.py -v |
The non-passing case-only clause gate, paired whole-document cluster-bootstrap intervals for privileged-label gain, and detectability controls |
| Stage 6 gate | .venv/bin/python -m pytest tests/test_stage6_gate.py -v |
The preregistered positive point estimate, descriptive live-filter run, and non-confirmatory document-clustered analysis |
| Oracle | .venv/bin/python -m pytest tests/test_oracle.py -v |
Closed-form and analytically anchored checks on
src/ailm/verification/oracle.py |
| Claims discipline | .venv/bin/python -m pytest tests/test_claims_discipline.py -v |
Ledger scan over real prose, with its planted-tag positive control |
| Artifact checksums | .venv/bin/python -m pytest tests/test_provenance_checksums.py -v |
tbl. 20 digests re-derived from disk |
| Render the publication | scripts/pipeline/stage_03_render.py; full command
below |
The assembled manuscript, web render, and combined PDF through the template’s locked environment |
| Resolve and check individual HTML references | .venv/bin/python scripts/z_render_docs.py --publication-references && .venv/bin/python scripts/z_render_docs.py --publication-references --check |
Links, visible reference kinds and numbers derived from the actual combined index; literal code examples preserved |
| Check PDF integrity | qpdf --check; full command below |
PDF structure and recovered TeX-error checks before Stage 04 |
| Validate the publication | scripts/pipeline/stage_04_validate.py; full command
below |
Structural, provenance, manifest, and PDF validation reports over the completed publication tree |
| Full suite and coverage gate, with generated and rendered prerequisites current | .venv/bin/python -m pytest tests/ --cov=ailm --cov-report=term-missing --cov-fail-under=90 |
The complete test suite, including controls and generated-artifact freshness checks |
| Authoritative release profile | .venv/bin/python -I -S scripts/verify_release.py full |
Static checks, required environment checks, the coverage suite, isolated replay, generation, rendering, and validation, with a release receipt |
The longer commands from the table are expanded here for copying. Run each at its position in the ordered reproduction path above.
Check the formal layer.
(cd formal && lake build && ./Scripts/axiom_report.sh) && .venv/bin/python -m pytest tests/test_formal_isomorphism.py::test_the_negative_control_does_not_compile -v --no-covRender the publication. Set
TEMPLATE_REPO_ROOT to the explicitly selected template
checkout and run the following from the AILM root.
export TEMPLATE_REPO_ROOT
.venv/bin/python scripts/z_render_docs.py --supporting-protocols
.venv/bin/python scripts/z_render_docs.py --check
(cd "$TEMPLATE_REPO_ROOT" && uv run --locked python scripts/pipeline/stage_03_render.py --project working/active_inference_language_model)Resolve and check individual HTML references. Run these commands from the AILM checkout after Stage 03. Complete supporting HTML acceptance follows the repair; the earlier documentation check covers only the hydrated mirror.
.venv/bin/python scripts/z_render_docs.py --publication-references
.venv/bin/python scripts/z_render_docs.py --publication-references --check
.venv/bin/python scripts/z_render_docs.py --check --supporting-protocolsCheck PDF integrity.
qpdf --check output/pdf/active_inference_language_model_combined.pdf && .venv/bin/python -m pytest tests/test_pdf_integrity.py -q --no-covValidate the publication.
(cd "$TEMPLATE_REPO_ROOT" && uv run --locked python scripts/pipeline/stage_04_validate.py --project working/active_inference_language_model)Generated prerequisites must be current before the full suite or
release profile starts: those tests consume figure and cover outputs,
local web artifacts, both gate-audit reports, and Stage 04 provenance.
Hydrated repository documentation is also generated and checked before
rendering. The release profile subsequently repairs individual HTML
references from the actual combined index and performs strict complete
HTML checks before Stage 04 binds final provenance. It regenerates and
checks these outputs. Its receipt distinguishes completed checks
(success) from release eligibility
(publication_acceptance); a run using the development
dirty-tree override cannot establish publication acceptance.
docs/method/release_checklist.md records the required local
model cache, upstream GNN checkout, template checkout, and toolchain
configuration. Structural checks do not establish visual correctness:
inspect the final PDF’s rendered pages, figure labels, tables,
equations, and metadata after regeneration.
The gate-audit and claims-discipline rows of tbl. 21 are the minimum pair a
reader should run. scripts/audit_gates.py re-derives the
gate classification from measured baselines and ceilings rather than
from anything recorded, so it would catch a threshold that had drifted
back into vacuity. tests/test_claims_discipline.py scans
the real repository tree rather than a fixture, which is what makes it a
statement about the shipped artifact (sec. 4.11). Where a
reproducibility checklist such as (Pineau et al.
2021) asks an author
to self-report a study’s degrees of freedom, this repository’s gate
audit and claims-discipline scan check the corresponding properties
mechanically against the shipped tree on every run, rather than once at
submission time.
Interactive inspection and the reply-generation boundary
The local dashboard exposes input controls and a temporal trajectory beside a chat demonstration (fig. 27). Its input-analysis views and generated reply have different computational scopes: the reply follows the L3-to-L1g policy path described in sec. 4.9. The upper-level input posteriors do not constitute an end-to-end reply-generation cascade. The matrix explorer provides a separate inspection surface. These interfaces support inspection; they do not add an evaluation population to the results.
data/dashboard_capture/; figure provenance binds these
inputs and the framing generator. Altered pixels or source assets
inconsistent with those bindings would falsify the capture’s provenance
and cause the generator to refuse.Variable injection and source provenance
All 2577 claims live in data/claims.json, each recorded
by the run that produced it with its run_id and source
location. src/ailm/manuscript_variables/ supplies the
double-brace token map this manuscript is written against.
Recorded-value tokens follow a mechanical rule: the token is the ledger
label uppercased, so stage1_letter_perplexity becomes
STAGE1_LETTER_PERPLEXITY. Provenance companions are
generated alongside each value, so a claim’s originating run is
available without a separate lookup. Other tokens are explicitly derived
expressions or configuration and metadata values; they do not acquire
ledger entries merely by appearing in the map.
The failure behavior is the point. A required claim absent from the
ledger raises MissingClaimError and the render stops; it
does not emit a plausible default and does not leave an unresolved
marker in the output, because an unresolved token in a rendered PDF
reads as a fabricated result.
tests/test_manuscript_variables.py tests that failure path
claim by claim, deleting each required label in turn and requiring the
error to name it. The consequence for a reader is narrow but real: each
ledger-backed value in sec. 5 can be traced to its
entry and owning recorder; derived values require the additional
calculation in the token writer. The refusal protects required recorded
inputs. It does not prove the measurements correct or make arbitrary
hand-written numerals impossible.
A concrete trace starts at tbl. 9, which prints
the letter-level perplexity as the token
STAGE1_LETTER_PERPLEXITY. Lowercasing gives the ledger
label stage1_letter_perplexity; its companions resolve to
run stage1_letter_gate and source
scripts/record_stage1_claims.py. Running that recorder,
.venv/bin/python scripts/record_stage1_claims.py,
re-records the entry;
.venv/bin/python -m pytest tests/test_stage1_gate.py -v
recomputes the same perplexity from the vendored counts and re-applies
the declared bar; and
.venv/bin/python scripts/audit_gates.py re-derives the
verdict that bar is judged under. The first two steps of that walk —
token to label, label to run and source — are mechanical and hold for
every one of the 2577 claims. Only the last step is claim-specific, and
it is not guesswork either: the source field names the
script that recorded the number. tbl. 21 identifies the ordinary
recorder phases; the one-shot replication is retained under its separate
protocol above.
Selected mathematical claims are stated and proved in Lean 4 under
formal/: the gate taxonomy of eq. 10 and eq. 12,
the pre-registered sweep-shape predicates of sec. 4.10, both halves of eq. 6, and
the Bonferroni arithmetic behind tbl. 36.
The layer ships 149 named theorems and 34 witness examples with a
recorded formal_sorry_free verdict of true, and it cannot
drift from the recorded measurements: the one ledger-facing module is
generated from data/claims.json, byte-identity-checked on
regeneration, and every ledger-facing theorem that fixes a threshold
closes by decide, so a re-record that moves a measured
value across a declared threshold stops the corresponding proof from
compiling. What the layer does not establish — that any recorded number
is correct — and the rest of its deliberate scope boundaries
are set out in sec. 14.
Deterministic build epoch and figures
This document was rendered at 2026-10-27T02:45:22Z from version
1.0.0. The timestamp honors SOURCE_DATE_EPOCH; when it is
omitted, the manuscript orchestrator derives the epoch of the last
audited commit that touched an input outside the regenerable
output/ tree, so the build stamp remains reproducible along
with everything else and a commit that only refreshes rendered output
does not move it. Figures are written deterministically by
src/ailm/figures/ with fixed layout and recorded inputs.
Where a figure validates a bootstrap statistic, it uses the registered
seed. Numeric content is drawn from the same recorded values as the
prose. Sharing that source removes a separate transcription step;
correct token selection, current generation, and rendered figure/table
agreement still require their own checks.
One caveat on exact equality: pymdp computes in float32 under JAX, so
analytic anchors are compared with recorder- or test-owned tolerances
rather than exact equality. A uniform transition over 39 phones measures
marginally below 39, not exactly it. That float32 premise is recorded,
not assumed: jax_enable_x64 is recorded as
false, preserving the default float32 path used by the
shipped pymdp agents. The Stage 0 recorder pins the live flag at record
time (env_jax_enable_x64, alongside the JAX, jaxlib, and
pymdp versions and the platform) and refuses to record with JAX’s 64-bit
mode enabled, since a flipped flag would change the numeric story, not
merely the rendering. tests/test_pymdp_smoke.py asserts the
recorded value still matches the live interpreter after importing the
pymdp path, so the recorded premise cannot silently outlive the
environment it describes. Reproducing the figures to the byte requires
the same matplotlib and font stack; reproducing the numbers
requires only the pinned environment.
Availability and retained upstream licenses
AILM’s own code (src/, scripts/,
tests/, formal/, and gnn/) is
licensed MIT; the manuscript, documentation, figures, and other authored
data are licensed CC BY-SA 4.0. The vendored count artifacts keep their
own, narrower upstream terms, which neither AILM license relicenses: the
Brown-derived counts carry NLTK’s non-commercial package terms, the
Czech-PDTC artifact is CC BY-NC-SA 4.0, the English EWT artifacts are CC
BY-SA 4.0, and the CMUdict counts retain the upstream BSD-2-Clause
notice. THIRD_PARTY_NOTICES.md inventories each component
with its transformation, and LICENSE states the
commercial-use boundary the two non-commercial artifacts impose on the
distributed wheel.
The recorded environment names an arm64 workstation
(macOS-27.0.1-arm64-arm-64bit) and the pinned JAX precision
setting. The CUDA extra is an untested install path. These fields do not
record device placement for each computation and do not establish
CPU-only execution of the separate Ollama model server. No wall-clock
performance claim is made here.
The work has a single author, who wrote every gate the audit reports on and every control that tests it. The external scrutiny to date is the audit and cross-vendor model reviews recorded in the decisions log, which the author commissioned and answered; no independent reproduction of the checkout is recorded in this evidence.
The work received no funding: there are no grants and no external funding of any kind. The author has no competing interests to declare.
sec. 6.1 states what that single-author position means for the gate-audit method’s own evidence.