Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/fep-lean-pair.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"repository": "ActiveInferenceInstitute/fep_formal",
"revision": "184ee53f55b526fdc858e2d962eba16e6066fb19"
"revision": "0d980814b8a4cbf167cefbf262143b6498feeb86"
}
46 changes: 46 additions & 0 deletions docs/development/backend_scientific_contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,49 @@ estimates tensor allocation before composition and sampling; process RSS include
JAX runtime/compilation and is recorded separately. Estimated allocation is not
measured peak RSS. Unsupported model families or structural-zero mappings are
reported explicitly, without clipping or silently normalizing their values.


## Authored planning horizons

The PyMDP, ordinary JAX, RxInfer, ActiveInference.jl, PyTorch and NumPyro
planning adapters admit one-step scoring. Source-authored
`planning_horizon`, `policy_len` and `policy_horizon` declarations must agree
and equal one. A declared `num_policies` must equal an unambiguous declared
`num_actions`. Positive integer values are required; Boolean, string and
fractional values are refused. Explicit `policies`/`policy_sequences` are
refused because these adapters do not consume their authored identity/order.
The alternative JAX POMDP solver and combined demonstration refuse all explicit
planning declarations because they use their own solver/demo defaults.
Declarations in the model-parameter, initial-parameter and parser parameter-list
surfaces are checked without hiding conflicts through precedence.

Unsupported declarations produce `unsupported-planning:` before script writing
through the direct renderer, single-spec interface and Step 11 compatibility
gate. These checks do not alter sources, choose a pruned subset, reduce a horizon
or claim that one-step action scores implement cumulative multi-step EFE.
`discrete/deep_planning_horizon.md` therefore remains an authored research model
whose five-step/64-policy planning question is unsupported by those adapters.
Its source does not specify the retained 64 sequences or a pruning algorithm.

Separately named JAX execution contracts and the finite continuous cpomdp
contract retain their own horizon rules. Stan and bnlearn filtering/smoothing,
THRML fixed-action smoothing and DisCoPy diagrams do not gain planning semantics
from this admission rule. Independent source-to-numerics witnesses and broader
planning contracts remain E4 work; successful backend execution alone is not a
proof of the model's complete prose semantics.


## Source text and path identity

`gnn.validate_gnn_source(source, is_content=True)` and
`gnn.validate_gnn_syntax(source, is_content=True)` preserve literal source text,
including text that happens to name a real file. The public dictionary facade
delegates mode selection once to the formal validator; it does not probe a path,
read a document, then classify the document's contents as another filename.
Default mode retains the existing-file heuristic. Long Unicode text, embedded
NULs and empty text reach the validator without an unguarded path probe.

Both modes use the same private, lossless markdown staging and normative schema
validation. Required-section failures remain failures; source-mode selection is
separate from backend capability or numerical fidelity. Explicit content mode
also treats a `Path` object as its literal string rather than reading that path.
11 changes: 11 additions & 0 deletions docs/development/remaining_roadmap_contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ change EFE sign, omit cross covariance, substitute a source digest and change
precision. Each must fail or refuse with a quantity-specific diagnosis. Add a
new witness version before extending its scientific meaning.

### E4-P1: authored planning admission

The shared `render/planning_admission.py` guard refuses unsupported source
horizons and policy identities on the six ordinary one-step planning adapters,
including direct and Step 11 entry points. It checks all supported parameter
containers before canonicalization can hide conflicts. This closes silent
one-step fallback for these explicit declarations only. The tracked five-step,
64-policy example retains its original source and remains unsupported for
planning until it supplies an executable policy-set/pruning contract. Broader
policy search and independent numerical qualification remain open.

### E4-BN1: finite bnlearn source filtering

The new `render/bnlearn/source_program.py` installs declared finite A/B/D CPTs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ Dynamic
s=HiddenState
o=Observation
u=Action

