diff --git a/.zenodo.json b/.zenodo.json index 6b143dd..3b7ac0b 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -11,7 +11,7 @@ } ], "license": "other-nc", - "notes": "This repository is under a mixed-license scheme rather than a single SPDX license: original AILM source code (src/, scripts/, tests/, formal/, and the GNN conformance code) is MIT, while the manuscript, documentation, figures, and AILM-authored data (including the GNN model specifications in gnn/) are CC BY-SA 4.0. Several vendored third-party corpora carry narrower terms of their own, unaffected by either AILM license (including a non-commercial-use restriction inherited from the NLTK Brown Corpus package and from UD English-GUM and UD Czech-PDTC, CC BY-NC-SA 4.0). See LICENSE and THIRD_PARTY_NOTICES.md for the full, component-by-component terms; pyproject.toml records this as license = \"LicenseRef-AILM-Mixed\", which has no single Zenodo/SPDX equivalent.", + "notes": "This repository is under a mixed-license scheme rather than a single SPDX license: original AILM source code (src/, scripts/, tests/, formal/, and the GNN conformance code) is MIT, while the manuscript, documentation, figures, and AILM-authored data (including the GNN model specifications in gnn/) are CC BY-SA 4.0. Several vendored third-party corpora carry narrower terms of their own, unaffected by either AILM license (including a non-commercial-use restriction inherited from the NLTK Brown Corpus package and from UD English-GUM and UD Czech-PDTC, CC BY-NC-SA 4.0). See LICENSE and THIRD_PARTY_NOTICES.md for the full, component-by-component terms; pyproject.toml records this as license = \"LicenseRef-AILM-Mixed\", which has no single Zenodo/SPDX equivalent.\n\nPublication preparation: DOI 10.5281/zenodo.22409419 is reserved by the authenticated, unpublished deposition. Its reservation does not establish public archival availability. The GitHub release remains a draft pending acceptance of the final candidate.", "keywords": [ "active inference", "Generalized Notation Notation", diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a4fd16..4f86e31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,13 @@ rationale behind each decision is in [`docs/decisions.md`](docs/decisions.md). ### Added +- A released upstream GNN pin in `gnn/upstream.json` and offline source-custody + verification before parser interoperability. The full profile records and + forwards `AILM_GNN_UPSTREAM`, checks its release identity, and refuses modified + source even when Git index flags hide changes. This integration does not add + a runtime dependency on the upstream pipeline or on FEP_Formal. + Git replacement objects cannot redefine the pinned source inventory. + - A configuration reference (`docs/reference/configuration.md`): the `LevelConfig` hyperparameters and every `AILM_*` environment variable the shipped code reads, each with its reader, meaning and unset behavior, @@ -104,6 +111,14 @@ rationale behind each decision is in [`docs/decisions.md`](docs/decisions.md). ### Removed +- The duplicated dated script-count table in the agent guide. The checked + per-script table in `scripts/README.md` owns the inventory. + +- The dashboard's unused `build_unigram_a` re-export and `MAX_REQUEST_BYTES` + alias. Active callers use `build_letter_transition` and `DashboardConfig`. + Measured-source adapters stay bound to their original evidence until their + required scoring replay; historical decisions and controls remain intact. + - `scripts/generate_case_counts_test.py`, the decision-79 preparation twin of the Stage 4 case generator. Decision 111's confirmatory run read the whole UD English EWT test split through `generate_confirmatory_ewt_counts.py`, so @@ -115,6 +130,25 @@ rationale behind each decision is in [`docs/decisions.md`](docs/decisions.md). ### Fixed +- The bibliography header no longer contains an entry marker inside its own + comment block, which caused a real BibTeX syntax error despite a completed + PDF. Publication verification now invokes BibTeX against the canonical source + and proves that a deliberately malformed entry fails. Citation fields and + unresolved metadata remain unchanged. + +- The dashboard CLI restores Python's interrupt handler when a launcher has + inherited an ignored `SIGINT`. A real exec-based control reproduced the + server ignoring the interrupt before the fix. Worker completion and interrupted + startup also share an idempotent slot release: the former double release + replaced `KeyboardInterrupt` with a semaphore error that the HTTP server + caught, leaving it running. A synchronized real-thread/signal control catches + that race. Embedded server callers keep their own signal policy. + +- Availability identifies the Zenodo DOI as reserved for an unpublished + deposition, separately from the public GitHub source. The abstract names + the existing release repository directly. Older acceptance receipts remain + tied to their original source and do not certify the later mainline. + - The protocol companion delivers the HTML provider's own assets (scripts, styles, fonts and icons) beside the pages that reference them instead of refusing them as unregistered context sources, so a `docxology/template` diff --git a/CITATION.cff b/CITATION.cff index ce39fbb..9889914 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,5 +1,5 @@ cff-version: 1.2.0 -message: "If you use this work, please cite it as below." +message: "Cite the versioned GitHub source while the reserved Zenodo DOI awaits publication." title: "Active Inference Language Model: A Fully Explicit Discrete Language System and a Gate-Audit Method" abstract: >- AILM is a set of explicit discrete probabilistic language models implemented in diff --git a/README.md b/README.md index d918b67..81bb5bf 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,14 @@ behavioral comprehension claim or general-purpose conversational interface. ## At a glance +The public source is available on [GitHub](https://github.com/ActiveInferenceInstitute/active_inference_language_model). +The `v1.0.0` GitHub release remains a draft. Its Zenodo deposition reserves +[10.5281/zenodo.22409419](https://doi.org/10.5281/zenodo.22409419) but is not yet +published; the DOI does not yet resolve publicly. The retained release +verification describes the earlier frozen candidate. The current manuscript +and companions are prepared for review; replacing the release requires current +source-bound acceptance. + ![Two panels: the same example sentence run through the explicit level stack from letter to document position, one row per level with its hidden state, observation, likelihood and dynamics named; and that same stack drawn with its per-level pass/fail gate outcomes and the measured cross-level interventions between them, each labeled helps, harms, or prior-only.](docs/manuscript/cover.png) The recorded stage results cover discrete levels and separately measured diff --git a/SOURCE_DISTRIBUTION.md b/SOURCE_DISTRIBUTION.md index 8a3fe9f..38a9f43 100644 --- a/SOURCE_DISTRIBUTION.md +++ b/SOURCE_DISTRIBUTION.md @@ -1,11 +1,11 @@ # AILM 1.0.0 source distribution and verification scope -This is a curated public export of prepared software build 9ad57480397d2439592b12758702df08416e67d0. Its audited input epoch is 1792176328. Runtime and scientific source bytes match that build. Two AGENTS.md sentences identify the publication repository. The public CI workflow explicitly installs Pandoc for the real portable documentation checks; local quick verification also requires that executable. Private handoff records, private Git ancestry, model-call caches, credentials and local recovery material are excluded. +The initial public export came from prepared software build `9ad57480397d2439592b12758702df08416e67d0`. Later mainline commits improve the software and guidance, so that build's source identity and acceptance do not describe the current checkout. The public CI workflow installs Pandoc for the portable documentation checks. Private handoff records, private Git ancestry, model-call caches, credentials and local recovery material are excluded. The retained connected-GUM report is included with its ledger-authenticated original bytes. Generated HTML/demo companions remain ignored in source Git. The separate portable manuscript ZIP includes the complete local link dependencies and its own member manifest. -Reports in output/reports describe the prepared build, including ignored documentation and archived render outputs retained on the release workstation. They are not a fresh validation receipt for this curated checkout. The release source-tree manifest describes the shipped tree. Public quick checks the portable surface; publication_context and template_context tests require retained provenance/raw-source proofs or the configured renderer/staged auxiliaries. Full requires those tests and the complete recorder no-op. Missing prerequisites remain failures, not exemptions from full acceptance. +Reports in `output/reports` describe their own recorded source and artifact identities. The historical full verification is not a fresh receipt for this checkout; current rendering and software checks must be recorded separately. The release source-tree manifest describes the shipped tree. Public quick checks the portable surface; publication_context and template_context tests require retained provenance/raw-source proofs or the configured renderer/staged auxiliaries. Full requires those tests and the complete recorder no-op. Missing prerequisites remain failures, not exemptions from full acceptance. -The full software profile ran with the declared retained inputs and toolchain. Those private proof/cache prerequisites are not redistributed; this is not independent scientific replication. Rebuilding full acceptance requires the documented inputs, toolchain and regenerated outputs. Consult the actual release verification and final independent review for their precise scope and limits. +The historical full software profile ran with the declared retained inputs and toolchain. Those private proof/cache prerequisites are not redistributed; this is not independent scientific replication. Rebuilding full acceptance requires the documented inputs, toolchain and regenerated outputs. The new upstream-parser check uses the released source pinned in `gnn/upstream.json`; it does not revalidate or replace historical measurements. Consult each source-bound receipt and independent review for its scope and limits. -Source/output import commits use the audited input epoch for reproducible build semantics; the annotated tag and publication records use their actual creation dates. LICENSE and THIRD_PARTY_NOTICES.md retain the component-specific terms, including non-commercial third-party corpus restrictions. The optional renderer runtime support archive has its own Apache-2.0 license. +Development commits use their actual creation dates. Flat source imports preserve the audited input epoch for reproducible build semantics; the snapshot manifest separately records the actual export time and original source identity. Publication records use the actual publication date. LICENSE and THIRD_PARTY_NOTICES.md retain the component-specific terms, including non-commercial third-party corpus restrictions. The optional renderer runtime support archive has its own Apache-2.0 license. diff --git a/TODO.md b/TODO.md index b574ae1..90b89b1 100644 --- a/TODO.md +++ b/TODO.md @@ -11,12 +11,6 @@ changes what the paper claims or what the artifact is. ## Minor -- [ ] At the next render, change the abstract's closing sentence from "The - planned release repository is" to "The release repository is": the public - `v1.0.0` tag exists. The edit is deferred rather than applied because - `tests/test_manuscript_crossrefs.py` requires the tracked rendered - provenance to match the authored sources, so a manuscript wording change - ships only with a template Stage 03/04 render. - [ ] At the next connected re-bind, apply the two source edits that the connected report's execution inventory blocks today (it binds 76 modules byte for byte, `src/ailm/claims.py` and `src/ailm/gnn/conformance.py` among diff --git a/docs/architecture.md b/docs/architecture.md index c61f697..79830f7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -124,6 +124,7 @@ AST/fresh-process tests. | `ailm/levels/synthetic.py` | The stipulated synthetic letter chain, deterministic corpus generator, independent evaluation-trajectory generator, and order-one comparator used to reduce exact-artifact overlap without asserting external pretraining contents | numpy, `ailm.levels.letter` | `tests/test_synthetic_benchmark.py` | | `ailm/levels/_stochastic.py` | The one column-stochastic normalizer (`column_stochastic`: counts divided by their axis-0 sums) and the one validator (`validate_column_stochastic`) every level builder shares, so the `[next, current]` orientation is normalized and checked in a single place instead of once per level. The oracle keeps its own copy by contract | numpy | `tests/test_coupling.py`, `tests/test_phoneme.py` | | `ailm/verification/connected_provenance.py` | Complete execution-input inventory shared by the connected recorder and figure; authenticates exact regular source and artifact files without model inference | stdlib | `tests/test_connected_provenance.py`, `tests/test_connected_gum.py`, `tests/test_figures_connected.py` | +| `ailm/verification/upstream_gnn.py` | Offline verification of the released upstream GNN checkout against its authored tag and commit pin, including actual source bytes and unexpected files before parser import | stdlib, Git executable | `tests/test_gnn_release.py`, `tests/test_gnn_conformance.py` | | `ailm/verification/oracle.py` | The closed-form HMM instrument: `forward_filter`, `forward_backward`, `viterbi`, `sequence_perplexity`, `markov_chain_perplexity`, `identity_emission`, `word_path_logprob` | **numpy and stdlib only** | `tests/test_oracle.py`, `tests/test_oracle_independence.py`, `tests/test_stage2_gate.py` | | `ailm/generation.py` | The independent L3→L1g generation seam: next-letter policy selection with lexicon `C` and Brown-bigram habit `E`, scored against gamma-sweep and scrambled-`C` controls. L6 and L5 are absent from this run | pymdp, jax, numpy, `ailm.levels.letter` | `tests/test_generation.py` | | `ailm/learning.py` | Parameter learning inside pymdp — `infer_parameters` as conjugate counting, and the agreement identity against an external count (decisions 22–23) | pymdp, numpy, `ailm.levels.letter` | `tests/test_learning.py` | diff --git a/docs/decisions.md b/docs/decisions.md index 5c771b5..ba233c2 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -157,6 +157,7 @@ Forward-looking guidance on how to *specify* a gate is a separate document: | [138](#138--operational-continuation-preserve-interrupted-scopes-and-verify-the-current-upstream-checkout-2026-10-07) | OPERATIONAL CONTINUATION: preserve interrupted scopes and verify the current upstream checkout (2026-10-07) | | [139](#139--operational-selection-amendment-current-gnn-interoperability-after-release-recovery-2026-10-09) | OPERATIONAL SELECTION AMENDMENT: current GNN interoperability after release recovery (2026-10-09) | | [140](#140--publication-metadata-alignment-institute-release-destination-2026-10-14) | PUBLICATION METADATA ALIGNMENT: Institute release destination (2026-10-14) | +| [141](#141--release-preparation-pinned-gnn-interoperability-and-dashboard-interruption-2026-10-26) | RELEASE PREPARATION: pinned GNN interoperability and dashboard interruption (2026-10-26) | --- @@ -9474,3 +9475,40 @@ maintenance, retaining full catalogs at startup and completion and checking ever recorded model identity periodically. Actual timeout, identity, retention and terminal catalog controls remain required. Fresh source-bound rendering, package verification and independent review are required before successor delivery. + +## 141 — RELEASE PREPARATION: pinned GNN interoperability and dashboard interruption (2026-10-26) + +**Current upstream selection.** The release-verification pin in +`gnn/upstream.json` selects public GNN `v5.0.1` at +`e54813b4197df36f7ae0054d5e79f3ad2d5db0ff`. Decision 139's earlier selection +remains historical evidence. The standalone verifier checks the release tag, +commit and actual source inventory before import; interoperability repeats the +check after use. The full profile records and forwards `AILM_GNN_UPSTREAM` +instead of silently selecting a moving sibling checkout. Real Git/filesystem +controls reject another head, a retargeted tag, altered source hidden by index +flags, unexpected source and symlinks. This is parser interoperability, not a +new linguistic measurement or acceptance of the whole GNN pipeline. +The real parser runs in a fresh interpreter with bytecode writes disabled and +a private empty cache prefix; the parent interpreter's configuration is not +replaced. Its measured results are compared directly with AILM's reader. +FEP_Formal is not a dependency; the local dependency-free Lean layer is retained. + +**Observed lifecycle defects.** A real exec-based control established that a +launcher can pass an ignored interrupt disposition to the dashboard. The CLI +now installs its own interrupt handler; callers embedding the server retain +their signal policy. A separate real-thread/signal control reproduced an +interrupted worker start after completion: cleanup released its semaphore slot +again, replacing `KeyboardInterrupt` with a `ValueError` that the HTTP server +caught. Startup and completion now share an idempotent release. The initial +timeouts and failing controls remain evidence beside the corrected checks. +Dashboard capture binding also requires the named checkout root: an +uninitialized directory cannot borrow the HEAD of an enclosing repository. + +**Cleanup and publication boundary.** Unused dashboard aliases are removed. +The conformance adapter and other measurement-bound source remain unchanged; +removing them still requires the scoring replay recorded in the open queue. +The scientific ledger, models, corpora and original measurement reports retain +their bytes. The configured Zenodo identifier is authenticated as a reservation +in an unpublished deposition, not an available public archive. Current source +and regenerated outputs require their own acceptance and independent review; +historical full verification cannot be transferred to this candidate. diff --git a/docs/guides/quickstart.md b/docs/guides/quickstart.md index 230036c..6eb48f6 100644 --- a/docs/guides/quickstart.md +++ b/docs/guides/quickstart.md @@ -515,13 +515,14 @@ already-declared upstream-parser extra: uv sync --locked --extra gnn-interop ``` -Direct upstream interoperability tests accept `AILM_GNN_UPSTREAM`. The full -release’s controlled child environment does not inherit it, so the intended -checkout must resolve through `_UPSTREAM_CANDIDATES` in -`tests/test_gnn_conformance.py`; its first candidate follows the shared checkout -hierarchy. Confirm the actual selected parser path as described in the -[release prerequisites](../method/release_checklist.md#preconditions). A missing -checkout or extra fails the full profile instead of skipping. Returning to +Direct interoperability tests and the full release profile accept +`AILM_GNN_UPSTREAM`, which the runner records and forwards. Select the released +checkout pinned in [`gnn/upstream.json`](../../gnn/upstream.json), rather than a +moving development branch. Follow the [GNN setup](../../gnn/README.md#upstream-release) +and run `.venv/bin/python scripts/verify_gnn_release.py`: the command checks the +tag, commit and actual source bytes offline. Without an explicit selection, +durable sibling discovery applies and the same identity checks follow. +A missing checkout or extra fails the full profile instead of skipping. Returning to `quick` requires `uv sync --locked` to restore the base dependency set. `scripts/verify_release.py full` enforces the `pyproject.toml` coverage floor. diff --git a/docs/manuscript/00_abstract.md b/docs/manuscript/00_abstract.md index d0629e1..26a76b2 100644 --- a/docs/manuscript/00_abstract.md +++ b/docs/manuscript/00_abstract.md @@ -38,5 +38,5 @@ linguistic inference mechanisms together with an audit method that makes their failures visible. External neural models serve as supplemental reference probes; integration with them remains a proposal. -The planned release repository is +The release repository is . diff --git a/docs/manuscript/07_reproducibility.md b/docs/manuscript/07_reproducibility.md index f9f8557..2586ff0 100644 --- a/docs/manuscript/07_reproducibility.md +++ b/docs/manuscript/07_reproducibility.md @@ -21,10 +21,11 @@ in `LICENSE` and `THIRD_PARTY_NOTICES.md`. **Availability.** The versioned release source is [the Institute repository's release tag](https://github.com/ActiveInferenceInstitute/Active_Inference_Language_Model/tree/v1.0.0). -The corresponding archival record is identified by -[the release DOI](https://doi.org/10.5281/zenodo.22409419). -The citation, package metadata and title page identify the same archive and -release destination. Public source and archival availability do not establish +The corresponding Zenodo deposition is unpublished. Its +[reserved DOI](https://doi.org/10.5281/zenodo.22409419) 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 diff --git a/docs/manuscript/references.bib b/docs/manuscript/references.bib index 92a5c37..8c40e99 100644 --- a/docs/manuscript/references.bib +++ b/docs/manuscript/references.bib @@ -10,7 +10,7 @@ @comment{ A `note` field RENDERS into the printed reference list, so it is reserved for what a reader of the bibliography needs: an edition, a locator, what a resource is. Provenance uncertainty about this file is not that, and it lives here - instead, because an `@comment` block never renders. Entry by entry: + instead, because a bibliography comment block never renders. Entry by entry: brier1950 — the registered DOI is of the form 10.1175/1520-0493(1950)078<0001: VOFEIT>2.0.CO;2. The angle brackets do not survive a LaTeX text-mode round diff --git a/docs/method/release_checklist.md b/docs/method/release_checklist.md index 330e808..980f4c1 100644 --- a/docs/method/release_checklist.md +++ b/docs/method/release_checklist.md @@ -98,14 +98,14 @@ candidate before delivery. This does not authorize a tag, push or deposition. Switching profiles requires the corresponding sync: returning to `quick` removes the optional parser dependency. The release runner checks this state without changing it. -- **Upstream GNN checkout.** The full profile requires the real parser and the - `gnn-interop` extra. Its controlled environment does not forward - `AILM_GNN_UPSTREAM`; make the intended checkout discoverable through - `_UPSTREAM_CANDIDATES` in `tests/test_gnn_conformance.py`. The first candidate - is checkout-relative under the shared `Username` hierarchy at - `ActiveInferenceInstitute/Public/Generalized_Notation_Notation`. Direct test - invocations can use `AILM_GNN_UPSTREAM`, but exporting it alone does not select - the full-profile checkout. Verify the actual resolved parser path. +- **Pinned upstream GNN release.** The full profile requires the real parser, + the `gnn-interop` extra and the release identity in `gnn/upstream.json`. + Export `AILM_GNN_UPSTREAM` to its isolated checkout; the controlled runner + records and forwards it. The `gnn-upstream-release` step checks the exact tag, + commit and source bytes before interoperability tests import the parser. + The fixture repeats that check after use. Without an explicit selection, + durable sibling discovery applies; a moving sibling head still fails the pin. + See [`gnn/README.md`](../../gnn/README.md#upstream-release) for setup. ## The sequence diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index f8e2b23..4b87835 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -114,7 +114,7 @@ behavior the quick profile deselects. | `AILM_RELEASE_MANDATORY_ENVIRONMENT=1` | the full test step | `tests/test_synthetic_benchmark.py`, `tests/test_gnn_conformance.py` | turn an environment gap (unserved probe, absent upstream GNN checkout) into a failure that names it, because the full profile forbids skips | | `AILM_PUBLICATION_DERIVATIVE_CONTRACT` | the derivative route only | `tests/test_release_orchestration.py` | the reviewed external derivative contract under test | | `AILM_PUBLICATION_DERIVATIVE_LIVE_PROOF` | the derivative route only | `tests/test_release_orchestration.py` | the live local proof the derivative audit produced | -| `AILM_GNN_UPSTREAM` | nothing (not forwarded by the runner) | `tests/test_gnn_conformance.py` | a direct test invocation's upstream GNN checkout; the full profile discovers its checkout through the test's candidate list instead | +| `AILM_GNN_UPSTREAM` | inherited and recorded by the release runner | `ailm.verification.upstream_gnn`, `tests/test_gnn_conformance.py` | explicitly select the checkout matching `gnn/upstream.json`; an empty value, wrong commit or changed source is refused; absence uses durable sibling discovery | The runner also strips any `AILM_OPENROUTER_BUDGET_*` value from its child environment, so a release run can never make a hosted acquisition under a diff --git a/gnn/README.md b/gnn/README.md index c8bbc30..11981b6 100644 --- a/gnn/README.md +++ b/gnn/README.md @@ -57,6 +57,30 @@ it is not merely necessary-but-insufficient: it pins each slot by declared name and checks the declaration against the live pymdp object. A matrix in the wrong slot becomes a named violation instead of a slightly different number. +## Upstream release + +[`upstream.json`](upstream.json) pins the public +[GNN v5.0.1 release](https://github.com/ActiveInferenceInstitute/Generalized_Notation_Notation/releases/tag/v5.0.1) +to commit `e54813b4197df36f7ae0054d5e79f3ad2d5db0ff`. This is an optional parser +interoperability dependency, separate from AILM's own strict reader and model. +Use an isolated checkout so ongoing upstream development cannot silently change +the parser used for release verification: + +```bash +git clone --depth 1 --branch v5.0.1 https://github.com/ActiveInferenceInstitute/Generalized_Notation_Notation.git ../ailm-gnn-v5.0.1 +export AILM_GNN_UPSTREAM="$(cd ../ailm-gnn-v5.0.1 && pwd)" +uv sync --locked --extra gnn-interop +.venv/bin/python scripts/verify_gnn_release.py +.venv/bin/python -m pytest tests/test_gnn_conformance.py -q --no-cov +``` + +The standalone verifier and upstream test fixture refuse a different commit, +retargeted tag, missing or altered source, and unexpected source files. The full +release runner forwards the explicit selection and records its identity check. +Changing the pin requires actual parser interoperability and mutation controls; +it changes no historical scientific result. AILM's Lean layer remains local and +dependency-free; FEP_Formal is not required by this integration. + ## The naming grammar ``` diff --git a/gnn/upstream.json b/gnn/upstream.json new file mode 100644 index 0000000..cc1a08e --- /dev/null +++ b/gnn/upstream.json @@ -0,0 +1,5 @@ +{ + "repository": "https://github.com/ActiveInferenceInstitute/Generalized_Notation_Notation", + "tag": "v5.0.1", + "commit": "e54813b4197df36f7ae0054d5e79f3ad2d5db0ff" +} diff --git a/output/data/manuscript_variables.json b/output/data/manuscript_variables.json index 520ec96..89aa4cb 100644 --- a/output/data/manuscript_variables.json +++ b/output/data/manuscript_variables.json @@ -5711,7 +5711,7 @@ "META_BROWN_WORD_COUNTS_KB": "2082", "META_BROWN_WORD_COUNTS_SHA256": "2d10d0c6e237207a53566e37ed6c66e95ae9258aa4e3c8fc953f3a2ce84a2268", "META_BROWN_WORD_COUNTS_SHA256_SHORT": "2d10d0c6e237", - "META_BUILD_TIMESTAMP": "2026-10-16T18:45:28Z", + "META_BUILD_TIMESTAMP": "2026-10-27T02:45:22Z", "META_CLAIM_COUNT": "2577", "META_CMUDICT_COUNTS_KB": "978", "META_CMUDICT_COUNTS_SHA256": "9f0f20746086e378b54f5cef82792c9d99f51c80a00b65a00bd783ef917d3def", diff --git a/output/figures/figure_provenance.json b/output/figures/figure_provenance.json index 41c924c..cdad8d5 100644 --- a/output/figures/figure_provenance.json +++ b/output/figures/figure_provenance.json @@ -1,7 +1,7 @@ { "schema": "ailm-figure-provenance-v3", "environment": { - "python": "3.12.13", + "python": "3.12.15", "jax": "0.4.38", "jaxlib": "0.4.38", "jax_backend": "cpu", @@ -14,7 +14,7 @@ }, "manuscript_variables": { "path": "output/data/manuscript_variables.json", - "sha256": "399f81ef66a7a60b4c0bb88395ece9107955740cdd18417f9dd4ca0e98a5b8cc" + "sha256": "c841514f89db60203707e2eb609745c0a834be335b564ccf650f35e9f39e8a38" }, "shared_sources": [ { @@ -221,11 +221,11 @@ }, { "path": "src/ailm/dashboard/__main__.py", - "sha256": "abd23041f9c8dd925b7de3f0e29b928de3c582586e529fc4a0389034a924f715" + "sha256": "502c2b175be82c3f3d91cb50285a09efcfb44e219bf4b84e4fbc9be3a51c28fa" }, { "path": "src/ailm/dashboard/capture.py", - "sha256": "4bcb616ea22b5a523356b74dc1d2e0bb781e0cdc7b16870a7c508df8bd28621e" + "sha256": "ee414ac8237b63abea2675a9a39e1651a15bf479e3d75cc09c6072291327abe1" }, { "path": "src/ailm/dashboard/config.py", @@ -233,11 +233,11 @@ }, { "path": "src/ailm/dashboard/engine.py", - "sha256": "543fab111dd80f4da0c6807e3f63c81098a495b4010e57192ce36cd0c81f07ee" + "sha256": "4f1ed973af345952944134f419966422895e0df106e9768e018f01568e1c5947" }, { "path": "src/ailm/dashboard/server.py", - "sha256": "81e4893005af641fdf1f21ad4499b051e62d293d30ac0350edc2436c560875b0" + "sha256": "4e0e2251310401bde3ab869a446ab9a376161f0f43f57944d4ac72c122c5cff2" }, { "path": "src/ailm/demo.py", @@ -631,6 +631,10 @@ "path": "src/ailm/verification/oracle.py", "sha256": "323808c6dbf96f848a5259ff2f381b828dd65218e37264d26750c3f626971cea" }, + { + "path": "src/ailm/verification/upstream_gnn.py", + "sha256": "b32032dcd25f57824fa803309a289ba1f12e0441e7cf3cbf12c7548c416e40ca" + }, { "path": "src/ailm/viz_config.py", "sha256": "198fd4d93c38e27e0be653accc8591e4d144b39b3271ce2dd0613f8576d5f39d" diff --git a/output/manuscript/00_abstract.md b/output/manuscript/00_abstract.md index d99ede2..0b1e65d 100644 --- a/output/manuscript/00_abstract.md +++ b/output/manuscript/00_abstract.md @@ -38,5 +38,5 @@ linguistic inference mechanisms together with an audit method that makes their failures visible. External neural models serve as supplemental reference probes; integration with them remains a proposal. -The planned release repository is +The release repository is . diff --git a/output/manuscript/07_reproducibility.md b/output/manuscript/07_reproducibility.md index a4a2d97..5619149 100644 --- a/output/manuscript/07_reproducibility.md +++ b/output/manuscript/07_reproducibility.md @@ -21,10 +21,11 @@ in `LICENSE` and `THIRD_PARTY_NOTICES.md`. **Availability.** The versioned release source is [the Institute repository's release tag](https://github.com/ActiveInferenceInstitute/Active_Inference_Language_Model/tree/v1.0.0). -The corresponding archival record is identified by -[the release DOI](https://doi.org/10.5281/zenodo.22409419). -The citation, package metadata and title page identify the same archive and -release destination. Public source and archival availability do not establish +The corresponding Zenodo deposition is unpublished. Its +[reserved DOI](https://doi.org/10.5281/zenodo.22409419) 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 @@ -339,7 +340,7 @@ out in [@sec:lean]. ## Deterministic build epoch and figures -This document was rendered at 2026-10-16T18:45:28Z from version +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 diff --git a/output/manuscript/references.bib b/output/manuscript/references.bib index 92a5c37..8c40e99 100644 --- a/output/manuscript/references.bib +++ b/output/manuscript/references.bib @@ -10,7 +10,7 @@ @comment{ A `note` field RENDERS into the printed reference list, so it is reserved for what a reader of the bibliography needs: an edition, a locator, what a resource is. Provenance uncertainty about this file is not that, and it lives here - instead, because an `@comment` block never renders. Entry by entry: + instead, because a bibliography comment block never renders. Entry by entry: brier1950 — the registered DOI is of the form 10.1175/1520-0493(1950)078<0001: VOFEIT>2.0.CO;2. The angle brackets do not survive a LaTeX text-mode round diff --git a/output/pdf/active_inference_language_model_combined.pdf b/output/pdf/active_inference_language_model_combined.pdf index d01b473..25ac2f3 100644 Binary files a/output/pdf/active_inference_language_model_combined.pdf and b/output/pdf/active_inference_language_model_combined.pdf differ diff --git a/output/reports/artifact_manifest.json b/output/reports/artifact_manifest.json index c1400fc..21ca4b7 100644 --- a/output/reports/artifact_manifest.json +++ b/output/reports/artifact_manifest.json @@ -1,1417 +1,1237 @@ { "entries": [ - { - "contract_match": true, - "path": "output/architecture-map/render.js", - "sha256": "227a3a5c4f4b7a57e2d2d90b44130cd0d75a899a792d3dac414beb61176aedd4", - "size_bytes": 988519, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/architecture-map/snapshot.js", - "sha256": "55fad86cc177de437017da4b38da9cbb1b6216e9d155e0d33c6fef64b3a29025", - "size_bytes": 5336442, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/architecture-map/version.js", - "sha256": "f717d7f0c61fd380f57023bf2fb1b6758a62b9be583af943ac5c734cdcbfc45d", - "size_bytes": 97, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, { "contract_match": true, "path": "output/data/manuscript_variables.json", - "sha256": "399f81ef66a7a60b4c0bb88395ece9107955740cdd18417f9dd4ca0e98a5b8cc", + "sha256": "c841514f89db60203707e2eb609745c0a834be335b564ccf650f35e9f39e8a38", "size_bytes": 568041, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/AGENTS.md", - "sha256": "333126ff8d87ceaef8a3618e52daf79463fd9f3e40b8d352cbbbd30bf12d32f8", - "size_bytes": 23076, - "stage_name": "current-output-snapshot", + "sha256": "d1ff3093bfe68a8a1ce2e396fd137893712ea634dbe6be32d2c090dfe76f4bd8", + "size_bytes": 23440, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/CHANGELOG.md", - "sha256": "6cf69904c5e948575899a34c000d7acc778210e73b621ab1bb55c25a34591e7c", - "size_bytes": 5616, - "stage_name": "current-output-snapshot", + "sha256": "a60091951089869072b6e67e135c46b9e2cb8518e68b52edec3e47c0ae73e729", + "size_bytes": 16212, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/README.md", - "sha256": "eea00931d358a1de7af1ebe43ba4e14c29adecdc7d45b01007eb7c08df0b967b", - "size_bytes": 31268, - "stage_name": "current-output-snapshot", + "sha256": "48a898f0fb194c3e548e15f2a7972fbc54a12fe0539a297d686692a3548e3887", + "size_bytes": 32179, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/AGENTS.md", - "sha256": "03b7524ee2e873e159dbaf34bea1dae6f4926974f7f089bad64c2b001ee5e9df", - "size_bytes": 9731, - "stage_name": "current-output-snapshot", + "sha256": "7ebf0fa178b64946f1c552394c11adb492609da667342e3d88d2ea087d36cb21", + "size_bytes": 9804, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/README.md", - "sha256": "c23fa5c35f2a8e734585d6b2d531b8d15aec1efe21fae5fad0255618f6c61905", - "size_bytes": 20050, - "stage_name": "current-output-snapshot", + "sha256": "f8df15250aaee39ad650dbffdda76be644223cf9a3dccf1ea0d5b4cb1344d45f", + "size_bytes": 20342, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/architecture.md", - "sha256": "b15282f454ad2af7fd29691c1f2e14d3567ea2ee7a1a2d1c7569a7f133c96ff8", - "size_bytes": 63065, - "stage_name": "current-output-snapshot", + "sha256": "08929a6184d00a05b9c14f153616d29b5dad53d2feb7ad951b632f6777e37af9", + "size_bytes": 64205, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/decisions.md", - "sha256": "386440800161278634dd077dbbcf28f3b73c61ae5d5ddcf55e70154717d88bc0", - "size_bytes": 587389, - "stage_name": "current-output-snapshot", + "sha256": "b227dfc48300500636b5f5d4ef2cdafb1146d41e21a2c00799537849fab459a6", + "size_bytes": 590088, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/AGENTS.md", "sha256": "61fe392074e7ed34c9bcdace33a957ef46129b822555e3b95def02d6a88e4820", "size_bytes": 4719, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/README.md", "sha256": "8aa9eb19bfeaebaffbe637dff7050ebacf9b8187ff1adcd0017acf20536e2ccb", "size_bytes": 3346, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/architecture.md", "sha256": "67c40b3101a96b86cfc34f4b5ba86b348d07680023290a11bc24b0fe8021fbd0", "size_bytes": 14921, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/cerebrum_mapping.md", "sha256": "613c49ec1b0ace98403fb432b42e7a818813e9ac999f544ec6f0914b81510564", "size_bytes": 6807, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/connected_runtime.md", "sha256": "a98408e7352ebc6386a79c458e26572679c3bec230eb31a0c92fe823155fd1fe", "size_bytes": 12817, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/generation_problem.md", "sha256": "e9233d959ed07483e9c3871357d3476f691a270612efcbb7c2ba2e847485c672", "size_bytes": 6228, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/no_embeddings.md", "sha256": "9676f2cbde451a449aa2365b697d8eb837fd5b219eb1914fea38f89d195c5e02", "size_bytes": 4095, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/power_and_ci.md", "sha256": "5e322e7fd081acb9212ce70e38f89b65efa9867d3ed0aa8e513f26203100dc76", "size_bytes": 3121, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/speech_boundary.md", "sha256": "0eb633e28e1a365a1ec8afcd41a21e245a03e73a704bbf623a5b9e64cb3cd324", "size_bytes": 3794, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/stage2_g2p.md", "sha256": "c9ff75694330646036287908aaf85a88d237c444e81982886bae131ed6f41535", "size_bytes": 6166, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/stage3_word.md", "sha256": "1e02dd4762f2a68ca50ed0dc228fc2f90d0f19be082224b5915e0c3053c32719", "size_bytes": 9052, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/design/stage4_case.md", "sha256": "d06eaedf39b15975be05428ddecacbf984d2d8e071c740a38ff0d5c08bbe5d57", "size_bytes": 10241, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/development_history.md", "sha256": "831a4334bb09c778e5b125f738d20db1c6fdfd7d3657edab3195f544389faf67", "size_bytes": 145580, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/extension_protocols.md", "sha256": "0799aa461a37106daac8f04c61daaf98f699bfea9c27f68c723c03a885d7f23d", "size_bytes": 65271, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/formal.md", "sha256": "d5a3b55d83efe16f541db230575326ebd9a53c7453b0d53535552f337be99565", "size_bytes": 22860, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/gate_design.md", - "sha256": "dea3f8dce87119317bc54bb21fc43b45a073985f9b98bde9c616d81c89e0be46", - "size_bytes": 28480, - "stage_name": "current-output-snapshot", + "sha256": "f815c14a747107b9d7ca90e677312f2edb55b2e0d510fece99daaac7fbbacdb1", + "size_bytes": 28493, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/gnn_composition.md", "sha256": "ea49821dc9b5d69b66601c72f0d83dd03e7440d860e8bb706c97a820774fcc01", "size_bytes": 31073, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/guides/agent_instructions.md", "sha256": "6986f245eb87c73e6c4e4037c39f25aebde86a244b9366d220f0012212cec0c4", "size_bytes": 13387, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/guides/faq.md", "sha256": "4d86fe5505e4f3e0159a58780531f781ccebcfdfd26b38afe308daadc362836c", "size_bytes": 16543, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/guides/forking_guide.md", "sha256": "8269a09eb09a7118dd96a934b889f2041263c38cc0c1bbc852abee314d033bf8", "size_bytes": 20928, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/guides/quickstart.md", - "sha256": "523565877728c18d42108cafc89c9085fecde7de7ad499585eec450d8cb15805", - "size_bytes": 33361, - "stage_name": "current-output-snapshot", + "sha256": "f0f2364fcd341fe611f782adf47d6c2285cfedaff4828e843ac0111d3b618834", + "size_bytes": 34016, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/guides/roadmap.md", "sha256": "6db123fad1fded5715989bdbffb94d344370c3ea3733a5602ab45912b203ce13", "size_bytes": 18296, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/hierarchy.md", "sha256": "c97739ee53b1f980c3b4f3807b72e86534c556cbedcd8f87489a1174f9fc8f54", "size_bytes": 26851, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/00_abstract.md", - "sha256": "d00eb3573c0f6a3cb8a3b953bdfc2612f8592cad0c568fe85cdf6d6e9a2fd8d7", - "size_bytes": 2696, - "stage_name": "current-output-snapshot", + "sha256": "4ea6de835550d112f8002158515e957f9dd34b82412f566e6fca4568e21f4b5d", + "size_bytes": 2688, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/01_introduction.md", "sha256": "24f8e5332b108da00c71b4693d072ef64f2365256aad2911539c64fc4cb88f50", "size_bytes": 33620, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/02_background.md", "sha256": "7dfc0395edf22fbadb21ce9c2cf822a6a1d63865b09be5969d559f0971e26355", "size_bytes": 20323, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/03_methods.md", "sha256": "b443418d267292188c5b6b88949b3e95d59c2b8374c701396156461fe2782f19", "size_bytes": 159230, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/04_results.md", "sha256": "be1a95a5f25b20c8298d7e1bd3e4b60a06f269a220d63037b2673daea412c30c", "size_bytes": 151942, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/05_discussion.md", "sha256": "6f7bbafad41e70b3a207c025754b2fa3e34a87ea7c3d696382edf9ae974f93d6", "size_bytes": 54391, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/06_related_work.md", "sha256": "04bb21def36559580711e3c8d2745cfce420767f55838a023051ca68ff834ba2", "size_bytes": 52635, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/07_reproducibility.md", - "sha256": "062df26a6056f365d38a6da683e8c98e3354fdaec91eef3a350adf322799028c", - "size_bytes": 32840, - "stage_name": "current-output-snapshot", + "sha256": "01a2de507e62d7859071213a8fd9b535cc4d8b3f9bc86718e842577967709fdc", + "size_bytes": 32927, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/08_conclusion.md", "sha256": "ca81550c1ece3f5591d8da04891a9d063f358b081aef97b6687e9267d5da3936", "size_bytes": 17837, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/98_supplement_audit_trails.md", "sha256": "8c44e5116b4fc306fd577a7923168c60f432ebf6845060d8157b8c1f05d6512f", "size_bytes": 66858, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/98_supplement_channel_factorial.md", "sha256": "bb1c37632926236f2635785929908eac3a23c735e8f11ad323130d825e889e7f", "size_bytes": 24682, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/98_supplement_complexity.md", "sha256": "c958590ab080c89b94befe476f3ccf38d215adf968837727b09ebd4ebf487b17", "size_bytes": 23156, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/98_supplement_external_benchmarks.md", "sha256": "4a7dac45e5d6cc8feb5f0144d769def1e0dfc5490f92c24844ae0b89ead7d1e5", "size_bytes": 123269, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/98_supplement_lean.md", "sha256": "e9cae0b3375e0f160436a29c1da1cec9f0e4eef42e9c164ca8ceb71fbc4374a4", "size_bytes": 4112, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/98_supplement_statistics.md", "sha256": "eb4cbb5b55986dbbe91a3de30168cbd219143b6b4dd95456c7cc2131763dd202", "size_bytes": 85905, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/99_references.md", "sha256": "20f4a91ee979db68b8c62777d4518e3a6bd40994562308aa12f827ba621567a0", "size_bytes": 31, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/AGENTS.md", "sha256": "dedfba686394010615b80f7d6ac4511d295ad2916767c9e815dabbef4c5f3dc8", "size_bytes": 11155, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/MANUSCRIPT_STATUS.md", "sha256": "82db98ccd0ab8dec87c8ce3ddba6de10e1862242a946733305de674606bb8d7d", "size_bytes": 6433, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/README.md", "sha256": "363be29d20cd08c8c135da08d5c6ccd7507e0bc05857ae529d554de4af1c4381", "size_bytes": 9489, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/SYNTAX.md", "sha256": "38ef926faa4f330faacf6f1d1838caa264eead57f94a089f349a106b05cc222a", "size_bytes": 34143, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/manuscript/preamble.md", "sha256": "171efb5cb2640a6a2aefd88b96d3c0b13b35be7fde30911aee155e71529bbc48", "size_bytes": 4649, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/method/release_checklist.md", - "sha256": "19f7eba1d0f002dd1af971eff604da23012087aac4c0e2114315cad25f185ffc", - "size_bytes": 18609, - "stage_name": "current-output-snapshot", + "sha256": "55e8e6d78f94888b2c7dd114c938e20d5114bc242ed1e01593d4819067673752", + "size_bytes": 18858, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/method/rendering_pipeline.md", - "sha256": "f68c13df0461d7276f712e0c8f790f7b63aa026fcb53eeefe22cfdc9d897d847", - "size_bytes": 24935, - "stage_name": "current-output-snapshot", + "sha256": "6225b4129b633ee6a219100ea10a72feac5cd2376ca21714a3a36a17e9865a38", + "size_bytes": 25343, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/method/style_guide.md", - "sha256": "ed83c6692bf60ed2c3877947c888f5d22d1e6f49c138988bb20ff24c0cd38f36", - "size_bytes": 13993, - "stage_name": "current-output-snapshot", + "sha256": "ab2bf37cf1b6a10456f99196c6fa27d86eb87f6da2ecc4d839d6f71bde3268b7", + "size_bytes": 14067, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/provenance/AGENTS.md", "sha256": "aed2c2bfdd086a901e8783c3478af4300b6965dabc9a92696983ef00c9da9f0f", "size_bytes": 5205, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/provenance/README.md", "sha256": "41259699de28bff5dae1cb84a2614652db4a00ffd15e109ef7ec25ce5c8346f5", "size_bytes": 3327, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/provenance/sources.md", "sha256": "c7a850dc428289e9d913c246388c97b773096fdb8f71dfe4c752ea504368b12c", "size_bytes": 56829, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/publication_derivative.md", "sha256": "cc1b6ae5a24c6561863def50dddaf2bce76251ce2ae9eaf8b49f2a4a21c4cad6", "size_bytes": 10095, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", + "stage_num": 0, + "timestamp": "2026-10-27T02:45:22+00:00" + }, + { + "contract_match": true, + "path": "output/docs/docs/reference/configuration.md", + "sha256": "c47445e593dd91fafbea4bc9d467fdc3e8ad570a57d7b9a5d16e3b0485708d06", + "size_bytes": 11643, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/reference/data_statement.md", "sha256": "b23a6106bfdee64ddaca081bdcedadd59063c038f7fdd8e63721ac1b6ad9b02d", "size_bytes": 16630, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/reference/formalism_map.md", "sha256": "54307d13b4d3a2792be5b8c4cdf1c20a467e12bf24a0bebf419cd168e0745021", "size_bytes": 30541, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/reference/glossary.md", "sha256": "1dd2fc7d347590bd29a5f5262e15da150cb1394044d3ff5d6bbf87a06898ad76", "size_bytes": 24568, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/reference/notation.md", "sha256": "1e7af6e7e38f4266b292947a22601c0f8a46155ceba81192f3c4fd300fbc8520", "size_bytes": 10159, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/reference/output_conventions.md", - "sha256": "5b38ab368039ed44fbd5ab069595e3023d2d9c14dc919013ebc5275fa5d5b1ff", - "size_bytes": 20680, - "stage_name": "current-output-snapshot", + "sha256": "6af0673725478ba2e970b88a8d6e1a093276e050eb72c0afb84f5fbb40fa87c3", + "size_bytes": 20362, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/reference/output_inventory.md", - "sha256": "ec960e2acfcdae1cf15b0012ff9194fd9155638dfcdfaacc3ef34d874d2809c4", - "size_bytes": 22406, - "stage_name": "current-output-snapshot", + "sha256": "a63eea7c13d3086f04b7a5a34f8618126e668a8ccc2b165af45bd0af8eb469c4", + "size_bytes": 21658, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/research_queue.md", "sha256": "7c68f12b59c14d6b1a65e75843dd439e3af27aae92da50b2ececfc3bf4eb8658", "size_bytes": 149692, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/syntax_guide.md", "sha256": "2653a52ec4eb94fda59bf2f649da2d13eab109c05d548a79f24bb0d55d95e37d", "size_bytes": 29264, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/testing_philosophy.md", "sha256": "a7be13be30d793faf9b707cdea1c274f1ee710a1856e2d1732553eb4633c88a1", "size_bytes": 25117, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/docs/docs/troubleshooting.md", "sha256": "c85a4c3b9a329a1dea578c619f03a8c9943df09ff05825e0fb1e036757f6628a", "size_bytes": 26346, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/aligned_g2p.png", "sha256": "8ee8ca9af559aedeb2d905f87bfefe688f0b07e21a3c251b3242ae4a97b4f903", "size_bytes": 74526, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/belief_dynamics.png", "sha256": "44e55b08828370cd80f30f1bb64c01db8ffeae4ed84f7ebeb4d81467f5ae934b", "size_bytes": 409242, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/calibration_floor.png", "sha256": "6187fc3d2d1c3a006daeb3725fbfe35bf8b5ae428781ce42704c6ed873f97e53", "size_bytes": 605092, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/case_both_defects.png", "sha256": "db8f0d59243b6eeb5ef9d0405c9e2860e6ef3ae979cf1f0a0b8b6684a964ee85", "size_bytes": 119159, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/case_matrices.png", "sha256": "faef600511b91f4c95e1988a0a860fdcc4e39f114177a5da67956862034b8e60", "size_bytes": 233861, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/case_word_sweep.png", "sha256": "b96449927e0059b2aefb934069abc3d927593b12c390265f395fb9cf1451a88b", "size_bytes": 122796, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/channel_comparison.png", "sha256": "ece5f4d8c9af9be7835d1400434ad1217797d2b2ed44edcafd8fa132b7729e75", "size_bytes": 226246, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/clause_null.png", "sha256": "1538f43dc4f5e22a0107d86bc98c17ed53c2e9db6f0c75119ab2c18d856adc3e", "size_bytes": 125003, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/complexity_memory.png", "sha256": "1c5d560280be2a576aae5d535eb80da114a2059aca2f326bc0d0d28cec12a4c5", "size_bytes": 180389, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/complexity_ops.png", "sha256": "7dad835c981b7eb6989972cb3e4608ac43bc7cf384bafcc1ed06e72e17b5a942", "size_bytes": 228708, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/composition.png", "sha256": "3f2919a8b360a42851efd2d1e06bee602b5f515f5e6fa237d232818e1daddf21", "size_bytes": 420214, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/confirmatory_replication.png", "sha256": "ca9f812fbf1fc000e8db540185121c35b15a37746fe1a6eebf9ae5b2862989f6", "size_bytes": 371183, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/connected_core.png", "sha256": "59e214ecc5324b2665d41ff0c9b7bd52e420a615731416e1767eae29aba4d723", "size_bytes": 385586, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/dashboard_observation.png", - "sha256": "cbfb6253d7f0fb612e2e696297f4a807cefd2a19c77f3b744d7912821440495f", - "size_bytes": 406133, - "stage_name": "current-output-snapshot", + "sha256": "4cd03ca18ecac8311cefd89c5fc70955f44eafaa8331220037c215ca69530d90", + "size_bytes": 503004, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/external_benchmarks.png", "sha256": "607331bf1ff8842d5585fd5b8ba44c9eb7fd6e9835273a4acb19b96639d8c87a", "size_bytes": 317824, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/figure_provenance.json", - "sha256": "3bc3d3c4edc5f66de990f3305b399d8a814266a390ea7af8ce4c9be37a491126", - "size_bytes": 48637, - "stage_name": "current-output-snapshot", + "sha256": "59824dc6ff99a49cd79a2b9e176e3cacebb93499fbee66e6c72d1a039097f9ba", + "size_bytes": 49070, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/figure_registry.json", "sha256": "934e69ee60e35c6b3930d518b0e53e0dd2fb0578e9dca7080d289caaab9ffdfc", "size_bytes": 66276, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/g2p_accuracy.png", "sha256": "a324402558d83703e52c21d616e655442626cfcdfa4b83fb634f3e30922701fa", "size_bytes": 184371, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/gate_taxonomy.png", "sha256": "bf721a577c07bcf754214bbb7e924ec7f4b042911b3324b3ca2c265262b11c97", "size_bytes": 753785, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/generation_samples.png", "sha256": "bfb5be7b753b958abcda5a2434d11c5542a632632e65390b21c97fb1637a06f4", "size_bytes": 101710, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/generation_sweep.png", "sha256": "7b6956dffaf5d83f95918da1e87365b7860f634d8a1ad8105ff5568fd5caeb73", "size_bytes": 117164, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/gnn_pipeline.png", "sha256": "0d4c9f0e2b94b749552a31a43fdfa929556d53d537253e01ed51c001b5adb2a3", "size_bytes": 430674, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/hierarchy.png", "sha256": "084035b640aea97603a7f660612875afc76792afcafc2807b5faa07b587d29d3", "size_bytes": 495720, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/incontext_sweep.png", "sha256": "5586223720da011a316caeb4a743364ace124367bcc60d5dfd4d7b42a57f0a3c", "size_bytes": 182296, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/inference_cycle.png", "sha256": "4c3f2f96de5f5bc08e9c46ad578c06506ecc0ed3e011bd60236c9efb2c52e7ca", "size_bytes": 283488, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/inference_evidence.png", "sha256": "87236ce52d637269bc5f0200074bde8d317e0b50c73a5a1cbf5a29ca172529e7", "size_bytes": 250420, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/information_ceiling.png", "sha256": "995a18d0ca831fb1226a6069de6cf52d617ab4cc75cc7da80579c3ba659dfcd0", "size_bytes": 190475, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/learning_agreement.png", "sha256": "af13b553e9a08e53678dad5d1d04a2c7c9663ce58ef974748fd1ef2a6a7285c8", "size_bytes": 110803, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/letter_transition.png", "sha256": "1c7504e5cf61921adf456555d08dedee97f27d39a3d46cb9fa8a02b0bda6a8c0", "size_bytes": 222901, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/level_gate_summary.png", "sha256": "849d9a8630fe7e8e962e6d13236871a0ad1d71b4aa2c07b3fb68a5638e81e0ff", "size_bytes": 245527, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/multiplicity_forest.png", "sha256": "06c47ab4fed5e69d5770b4cc5530cc421a974d4732521eca433a13b9b5f7adf3", "size_bytes": 403604, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/narrative_channel.png", "sha256": "65dc26f00821f7937c5f6f2b117c8a188cecd62a6e52c9fc27f98b9810c638b2", "size_bytes": 153747, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/null_bounds.png", "sha256": "e40770f6a2bcc8f66801eefa0b07ae134f760711b6f2b3d8554a8d320b3de033", "size_bytes": 312598, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/perplexity_ladder.png", "sha256": "b8b5c5b80b2d713763d1fe6258bff6039e6687dfbb5212283f83fb961d4e822d", "size_bytes": 200060, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/phoneme_matrices.png", "sha256": "4b4e26eea15e8760d26e0675a8ce764ab91f57876c633f07583b9ced3d0e748e", "size_bytes": 243162, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/scaling_ladder.png", "sha256": "0c216b86ed64b210b4df0f21bea3363ed125e8f6c46f8960507a29e4559e9c57", "size_bytes": 147993, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/subsample_bias.png", "sha256": "6de2041acc8b334db1f07b599bf3dd3458319ca722ec8a1105e7a7192c48fa66", "size_bytes": 340994, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/trie_narrowing.png", "sha256": "e9728152475335f90e62dc8f30d719f0b52b407f99e5ebd60ff193a6eb675c1b", "size_bytes": 149933, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/wiring_comparison.png", "sha256": "0f75d4485eb4844bd4dbde68d87df1d0ac1a75c9a14ce6728464add63f0f1079", "size_bytes": 379455, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/word_matrices.png", "sha256": "4cc935c27b9277288b1bcc0b8e23905abf13824e18871f221c76e64a537b951b", "size_bytes": 137340, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/figures/word_miswirings.png", "sha256": "3b27143207584420f1b000a7479cbafe3c443b136e5dff1c90e63acf435549f1", "size_bytes": 122939, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/00_abstract.md", - "sha256": "fccb33ff2b77b9d3931f2cbd58c14d1b91b484cf42a1177a5dfd2853977f2274", - "size_bytes": 2703, - "stage_name": "current-output-snapshot", + "sha256": "d4c609374ec9962ee00e6f935f8683dcb0a1e7722d31341e4d96e1f509be7889", + "size_bytes": 2695, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/01_introduction.md", "sha256": "3a0e3d5d6cd31f827203183e6b247f80246a0fb9d7109b0a5a024b7be86cec55", "size_bytes": 33113, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/02_background.md", "sha256": "aab80f7cac501c3cf8dc329547928da7d6679c73b025e3cf0a1a8a3cdc97500b", "size_bytes": 20221, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/03_methods.md", "sha256": "8991ea722823c729f88fcc85381be83d2d81852ea06236095a1ea2a4e9b0e4ba", "size_bytes": 153751, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/04_results.md", "sha256": "df2788c09ef161496ed598bbe07d6184525e5b7625908c4e1105bb095f7b3fae", "size_bytes": 133590, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/05_discussion.md", "sha256": "b3956811e20e49373f877d9065101f77a2c1fed4cc8c9378bc39dd06cfbeec54", "size_bytes": 52162, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/06_related_work.md", "sha256": "007bfd07d4058f5e4f90ac02489af281343b55c9f71662ea19b4c0e8eae44bfb", "size_bytes": 52214, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/07_reproducibility.md", - "sha256": "2b059585240dda275c584ede5a73b0321c81c7587c106676b7733aa91b7d7587", - "size_bytes": 32188, - "stage_name": "current-output-snapshot", + "sha256": "9893af7e6d140adbaffde8ee8667d4afafdfa24a92f1fceda29564e04fb41bc8", + "size_bytes": 32275, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/08_conclusion.md", "sha256": "a9da1903fcf285ca8e7ba2df9da6c0464ac56ba772991cf3e46cdde362e9da8e", "size_bytes": 16992, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/98_supplement_audit_trails.md", "sha256": "ad9afe3ed862fd2af018bedd7c704f99aedfc84f00646693f9dac4ba46ba4f47", "size_bytes": 59756, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/98_supplement_channel_factorial.md", "sha256": "d42944553d2d66459a26083a396fbc78842766b73ca497f0f907bc031d69bf22", "size_bytes": 20409, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/98_supplement_complexity.md", "sha256": "6a750e8c3d392e8446069b0858b7137f4849d47b15292f913cd25243ed6e6952", "size_bytes": 21553, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/98_supplement_external_benchmarks.md", "sha256": "36dab5c0b27d64604950b2a7d01a7299e6f1b7de4244d02aaa2f94e5d6b4375b", "size_bytes": 111660, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/98_supplement_lean.md", "sha256": "2c65efe3cee68fd200bb6d4b04a25f71098605de5f7c95b4cd6e42263f13442f", "size_bytes": 4024, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/98_supplement_statistics.md", "sha256": "e942e19eab78fa6f3fe901b611cc45119e54d11ab524e3530c5f7ec95c6cb67d", "size_bytes": 76909, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/99_references.md", "sha256": "20f4a91ee979db68b8c62777d4518e3a6bd40994562308aa12f827ba621567a0", "size_bytes": 31, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/config.yaml", "sha256": "05bbd96af3a16f5192f1023ed7044fc848709d64b7a179523c2fa42cd67dd830", "size_bytes": 2915, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/preamble.md", "sha256": "171efb5cb2640a6a2aefd88b96d3c0b13b35be7fde30911aee155e71529bbc48", "size_bytes": 4649, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/manuscript/references.bib", - "sha256": "aa4e53c864a329188fa559d3c548c3335bd481064ff99c6ae9c5761060677966", - "size_bytes": 58917, - "stage_name": "current-output-snapshot", + "sha256": "5cf0775742958cf87c54df770ec82387f2a90b246078378a5f1c17d0b1c9c429", + "size_bytes": 58926, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/pdf/active_inference_language_model_combined.pdf", - "sha256": "61e8be6927b9879312d34a47105e359b58700d44d0857ef6ec8e0772a085f8f1", - "size_bytes": 12557861, - "stage_name": "current-output-snapshot", + "sha256": "43ceee4f3859c9103812db1373761c0783f8f99473ba8671846ff6b07408d847", + "size_bytes": 12653976, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/reports/connected_gum.json", "sha256": "045d953dd1d46227e1d4e3d484479c50c947f485514b820f3f82a24cd90c5255", "size_bytes": 43379, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/reports/gate_audit.json", "sha256": "4f4fc8f703ee5b5c0eeee185f0476666c7aa0da18d293ac95a4e9d62fa5f1a8d", "size_bytes": 6968, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/reports/gate_audit_ablation.json", "sha256": "5cf2511909ffe7e773e111b7a98fc0d01431eec4e76b3b4df94371ee78e5bcec", "size_bytes": 1135, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/reports/manuscript_composition.json", - "sha256": "174ee93d988d4301b78a2e65c8c050885762a9fbf4609527fbf23f5806c41bfb", + "sha256": "789368484217ffaef0f56d04b993622882b28954f5cbf56ff1307448b30de52c", "size_bytes": 3784, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/00_abstract_slides.pdf", - "sha256": "3cb68ab61973490d731e35464beb5b1c4d37df138ab44eb9088c1418356466d6", - "size_bytes": 20672, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/01_introduction_slides.pdf", - "sha256": "292ea0260d5cc29f826ec2e08333d9f5b4bd769b7fb354a8c4a9a369d9069794", - "size_bytes": 117269, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/02_background_slides.pdf", - "sha256": "16b2bdbcc146389ecaf2f00e670331219ef873d063fbf6d2ba028b1276a8f927", - "size_bytes": 128381, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/03_methods_slides.pdf", - "sha256": "f90a605114e0ba2f4afa8a342bd96018c882a59db3b20d2d18389b41369d33a2", - "size_bytes": 4658203, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/04_results_slides.pdf", - "sha256": "aa6014e445b933e98b768f39e9ba6bc0017f0369a69dff6fd031d1c2d8725642", - "size_bytes": 2741763, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/05_discussion_slides.pdf", - "sha256": "e04fac16ac44a9ceaf54eb81e736ef57e814458b169ff9c070cc0e5fc9276ced", - "size_bytes": 423518, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/06_related_work_slides.pdf", - "sha256": "8905006787fc91891fa19d181f7662478c7daa2fa8d2189dbe36d6a7002366dc", - "size_bytes": 184668, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/07_reproducibility_slides.pdf", - "sha256": "5df2b4662e0bd05ad234c5b47589effd1c41db024d6db472db0c54392805e89c", - "size_bytes": 520071, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/08_conclusion_slides.pdf", - "sha256": "f8d384c0a015da41b8b45149ec7bf7ba1ceae12a0bbe4f1e4ac1c08386f30f91", - "size_bytes": 60856, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/98_supplement_audit_trails_slides.pdf", - "sha256": "5eb180d9d417bbda14ebdcfebff56cb6ae40d188a67d94cae45c35ae39341b5b", - "size_bytes": 1235844, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/98_supplement_channel_factorial_slides.pdf", - "sha256": "4d1de312f7ee473aa4b5af4044f437a1ef6409ad728fbdb5ae18c9135d51a1b8", - "size_bytes": 93859, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/98_supplement_complexity_slides.pdf", - "sha256": "41c49e3692b5606ea5325b8da30c75396a85c047367aae95536f1ab6517a1dca", - "size_bytes": 516103, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/98_supplement_external_benchmarks_slides.pdf", - "sha256": "3d2f146558a619434cc43179bfaffb3639db5ff04fcdee3322bb91efbfdcb75d", - "size_bytes": 1508278, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/98_supplement_lean_slides.pdf", - "sha256": "7b39c35aeb2ab6d24b29164f150fcaee01d908c78e9ed2e1a70f5f6cd387f0c0", - "size_bytes": 34671, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/98_supplement_statistics_slides.pdf", - "sha256": "6ebb0420199298137e4d5b44a26d718700c8916eebeee68102009ebd2a27340d", - "size_bytes": 1002196, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/slides/99_references_slides.pdf", - "sha256": "fd33045f2285acf934e3e1bad65eb1d7279c84f566183078500c6a0aec78e279", - "size_bytes": 4648, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/upstream_pymdp_pr/0001-feat-sparse-B-support-in-Agent-and-FPI.patch", - "sha256": "2cfd26352cfec7bc63a66f80a8787263c9bd24df4007399cd08c480e86afcafd", - "size_bytes": 2733, - "stage_name": "current-output-snapshot", - "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" - }, - { - "contract_match": true, - "path": "output/upstream_pymdp_pr/PR_DESCRIPTION.md", - "sha256": "c37807bbfcd9a797d4640093b321db1c8cbd0ac9bfe8d35f6e743fc402e3366c", - "size_bytes": 2635, - "stage_name": "current-output-snapshot", + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/web/_combined_manuscript.md", - "sha256": "3bdbace8acf94b70024e7f1e1bb24741c723e9e6a25307d66abe4e057dbcf8f0", - "size_bytes": 790979, - "stage_name": "current-output-snapshot", + "sha256": "72426ee895ff0236d86d0682ab46cf08b540f7552e4f6db4ab252ef57f6f05e8", + "size_bytes": 791058, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" }, { "contract_match": true, "path": "output/web/index.html", - "sha256": "27ccbb96864587e3509b8df9fffc7ba72b74409380820ee2f19edcae127e0df3", - "size_bytes": 1093270, - "stage_name": "current-output-snapshot", + "sha256": "635e51174a1e86f01afe461ae3ccd7827d486319a4afd41738dca4179a174267", + "size_bytes": 1093349, + "stage_name": "standalone-output-scan", "stage_num": 0, - "timestamp": "2026-10-16T18:45:28+00:00" + "timestamp": "2026-10-27T02:45:22+00:00" } ], "inventory_mode": "stable-local-output-v1", diff --git a/output/reports/evidence_registry.json b/output/reports/evidence_registry.json index 35fcf4a..2625220 100644 --- a/output/reports/evidence_registry.json +++ b/output/reports/evidence_registry.json @@ -1,17 +1,17 @@ { "claim_boundary": "Compact evidence summary for manuscript validation; full fact dumps are opt-in debug output.", - "fact_count": 22048, + "fact_count": 22030, "freshness_warnings": [], "kind_counts": { - "artifact": 156, + "artifact": 136, "citation": 125, "equation": 51, "figure": 120, - "number": 21449, + "number": 21451, "section": 74, "table": 73 }, - "omitted_fact_count": 21848, + "omitted_fact_count": 21830, "sample_facts": [ { "active": true, @@ -2416,10 +2416,10 @@ ], "schema": "template-evidence-registry-report-v1", "source_tiers": { - "artifact": 474, + "artifact": 454, "bibliography": 125, "configuration": 66, - "data_source": 19392, + "data_source": 19394, "generated_metric": 1991 } } diff --git a/output/reports/manuscript_composition.json b/output/reports/manuscript_composition.json index d56155d..669201c 100644 --- a/output/reports/manuscript_composition.json +++ b/output/reports/manuscript_composition.json @@ -1,16 +1,16 @@ { "algorithm": "web-renderer-combine-v1", - "binding_sha256": "d5b8e005916485657b32c8a5e5f14ea375dc2b82c11604ca511c1b79af983213", + "binding_sha256": "98125b5bafeed550e3fcf60b154711b19e1afad98a08f147fe0c37d194d7fdd0", "combined_path": "output/web/_combined_manuscript.md", - "combined_sha256": "3bdbace8acf94b70024e7f1e1bb24741c723e9e6a25307d66abe4e057dbcf8f0", - "combined_size_bytes": 790979, + "combined_sha256": "72426ee895ff0236d86d0682ab46cf08b540f7552e4f6db4ab252ef57f6f05e8", + "combined_size_bytes": 791058, "input_root_kind": "hydrated", "ordered_inputs": [ { "ordinal": 1, "path": "output/manuscript/00_abstract.md", - "sha256": "fccb33ff2b77b9d3931f2cbd58c14d1b91b484cf42a1177a5dfd2853977f2274", - "size_bytes": 2703 + "sha256": "d4c609374ec9962ee00e6f935f8683dcb0a1e7722d31341e4d96e1f509be7889", + "size_bytes": 2695 }, { "ordinal": 2, @@ -51,8 +51,8 @@ { "ordinal": 8, "path": "output/manuscript/07_reproducibility.md", - "sha256": "2b059585240dda275c584ede5a73b0321c81c7587c106676b7733aa91b7d7587", - "size_bytes": 32188 + "sha256": "9893af7e6d140adbaffde8ee8667d4afafdfa24a92f1fceda29564e04fb41bc8", + "size_bytes": 32275 }, { "ordinal": 9, @@ -103,7 +103,7 @@ "size_bytes": 31 } ], - "ordered_inputs_sha256": "08f53430e1e45d60d90c068686ed7c43feb54bd68c0a1f09c93e29c054094fec", + "ordered_inputs_sha256": "d1c200fc2bdb4dc71ddc9a477e3a88cea8b281b91dfe6829df05827e217e09fb", "project": "working/active_inference_language_model", "schema_version": "template-manuscript-composition-v1" } diff --git a/output/reports/rendered_provenance.json b/output/reports/rendered_provenance.json index 41eb9bb..4abd5fe 100644 --- a/output/reports/rendered_provenance.json +++ b/output/reports/rendered_provenance.json @@ -2,9 +2,9 @@ "consumed_manuscript": [ { "rendered_path": "output/manuscript/00_abstract.md", - "rendered_sha256": "fccb33ff2b77b9d3931f2cbd58c14d1b91b484cf42a1177a5dfd2853977f2274", + "rendered_sha256": "d4c609374ec9962ee00e6f935f8683dcb0a1e7722d31341e4d96e1f509be7889", "source_path": "docs/manuscript/00_abstract.md", - "source_sha256": "d00eb3573c0f6a3cb8a3b953bdfc2612f8592cad0c568fe85cdf6d6e9a2fd8d7" + "source_sha256": "4ea6de835550d112f8002158515e957f9dd34b82412f566e6fca4568e21f4b5d" }, { "rendered_path": "output/manuscript/01_introduction.md", @@ -44,9 +44,9 @@ }, { "rendered_path": "output/manuscript/07_reproducibility.md", - "rendered_sha256": "2b059585240dda275c584ede5a73b0321c81c7587c106676b7733aa91b7d7587", + "rendered_sha256": "9893af7e6d140adbaffde8ee8667d4afafdfa24a92f1fceda29564e04fb41bc8", "source_path": "docs/manuscript/07_reproducibility.md", - "source_sha256": "062df26a6056f365d38a6da683e8c98e3354fdaec91eef3a350adf322799028c" + "source_sha256": "01a2de507e62d7859071213a8fd9b535cc4d8b3f9bc86718e842577967709fdc" }, { "rendered_path": "output/manuscript/08_conclusion.md", @@ -100,42 +100,42 @@ "evidence_files": { "artifact_manifest": { "path": "output/reports/artifact_manifest.json", - "sha256": "ccf58335da29f56d1cd8bde9e821ec79e97e6eb7c61def18f3390e404dd29cd8", - "size_bytes": 51355 + "sha256": "373680a1e067c8d643540d55c9d9d13701ccee4b5cbad160aa09ee9058174c96", + "size_bytes": 44584 }, "combined_manuscript": { "path": "output/web/_combined_manuscript.md", - "sha256": "3bdbace8acf94b70024e7f1e1bb24741c723e9e6a25307d66abe4e057dbcf8f0", - "size_bytes": 790979 + "sha256": "72426ee895ff0236d86d0682ab46cf08b540f7552e4f6db4ab252ef57f6f05e8", + "size_bytes": 791058 }, "composition_manifest": { "path": "output/reports/manuscript_composition.json", - "sha256": "174ee93d988d4301b78a2e65c8c050885762a9fbf4609527fbf23f5806c41bfb", + "sha256": "789368484217ffaef0f56d04b993622882b28954f5cbf56ff1307448b30de52c", "size_bytes": 3784 }, "validation_report": { "path": "output/reports/validation_report.json", - "sha256": "85a9d35e898102b344a2805aa36d56e43d525b1d634836a1664a61818ce79174", - "size_bytes": 15391 + "sha256": "dc853ca4cf5d43b3055eb1f1d8a59425593213737f8a13962f320a1e868ac4d8", + "size_bytes": 13923 } }, "evidence_mode": "validated-co-snapshot-fingerprint-bridge", "fingerprints": { "config": { "file_count": 20, - "sha256": "83334dec251c696d59ce18ec69e00735f1de8b5cadd978682232bf4fe02f01b2" + "sha256": "bee4c6a55730390f4584cb11a93c0f00d3596728ee2d49c7c7a6ab1ea6ee9733" }, "output": { - "file_count": 157, - "sha256": "6fe56cb6781dad6747bd21b8541284e7061efe84e0e92336680437b66d942c31" + "file_count": 137, + "sha256": "b8b9ec8e18bd2109b4d33367adc8721c822848b4e8043569672be959db77d3bc" }, "source": { - "file_count": 399, - "sha256": "a0188d361a53e2afeb8f94b4c75f3e02ea9814f003039c5f0766f125090bb402" + "file_count": 368, + "sha256": "17d42b847c487142065d01641327f8707c2979c31cdb7e0edecf334e379c20fe" }, "stage": { "file_count": 1221, - "sha256": "7035307f56a18c1fff22919a449a79c12de81b1e94ebfd15f23a9c3441e76ecd" + "sha256": "a4fa6fb1c1512820dc7f4d37e2894f5a7f8255ba292265aa0cc655b8291c416d" } }, "project": "working/active_inference_language_model", diff --git a/output/reports/validation_report.json b/output/reports/validation_report.json index 27a9698..f2cb772 100644 --- a/output/reports/validation_report.json +++ b/output/reports/validation_report.json @@ -18,13 +18,6 @@ }, "detailed_validation": { "directories": { - "architecture-map": { - "exists": true, - "file_count": 3, - "largest_file": "snapshot.js", - "largest_file_path": "architecture-map/snapshot.js", - "size_mb": "6.03" - }, "data": { "exists": true, "file_count": 1, @@ -34,10 +27,10 @@ }, "docs": { "exists": true, - "file_count": 68, + "file_count": 69, "largest_file": "decisions.md", "largest_file_path": "docs/docs/decisions.md", - "size_mb": "2.53" + "size_mb": "2.56" }, "docx": { "exists": false, @@ -54,7 +47,7 @@ "file_count": 41, "largest_file": "gate_taxonomy.png", "largest_file_path": "figures/gate_taxonomy.png", - "size_mb": "10.02" + "size_mb": "10.11" }, "llm": { "exists": false, @@ -78,7 +71,7 @@ "file_count": 1, "largest_file": "active_inference_language_model_combined.pdf", "largest_file_path": "pdf/active_inference_language_model_combined.pdf", - "size_mb": "11.98" + "size_mb": "12.07" }, "reports": { "exists": true, @@ -93,18 +86,9 @@ "size_mb": "0.00" }, "slides": { - "exists": true, - "file_count": 16, - "largest_file": "03_methods_slides.pdf", - "largest_file_path": "slides/03_methods_slides.pdf", - "size_mb": "12.64" - }, - "upstream_pymdp_pr": { - "exists": true, - "file_count": 2, - "largest_file": "0001-feat-sparse-B-support-in-Agent-and-FPI.patch", - "largest_file_path": "upstream_pymdp_pr/0001-feat-sparse-B-support-in-Agent-and-FPI.patch", - "size_mb": "0.01" + "exists": false, + "file_count": 0, + "size_mb": "0.00" }, "web": { "exists": true, @@ -115,15 +99,12 @@ } }, "file_counts": { - "architecture-map": 3, "data": 1, - "docs": 68, + "docs": 69, "figures": 41, "manuscript": 19, "pdf": 1, "reports": 4, - "slides": 16, - "upstream_pymdp_pr": 2, "web": 2 }, "inventory_mode": "stable-local-output-v1", @@ -135,18 +116,10 @@ "recommendations": [], "structure": { "directory_structure": { - "architecture-map": { - "exists": true, - "files": 3, - "optional": false, - "readable": true, - "required": true, - "size_mb": 6.03 - }, "combined_pdf": { "exists": true, "readable": true, - "size_mb": 11.98 + "size_mb": 12.07 }, "data": { "exists": true, @@ -158,11 +131,11 @@ }, "docs": { "exists": true, - "files": 68, + "files": 69, "optional": false, "readable": true, "required": true, - "size_mb": 2.53 + "size_mb": 2.56 }, "docx": { "exists": false, @@ -184,7 +157,7 @@ "optional": false, "readable": true, "required": true, - "size_mb": 10.02 + "size_mb": 10.11 }, "llm": { "exists": false, @@ -214,7 +187,7 @@ "optional": false, "readable": true, "required": true, - "size_mb": 11.98 + "size_mb": 12.07 }, "reports": { "exists": true, @@ -232,20 +205,11 @@ "size_mb": 0.0 }, "slides": { - "exists": true, - "files": 16, - "optional": false, - "readable": true, - "required": true, - "size_mb": 12.64 - }, - "upstream_pymdp_pr": { - "exists": true, - "files": 2, + "exists": false, + "files": 0, "optional": false, - "readable": true, - "required": true, - "size_mb": 0.01 + "required": false, + "size_mb": 0.0 }, "web": { "exists": true, @@ -263,63 +227,51 @@ "valid": true, "warnings": [] }, - "total_size_mb": 46.40823173522949 + "total_size_mb": 27.945448875427246 }, "figures": { "files": 41, - "size_mb": 10.015520095825195 + "size_mb": 10.108316421508789 }, "inventory_mode": "stable-local-output-v1", "pdf": { "files": 1, - "size_mb": 11.976109504699707 + "size_mb": 12.067771911621094 }, "stable_inventory": { "categories": { - "architecture-map": { - "files": 3, - "size_bytes": 6325058 - }, "data": { "files": 1, "size_bytes": 568041 }, "docs": { - "files": 68, - "size_bytes": 2655924 + "files": 69, + "size_bytes": 2684054 }, "figures": { "files": 41, - "size_bytes": 10502034 + "size_bytes": 10599338 }, "manuscript": { "files": 19, - "size_bytes": 857757 + "size_bytes": 857845 }, "pdf": { "files": 1, - "size_bytes": 12557861 + "size_bytes": 12653976 }, "reports": { "files": 4, "size_bytes": 55266 }, - "slides": { - "files": 16, - "size_bytes": 13251000 - }, - "upstream_pymdp_pr": { - "files": 2, - "size_bytes": 5368 - }, "web": { "files": 2, - "size_bytes": 1884249 + "size_bytes": 1884407 } }, "mode": "stable-local-output-v1", - "total_files": 157, - "total_size_bytes": 48662558 + "total_files": 137, + "total_size_bytes": 29302927 } }, "recommendations": [], @@ -330,29 +282,29 @@ "passed": 9, "total_checks": 9 }, - "timestamp": "2026-10-16T18:45:28Z", + "timestamp": "2026-10-27T02:45:22Z", "validated_inputs": { "artifact_manifest": { "path": "output/reports/artifact_manifest.json", - "sha256": "ccf58335da29f56d1cd8bde9e821ec79e97e6eb7c61def18f3390e404dd29cd8", - "size_bytes": 51355 + "sha256": "373680a1e067c8d643540d55c9d9d13701ccee4b5cbad160aa09ee9058174c96", + "size_bytes": 44584 }, "combined_manuscript": { "path": "output/web/_combined_manuscript.md", - "sha256": "3bdbace8acf94b70024e7f1e1bb24741c723e9e6a25307d66abe4e057dbcf8f0", - "size_bytes": 790979 + "sha256": "72426ee895ff0236d86d0682ab46cf08b540f7552e4f6db4ab252ef57f6f05e8", + "size_bytes": 791058 }, "composition_manifest": { "path": "output/reports/manuscript_composition.json", - "sha256": "174ee93d988d4301b78a2e65c8c050885762a9fbf4609527fbf23f5806c41bfb", + "sha256": "789368484217ffaef0f56d04b993622882b28954f5cbf56ff1307448b30de52c", "size_bytes": 3784 }, "consumed_manuscript": [ { "rendered_path": "output/manuscript/00_abstract.md", - "rendered_sha256": "fccb33ff2b77b9d3931f2cbd58c14d1b91b484cf42a1177a5dfd2853977f2274", + "rendered_sha256": "d4c609374ec9962ee00e6f935f8683dcb0a1e7722d31341e4d96e1f509be7889", "source_path": "docs/manuscript/00_abstract.md", - "source_sha256": "d00eb3573c0f6a3cb8a3b953bdfc2612f8592cad0c568fe85cdf6d6e9a2fd8d7" + "source_sha256": "4ea6de835550d112f8002158515e957f9dd34b82412f566e6fca4568e21f4b5d" }, { "rendered_path": "output/manuscript/01_introduction.md", @@ -392,9 +344,9 @@ }, { "rendered_path": "output/manuscript/07_reproducibility.md", - "rendered_sha256": "2b059585240dda275c584ede5a73b0321c81c7587c106676b7733aa91b7d7587", + "rendered_sha256": "9893af7e6d140adbaffde8ee8667d4afafdfa24a92f1fceda29564e04fb41bc8", "source_path": "docs/manuscript/07_reproducibility.md", - "source_sha256": "062df26a6056f365d38a6da683e8c98e3354fdaec91eef3a350adf322799028c" + "source_sha256": "01a2de507e62d7859071213a8fd9b535cc4d8b3f9bc86718e842577967709fdc" }, { "rendered_path": "output/manuscript/08_conclusion.md", @@ -448,19 +400,19 @@ "fingerprints": { "config": { "file_count": 20, - "sha256": "83334dec251c696d59ce18ec69e00735f1de8b5cadd978682232bf4fe02f01b2" + "sha256": "bee4c6a55730390f4584cb11a93c0f00d3596728ee2d49c7c7a6ab1ea6ee9733" }, "output": { - "file_count": 157, - "sha256": "6fe56cb6781dad6747bd21b8541284e7061efe84e0e92336680437b66d942c31" + "file_count": 137, + "sha256": "b8b9ec8e18bd2109b4d33367adc8721c822848b4e8043569672be959db77d3bc" }, "source": { - "file_count": 399, - "sha256": "a0188d361a53e2afeb8f94b4c75f3e02ea9814f003039c5f0766f125090bb402" + "file_count": 368, + "sha256": "17d42b847c487142065d01641327f8707c2979c31cdb7e0edecf334e379c20fe" }, "stage": { "file_count": 1221, - "sha256": "7035307f56a18c1fff22919a449a79c12de81b1e94ebfd15f23a9c3441e76ecd" + "sha256": "a4fa6fb1c1512820dc7f4d37e2894f5a7f8255ba292265aa0cc655b8291c416d" } }, "project": "working/active_inference_language_model", diff --git a/output/web/_combined_manuscript.md b/output/web/_combined_manuscript.md index 3bbdec8..93bda1d 100644 --- a/output/web/_combined_manuscript.md +++ b/output/web/_combined_manuscript.md @@ -38,7 +38,7 @@ linguistic inference mechanisms together with an audit method that makes their failures visible. External neural models serve as supplemental reference probes; integration with them remains a proposal. -The planned release repository is +The release repository is . @@ -6887,10 +6887,11 @@ in `LICENSE` and `THIRD_PARTY_NOTICES.md`. **Availability.** The versioned release source is [the Institute repository's release tag](https://github.com/ActiveInferenceInstitute/Active_Inference_Language_Model/tree/v1.0.0). -The corresponding archival record is identified by -[the release DOI](https://doi.org/10.5281/zenodo.22409419). -The citation, package metadata and title page identify the same archive and -release destination. Public source and archival availability do not establish +The corresponding Zenodo deposition is unpublished. Its +[reserved DOI](https://doi.org/10.5281/zenodo.22409419) 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 @@ -7205,7 +7206,7 @@ out in [@sec:lean]. ## Deterministic build epoch and figures -This document was rendered at 2026-10-16T18:45:28Z from version +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 diff --git a/output/web/index.html b/output/web/index.html index 9baa7d9..b3a7588 100644 --- a/output/web/index.html +++ b/output/web/index.html @@ -1826,7 +1826,7 @@

-

The planned release repository is The release repository is https://github.com/ActiveInferenceInstitute/Active_Inference_Language_Model.


@@ -10942,15 +10942,16 @@

THIRD_PARTY_NOTICES.md.

Availability. The versioned release source is the -Institute repository’s release tag. The corresponding archival -record is identified by the release DOI. The -citation, package metadata and title page identify the same 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.

+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.

8.1 Pinned environment and @@ -11581,7 +11582,7 @@

8.6 Deterministic build epoch and figures

-

This document was rendered at 2026-10-16T18:45:28Z from version +

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 diff --git a/scripts/AGENTS.md b/scripts/AGENTS.md index 9e41288..324acb7 100644 --- a/scripts/AGENTS.md +++ b/scripts/AGENTS.md @@ -49,18 +49,10 @@ decision entry and a matching edit here. ## Inventory -101 Python files (2026-10-23 audit). `scripts/README.md` carries the -per-script table — script | purpose | delegates to | run command. By family: - -| Pattern | Count | Role | -| --- | --- | --- | -| `generate_*` | 23 | `vendor/` corpus artifacts, figures, cover, Lean ledger bridge, figure registry, pymdp patch | -| `record_*` | 47 | the only writers of `data/claims.json`; each owns one claim namespace — the 46 `record_*_claims.py` recorders plus `record_confirmatory_replication.py` (decision 111) | -| `evaluate_*` | 2 | structural/evaluation reports that print and record nothing | -| `probe_*` | 5 | standalone measurements that record nothing | -| `verify_*` | 4 | release profiles, network-claim bindings, reference sources, the publication derivative | -| `z_*` | 2 | last-pipeline-step renderers: manuscript tokens, docs hydration | -| other | 18 | `audit_gates.py`, `orchestrate_claim_recorders.py`, `assign_claim_status.py`, `sweep_smoothing.py`, `warm_call_cache.py`, `build_web_ailm.py`, `export_web_model.py`, `capture_dashboard.py`, `run_connected_ailm.py`, `precheck_confirmatory_replication.py`, `list_raw_corpus_inputs.py`, `fillmore_subject_rerun.py`, the shared `_artifact_io.py` atomic writer, and the five `_publication_*.py` workers behind `verify_publication_derivative.py` | +[`README.md`](README.md) owns the current per-script inventory: purpose, +delegated module and run command. Add or retire its row with the script, and run +the documentation inventory checks. Keep that checked table as the reference +rather than duplicating counts or script lists here. ## May change freely diff --git a/scripts/README.md b/scripts/README.md index d0d1dfb..93b51ad 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -121,6 +121,7 @@ command with `.venv/bin/python` — never `uv run` in this sidecar (see | `record_connected_gum_claims.py` | Execute the frozen local raw-text GUM comparison with paired document uncertainty; authenticate inputs before writing claims | `ailm.corpus.connected_gum`, `ailm.levels.connected_evaluation` | `.venv/bin/python scripts/record_connected_gum_claims.py` | | `run_connected_ailm.py` | Execute raw or structured connected inference, channel controls and optional next-word generation; emit strict JSON | `ailm.levels.connected`, connected model and input contracts | `.venv/bin/python scripts/run_connected_ailm.py --text "The man." --generate` | | `verify_release.py` | Run reproducible release profiles and emit an evidence receipt | orchestrates subprocess steps | `.venv/bin/python -I -S scripts/verify_release.py` | +| `verify_gnn_release.py` | Verify the selected released upstream GNN source offline before importing its parser | `ailm.verification.upstream_gnn` | `.venv/bin/python scripts/verify_gnn_release.py` | | `warm_call_cache.py` | Warm the memoized external-model call store, then say what to run next; `--check` preflights only | `ailm.benchmarks.ollama`, `ailm.call_cache` | `.venv/bin/python scripts/warm_call_cache.py` | | `z_generate_manuscript_variables.py` | Generate and inject AILM manuscript `{{TOKEN}}` values; the `z_` prefix means it runs last | `ailm.manuscript_variables`, `infrastructure.rendering.manuscript_injection` | `.venv/bin/python scripts/z_generate_manuscript_variables.py` | | `z_render_docs.py` | Resolve documentation claims; publish portable protocol companions; `--publication-references` repairs individual HTML references after rendering from actual combined-index links; `--check` rejects stale output without writing; `--prune-retired --dry-run` inventories retention and `--prune-retired` applies it | `ailm.docs_hydration`, `ailm.supporting_package` | `.venv/bin/python scripts/z_render_docs.py` | diff --git a/scripts/verify_gnn_release.py b/scripts/verify_gnn_release.py new file mode 100644 index 0000000..78d3a97 --- /dev/null +++ b/scripts/verify_gnn_release.py @@ -0,0 +1,33 @@ +"""Verify the pinned upstream GNN release offline, without importing its parser.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "src")) + +from ailm.verification.upstream_gnn import ( # noqa: E402 + UpstreamReleaseError, + load_release_pin, + selected_upstream_root, + verify_release_checkout, +) + + +def main() -> int: + try: + evidence = verify_release_checkout( + selected_upstream_root(ROOT), load_release_pin(ROOT / "gnn/upstream.json") + ) + except (OSError, UpstreamReleaseError) as error: + print(f"GNN release verification refused: {error}", file=sys.stderr) + return 1 + print(json.dumps(evidence, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/verify_release.py b/scripts/verify_release.py index 3c4959e..f8d6b6e 100755 --- a/scripts/verify_release.py +++ b/scripts/verify_release.py @@ -102,6 +102,7 @@ { "HOME", "AILM_OLLAMA_ENDPOINT", + "AILM_GNN_UPSTREAM", "LANG", "LC_ALL", "LC_CTYPE", @@ -996,6 +997,7 @@ def build_steps( "web-model", "web-page", "package-distributions", + "gnn-upstream-release", "network-claim-bindings", "cache-audit", "raw-corpus-reproducibility", @@ -1009,6 +1011,12 @@ def build_steps( "lean-negative-control", ) full_steps = common + ( + Step( + "gnn-upstream-release", + _controlled_python_argv("script", "scripts/verify_gnn_release.py"), + 300, + depends_on=("environment-compatibility",), + ), Step( "package-distributions", _controlled_python_argv( @@ -1132,6 +1140,7 @@ def build_steps( ), 43_200, depends_on=( + "gnn-upstream-release", "cache-audit", "raw-corpus-reproducibility", "web-page", @@ -2109,6 +2118,7 @@ def _release_environment( "inherited_environment_policy": "allowlist-v1", "inherited_environment_keys": sorted(set(environment) - {"PATH"}), "AILM_OLLAMA_ENDPOINT": environment.get("AILM_OLLAMA_ENDPOINT"), + "AILM_GNN_UPSTREAM": environment.get("AILM_GNN_UPSTREAM"), "HOME": environment["HOME"], "home_origin": "login-account-database", "PATH": environment["PATH"], diff --git a/src/ailm/dashboard/__main__.py b/src/ailm/dashboard/__main__.py index 3cb7d5a..c6be0bf 100644 --- a/src/ailm/dashboard/__main__.py +++ b/src/ailm/dashboard/__main__.py @@ -25,6 +25,7 @@ from __future__ import annotations +import signal import sys from ailm.dashboard.config import DashboardConfig, load_config, require_loopback_host @@ -82,4 +83,7 @@ def main(argv: list[str] | None = None) -> int: if __name__ == "__main__": + # Launchers may ignore SIGINT before exec. Own Ctrl-C handling at the CLI + # boundary without changing signal policy for callers embedding the server. + signal.signal(signal.SIGINT, signal.default_int_handler) raise SystemExit(main()) diff --git a/src/ailm/dashboard/capture.py b/src/ailm/dashboard/capture.py index caf2837..143b2f0 100644 --- a/src/ailm/dashboard/capture.py +++ b/src/ailm/dashboard/capture.py @@ -173,17 +173,18 @@ def git_blob(root: Path, commit: str, path: str) -> bytes | None: def git_head(root: Path) -> str: - """Return the checkout's HEAD commit.""" + """Return this checkout root's HEAD, refusing an enclosing repository.""" completed = subprocess.run( - ["git", "-C", str(root), "rev-parse", "--verify", "-q", "HEAD"], + ["git", "-C", str(root), "rev-parse", "--show-toplevel", "--verify", "-q", "HEAD"], stdin=subprocess.DEVNULL, capture_output=True, text=True, check=False, ) - if completed.returncode != 0: + lines = completed.stdout.splitlines() + if completed.returncode != 0 or len(lines) != 2 or Path(lines[0]).resolve() != root.resolve(): raise CaptureError(f"{root} has no HEAD commit to bind the capture to") - return completed.stdout.strip() + return lines[1].strip() def build_receipt( diff --git a/src/ailm/dashboard/engine.py b/src/ailm/dashboard/engine.py index be11bc9..e0ae2be 100644 --- a/src/ailm/dashboard/engine.py +++ b/src/ailm/dashboard/engine.py @@ -76,9 +76,6 @@ load_word_artifact, ) -# Preserve the historical re-export while all active callers name the transition. -build_unigram_a = build_letter_transition - #: Parts of speech that occupy a slot in the widened Level 5 sequence but #: carry no case role, so they must not advance the Level 4 case chain. NON_CASE_UPOS = ("VERB", "AUX") diff --git a/src/ailm/dashboard/server.py b/src/ailm/dashboard/server.py index 1560c06..af4bde4 100644 --- a/src/ailm/dashboard/server.py +++ b/src/ailm/dashboard/server.py @@ -26,7 +26,7 @@ from http.server import SimpleHTTPRequestHandler from pathlib import Path from socketserver import ThreadingTCPServer -from threading import BoundedSemaphore, Lock +from threading import BoundedSemaphore, Lock, Thread from typing import Any from urllib.parse import urlsplit @@ -51,13 +51,6 @@ #: instead of raising while the package itself is still importing. CONFIG: DashboardConfig = DashboardConfig() -#: Compatibility alias preserving this module's historical public surface -#: (the limit lived here before ``config.py``). It is a view onto the -#: configuration, not a second place the limit is written. No repository -#: caller or test uses it today; removal is a pending cutover decision, not -#: a dependency. -MAX_REQUEST_BYTES = CONFIG.max_request_bytes - def _infer_sentence_hierarchy(*args: Any, **kwargs: Any) -> dict[str, Any]: from ailm.dashboard.engine import infer_sentence_hierarchy @@ -448,18 +441,31 @@ def get_request(self): def process_request(self, request, client_address) -> None: self._worker_slots.acquire() + release_lock = Lock() + released = False + + def release_slot() -> None: + nonlocal released + with release_lock: + if not released: + self._worker_slots.release() + released = True + + def serve_request() -> None: + try: + self.process_request_thread(request, client_address) + finally: + release_slot() + try: - super().process_request(request, client_address) + # A worker can finish before Thread.start returns. If that return + # is interrupted, startup and completion share one slot release; + # cleanup must not replace KeyboardInterrupt with ValueError. + Thread(target=serve_request, daemon=True).start() except BaseException: - self._worker_slots.release() + release_slot() raise - def process_request_thread(self, request, client_address) -> None: - try: - super().process_request_thread(request, client_address) - finally: - self._worker_slots.release() - def run_dashboard( host: str | None = None, port: int | None = None, config: DashboardConfig | None = None diff --git a/src/ailm/verification/upstream_gnn.py b/src/ailm/verification/upstream_gnn.py new file mode 100644 index 0000000..4012c8d --- /dev/null +++ b/src/ailm/verification/upstream_gnn.py @@ -0,0 +1,197 @@ +"""Offline custody of the released upstream parser used by interoperability tests.""" + +from __future__ import annotations + +import hashlib +import json +import os +import re +import stat +import subprocess +from dataclasses import dataclass +from pathlib import Path + + +class UpstreamReleaseError(ValueError): + """The selected checkout does not supply the pinned release's source bytes.""" + + +@dataclass(frozen=True) +class UpstreamRelease: + repository: str + tag: str + commit: str + + +def load_release_pin(path: Path) -> UpstreamRelease: + """Read the authored release identity, refusing ambiguous or malformed pins.""" + + def unique(pairs: list[tuple[str, object]]) -> dict[str, object]: + result: dict[str, object] = {} + for key, value in pairs: + if key in result: + raise UpstreamReleaseError(f"duplicate upstream pin field: {key}") + result[key] = value + return result + + try: + data = json.loads(path.read_text(encoding="utf-8"), object_pairs_hook=unique) + except (OSError, UnicodeError, json.JSONDecodeError) as error: + raise UpstreamReleaseError(f"cannot read upstream release pin: {error}") from error + if not isinstance(data, dict) or set(data) != {"repository", "tag", "commit"}: + raise UpstreamReleaseError("upstream pin must name repository, tag and commit only") + if not all(isinstance(value, str) for value in data.values()): + raise UpstreamReleaseError("upstream pin fields must be strings") + if not data["repository"].startswith("https://github.com/"): + raise UpstreamReleaseError("upstream repository must be an HTTPS GitHub URL") + if not re.fullmatch(r"v\d+\.\d+\.\d+", data["tag"]): + raise UpstreamReleaseError("upstream tag must name a stable version") + if not re.fullmatch(r"[0-9a-f]{40}", data["commit"]): + raise UpstreamReleaseError("upstream commit must be a complete Git object identity") + return UpstreamRelease(**data) + + +def upstream_candidates(project: Path) -> tuple[Path, ...]: + """Durable conventional checkouts, independent of a user's home directory.""" + namespace = ( + (project.parents[2] / "ActiveInferenceInstitute/Public/Generalized_Notation_Notation",) + if len(project.parents) > 2 + else () + ) + return (*namespace, project.parent / "Generalized_Notation_Notation") + + +def default_upstream_root(candidates: tuple[Path, ...]) -> Path: + """Choose a checkout supplying a parser; its identity is checked before import.""" + for candidate in candidates: + if (candidate / "src/gnn/parsers/markdown_parser.py").is_file(): + return candidate + return candidates[0] + + +def selected_upstream_root(project: Path) -> Path: + """An explicit selection is final, including refusal of an empty value.""" + if "AILM_GNN_UPSTREAM" in os.environ: + value = os.environ["AILM_GNN_UPSTREAM"].strip() + if not value: + raise UpstreamReleaseError("AILM_GNN_UPSTREAM must not be empty") + return Path(value).expanduser().resolve() + return default_upstream_root(upstream_candidates(project)).resolve() + + +def _git(root: Path, *arguments: str) -> bytes: + environment = {key: value for key, value in os.environ.items() if not key.startswith("GIT_")} + environment.update( + GIT_CONFIG_GLOBAL=os.devnull, + GIT_CONFIG_NOSYSTEM="1", + GIT_NO_REPLACE_OBJECTS="1", + ) + try: + result = subprocess.run( + [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "-C", + str(root), + *arguments, + ], + env=environment, + capture_output=True, + check=True, + timeout=30, + ) + except (OSError, subprocess.SubprocessError) as error: + detail = ( + error.stderr.decode(errors="replace") + if isinstance(error, subprocess.CalledProcessError) + else str(error) + ) + raise UpstreamReleaseError(f"cannot inspect upstream checkout: {detail.strip()}") from error + return result.stdout + + +def verify_release_checkout(root: Path, pin: UpstreamRelease) -> dict[str, str | int]: + """Verify HEAD, tag and every source file against Git objects before import. + + Reading actual files catches changes hidden by assume-unchanged or + skip-worktree flags. Unexpected source files and symlinked paths also fail. + Interpreter __pycache__ directories are excluded from the source inventory; + unversioned sourceless modules elsewhere are refused. + """ + root = root.resolve() + commit = _git(root, "rev-parse", "HEAD").decode().strip() + if commit != pin.commit: + raise UpstreamReleaseError( + f"upstream HEAD {commit} differs from pinned {pin.tag} ({pin.commit}); " + "select its isolated release checkout with AILM_GNN_UPSTREAM" + ) + tag = _git(root, "rev-parse", f"refs/tags/{pin.tag}^{{commit}}").decode().strip() + if tag != pin.commit: + raise UpstreamReleaseError(f"upstream tag {pin.tag} differs from its pinned commit") + expected: dict[str, str] = {} + for record in _git(root, "ls-tree", "-r", "-z", "HEAD", "--", "src").split(b"\0"): + if not record: + continue + header, raw_path = record.split(b"\t", 1) + mode, kind, oid = header.decode().split() + relative = raw_path.decode("utf-8") + if mode not in {"100644", "100755"} or kind != "blob": + raise UpstreamReleaseError(f"nonregular upstream source: {relative}") + expected[relative] = oid + if "src/gnn/parsers/markdown_parser.py" not in expected: + raise UpstreamReleaseError("upstream release has no Markdown parser") + if (root / "src").is_symlink(): + raise UpstreamReleaseError("symlinked upstream source: src") + actual: set[str] = set() + for path in (root / "src").rglob("*"): + relative = path.relative_to(root).as_posix() + if path.is_symlink(): + raise UpstreamReleaseError(f"symlinked upstream source: {relative}") + if "__pycache__" in path.parts: + continue + if not path.is_dir(): + actual.add(relative) + if actual != expected.keys(): + raise UpstreamReleaseError( + f"upstream source inventory differs: missing={sorted(expected.keys() - actual)}, " + f"unexpected={sorted(actual - expected.keys())}" + ) + digests: dict[str, str] = {} + for relative, oid in sorted(expected.items()): + path = root / relative + before = path.stat() + if not stat.S_ISREG(before.st_mode): + raise UpstreamReleaseError(f"nonregular upstream source: {relative}") + content = path.read_bytes() + after = path.stat() + if ( + before.st_dev, + before.st_ino, + before.st_mode, + before.st_size, + before.st_mtime_ns, + before.st_ctime_ns, + ) != ( + after.st_dev, + after.st_ino, + after.st_mode, + after.st_size, + after.st_mtime_ns, + after.st_ctime_ns, + ): + raise UpstreamReleaseError(f"upstream source changed while reading: {relative}") + blob = hashlib.sha1(f"blob {len(content)}\0".encode() + content).hexdigest() + if blob != oid: + raise UpstreamReleaseError(f"modified upstream source: {relative}") + digests[relative] = hashlib.sha256(content).hexdigest() + return { + "repository": pin.repository, + "tag": pin.tag, + "commit": commit, + "tree": _git(root, "rev-parse", "HEAD^{tree}").decode().strip(), + "source_files": len(digests), + "source_sha256": hashlib.sha256(json.dumps(digests, sort_keys=True).encode()).hexdigest(), + "checkout": str(root), + } diff --git a/tests/README.md b/tests/README.md index c2ec057..2fbeead 100644 --- a/tests/README.md +++ b/tests/README.md @@ -74,6 +74,7 @@ newcomer needs to find first. | `test_figure_layout.py` | no overlapping text, nothing clipped — the part `assert_legible` cannot see | | `test_figure_provenance.py` | the v3 receipt binds the pinned real numeric stack, canonical token map, complete AILM code inventory, bounded data/vendor/GNN inputs, shared renderer/writer, and PNG bytes; real FIFO, descriptor-swap, dependency-mutation, stale-input, symlink, mutated-PNG, and generator-failure controls prove selective preflight and receipt-last publication fail closed | | `test_gnn_conformance.py`, `test_gnn_registry.py`, `test_spec_agent.py` | each level's GNN spec declares the semantic role of every matrix, the registry is a grammar rather than a hand-kept index, and a spec-built agent is bit-identical to the builder-built one | +| `test_gnn_release.py` | real Git and filesystem controls reject a wrong release, modified source, hidden index changes, unexpected files and symlinks before upstream parser import | | `test_formal_isomorphism.py` | the generated Lean ledger regenerates byte-identically and matches the recorded values | | `test_worked_example.py` | the interpretability walk-through in the architecture section names the transition column the model actually read | | `test_no_self_offset_strict_zip.py` | `strict=True` is never applied to a self-offset zip, where it raises on every non-empty input | diff --git a/tests/test_availability_disclosure.py b/tests/test_availability_disclosure.py index 81ad5c1..341981a 100644 --- a/tests/test_availability_disclosure.py +++ b/tests/test_availability_disclosure.py @@ -31,8 +31,12 @@ def _disclosure_problems(text: str) -> list[str]: problems.append("the section omits the release archive identity") if "availability do not establish independent reproduction" not in lowered: problems.append("the section conflates availability and reproduction") - if any(phrase in lowered for phrase in ("reserved draft", "publication there remains planned")): - problems.append("the section retains provisional release metadata") + if "zenodo deposition is unpublished" not in lowered or "reserved doi" not in lowered: + problems.append("the section omits the unpublished archive's reservation status") + if "does not yet resolve to a public record" not in lowered: + problems.append("the section presents a reserved DOI as a public archive") + if "the archive has been published" in lowered: + problems.append("the section claims an unverified published archive") if "has been independently reproduced" in lowered: problems.append("the section claims an unrecorded independent reproduction") if "no independent reproduction outside the project is recorded" not in lowered: @@ -88,10 +92,13 @@ def test_the_guard_would_notice_the_stale_disclosures() -> None: SOURCE_REPOSITORY, "/tree/v1.0.0", RELEASE_DOI, + "Zenodo deposition is unpublished", + "reserved DOI", + "does not yet resolve to a public record", "availability do not establish independent reproduction", "No independent reproduction outside the project is recorded", ): assert phrase in current assert _disclosure_problems(current.replace(phrase, "omitted")), phrase - assert _disclosure_problems(current + " Publication there remains planned.") + assert _disclosure_problems(current + " The archive has been published.") assert _disclosure_problems(current + " It has been independently reproduced.") diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index c8bcf9c..ba39f74 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -24,6 +24,7 @@ import time from functools import partial from pathlib import Path +from socketserver import BaseRequestHandler from urllib.error import URLError from urllib.request import Request, urlopen @@ -2328,6 +2329,80 @@ def test_run_dashboard_binds_what_it_is_given_and_shuts_down_on_interrupt(tmp_pa assert "Shutting down dashboard server" in stdout +@pytest.mark.timeout(45) +def test_dashboard_cli_handles_sigint_inherited_as_ignored(tmp_path): + """A real launcher may ignore SIGINT; the dashboard CLI must still close.""" + port = _unused_loopback_port() + environment = _dashboard_environment(tmp_path, port=port) + launcher = ( + "import os, signal, sys\n" + "signal.signal(signal.SIGINT, signal.SIG_IGN)\n" + "os.execv(sys.executable, [sys.executable, '-m', 'ailm.dashboard'])\n" + ) + process = subprocess.Popen( + [sys.executable, "-c", launcher], + cwd=Path(__file__).resolve().parents[1], + env=environment, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + try: + _wait_for_dashboard(process, port) + process.send_signal(signal.SIGINT) + try: + stdout, stderr = process.communicate(timeout=5) + except subprocess.TimeoutExpired: + pytest.fail("dashboard kept an inherited ignored SIGINT disposition") + finally: + if process.poll() is None: + process.terminate() + process.communicate(timeout=5) + assert process.returncode == 0, stderr + assert "Shutting down dashboard server" in stdout + + +def test_interrupt_after_worker_completion_preserves_the_interrupt(): + """A completed worker and interrupted start must return the same slot once. + + The profile hook delivers a real interrupt at Thread.start's return, after + the real worker has returned its slot. It does not replace Thread.start or + the semaphore: this is the observed startup/completion race, synchronized. + """ + from ailm.dashboard.server import ReusableThreadingServer + + class FinishedHandler(BaseRequestHandler): + def handle(self): + pass + + server = ReusableThreadingServer(("127.0.0.1", 0), FinishedHandler, max_workers=1) + request, peer = socket.socketpair() + previous_profile = sys.getprofile() + previous_signal = signal.signal(signal.SIGINT, signal.default_int_handler) + + def interrupt_completed_start(frame, event, argument): + if frame.f_code is threading.Thread.start.__code__ and event == "return": + sys.setprofile(None) + # Acquiring the slot proves the real worker's finally completed. + assert server._worker_slots.acquire(timeout=5) + server._worker_slots.release() + signal.raise_signal(signal.SIGINT) + + try: + sys.setprofile(interrupt_completed_start) + with pytest.raises(KeyboardInterrupt): + server.process_request(request, ("127.0.0.1", 0)) + assert server._worker_slots.acquire(blocking=False) + assert not server._worker_slots.acquire(blocking=False) + server._worker_slots.release() + finally: + sys.setprofile(previous_profile) + signal.signal(signal.SIGINT, previous_signal) + request.close() + peer.close() + server.server_close() + + def test_the_static_matrices_endpoint_serves_every_declared_matrix(): status, _, body = _request("GET /api/static_matrices HTTP/1.1\r\nHost: x\r\n\r\n") assert status == 200 diff --git a/tests/test_dashboard_capture.py b/tests/test_dashboard_capture.py index 9094f5b..b8ab92e 100644 --- a/tests/test_dashboard_capture.py +++ b/tests/test_dashboard_capture.py @@ -178,6 +178,10 @@ def git(*args: str) -> str: assert capture.git_blob(repo, head, "tracked.txt") == b"committed\n" (repo / "untracked.txt").write_bytes(b"new\n") assert capture.git_blob(repo, head, "untracked.txt") is None + nested = repo / "uninitialized-checkout" + nested.mkdir() + with pytest.raises(capture.CaptureError, match="no HEAD commit"): + capture.git_head(nested) with pytest.raises(capture.CaptureError, match="no HEAD commit"): capture.git_head(tmp_path) diff --git a/tests/test_gnn_conformance.py b/tests/test_gnn_conformance.py index 3b5ae33..c4b8768 100644 --- a/tests/test_gnn_conformance.py +++ b/tests/test_gnn_conformance.py @@ -88,6 +88,7 @@ import json import os import re +import subprocess import sys from dataclasses import replace from pathlib import Path @@ -117,6 +118,15 @@ ) from ailm.levels.word import N_OBS as WORD_N_OBS from ailm.levels.word import load_word_artifact +from ailm.verification.upstream_gnn import ( + default_upstream_root as _default_upstream_root, +) +from ailm.verification.upstream_gnn import ( + load_release_pin, + selected_upstream_root, + upstream_candidates, + verify_release_checkout, +) PROJECT_ROOT = Path(__file__).resolve().parent.parent GNN_DIR = PROJECT_ROOT / "gnn" @@ -350,36 +360,8 @@ #: interoperability tests stopped running and reported "no checkout" at a path #: where a checkout plainly was. Evidence for a manuscript claim should not live #: where the operating system tidies up. -_UPSTREAM_CANDIDATES = ( - *( - ( - PROJECT_ROOT.parents[2] - / "ActiveInferenceInstitute" - / "Public" - / "Generalized_Notation_Notation", - ) - if len(PROJECT_ROOT.parents) > 2 - else () - ), - PROJECT_ROOT.parent / "Generalized_Notation_Notation", -) - - -def _default_upstream_root(candidates: tuple[Path, ...] = _UPSTREAM_CANDIDATES) -> Path: - """The first candidate that supplies the parser, else the most durable one. - - Falling back to the first candidate rather than the last keeps the skip - message pointing at the durable location, so a reader is told where to put a - checkout instead of where one was once reaped. - """ - for candidate in candidates: - if (candidate / "src" / "gnn" / "parsers" / "markdown_parser.py").is_file(): - return candidate - return candidates[0] - - -_UPSTREAM_DEFAULT = _default_upstream_root() -UPSTREAM_ROOT = Path(os.environ.get("AILM_GNN_UPSTREAM", str(_UPSTREAM_DEFAULT))) +_UPSTREAM_CANDIDATES = upstream_candidates(PROJECT_ROOT) +UPSTREAM_ROOT = selected_upstream_root(PROJECT_ROOT) UPSTREAM_SRC = UPSTREAM_ROOT / "src" @@ -2351,37 +2333,82 @@ def _upstream_skip_reason() -> str: @pytest.fixture(scope="module") -def upstream_parser(): - """The REAL GeneralizedNotationNotation Markdown parser, if available. - - Imported by inserting the upstream ``src/`` on ``sys.path`` for the duration - of the module, then asserting the module actually came from that checkout — - this repository has its own top-level ``gnn/`` directory, and a namespace - shadowing would make every test in the class pass while proving nothing. - - When the parser cannot run this yields nothing and leaves the verdict to the - class's autouse guard, which runs after every module-scoped fixture and is - where "skip" or "fail" is decided; importing here would turn a documented - environment gap into an opaque setup error. +def upstream_results(tmp_path_factory): + """Parse every spec with real upstream code in a fresh isolated interpreter. + + Interpreter flags select a private empty bytecode prefix and disable writes, + so verified source is compiled without replacing dependencies or changing + the parent interpreter's global configuration. The subprocess emits the + real parser's result data; no replacement parser object is constructed. + The class guard owns missing-prerequisite skip/failure decisions. """ if not _UPSTREAM_RUNNABLE: yield None return - inserted = str(UPSTREAM_SRC) - sys.path.insert(0, inserted) - try: - from gnn.parsers.markdown_parser import MarkdownGNNParser + pin = load_release_pin(PROJECT_ROOT / "gnn/upstream.json") + identity = verify_release_checkout(UPSTREAM_ROOT, pin) + cache_prefix = tmp_path_factory.mktemp("gnn-release-bytecode") + code = """ +import json +import sys +from pathlib import Path - module_file = Path(sys.modules["gnn.parsers.markdown_parser"].__file__) - assert UPSTREAM_ROOT in module_file.parents, ( - f"imported 'gnn' from {module_file}, not from the upstream checkout " - f"at {UPSTREAM_ROOT} — the repository's own gnn/ directory has " - f"shadowed it and these tests would prove nothing." - ) - yield MarkdownGNNParser() +source, cache_prefix, *specs = sys.argv[1:] +assert sys.dont_write_bytecode and sys.pycache_prefix == cache_prefix +sys.path.insert(0, source) +from gnn.parsers.markdown_parser import MarkdownGNNParser + +module_file = Path(sys.modules['gnn.parsers.markdown_parser'].__file__).resolve() +assert Path(source).resolve() in module_file.parents, module_file +parser = MarkdownGNNParser() +results = {} +for spec in specs: + result = parser.parse_file(spec) + model = result.model + results[Path(spec).name.removesuffix('.gnn.md')] = { + 'success': result.success, + 'errors': result.errors, + 'warnings': result.warnings, + 'model': { + 'model_name': model.model_name, + 'variables': [{'name': v.name, 'dimensions': v.dimensions} for v in model.variables], + 'ontology_mappings': [ + {'variable_name': m.variable_name, 'ontology_term': m.ontology_term} + for m in model.ontology_mappings + ], + 'parameters': [{'name': p.name, 'value': p.value} for p in model.parameters], + }, + } +print(json.dumps(results)) +""" + try: + completed = subprocess.run( + [ + sys.executable, + "-I", + "-B", + "-X", + f"pycache_prefix={cache_prefix}", + "-c", + code, + str(UPSTREAM_SRC), + str(cache_prefix), + *(str(spec_path(name)) for name in SPEC_NAMES), + ], + capture_output=True, + text=True, + check=False, + timeout=120, + ) + assert completed.returncode == 0, completed.stdout + completed.stderr + results = json.loads(completed.stdout) + assert set(results) == set(SPEC_NAMES) + assert not list(cache_prefix.iterdir()), "the no-bytecode parser invocation wrote a cache" + yield results finally: - if inserted in sys.path: - sys.path.remove(inserted) + assert verify_release_checkout(UPSTREAM_ROOT, pin) == identity, ( + "upstream source changed during interoperability tests" + ) class TestUpstreamInteroperability: @@ -2394,7 +2421,7 @@ class TestUpstreamInteroperability: """ @pytest.fixture(autouse=True) - def _require_the_upstream_parser(self) -> None: + def _require_the_upstream_results(self) -> None: """Skip when the parser cannot run; fail instead under the release profile. A class-level ``skipif`` would skip unconditionally, and the full @@ -2410,22 +2437,23 @@ def _require_the_upstream_parser(self) -> None: pytest.skip(reason) @pytest.mark.parametrize("name", SPEC_NAMES) - def test_upstream_parses_the_spec(self, name, upstream_parser): - result = upstream_parser.parse_file(str(spec_path(name))) - assert result.success, f"{name}: upstream parse failed: {result.errors}" - assert not result.errors, f"{name}: {result.errors}" - assert not result.warnings, f"{name}: {result.warnings}" + def test_upstream_parses_the_spec(self, name, upstream_results): + result = upstream_results[name] + assert result["success"], f"{name}: upstream parse failed: {result['errors']}" + assert not result["errors"], f"{name}: {result['errors']}" + assert not result["warnings"], f"{name}: {result['warnings']}" @pytest.mark.parametrize("name", SPEC_NAMES) - def test_upstream_and_ailm_agree_on_the_model(self, name, upstream_parser): + def test_upstream_and_ailm_agree_on_the_model(self, name, upstream_results): """Both readers must extract the SAME model, not merely both succeed.""" ours = parse_gnn_spec(spec_path(name)) - theirs = upstream_parser.parse_file(str(spec_path(name))).model + theirs = upstream_results[name]["model"] - assert theirs.model_name == ours.model_name + assert theirs["model_name"] == ours.model_name upstream_vars = { - UPSTREAM_NAME_ALIASES.get(v.name, v.name): tuple(v.dimensions) for v in theirs.variables + UPSTREAM_NAME_ALIASES.get(v["name"], v["name"]): tuple(v["dimensions"]) + for v in theirs["variables"] } our_vars = {n: dims for n, (dims, _dtype) in ours.variables.items()} assert upstream_vars == our_vars, ( @@ -2434,21 +2462,21 @@ def test_upstream_and_ailm_agree_on_the_model(self, name, upstream_parser): ) upstream_ontology = { - UPSTREAM_NAME_ALIASES.get(m.variable_name, m.variable_name): m.ontology_term - for m in theirs.ontology_mappings + UPSTREAM_NAME_ALIASES.get(m["variable_name"], m["variable_name"]): m["ontology_term"] + for m in theirs["ontology_mappings"] } assert upstream_ontology == ours.ontology # Every ModelParameters key we read, not a fixed four: L3 has no scalar # num_hidden_states and L1g adds num_controls and gamma, so a hardcoded # list would silently stop covering whatever a spec declares next. - upstream_params = {p.name: p.value for p in theirs.parameters} + upstream_params = {p["name"]: p["value"] for p in theirs["parameters"]} assert len(ours.parameters) >= 4, ours.parameters for key, value in ours.parameters.items(): assert upstream_params[key] == value, key @pytest.mark.parametrize("name", SPEC_NAMES) - def test_the_recorded_rename_is_the_only_reader_disagreement(self, name, upstream_parser): + def test_the_recorded_rename_is_the_only_reader_disagreement(self, name, upstream_results): """An alias must never grow into a place a real disagreement can hide. :data:`UPSTREAM_NAME_ALIASES` is applied above to reconcile the two @@ -2456,7 +2484,7 @@ def test_the_recorded_rename_is_the_only_reader_disagreement(self, name, upstrea ``π`` in L1g, and nothing else anywhere. """ ours = set(parse_gnn_spec(spec_path(name)).variables) - theirs = {v.name for v in upstream_parser.parse_file(str(spec_path(name))).model.variables} + theirs = {v["name"] for v in upstream_results[name]["model"]["variables"]} renamed = theirs - ours assert renamed <= set(UPSTREAM_NAME_ALIASES), ( f"{name}: upstream reports variable(s) {sorted(renamed)} that AILM " @@ -2471,30 +2499,30 @@ def test_the_recorded_rename_is_the_only_reader_disagreement(self, name, upstrea ) @pytest.mark.parametrize("name", SINGLE_FACTOR_SPEC_NAMES) - def test_upstream_sees_the_matrix_roles(self, name, upstream_parser): + def test_upstream_sees_the_matrix_roles(self, name, upstream_results): """The ontology block is the load-bearing part; upstream must read it.""" - theirs = upstream_parser.parse_file(str(spec_path(name))).model - roles = {m.variable_name: m.ontology_term for m in theirs.ontology_mappings} + theirs = upstream_results[name]["model"] + roles = {m["variable_name"]: m["ontology_term"] for m in theirs["ontology_mappings"]} assert roles["A"] == "RecognitionMatrix" assert roles["B"] == "TransitionMatrix" assert roles["D"] == "Prior" @pytest.mark.parametrize("name", MULTIFACTOR_SPEC_NAMES) - def test_upstream_sees_the_per_factor_matrix_roles(self, name, upstream_parser): + def test_upstream_sees_the_per_factor_matrix_roles(self, name, upstream_results): """The factor-suffixed roles are what bind a matrix to a factor.""" - theirs = upstream_parser.parse_file(str(spec_path(name))).model - roles = {m.variable_name: m.ontology_term for m in theirs.ontology_mappings} + theirs = upstream_results[name]["model"] + roles = {m["variable_name"]: m["ontology_term"] for m in theirs["ontology_mappings"]} assert roles["A"] == "RecognitionMatrix" assert roles["B_f0"] == roles["B_f1"] == "TransitionMatrix" assert roles["D_f0"] == roles["D_f1"] == "Prior" - def test_upstream_reads_the_g2p_asymmetry(self, upstream_parser): + def test_upstream_reads_the_g2p_asymmetry(self, upstream_results): """30 letter observations over 39 hidden phones, read by upstream.""" - theirs = upstream_parser.parse_file(str(spec_path("L2b_grapheme_to_phoneme"))).model - dims = {v.name: tuple(v.dimensions) for v in theirs.variables} + theirs = upstream_results["L2b_grapheme_to_phoneme"]["model"] + dims = {v["name"]: tuple(v["dimensions"]) for v in theirs["variables"]} assert dims["A"] == (30, 39) assert dims["B"] == (39, 39, 1) - params = {p.name: p.value for p in theirs.parameters} + params = {p["name"]: p["value"] for p in theirs["parameters"]} assert params["num_obs"] == 30 assert params["num_hidden_states"] == 39 diff --git a/tests/test_gnn_release.py b/tests/test_gnn_release.py new file mode 100644 index 0000000..097e622 --- /dev/null +++ b/tests/test_gnn_release.py @@ -0,0 +1,201 @@ +"""Real Git and filesystem controls for upstream release selection and custody.""" + +from __future__ import annotations + +import json +import os +import subprocess +from dataclasses import replace +from pathlib import Path + +import pytest + +from ailm.verification.upstream_gnn import ( + UpstreamRelease, + UpstreamReleaseError, + load_release_pin, + selected_upstream_root, + verify_release_checkout, +) + + +def _git(root: Path, *args: str) -> str: + environment = {key: value for key, value in os.environ.items() if not key.startswith("GIT_")} + environment.update(GIT_CONFIG_GLOBAL=os.devnull, GIT_CONFIG_NOSYSTEM="1") + return subprocess.run( + ["git", "-C", str(root), *args], + env=environment, + check=True, + capture_output=True, + text=True, + timeout=30, + ).stdout.strip() + + +@pytest.fixture +def release(tmp_path: Path) -> tuple[Path, UpstreamRelease]: + root = tmp_path / "upstream" + parser = root / "src/gnn/parsers/markdown_parser.py" + parser.parent.mkdir(parents=True) + parser.write_text("VALUE = 'released'\n") + (root / "src/gnn/__init__.py").write_text("") + _git(root, "init", "-q") + _git(root, "config", "user.name", "AILM release control") + _git(root, "config", "user.email", "release@example.invalid") + _git(root, "add", "src") + _git(root, "commit", "-qm", "release") + _git(root, "tag", "v1.2.3") + return root, UpstreamRelease( + "https://github.com/example/upstream", "v1.2.3", _git(root, "rev-parse", "HEAD") + ) + + +def test_matching_release_source_produces_a_stable_identity(release): + root, pin = release + identity = verify_release_checkout(root, pin) + assert identity["commit"] == pin.commit + assert identity["tag"] == pin.tag + assert identity["source_files"] == 2 + assert len(str(identity["source_sha256"])) == 64 + assert verify_release_checkout(root, pin) == identity + + +def test_newer_head_is_refused_even_with_the_release_tag_present(release): + root, pin = release + _git(root, "commit", "--allow-empty", "-qm", "development") + with pytest.raises(UpstreamReleaseError, match="HEAD .* differs"): + verify_release_checkout(root, pin) + + +def test_tag_pointing_elsewhere_is_refused(release): + root, pin = release + _git(root, "commit", "--allow-empty", "-qm", "development") + altered = replace(pin, commit=_git(root, "rev-parse", "HEAD")) + with pytest.raises(UpstreamReleaseError, match="tag .* differs"): + verify_release_checkout(root, altered) + + +@pytest.mark.parametrize("flag", [None, "--assume-unchanged", "--skip-worktree"]) +def test_modified_source_is_refused_despite_index_flags(release, flag): + root, pin = release + relative = "src/gnn/parsers/markdown_parser.py" + if flag is not None: + _git(root, "update-index", flag, relative) + (root / relative).write_text("VALUE = 'modified'\n") + with pytest.raises(UpstreamReleaseError, match="modified upstream source"): + verify_release_checkout(root, pin) + + +def test_git_replacement_objects_cannot_redefine_the_pinned_source(release): + root, pin = release + parser = root / "src/gnn/parsers/markdown_parser.py" + parser.write_text("VALUE = 'replacement'\n") + _git(root, "add", "src") + _git(root, "commit", "-qm", "replacement") + replacement = _git(root, "rev-parse", "HEAD") + _git(root, "update-ref", "HEAD", pin.commit) + _git(root, "replace", pin.commit, replacement) + with pytest.raises(UpstreamReleaseError, match="modified upstream source"): + verify_release_checkout(root, pin) + + +@pytest.mark.parametrize("kind", ["missing", "extra", "extra-bytecode", "symlink", "fifo"]) +def test_changed_source_inventory_is_refused(release, tmp_path, kind): + root, pin = release + parser = root / "src/gnn/parsers/markdown_parser.py" + if kind == "extra": + (parser.parent / "injected.py").write_text("VALUE = 'injected'\n") + elif kind == "extra-bytecode": + (parser.parent / "injected.pyc").write_bytes(b"unversioned sourceless module") + else: + content = parser.read_bytes() + parser.unlink() + if kind == "symlink": + target = tmp_path / "outside.py" + target.write_bytes(content) + parser.symlink_to(target) + elif kind == "fifo": + os.mkfifo(parser) + with pytest.raises(UpstreamReleaseError): + verify_release_checkout(root, pin) + + +def test_unversioned_bytecode_cache_does_not_change_source_identity(release): + root, pin = release + before = verify_release_checkout(root, pin) + cache = root / "src/gnn/__pycache__" + cache.mkdir() + (cache / "__init__.cpython-312.pyc").write_bytes(b"cache") + assert verify_release_checkout(root, pin) == before + + +def test_symlinked_source_directory_is_refused(release, tmp_path): + root, pin = release + source = root / "src" + moved = tmp_path / "moved-source" + source.rename(moved) + source.symlink_to(moved, target_is_directory=True) + with pytest.raises(UpstreamReleaseError, match="symlinked upstream source"): + verify_release_checkout(root, pin) + + +def test_missing_checkout_is_a_refusal(release, tmp_path): + _, pin = release + with pytest.raises(UpstreamReleaseError, match="cannot inspect"): + verify_release_checkout(tmp_path / "absent", pin) + + +def test_release_without_parser_is_refused(release): + root, pin = release + _git(root, "rm", "src/gnn/parsers/markdown_parser.py") + _git(root, "commit", "-qm", "remove parser") + _git(root, "tag", "v1.2.4") + altered = replace(pin, tag="v1.2.4", commit=_git(root, "rev-parse", "HEAD")) + with pytest.raises(UpstreamReleaseError, match="has no Markdown parser"): + verify_release_checkout(root, altered) + + +def test_pin_round_trips_the_release_identity(release, tmp_path): + _, pin = release + path = tmp_path / "pin.json" + path.write_text( + json.dumps({"repository": pin.repository, "tag": pin.tag, "commit": pin.commit}) + ) + assert load_release_pin(path) == pin + + +@pytest.mark.parametrize( + "payload", + [ + "[]", + "{", + '{"tag":"v1.0.0","tag":"v1.0.1"}', + '{"repository":1,"tag":"v1.0.0","commit":"a"}', + '{"repository":"http://example.org","tag":"v1.0.0","commit":"a"}', + '{"repository":"https://github.com/a/b","tag":"main","commit":"a"}', + '{"repository":"https://github.com/a/b","tag":"v1.0.0","commit":"short"}', + ], +) +def test_malformed_or_ambiguous_pin_is_refused(tmp_path, payload): + path = tmp_path / "pin.json" + path.write_text(payload) + with pytest.raises(UpstreamReleaseError): + load_release_pin(path) + + +def test_missing_pin_is_a_refusal(tmp_path): + with pytest.raises(UpstreamReleaseError, match="cannot read"): + load_release_pin(tmp_path / "absent") + + +def test_explicit_upstream_selection_is_final(tmp_path, monkeypatch): + project = tmp_path / "project" + chosen = tmp_path / "chosen" + monkeypatch.setenv("AILM_GNN_UPSTREAM", str(chosen)) + assert selected_upstream_root(project) == chosen + + +def test_empty_explicit_upstream_selection_is_refused(tmp_path, monkeypatch): + monkeypatch.setenv("AILM_GNN_UPSTREAM", " ") + with pytest.raises(UpstreamReleaseError, match="must not be empty"): + selected_upstream_root(tmp_path) diff --git a/tests/test_interface_inventory.py b/tests/test_interface_inventory.py index 67d78d8..d58949a 100644 --- a/tests/test_interface_inventory.py +++ b/tests/test_interface_inventory.py @@ -74,7 +74,6 @@ def test_the_dashboard_and_the_page_share_one_model_builder(): "the dashboard no longer uses the shipped letter builder; the standalone " "page and the dashboard would now be two models rather than two views" ) - assert engine.build_unigram_a is build_letter_transition def test_every_interface_reads_the_same_alphabet(): diff --git a/tests/test_pdf_integrity.py b/tests/test_pdf_integrity.py index 15f4f95..04add3f 100644 --- a/tests/test_pdf_integrity.py +++ b/tests/test_pdf_integrity.py @@ -53,6 +53,7 @@ _STARTXREF_RE = re.compile(rb"startxref\s+(\d+)\s*%%EOF\s*$", re.DOTALL) _TEX_ERROR_RE = re.compile(r"(?m)^! .+$") +_BIBTEX_ERROR_RE = re.compile(r"(?m)^\(There (?:was|were) [1-9]\d* error messages?\)") _COMBINED_LOG = PDF_DIR / "_combined_manuscript.log" @@ -136,6 +137,12 @@ def test_combined_render_log_contains_no_tex_errors() -> None: "the combined manuscript log contains explicit TeX errors even though " f"a PDF was written: {errors}" ) + bibliography_log = PDF_DIR / "_combined_manuscript.blg" + assert bibliography_log.is_file(), "the actual bibliography compiler log is missing" + bibliography = bibliography_log.read_text(encoding="utf-8", errors="replace") + assert re.search(r"You've used \d+ entries", bibliography), "incomplete BibTeX log" + assert re.search(r"(?m)^write\$ -- \d+", bibliography), "incomplete BibTeX statistics" + assert _BIBTEX_ERROR_RE.findall(bibliography) == [], bibliography def test_tex_error_scan_rejects_a_recovered_render() -> None: @@ -144,6 +151,33 @@ def test_tex_error_scan_rejects_a_recovered_render() -> None: assert _tex_errors(planted) == ["! Missing $ inserted."] +@pytest.mark.template_context +@pytest.mark.parametrize("broken", [False, True]) +def test_bibliography_source_passes_bibtex_and_malformed_entry_fails(tmp_path, broken): + """Use the actual bibliography compiler; a written PDF can conceal its failure.""" + bibtex = shutil.which("bibtex") + assert bibtex is not None, "BibTeX is required for publication verification" + source = (PROJECT_ROOT / "docs/manuscript/references.bib").read_text(encoding="utf-8") + if broken: + source += "\n@article{deliberately_unclosed,\n" + (tmp_path / "references.bib").write_text(source, encoding="utf-8") + (tmp_path / "paper.aux").write_text( + "\\relax\n\\citation{*}\n\\bibstyle{plainnat}\n\\bibdata{references}\n", + encoding="utf-8", + ) + result = subprocess.run( + [bibtex, "paper"], cwd=tmp_path, capture_output=True, text=True, check=False, timeout=30 + ) + diagnostics = result.stdout + result.stderr + log_errors = _BIBTEX_ERROR_RE.findall((tmp_path / "paper.blg").read_text(encoding="utf-8")) + if broken: + assert result.returncode != 0 and "error message" in diagnostics, diagnostics + assert log_errors, "the actual-render error scanner missed a failed BibTeX run" + else: + assert result.returncode == 0, diagnostics + assert log_errors == [], diagnostics + + def test_the_scan_knows_where_pdfs_live(): """POSITIVE CONTROL: a wrong directory would skip every check silently. diff --git a/tests/test_release_orchestration.py b/tests/test_release_orchestration.py index 7a06404..9a1320b 100644 --- a/tests/test_release_orchestration.py +++ b/tests/test_release_orchestration.py @@ -353,6 +353,8 @@ def test_profiles_have_distinct_bounded_acceptance_surfaces(tmp_path, monkeypatc assert full_names.index("pymdp-sparse-bundle-check") < full_names.index("tests-full") assert full_names.index("release-infrastructure-coverage") < full_names.index("tests-full") assert "package-distributions" in full_names + assert "gnn-upstream-release" in full_names + assert full_names.index("gnn-upstream-release") < full_names.index("tests-full") assert full_names.index("package-distributions") < full_names.index("tests-full") assert full_names.index("network-claim-bindings") < full_names.index("cache-audit") assert full_names.index("cache-audit") < full_names.index("tests-full"), ( @@ -550,6 +552,7 @@ def test_profiles_have_distinct_bounded_acceptance_surfaces(tmp_path, monkeypatc "web-model": ("script", "scripts/export_web_model.py"), "web-page": ("script", "scripts/build_web_ailm.py"), "package-distributions": ("module", "pytest"), + "gnn-upstream-release": ("script", "scripts/verify_gnn_release.py"), "network-claim-bindings": ("script", "scripts/verify_network_claim_bindings.py"), "cache-audit": ("script", "scripts/record_external_benchmark_claims.py"), "raw-corpus-reproducibility": ("module", "pytest"), @@ -1734,6 +1737,17 @@ def test_release_environment_defeats_collect_only_and_other_inherited_poison(tmp assert "1 failed" in result["stdout_tail"] +def test_release_environment_forwards_and_records_explicit_gnn_checkout(tmp_path, monkeypatch): + module = _module() + repository = tmp_path / "repository" + commit = _init_git_repository(repository) + selected = str(tmp_path / "pinned-release") + monkeypatch.setenv("AILM_GNN_UPSTREAM", selected) + environment, recorded = module._release_environment(commit, root=repository) + assert environment["AILM_GNN_UPSTREAM"] == selected + assert recorded["AILM_GNN_UPSTREAM"] == selected + + @pytest.mark.timeout(480) def test_release_uv_config_defeats_a_poisoned_user_config(tmp_path, monkeypatch): """NEGATIVE CONTROL: caller HOME cannot inject uv behavior into release steps."""