## Footer
Multi-Agent Coordination Acceptance Fixture
36 changes: 18 additions & 18 deletions output/data/manuscript_render_manifest.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
{
"counts_describe_commit": "4ed8b33",
"counts_describe_commit": "48db291",
"manifest_version": "gnn_render_manifest_v1",
"receipt_counts_describe_commit": "4ed8b33",
"receipt_counts_describe_commit": "48db291",
"recorded_by": "uv run python scripts/z_record_manuscript_render_manifest.py",
"render_artifacts_normalized_sha256": {
"output/pdf/_combined_manuscript.log": "1b46412330c82f3d1a22a5654fa24d3a8926c8b8f2906118c142360d7f6389f9",
"output/pdf/_combined_manuscript.md": "f8d7d333a127274c8068e4dd0640ecb2b88544053d69e3930d3dcc0fd1291e93",
"output/pdf/_combined_manuscript.tex": "bbc7b51b5606eb5558518d56e02ab55ddb5377d146993ee68ba810c246778beb"
"output/pdf/_combined_manuscript.log": "3f8fc9495762bc1d2b66f668c470a4d6fee6792c6bff8da2d1d55e416725d5c2",
"output/pdf/_combined_manuscript.md": "055874270cc69740c3a5549ed48d695b74ee444aa8c933b4def85c99b196f138",
"output/pdf/_combined_manuscript.tex": "b03354e0b47272f3a611f600f46843aa96132dbea6811dff2a246599b1ea9b0b"
},
"render_artifacts_sha256": {
"output/pdf/_combined_manuscript.log": "be663fe9a5fdb54b885ca1f2aba03bc8325a95c267377af82c2e3e7e49071803",
"output/pdf/_combined_manuscript.md": "27acaca71d11d3a887658df1ae0eebb1683e752b2fda1f72862c36d230c7b13b",
"output/pdf/_combined_manuscript.tex": "ee7f039e06d573825093dae08f580b3c0582401287c5378ddc2a8ca0f725bfdc"
"output/pdf/_combined_manuscript.log": "82794bc13a0d48150cd6390c4ce8f63ffccf297bd1ce04a2a30db0758cf4b2c7",
"output/pdf/_combined_manuscript.md": "3ac83f8cae6e585a4d080d3f14516990599cea58dcc5ed46c108976dc5cc716c",
"output/pdf/_combined_manuscript.tex": "e5d83a4477da3286a89dcb7fb844ba198637ccfdcbe2301e2574c8c6f8b271c3"
},
"render_inputs_normalized_sha256": {
"output/manuscript/00_abstract.md": "a66f146435f8300a5bfa2b3fbbc60373dec0e2e3c3fa4de9856f71e8b7eef27e",
"output/manuscript/01_introduction.md": "5d0d444605725927d88c415bbd7b2b6d27dfe62d33130cddc3cdbc4669ccb771",
"output/manuscript/02_system_context.md": "8da04dfdff5ba163f4c9e944150cff92de19d9ab76e3bf00fda1ee4c279a2e5b",
"output/manuscript/03_methods.md": "b23b0a2717f6e4006c6016672ab8ff9f319494a29584e838970e3ffcaa3fe082",
"output/manuscript/04_artifacts_and_evidence.md": "53a557380bfe681f84830018b99f51ae4e36f2445e4a78993ace1a5bc53b7e45",
"output/manuscript/05_reproducibility.md": "ef7da6b1d821b4129053458c46bca80048a50a26cad59348aaa5aa21475a45bb",
"output/manuscript/04_artifacts_and_evidence.md": "8ed3e1144e9cb4e449acc09ed36c1e1999e7594bd3bbe4223cf0b45812947e21",
"output/manuscript/05_reproducibility.md": "91852ba88dac3ec4b708809a4d85222001cbacd4f350ded2386ee0513d57fc5c",
"output/manuscript/06_limitations_and_next_steps.md": "86fdf003b8f486ce262699aca59d5b6bf2cea5b4ff9916acb87399d225a12d6e",
"output/manuscript/98_symbols_glossary.md": "4342b4bac17e063cd34f0e0805afe4769048efb22beced4887080ff198577c60",
"output/manuscript/99_references.md": "5e80feaa0ff39228501260f8e18f34debc071e1431de9c81a48016cb428aeef2",
"output/manuscript/S01_source_surface.md": "5d707901f2045b7d39c925f51551558c1a44928257b7025411b80045b2fd2eea",
"output/manuscript/S01_source_surface.md": "a098d8e41abc250a4586e9aadda7e8e61bcdd0d58084ac7ef835ba33f4327761",
"output/manuscript/config.yaml": "94d56ef0b383c482d2807b49b9ed5df26705009203746aa4e06a2819313eebfa",
"output/manuscript/preamble.md": "ebdb657038ccf007dffefe5e3d5834145b956e6580628356975d741bcd6fb01e",
"output/manuscript/references.bib": "ed44f4594867a193123aaf03334e12c2f12e167584d42ac5bc6074c4bfec9f0d"
},
"render_inputs_sha256": {
"output/manuscript/00_abstract.md": "9f41eac73a95505cccade998c67fc0a2245a1b079f9b6b378ff8307c6f9de50e",
"output/manuscript/00_abstract.md": "40e3726fbb3d6d491f517ae30e56c1b455315e00047bd3d43beb4543d718cbb0",
"output/manuscript/01_introduction.md": "5d0d444605725927d88c415bbd7b2b6d27dfe62d33130cddc3cdbc4669ccb771",
"output/manuscript/02_system_context.md": "3e6e912afca37b0c441b78f8c0059679b9f3698823ebc022cdb1014cda777249",
"output/manuscript/03_methods.md": "d8e8176ceaf484f5081ae251273f5e90ee46ea26cca7e5c1ab7357dd8545b6e6",
"output/manuscript/04_artifacts_and_evidence.md": "58a5d4ddb764086e2acd7cd46f701cda41290cffa8dabfdb9777fc0a4a1cd403",
"output/manuscript/05_reproducibility.md": "c454fc494d108f76b99b4963ce567d7d04b63825336079c8f0d1955d96dbec6b",
"output/manuscript/02_system_context.md": "d86338576cdd98823e43bfa47080b6fbf7db0bf3f846687c12a0750785e0104c",
"output/manuscript/03_methods.md": "d08ed236de295a5cb848b3d02e7877a0c631299e62cf2a50aa777def131c32f3",
"output/manuscript/04_artifacts_and_evidence.md": "85bced0b1d8b13d73cc1aafffbc96c0592ca262f468467d34d733d5ed4ba78da",
"output/manuscript/05_reproducibility.md": "66e147c56206ea5e09557b6e0acd18fe8227e9b55627e7f87d9e5581b447be52",
"output/manuscript/06_limitations_and_next_steps.md": "86fdf003b8f486ce262699aca59d5b6bf2cea5b4ff9916acb87399d225a12d6e",
"output/manuscript/98_symbols_glossary.md": "4342b4bac17e063cd34f0e0805afe4769048efb22beced4887080ff198577c60",
"output/manuscript/99_references.md": "5e80feaa0ff39228501260f8e18f34debc071e1431de9c81a48016cb428aeef2",
"output/manuscript/S01_source_surface.md": "5d707901f2045b7d39c925f51551558c1a44928257b7025411b80045b2fd2eea",
"output/manuscript/S01_source_surface.md": "a098d8e41abc250a4586e9aadda7e8e61bcdd0d58084ac7ef835ba33f4327761",
"output/manuscript/config.yaml": "94d56ef0b383c482d2807b49b9ed5df26705009203746aa4e06a2819313eebfa",
"output/manuscript/preamble.md": "ebdb657038ccf007dffefe5e3d5834145b956e6580628356975d741bcd6fb01e",
"output/manuscript/references.bib": "ed44f4594867a193123aaf03334e12c2f12e167584d42ac5bc6074c4bfec9f0d"
},
"variables_sha256": "a8751fd723486c28d7a7975e8126013211ab177f3c2a6a48108936a72762799a"
"variables_sha256": "abfea8c9b090da4eb05047d80315e8f178baa391f1178301aa590d83180fa21c"
}
12 changes: 6 additions & 6 deletions output/data/manuscript_variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"GNN_FAMILY_TARGET_DIR_COUNT": "9",
"GNN_FIRST_AUTHOR": "Daniel Ari Friedman",
"GNN_FRAMEWORK_TABLE": "| Framework | Discrete render | Continuous render | Executor status |\n|---|---|---|---|\n| PyMDP | yes | unsupported | executor |\n| RxInfer.jl | yes | yes | executor |\n| ActiveInference.jl | yes | unsupported | executor |\n| JAX | yes | yes | executor |\n| DisCoPy | yes | unsupported | executor |\n| PyTorch | yes | yes | executor |\n| NumPyro | yes | yes | executor |\n| Stan | yes | yes | executor |\n| bnlearn | yes | unsupported | executor |\n| cpomdp | no | yes | executor |\n| THRML | yes | unsupported | executor |\n| ngc-learn | no | yes | executor |\n: Model kinds each render framework supports, read entirely from the flags in `src/gnn/render/framework_registry.py` — the same source as [@tbl:backend_registry]. A continuous cell of `unsupported` is the renderer's own status for continuous-state models; continuous-only targets do not render categorical models. An executor entry declares dispatch support, not acceptance of every model or inference mode; a render-only entry has no Step-12 executor. Read with [@tbl:model_kinds], which groups the same flags by model kind. {#tbl:framework_capability}",
"GNN_GIT_COMMIT": "4ed8b33",
"GNN_GIT_COMMIT": "48db291",
"GNN_INPUT_FAMILY_DIR_COUNT": "12",
"GNN_KEYWORDS": "GNN, active inference, generative models, model notation, pipeline automation",
"GNN_LICENSE": "CC-BY-NC-SA-4.0",
Expand All @@ -45,9 +45,9 @@
"GNN_RELEASE_CODENAME": "Public contracts and native boundaries",
"GNN_RELEASE_DATE": "2026-10-08",
"GNN_REPO_URL": "https://github.com/ActiveInferenceInstitute/Generalized_Notation_Notation",
"GNN_SRC_LOC": "225800",
"GNN_SRC_LOC": "225920",
"GNN_SRC_PACKAGE_COUNT": "44",
"GNN_SRC_PY_FILE_COUNT": "766",
"GNN_SRC_PY_FILE_COUNT": "767",
"GNN_STEP_ADVANCED_VIZ": "9",
"GNN_STEP_ANALYSIS": "16",
"GNN_STEP_AUDIO": "15",
Expand Down Expand Up @@ -80,9 +80,9 @@
"GNN_STEP_WEBSITE": "20",
"GNN_SUBTITLE": "A text language and modular processing pipeline for Active Inference generative models",
"GNN_TARGET_DIR_COVERAGE_NOTE": "All 9 registered family target directories lie inside that tree, so a single invocation reaches every registered family.",
"GNN_TEST_COUNT": "6790",
"GNN_TEST_FILE_COUNT": "658",
"GNN_TEST_FUNCTION_COUNT": "6790",
"GNN_TEST_COUNT": "6809",
"GNN_TEST_FILE_COUNT": "660",
"GNN_TEST_FUNCTION_COUNT": "6809",
"GNN_TITLE": "GeneralizedNotationNotation: A Text Language for Active Inference Models",
"GNN_TOKEN_COUNT": "93",
"GNN_TOOL_COUNT": "164",
Expand Down
7 changes: 3 additions & 4 deletions output/data/manuscript_variables_receipt.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"counts_describe_commit": "4ed8b33",
"dirty_path_count": 11,
"counts_describe_commit": "48db291",
"dirty_path_count": 10,
"dirty_paths": [
"output/.pipeline/",
"output/data/manuscript_variables.json",
Expand All @@ -11,8 +11,7 @@
"output/manuscript/02_system_context.md",
"output/manuscript/03_methods.md",
"output/manuscript/04_artifacts_and_evidence.md",
"output/manuscript/05_reproducibility.md",
"output/manuscript/S01_source_surface.md"
"output/manuscript/05_reproducibility.md"
],
"generator": "scripts/z_generate_manuscript_variables.py",
"git_available": true,
Expand Down
4 changes: 2 additions & 2 deletions output/figures/figure_registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@
"GNN_MCP_TOOL_COUNT": "164",
"GNN_SRC_PACKAGE_COUNT": "44",
"GNN_STEP_COUNT": "25",
"GNN_TEST_FILE_COUNT": "658",
"GNN_TEST_FILE_COUNT": "660",
"GNN_VERSION": "4.1.0"
},
"filename": "gnn_repo_metrics.png",
"generated_by": "scripts/manuscript_fig_repo_metrics.py",
"label": "fig:repo_metrics",
"png_sha256": "ed52c9dc28d588cef5fb1aead3fb526601bfe01d595f813d61e23732c16a33be",
"png_sha256": "f34f344caf64fc88f67f16ebc767110dd305df4d2c566a5a3399e4418d947893",
"source_sha256": {}
},
{
Expand Down
Binary file modified output/figures/gnn_repo_metrics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion output/manuscript/00_abstract.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Abstract {#sec:abstract}

![The GeneralizedNotationNotation (GNN) pipeline at a glance, generated from the producer's token map at commit 4ed8b33. A plain-text specification — the `StateSpaceBlock` declaring the model's tensors, `A`, `B`, `C`, `D`, and `E` for the discrete categorical kind of [@eq:generative_model] through [@eq:policy] and its own matrix vocabulary for the other model kinds — is parsed (Step 3), type-checked and validated (Steps 5–6), rendered as backend-specific code (Step 11), executed (Step 12), and analyzed (Step 16), before artifacts flow into the cross-repository interchange checks against the pinned GEO-INFER and fep_lean pairs. Read the cards left to right: each header names the stage, each pill names the pipeline step (or the source role), and the body states what the stage produces. The validation stage includes the B-tensor orientation check — every discrete `B` literal is read as column-stochastic `B[s', s, a]`, and `--transpose-b` maps row-stochastic textbook literals onto that canonical order — and the execution stage includes the bnlearn lane, which generates runnable Python from the same parsed model and skips with a recorded status when its runtime is absent. The footer states the scale the panel summarizes: 25 pipeline steps, 9 model families, 12 registered render backends with 12 render targets having Step 12 execution adapters, and 164 Model Context Protocol tools.](../output/figures/gnn_graphical_abstract.png){#fig:graphical_abstract width=100%}
![The GeneralizedNotationNotation (GNN) pipeline at a glance, generated from the producer's token map at commit 48db291. A plain-text specification — the `StateSpaceBlock` declaring the model's tensors, `A`, `B`, `C`, `D`, and `E` for the discrete categorical kind of [@eq:generative_model] through [@eq:policy] and its own matrix vocabulary for the other model kinds — is parsed (Step 3), type-checked and validated (Steps 5–6), rendered as backend-specific code (Step 11), executed (Step 12), and analyzed (Step 16), before artifacts flow into the cross-repository interchange checks against the pinned GEO-INFER and fep_lean pairs. Read the cards left to right: each header names the stage, each pill names the pipeline step (or the source role), and the body states what the stage produces. The validation stage includes the B-tensor orientation check — every discrete `B` literal is read as column-stochastic `B[s', s, a]`, and `--transpose-b` maps row-stochastic textbook literals onto that canonical order — and the execution stage includes the bnlearn lane, which generates runnable Python from the same parsed model and skips with a recorded status when its runtime is absent. The footer states the scale the panel summarizes: 25 pipeline steps, 9 model families, 12 registered render backends with 12 render targets having Step 12 execution adapters, and 164 Model Context Protocol tools.](../output/figures/gnn_graphical_abstract.png){#fig:graphical_abstract width=100%}

Active Inference offers a unifying account of perception, learning, and action under the free energy principle [@friston2010], yet the generative models at its core are still communicated ad hoc: scattered across prose descriptions, bespoke notebooks, and framework-specific code that rarely agree. This fragmentation makes published models hard to reproduce, compare, or port between tools, and it raises the barrier for newcomers learning the formalism [@parr2022]. GeneralizedNotationNotation (GNN) addresses this gap with a standardized, human- and machine-readable text language for specifying Active Inference generative models, paired with a 25-step processing pipeline that transforms a single specification into validation, visualization, simulation, and analysis artifacts [@gnn2023]. A GNN file denotes a generative model, and the language lets that model take the several shapes the field actually uses: the notation blocks a file declares — categorical `A`/`B`/`C`/`D`[/`E`] tensors, linear-Gaussian system matrices `F`/`H`/`Q`/`R` with a Gaussian prior, per-agent and per-level compositions — fix its model kind, which the pipeline classifies structurally and carries through rendering and execution, recording explicitly which registered backends can render and run a model of each kind and which report it unsupported. GNN's "Triple Play" treats each model as three coordinated views — a textual specification, graphical visualizations, and executable cognitive models — so that outputs share an authored source and can be checked for consistency through identity, parameter, semantic, and numerical receipts. The framework spans 38 exemplar specifications (29 discrete-state and 9 continuous linear-Gaussian) across 9 model families and 12 registered rendering backends, with explicit gates for cross-format semantic fidelity and cross-framework reliability. GNN 3.0.0 layered safe-by-design long-running orchestration on top of this language and pipeline — durable observation streams, resumable run sessions, and auditable container plans that generate, validate, and replay data only, with no live infrastructure mutation. We describe the language, the model kinds it denotes, the pipeline architecture, and the validation contracts and source-bound checks used to assess specification round trips and admitted executions across simulation backends — with coverage gaps recorded as explicit profiled-unsupported statuses rather than silently omitted — providing inspectable infrastructure for reproducing and comparing Active Inference models within the recorded capability and verification boundaries.
Loading
Loading