# reporting { #aria_nbv.reporting }
`reporting`
Immutable scientific reports shared by Streamlit, CLI, and Typst.
The public interface is intentionally small: validate a
``ScientificReportConfig``, construct its ``ScientificReportBuilder``, build a
``ReportSnapshot`` once, and pass that exact snapshot to
``write_report_snapshot``. Domain calculations remain in their rollout and W&B
owners; the reporting module owns freezing, notation validation, canonical
Plotly specifications, and publication.
<!-- quartodoc-package-readme: aria_nbv.reporting -->
## Package guide
`aria_nbv.reporting` builds figures, tables, and named quantities once, seals
them in an immutable `ReportSnapshot`, and gives the exact snapshot to
Streamlit preview and static/Typst export. Export never receives a report
recipe, so it cannot silently reacquire a changed W&B run or rollout store.
```{mermaid}
flowchart LR
C["Shared TOML recipes"] --> D["ConfigDocument and Pydantic"]
R["Rollout Zarr stores"] --> S["Evidence snapshot"]
W["Frozen W&B runs"] --> S
M["Frozen measurement audit"] --> S
Q["Frozen QH diagnostic assignment"] --> S
N["symbols.typ to notation.yml"] --> B["ScientificReportBuilder"]
D --> B
S --> B
B --> P["Immutable ReportSnapshot"]
P --> A["Streamlit renderer"]
P --> E["Static Plotly exporter"]
E --> T["report.json and SVG or PNG to Typst"]
classDef input fill:#D5E8D4,stroke:#82B366,color:#17202A,stroke-width:1.5px,rx:0,ry:0;
classDef output fill:#F8CECC,stroke:#B85450,color:#17202A,stroke-width:1.5px,rx:0,ry:0;
classDef compute fill:#E1D5E7,stroke:#9673A6,color:#17202A,stroke-width:1.5px,rx:8,ry:8;
classDef data fill:#F5F5F5,stroke:#9E9E9E,color:#17202A,stroke-width:1.2px,rx:0,ry:0;
class C,R,W,M,Q,N input;
class D,S,B,E compute;
class P data;
class A,T output;
```
## Build, preview, and export
### Generation post-hoc analysis
`reporting.generation_posthoc` writes a standalone, sealed HTML/table/SVG report
from `rollouts.inspection.generation_posthoc.GenerationPosthocEvidence`. It
consumes completed reductions and does not reacquire stores or fit a learner.
The cold reader validates the exact files and returns recursively immutable
tables and asset bytes. This standalone product has its own explicit schema;
it is not a new `ScientificReportBuilder` section.
`datasets.bundles.posthoc_context` binds source-root statistics, the frozen
scene assignment, complete disposition accounting, compatible worker clocks,
TRAIN-only authored nominations, and optional archived Q1 validation states.
Candidate masks, missing values, physical scenes, target tasks, prefix risk
sets, and attempted costs retain distinct denominators. Conditional gain
headroom and geometric redundancy are descriptive proxies, not proof of
learning improvement or policy value.
The resumable CPU runner opens immutable stores in spawned workers and keeps
source identities and derived cache receipts. For an explicit input catalog:
```sh
uv run --project aria_nbv --no-sync python scripts/analyze_generation_posthoc.py \
--catalog /absolute/path/to/catalog.json \
--master-events /absolute/path/to/frozen-master-events.jsonl \
--stage train --workers 16 --output /absolute/path/to/new-analysis --render
```
Choose workers using the same fixed subset with `--benchmark 1,2,4,8,12` and
an explicit `--limit`; the runner seals exact serial/parallel comparisons,
observes worker RSS/swap, and checks source-file fingerprints. Further worker
counts are appropriate only after the measured resource guard passes. Resume
reuses matching sealed cache products; a changed source, catalog, or stage
binding receives a different identity. Source stores are never rewritten.
Verify the new interfaces with the generation post-hoc domain, VIN numeric
evidence, report, context, and runner tests. Register retained static outputs
through the existing figure gallery; gallery registration does not establish
thesis inclusion or scientific promotion.
```python
from aria_nbv.reporting import ScientificReportConfig, read_report_bundle, write_report_snapshot
# First replace the template's empty source selections with immutable stores
# and exact W&B run IDs.
recipe = ScientificReportConfig.from_toml(".configs/reports/qh-thesis.toml")
snapshot = recipe.setup_target(wandb_api=wandb_api).build()
# Streamlit reconstructs go.Figure from figure.plotly_json.
for figure in snapshot.figures:
st.plotly_chart(plotly.io.from_json(figure.plotly_json.decode()))
# Static export consumes the exact previewed snapshot; it performs no source reads.
write_report_snapshot(snapshot, Path("build/qh-thesis-report"))
# Later consumers can reconstruct the exact snapshot without source access.
verified_snapshot = read_report_bundle(Path("build/qh-thesis-report"))
```
Static consumers that need the already-verified figure fallbacks can call
`read_report_bundle_with_assets(path)`. It returns the same snapshot, the
manifest SHA-256, and immutable `(relative_path, bytes)` entries captured by
the bundle reader's single validation transaction. Consumers can copy those
bytes without reopening evidence sources or trusting unverified asset paths.
`snapshot` is the reconstructed typed report; `manifest_sha256` hashes the
captured `manifest.json` bytes. `file_bytes` is sorted by relative path and
includes `manifest.json`, the report, recipe, Plotly specifications, and static
assets as captured during that validation transaction.
`nbv-report build --config ... --output ...` is the same composition as the
Python example. A bundle contains `recipe.toml`, `report.json`, canonical
Plotly JSON under `figures/`, static assets under `assets/`, and an integrity
`manifest.json`. Two-dimensional figures default to SVG; WebGL/3D figures use
configured high-resolution PNG.
### Broad-queue selected motion
`nbv-report broad-scene --queue-root ... --output ...` freezes the validated
queue-prefix accounting and the successful-store selected-motion readout in one
source-bound export. The Rollout Dataset page calls the same
`broad_scene_motion_summary` and `broad_scene_motion_figures` producers, so its
translation/rotation tails and revisit/occupancy view match the CSV/JSON/SVG/PNG
export. Headline distributions reduce repeated stores and selected steps to one
value per source root. Queue attempts, successful motion stores, source roots,
and factual selected steps retain separate denominators; valid zero-step stores
remain visible and conditional fractions are unavailable rather than zero.
This completes the general queue-wide motion/readout portion deferred from
#504/#505: canonical queue composition, selected-step/store/root tables, shared
motion figures, frozen CLI export, and Streamlit consumption. It does not add a
new queue ledger parser, change the score-floor-specific matched comparison, or
restore the broader historical #504/#505 experiment dashboard. Target-relative
angular occupancy describes selected-camera direction cells. It is not
occlusion-aware visible-surface coverage, and untimed pose increments do not
measure speed, acceleration, jerk, or motion smoothness.
### Bounded evidence catalog
The report CLI and Scientific Reporting page share one explicit-root catalog.
Directory discovery stays inside the selected root. Before a domain reader
runs, the catalog also inventories external paths named directly by a candidate
recipe plan or QH assignment and charges that work against the same path and
file ceilings. It rejects symlinks in candidate and referenced evidence;
authoritative readers may then reopen the admitted exact paths. Familiar
marker names are only candidates:
report bundles, recipe plans, measurement summaries, and QH assignments enter
the catalog only after their authoritative readers validate them.
Invalid candidates remain visible with their validation error and without a
fabricated digest. Typed foreign plans, summaries and assignments are skipped;
malformed supported schemas stay visible for their authoritative reader error.
`registration.json` uses `aria-nbv-experiment-registration-v1` to associate
experiment evidence with distinct attempt IDs. `reporting.discovery` exposes
`read_experiment_registration` and immutable registration DTOs in the same
catalog's separate `registrations` projection. Evidence paths are sidecar-relative
and their SHA256 is freshly checked; store references are checkout-relative
lexical declarations and may be unavailable. Registration validity certifies
that byte association, not store payloads, scientific admission or promotion.
Sidecar/evidence paths reject symlinks before resolution; relative declarations
reject traversal. Duplicate experiment/attempt identities are rejected while
distinct attempt aliases to the same store remain distinct. Experiments and
nested attempts each consume one entry from the same global budget as report
entries, across all sidecars. Defaults remain depth6/entries100; callers can
explicitly request a larger finite budget. An oversized sidecar is not partially
admitted. The direct reader limits sidecar bytes to 2 MB and defaults to 100
records.
```sh
cd aria_nbv
uv run nbv-report index --root /absolute/evidence/root \
--max-depth 6 --max-paths 10000 --max-files 5000 --max-entries 100
```
The command prints deterministic `aria-nbv-report-catalog-v2` JSON. The
Streamlit page performs the same scan only after **Index evidence** is selected.
A raw recipe, measurement, or QH entry is bound into the existing
`ScientificReportConfig` interface and dispatched through
`ScientificReportBuilder`; a published bundle is cold-read through the bundle
validator. Neither path writes to the evidence root. QH assignment/receipt
admission delegates to the Lightning-owned typed diagnostic reader; catalog
and reporting code never parse or independently reduce those artifacts.
### Recipe-experiment reports
Config-v2 adds a `recipe` source and section for one frozen Oracle experiment
plan. Oracle remains the only owner that reads plans, receipts, and promoted
stores or computes matched-prefix effects. Reporting freezes its typed attempt
product, including every planned unit and missing/rejected dispositions, then
reuses the rollout-owned matched-prefix figure. Missing factual endpoints stay
unavailable rather than becoming zero reward.
Config-v1 still produces snapshot-v1/report-bundle-v2 byte semantics. A v2
recipe produces snapshot-v2/report-bundle-v3, whose report declares its exact
snapshot schema. Cold readers dispatch only these two explicit combinations;
historical bundles are read in place and never rewritten.
### Measurement-sensitivity reports
Config-v2 also admits one Oracle-owned `measurement` source and section. The
source names the frozen audit `summary.json`; the Oracle reader validates the
assignment and raw artifact bytes once and returns their captured content
digest. Reporting preserves that identity, the fixed raster/root/depth
protocol, accuracy/completeness components, repeat and no-op controls, and the
separate mesh-retessellation table. It reuses the rollout presentation figure
without reopening the JSON artifacts:
```toml
[sources.measurement]
summary_path = "path/to/summary.json"
[[sections]]
kind = "measurement"
id = "measurement"
```
Each row remains qualified by its fixed audit case. Counts describe diagnostic
support; they are not population estimates, and endpoint gains are not pooled
across the two retained cases.
### Finite-horizon diagnostic reports
Config-v2 admits one Lightning-owned `qh_diagnostic` source and section. The
source names the frozen assignment directory; the diagnostic reader validates
its cohort, held-out scene partitions, cell dispositions, fit/evaluation
receipts before reporting receives a typed product:
```toml
[sources.qh_diagnostic]
root = "path/to/qh-diagnostic-assignment"
[[sections]]
kind = "qh_diagnostic"
id = "qh"
```
The snapshot keeps every planned cell, including missing and failed cells;
supported H1 practical-regret values remain scene-held-out and seed-reduced.
The figure describes prediction of the retained original labels, **not**
calibrated reconstruction quality or policy return. Metric-history telemetry is
separate and optional; no loss curve is inferred.
### Rollout distribution figures
A rollout section can freeze complete-population figures from the same admitted
report-v1 tables that it places in the snapshot:
```toml
[[sections]]
kind = "rollout"
id = "rollout"
distribution_figures = [
"candidate_validity",
"rejection_reasons",
"selected_steps",
"terminal_endpoints",
]
```
Candidate masks remain separate predicates rather than a sequential funnel.
Selected-step panels retain missing-value support, and terminal endpoints are
the greatest persisted factual steps rather than independent endpoint
evaluations. Every figure names its complete canonical source table in the
immutable `ReportSnapshot`. The Scientific Reporting page and static exporter
consume those exact frozen Plotly specifications without recomputing the
reductions.
### Target-frame S² reports
The `rollout_s2` section freezes the same target-frame movement,
camera-forward, and calibrated proxy-frustum Plotly figures shown by the
stored-rollout application:
```toml
[[sections]]
kind = "rollout_s2"
id = "s2"
channels = ["movement", "view_direction", "frustum"]
[sections.analysis]
azimuth_bins = 36
elevation_bins = 18
projection_limit = 2000
```
The complete equal-solid-angle histograms and scalar support quantities are
computed from every admitted selected step. `projection_limit` bounds only the
incidence overlay. Surface colour represents complete cell counts; incidence
colour represents rollout-chain index and marker shape represents persisted
step index. The frustum channel reports geometric potential support on a
geometric-mean-scale target proxy, not observed target-mesh visibility.
`.configs/reports/s2-thesis-pilot.toml` is the exact pilot recipe used by the
development thesis. Regenerate its immutable bundle with:
```sh
cd aria_nbv
uv run nbv-report build \
--config ../.configs/reports/s2-thesis-pilot.toml \
--output ../docs/typst/thesis/data/s2-rollout-pilot
```
Typst loads the resulting `report.json` and resolves figure paths through
`experiment_data.typ`; it does not execute Python or reacquire rollout data.
The manifest fingerprints Plotly, Kaleido, Chrome, the resolved font files,
template payloads, locale, timezone, and Plotly's MathJax/TopoJSON defaults.
Report execution never installs browser assets. Recipes intended for isolated
publication must avoid map tiles, remote images, and other URL-backed traces;
the exporter rejects explicit remote resources before launching Kaleido.
## Ownership
- `aria_nbv.rollouts` owns Zarr validation, evidence compatibility, rollout
reductions, configured S² acquisition, and the shared Plotly builder used by
Streamlit and this module. Reporting freezes those products without
reimplementing geometry.
- W&B remains an external evidence store. Confirmatory recipes name exact,
finished run IDs and acquire complete `scan_history` rows.
- `docs/typst/shared/symbols.typ` and `equations.typ` own notation and theory.
Reports carry only validated canonical IDs.
- This README owns the public workflow and architecture. Public Python
docstrings own exact fields, invariants, failures, and lifecycle. Typst owns
scientific claims, captions, equations, and interpretation.
See the tracked [API reference index](index.qmd)
for the generated reporting interface. Report construction is explicitly dispatched;
configuration inspection and ordinary Streamlit reruns do not read full rollout
arrays or W&B histories.
### Development collection readouts
`reporting.score_floor` validates the exact baseline/floor writer-config
contrast and immutable successful stores, then reduces matched completed-store
pairs to independent source roots. Its pandas tables and Seaborn figure
factories are the **same objects** used by the versioned CSV/SVG export and the
Rollout Dataset page's explicit score-floor analysis; Streamlit does not
reimplement the estimator or redraw the figures. The build is intentionally
explicit because it scans all forty successful stores. Queue-wide attempt
accounting remains unavailable, and the original stores stay read-only.
## Immutable performance evidence
`reporting.performance_evidence` owns evaluator-result validation, the digest
of the exact input bytes, and ordered publication to W&B and OMX. It is
auxiliary experiment reporting; it does not define a learning objective or
save model weights. The cohesive `record_checkpoint` operation hides the
pending → publish/readback → final checkpoint sequence. A failed publication
leaves the checkpoint blocked.
Validate a version-two evaluator result without publication:
```python
from pathlib import Path
from aria_nbv.reporting.performance_evidence import record_checkpoint
outcome = record_checkpoint(Path("result.json"), dry_run=True)
```
The existing `aria_nbv/scripts/record_performance_checkpoint.py` CLI remains
available. Its `--dry-run` option validates and hashes without W&B or OMX
calls. Formal publication uses `PathConfig().root` for both OMX subprocesses,
independently of the caller's working directory. Result bytes, provenance and
metric values remain evaluator-owned; publication never rewrites the result.
Python callers migrate from `aria_nbv.performance_checkpoint` to the explicit
`aria_nbv.reporting.performance_evidence` leaf. The reporting root does not
re-export this separate workflow.
Proof from the repository root:
```sh
cd aria_nbv
uv run pytest tests/test_performance_checkpoint.py
```
The tests cover exact-byte digests, invalid/nonfinite results, publication
ordering and failure, W&B readback, and configured-root execution from an
unrelated working directory. External services are mocked.
## Nested surface-reference evidence
For a completed fixed-candidate 16,384/65,536 surface extension, run
`python -m aria_nbv.reporting.surface_reference --assignment ASSIGNMENT
--run-dir RUN --output-dir NEW_OUTPUT`. The Oracle reader verifies the
historical v1 or current v3 assignment, receipt, source-attempt, and
result-attempt bindings before returning matched scores. Mixed versions and
changed aggregate verdicts fail admission. The new report-v2 summary records
the producer comparison schema, source hashes, scene support denominators,
and the Oracle's independent top-set regret. Constant-score strata have
undefined rank correlation and appear as null aggregates when unsupported.
Use a new output directory for each reduction; retained measurements and
earlier reports remain immutable. Scene means count physical scenes, not
independent candidate rows or corpus admission.
## Retained recipe-family evidence
For retained family opportunity, run
`python -m aria_nbv.reporting.recipe_families --manifest INPUTS
--output-dir OUTPUT`. The manifest names exact completed stores, source
receipt elapsed times and chain lengths; the export records the manifest's exact
SHA-256 digest. The reader acquires one canonical typed recipe report per plan,
scans the named stores, reacquires the report, and rejects any snapshot drift.
Canonical plan, report and store identities are the evidence authority.
Additional context fields in the input manifest are not treated as evidence and
are not copied to the output. A display cohort must share measurement and
evaluator identities, while each displayed arm must retain one exact generation
cohort. The reader reuses `rollouts.inspection.candidate_audit_rows`.
Scene-level validity, best finite labelled gain, invalidity reasons and factual
H8/H12/H16 starts retain cohort boundaries. Removing a family from an already
sampled shell is a diagnostic only; it does not redraw poses or estimate policy
return. Tail-start rates condition on successful stores and their observed
execution time; the export retains full plan dispositions so rejected, failed
and unreached units remain visible. These static research figures are separate from the immutable
`ReportSnapshot` path used by the scientific report builder.
## W&B ownership
Run discovery, sampled history, local media, exploratory plots and the existing
exact report acquisition transaction live in [wandb](reporting.wandb.qmd). The report
builder remains the public entrypoint for immutable scientific evidence.
## Study consumers and reproduction
These standalone exports use admitted domain products; they have distinct output
contracts from `ReportSnapshot`. Source docstrings own exact admission and failure
rules, and experiment publications own frozen protocols, results and receipts.
Create fresh output directories, hydrate any required LFS payloads, and use the
current package implementation rather than archived producers. The complete
pre-consolidation descriptions remain at [this immutable revision](https://github.com/JanDuchscherer104/ARIA-NBV/blob/9d8b6abc0e81a6e94f64a09c10ecb73c002aca96/aria_nbv/aria_nbv/reporting/README.md#bounded-generation-throughput-evaluator).
### Bounded generation-throughput evaluator
[The evaluator](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/reporting/generation_throughput.py) consumes the Oracle-owned
[source-contrast reader](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/oracle/pipelines/source_contrast_report.py):
```sh
python -m aria_nbv.reporting.generation_throughput assignment.json \
--brief research-brief.md --output-dir NEW_OUTPUT \
--goal-slug generation-throughput-roi-20261003
```
Schema-v2 evidence passes only the prospectively frozen three-scene, two-block
log-cost contrast; missing costs stay unavailable. This engineering decision is
not a population significance test or corpus admission. Captured per-step 48px
causal equality differs from persisted float16 240px depth. Publication/readback
through `scripts/record_performance_checkpoint.py` and independent review are
separate gates; see the performance-evidence workflow above.
### Portable throughput attribution profiles
```sh
python -m aria_nbv.reporting.generation_profiles inputs.json --output-dir NEW_OUTPUT
```
[The profile exporter](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/reporting/generation_profiles.py) validates canonical recipe,
renderer, phase and worker receipts. The [E33 publication](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-10-generation/generation_throughput_attribution_20261003/README.md)
owns the six-attempt protocol, tables, reproduction and unchanged negative
optimization decision. Recorded endpoint/observer audits are not recomputed by
this exporter. Missing outcomes remain explicit; unsealed profiler probes and
overlapping clocks establish neither additive attribution nor production gain.
### Origin-aware E28 selector publication
[The selector reader](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/reporting/selector_screen.py) admits
`read_selector_bundle(bundle, expected_manifest_sha256=...)` with an external
manifest pin. [The E28 publication](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-09-research/selector_screen_20260930/README.md)
and its [terminal supplement](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-09-research/selector_screen_20260930/continuity_sensitivity/e28/README.md)
own protocol, captured support and historical outcomes. Cold readback verifies
consumed publication/plan/writer bytes; ancillary manifest entries remain
explicitly unverified and are not admitted evidence. Historical capture and
current readback identities stay separate. The live reader additionally checks
canonical recipe admission and original stores.
```sh
python -m aria_nbv.reporting.selector_figures --bundle BUNDLE \
--manifest-sha256 SHA256 --output NEW_OUTPUT
python -m aria_nbv.reporting.selector_geometry --bundle BUNDLE \
--manifest-sha256 SHA256 --output NEW_OUTPUT
```
Both consumers use the admitted readout, without another reducer or sampler.
Missing, failed and unreached arms retain intended denominators; factual states
and shadows retain originating arms. Conditional survivor means are not
all-attempt effects. Untimed geometry does not establish human naturalness or
policy return. The separate E29 terminal-effect delta remains deferred under
[issue #433](https://github.com/JanDuchscherer104/ARIA-NBV/issues/433); these
entrypoints do not revive its historical combined E28/E29 adapter.
### Matched H16 renderer figures and physical paths
[Rollout figures](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/reporting/renderer_rollout_figures.py) and
[trajectory figures](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/reporting/renderer_trajectory_figures.py) consume the
[canonical renderer reader](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/aria_nbv/oracle/pipelines/renderer_experiment_report.py).
The [E31 publication](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-10-generation/renderer_h16_equivalence_20261002/README.md)
preserves the failed checkpoint; [E32](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-10-generation/renderer_h16_equivalence_camera_stable_20261002/README.md)
owns the later qualified recipe and its bounded descriptive cost evidence.
From the repository root:
```sh
PYTHONPATH=aria_nbv python aria_nbv/scripts/verify_renderer_h16_readback.py \
--plan PLAN --bindings BINDINGS --output NEW_READBACK.json
PYTHONPATH=aria_nbv python aria_nbv/scripts/plot_renderer_h16_trajectories.py \
--analysis NEW_READBACK.json --runtime-worktree "$PWD" --output NEW_FIGURES
```
Figures preserve intended attempts and unavailable measurements; seeds reduce
within physical scenes before descriptive scene means. Qualified timing requires
successful full-horizon arms and explicit domain qualification. Positions are
metres in the initial target-aligned, world-Z-up frame; discrete bend/yaw/radius
are geometric proxies, not timed motion or perceptual naturalness. Use
`--checkpoint-stopped` for plan-bound genuinely unreached intentions. Exports
create directories exclusively and record hashes; they add no acquisition,
Streamlit consumer, whole-campaign efficiency claim or corpus promotion.
### Transport retained H16 acquisition evidence
From the repository root, the [transport adapter](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/aria_nbv/scripts/package_renderer_h16_evidence.py)
provides:
```sh
python aria_nbv/scripts/package_renderer_h16_evidence.py pack --source ROOT --output BUNDLE
python aria_nbv/scripts/package_renderer_h16_evidence.py hydrate --source BUNDLE --output ROOT
```
[The E31 portability supplement](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-10-generation/renderer_h16_portability_20261002/README.md)
owns its dated cold-readback proof. The adapter verifies inventory/member hashes,
keeps original bytes and absolute identities, requires hash-bound relocated config
copies, and admits through the canonical recipe reader. Inputs must remain
immutable; digest/drift checks do not provide an atomic snapshot. Symlinks and
special files fail closed. Twenty terminal intentions, or an explicit
`--checkpoint-stopped` subset with terminal receipts and genuinely unreached
intentions, are required; interrupted or receipt-less stores are not closure.
Transport closure does not establish renderer equivalence, complete campaign
accounting, corpus admission or promotion.
### Consolidated scorer studies
Config-v2 `scorer_study` selects Q1 or continuing-QH evidence through an
externally pinned archive. Use `.configs/diagnostics/scorer-q1-report.toml` or
`scorer-qh-report.toml` with `nbv-report build --config ... --output NEW_DIRECTORY`;
the `reporting` extra supplies static-export dependencies. Acquire once, then
`read_report_bundle` reconstructs the frozen snapshot without reopening sources.
[Scorer presentation](reporting.scorer.qmd) owns current consumer/output contracts;
[Lightning study admission](lightning.finite_horizon.studies.qmd) owns
support, version and checkpoint-role validation. The [scorer publication](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/2026-10-research/scorer/README.md)
owns sealed identities, historical producer provenance and scientific
qualifications. Relocation does not rewrite sealed configuration identities.
Q1 retains physical-scene pairing, seed/checkpoint conditioning and intervals;
interrupted QH retains failure/charge status with no fabricated completed
comparisons. These exposed-development sources remain pilot-only.
### Development generation thesis projection
`generation_thesis.write_generation_thesis_projection` consumes the immutable
cold readback returned by `read_generation_posthoc_report`, plus an independently
verified historical R1 member map. It writes a fresh closed projection and two
165 mm SVGs; the sibling `.sha256` file is the external manifest trust anchor.
`read_generation_thesis_projection(..., expected_manifest_sha256=...)` verifies
all bytes without opening source stores. The schema remains a separate
`aria-nbv-generation-thesis-projection-v1` development product.
The family figure separates Q-train yield from actor-label exclusive-best state
fraction. Ties remain non-exclusive; a scene with any state lacking finite
actor-label gains has an unavailable exclusive-best fraction. The acquisition
figure retains native scene-step Q-train means and finite actor/oracle-label
p90–p10 spans, with explicit finite/missing state support. Both figures show
physical-scene dots and equally weighted scene centers; acquisition IQRs are
linear-quantile descriptive spread. Sparse reached/intended annotations use only
the native H1/2/3/5/8/12/16 risk sets. Historical TRAIN, new-root TRAIN and exposed
validation remain separate, while the Mac diagnostic remains in coverage only.
Qualified lineage, unchanged nominations and limitations accompany the figures.
No fit, resampling, recipe selection, causal claim or corpus promotion is added.
Verify this seam with `tests/reporting/test_generation_thesis.py` together with
the native generation reporting and rollout post-hoc tests.
## Sealed-file acquisition
Native bundles, generation post-hoc/thesis products and compact public Q1
publications share descriptor-relative ordinary-file acquisition. Each reader
retains its manifest, JSON, scientific-source and external-pin rules. Native
bundles reject aliases throughout the root path; generation and compact public
readers preserve their supported ancestor aliases while rejecting a symlink at
the terminal root. Authenticated products consume the captured bytes rather
than reopening asset paths. Native Q1's historical path-based reader remains a
separate format and is not covered by this acquisition guarantee.
## Scientific reading path
The [experiment maintenance contract](https://github.com/JanDuchscherer104/ARIA-NBV/blob/main/experiments/README.md#report-reading-path) owns the report and mission outline. Producers use the private `_presentation.render_document` shell and adjacent `report.css` for standalone, responsive documents; these helpers do not admit evidence or compute statistics. Keep native measurements and scientific table/figure data stable across presentation revisions, with distinct authored-context and delivery identities. Historical sealed outputs remain unchanged.
Maintained benchmark and R1 presentation live in `reporting.m5_benchmark` and `reporting.r1_supervision`; their existing command-line entry points remain adapters.
## Figure identity
`figure_identity` resolves callable CAP handles, semantic output keys and exact
sealed-result FIG identities from the generated catalog projection. It imports
no scientific plotting implementation and retains no figure, tensor, dataset or
builder instance. `figure_origins` separately maps supported **current-builder**
report outputs through their exact section/result contracts. It cannot recover
unknown historical producer revisions from a retained recipe. Neither owner
changes sealed report bytes or certifies scientific acceptance.
The [gallery registration workflow](../figures/galleries/README.md#producer-identity-and-completeness) owns metadata generation, source/consumer/asset
coverage and handle-first lookup. Test the runtime at
`tests/reporting/test_figure_identity.py` and current report-origin mappings at
`tests/reporting/test_figure_origins.py`.
### Archived Plotly display compatibility
`plotly_decode.decode_frozen_plotly` strictly decodes saved specifications first.
For older Plotly templates, it may omit unsupported default trace families that
are absent from both data and animation frames, and obsolete style-only Mapbox
template defaults when no Mapbox trace or explicit Mapbox layout is used. It
never removes active traces, used styles or explicit layout settings. Other
validation errors remain errors. This adaptation affects an in-memory display
copy; retained specifications and sealed bundle hashes remain unchanged.
Streamlit identifies omitted template paths beside the chart. Static rendering
records the decoder policy/source in the exporter fingerprint, and gallery build
logs identify the omitted paths. The exporter honours an explicit `BROWSER_PATH`
before automatic browser discovery. Optional renderer/browser preparation is an
explicit environment step; reading metadata never downloads or launches them.
<!-- /quartodoc-package-readme -->
## Classes
| Name | Description |
| --- | --- |
| [NamedQuantity](#aria_nbv.reporting.NamedQuantity) | One named scalar linked to provenance and optional canonical notation. |
| [ReportColumn](#aria_nbv.reporting.ReportColumn) | One ordered table column and its canonical notation binding. |
| [ReportExplanation](#aria_nbv.reporting.ReportExplanation) | Presentation-free interpretation attached to one scientific result. |
| [ReportFigure](#aria_nbv.reporting.ReportFigure) | Canonical Plotly figure shared by Streamlit and static export. |
| [ReportRequest](#aria_nbv.reporting.ReportRequest) | Optional section/result selection for one explicit build dispatch. |
| [ReportSnapshot](#aria_nbv.reporting.ReportSnapshot) | Immutable transaction consumed by Streamlit and static/Typst export. |
| [ReportTable](#aria_nbv.reporting.ReportTable) | Canonical immutable table with typed scalar cells. |
| [ReportWriteReceipt](#aria_nbv.reporting.ReportWriteReceipt) | Identity of one atomically published report directory. |
| [ScientificReportBuilder](#aria_nbv.reporting.ScientificReportBuilder) | Materialize one validated recipe into a sealed report snapshot. |
| [ScientificReportConfig](#aria_nbv.reporting.ScientificReportConfig) | Build one immutable, provenance-closed scientific report snapshot. |
| [ScientificReportError](#aria_nbv.reporting.ScientificReportError) | Contextual failure crossing the reporting interface. |
| [SourceIdentity](#aria_nbv.reporting.SourceIdentity) | Frozen identity and provenance for one materialized evidence source. |
| [VerifiedReportBundle](#aria_nbv.reporting.VerifiedReportBundle) | A cold-verified snapshot and exact bundle bytes for static consumers. |
### NamedQuantity { #aria_nbv.reporting.NamedQuantity }
```python
reporting.NamedQuantity(id, value, unit, n, aggregation, source_ids, symbol_id)
```
One named scalar linked to provenance and optional canonical notation.
#### Attributes
| Name | Description |
| --- | --- |
| [id](#aria_nbv.reporting.NamedQuantity.id) | Globally unique result identifier. |
| [value](#aria_nbv.reporting.NamedQuantity.value) | Typed scalar; missing values remain ``None`` rather than fabricated zeroes. |
| [unit](#aria_nbv.reporting.NamedQuantity.unit) | Physical or reporting unit, when meaningful. |
| [n](#aria_nbv.reporting.NamedQuantity.n) | Population size underlying the quantity, when available. |
| [aggregation](#aria_nbv.reporting.NamedQuantity.aggregation) | Code-owned aggregation name such as ``mean`` or ``count``. |
| [source_ids](#aria_nbv.reporting.NamedQuantity.source_ids) | Source identities that support the value. |
| [symbol_id](#aria_nbv.reporting.NamedQuantity.symbol_id) | Canonical Typst symbol ID; ``None`` is an explicit operational opt-out. |
### ReportColumn { #aria_nbv.reporting.ReportColumn }
```python
reporting.ReportColumn(id, symbol_id)
```
One ordered table column and its canonical notation binding.
#### Attributes
| Name | Description |
| --- | --- |
| [id](#aria_nbv.reporting.ReportColumn.id) | Persisted column identifier. |
| [symbol_id](#aria_nbv.reporting.ReportColumn.symbol_id) | Canonical Typst symbol ID; ``None`` is an explicit operational opt-out. |
### ReportExplanation { #aria_nbv.reporting.ReportExplanation }
```python
reporting.ReportExplanation(
metric_id,
question,
answer,
narrative,
evidence_role,
population,
unit,
support_result_ids,
source_fields,
theory,
)
```
Presentation-free interpretation attached to one scientific result.
The explanation names supporting result IDs instead of rebuilding factual
counts or reductions. Its theory field carries registry identifiers only;
:func:`aria_nbv.reporting.notation.resolve_theory` validates and projects
those identifiers from the generated canonical notation owner.
#### Attributes
| Name | Description |
| --- | --- |
| [metric_id](#aria_nbv.reporting.ReportExplanation.metric_id) | Persisted metric identifier whose values the narrative interprets. |
| [question](#aria_nbv.reporting.ReportExplanation.question) | Reader-facing question answered by the result. |
| [answer](#aria_nbv.reporting.ReportExplanation.answer) | Concise interpretation of the observed result. |
| [narrative](#aria_nbv.reporting.ReportExplanation.narrative) | Ordered supporting paragraphs covering meaning and limitations. |
| [evidence_role](#aria_nbv.reporting.ReportExplanation.evidence_role) | Information role of the interpreted values. |
| [population](#aria_nbv.reporting.ReportExplanation.population) | Actual rows or entities summarized by the result. |
| [unit](#aria_nbv.reporting.ReportExplanation.unit) | Human-readable unit or dimensionless scale of the metric. |
| [support_result_ids](#aria_nbv.reporting.ReportExplanation.support_result_ids) | Report quantity or table IDs carrying factual support and missingness. |
| [source_fields](#aria_nbv.reporting.ReportExplanation.source_fields) | Persisted source fields from which the result was reduced. |
| [theory](#aria_nbv.reporting.ReportExplanation.theory) | Required canonical equation, symbol, and glossary identifiers. |
### ReportFigure { #aria_nbv.reporting.ReportFigure }
```python
reporting.ReportFigure(
id,
plotly_json,
source_ids,
source_result_ids,
symbol_ids,
uses_webgl,
)
```
Canonical Plotly figure shared by Streamlit and static export.
#### Attributes
| Name | Description |
| --- | --- |
| [id](#aria_nbv.reporting.ReportFigure.id) | Globally unique result identifier. |
| [plotly_json](#aria_nbv.reporting.ReportFigure.plotly_json) | UTF-8 canonical Plotly JSON with sorted keys and no trace UIDs. |
| [source_ids](#aria_nbv.reporting.ReportFigure.source_ids) | Source identities supporting the figure. |
| [source_result_ids](#aria_nbv.reporting.ReportFigure.source_result_ids) | Snapshot quantity/table results consumed by the figure builder. |
| [symbol_ids](#aria_nbv.reporting.ReportFigure.symbol_ids) | Canonical symbol IDs used by axes, legend, or explanation. |
| [uses_webgl](#aria_nbv.reporting.ReportFigure.uses_webgl) | Whether static export must use the configured raster profile. |
### ReportRequest { #aria_nbv.reporting.ReportRequest }
```python
reporting.ReportRequest(section_ids=(), result_ids=())
```
Optional section/result selection for one explicit build dispatch.
#### Attributes
| Name | Description |
| --- | --- |
| [section_ids](#aria_nbv.reporting.ReportRequest.section_ids) | Selected section IDs; empty means every configured section. |
| [result_ids](#aria_nbv.reporting.ReportRequest.result_ids) | Selected exact result IDs; empty means every result in selected sections. |
### ReportSnapshot { #aria_nbv.reporting.ReportSnapshot }
```python
reporting.ReportSnapshot(
schema_version,
evidence_status,
config_sha256,
notation_sha256,
source_identities,
quantities,
tables,
figures,
resolved_recipe,
snapshot_sha256,
)
```
Immutable transaction consumed by Streamlit and static/Typst export.
Exporters accept this object, never a report config. Consequently an export
cannot reacquire W&B history, reread a rollout store, or recompute a figure
after the user has previewed it.
#### Attributes
| Name | Description |
| --- | --- |
| [schema_version](#aria_nbv.reporting.ReportSnapshot.schema_version) | Closed snapshot schema version. |
| [evidence_status](#aria_nbv.reporting.ReportSnapshot.evidence_status) | Evidence class enforced during acquisition and publication. |
| [config_sha256](#aria_nbv.reporting.ReportSnapshot.config_sha256) | Digest of the canonical validated recipe. |
| [notation_sha256](#aria_nbv.reporting.ReportSnapshot.notation_sha256) | Digest of the generated canonical notation registry. |
| [source_identities](#aria_nbv.reporting.ReportSnapshot.source_identities) | Source identities sorted by stable ID. |
| [quantities](#aria_nbv.reporting.ReportSnapshot.quantities) | Named quantities sorted by result ID. |
| [tables](#aria_nbv.reporting.ReportSnapshot.tables) | Tables sorted by result ID. |
| [figures](#aria_nbv.reporting.ReportSnapshot.figures) | Figures sorted by result ID. |
| [resolved_recipe](#aria_nbv.reporting.ReportSnapshot.resolved_recipe) | Validated TOML recipe frozen at build time. |
| [snapshot_sha256](#aria_nbv.reporting.ReportSnapshot.snapshot_sha256) | Digest of all preceding snapshot fields. |
#### Methods
| Name | Description |
| --- | --- |
| [create](#aria_nbv.reporting.ReportSnapshot.create) | Canonicalize ordering and seal a snapshot with its content digest. |
| [result](#aria_nbv.reporting.ReportSnapshot.result) | Return one result by stable ID or raise ``KeyError``. |
##### create { #aria_nbv.reporting.ReportSnapshot.create }
```python
reporting.ReportSnapshot.create(
evidence_status,
config_sha256,
notation_sha256,
source_identities,
quantities,
tables,
figures,
resolved_recipe,
schema_version='aria-nbv-report-snapshot-v1',
)
```
Canonicalize ordering and seal a snapshot with its content digest.
##### result { #aria_nbv.reporting.ReportSnapshot.result }
```python
reporting.ReportSnapshot.result(result_id)
```
Return one result by stable ID or raise ``KeyError``.
### ReportTable { #aria_nbv.reporting.ReportTable }
```python
reporting.ReportTable(id, columns, rows, source_ids)
```
Canonical immutable table with typed scalar cells.
#### Attributes
| Name | Description |
| --- | --- |
| [id](#aria_nbv.reporting.ReportTable.id) | Globally unique result identifier. |
| [columns](#aria_nbv.reporting.ReportTable.columns) | Ordered column contract. |
| [rows](#aria_nbv.reporting.ReportTable.rows) | Canonical row-major scalar values. |
| [source_ids](#aria_nbv.reporting.ReportTable.source_ids) | Source identities supporting the table. |
### ReportWriteReceipt { #aria_nbv.reporting.ReportWriteReceipt }
```python
reporting.ReportWriteReceipt(
destination,
manifest_sha256,
snapshot_sha256,
assets,
)
```
Identity of one atomically published report directory.
#### Attributes
| Name | Description |
| --- | --- |
| [destination](#aria_nbv.reporting.ReportWriteReceipt.destination) | Absolute promoted report directory. |
| [manifest_sha256](#aria_nbv.reporting.ReportWriteReceipt.manifest_sha256) | Digest of the exact exported manifest bytes. |
| [snapshot_sha256](#aria_nbv.reporting.ReportWriteReceipt.snapshot_sha256) | Digest of the immutable input snapshot. |
| [assets](#aria_nbv.reporting.ReportWriteReceipt.assets) | Sorted relative asset path and SHA-256 pairs. |
### ScientificReportBuilder { #aria_nbv.reporting.ScientificReportBuilder }
```python
reporting.ScientificReportBuilder(
config,
*,
wandb_api=None,
root=None,
_recipe_evidence=None,
_measurement_evidence=None,
_qh_evidence=None,
)
```
Materialize one validated recipe into a sealed report snapshot.
Construction stores configuration and injected clients only. Expensive W&B
and rollout reads occur exclusively in :meth:`build`, which Streamlit and
CLI callers invoke explicitly. Each configured source family is acquired at
most once per build and reused by all selected sections.
#### Methods
| Name | Description |
| --- | --- |
| [build](#aria_nbv.reporting.ScientificReportBuilder.build) | Acquire selected evidence once and return a provenance-closed snapshot. |
##### build { #aria_nbv.reporting.ScientificReportBuilder.build }
```python
reporting.ScientificReportBuilder.build(request=None)
```
Acquire selected evidence once and return a provenance-closed snapshot.
### ScientificReportConfig { #aria_nbv.reporting.ScientificReportConfig }
```python
reporting.ScientificReportConfig()
```
Build one immutable, provenance-closed scientific report snapshot.
The config is the durable recipe shared by CLI and Streamlit. Calling
:meth:`setup_target` injects external clients and canonical-notation root;
parsing or describing the config performs no W&B or rollout payload reads.
#### Attributes
| Name | Description |
| --- | --- |
| [schema_version](#aria_nbv.reporting.ScientificReportConfig.schema_version) | Closed recipe schema version. |
| [evidence_status](#aria_nbv.reporting.ScientificReportConfig.evidence_status) | Scientific evidence class enforced by source and export gates. |
| [sources](#aria_nbv.reporting.ScientificReportConfig.sources) | Existing evidence-store selections; credentials and clients are excluded. |
| [sections](#aria_nbv.reporting.ScientificReportConfig.sections) | Closed, code-owned report products in author-selected order. |
| [theme](#aria_nbv.reporting.ScientificReportConfig.theme) | Shared interactive/static Plotly presentation settings. |
| [export](#aria_nbv.reporting.ScientificReportConfig.export) | Static renderer settings recorded in the exported manifest. |
#### Methods
| Name | Description |
| --- | --- |
| [setup_target](#aria_nbv.reporting.ScientificReportConfig.setup_target) | Construct a builder with late-bound external adapters. |
| [bind_rollout_stores](#aria_nbv.reporting.ScientificReportConfig.bind_rollout_stores) | Return a validated recipe bound to an explicit rollout population. |
| [rollout_s2_section](#aria_nbv.reporting.ScientificReportConfig.rollout_s2_section) | Return one configured S2 section or fail before evidence acquisition. |
| [validate_build_readiness](#aria_nbv.reporting.ScientificReportConfig.validate_build_readiness) | Fail before client construction when selected source selectors are incomplete. |
##### setup_target { #aria_nbv.reporting.ScientificReportConfig.setup_target }
```python
reporting.ScientificReportConfig.setup_target(wandb_api=None, root=None)
```
Construct a builder with late-bound external adapters.
##### bind_rollout_stores { #aria_nbv.reporting.ScientificReportConfig.bind_rollout_stores }
```python
reporting.ScientificReportConfig.bind_rollout_stores(
store_paths,
*,
sidecar_paths=(),
)
```
Return a validated recipe bound to an explicit rollout population.
This immutable composition helper is shared by interactive previews and
report automation. It replaces only the rollout source selection;
section analysis, Plotly theme, evidence status, export policy, and any
configured W&B source remain unchanged.
##### rollout_s2_section { #aria_nbv.reporting.ScientificReportConfig.rollout_s2_section }
```python
reporting.ScientificReportConfig.rollout_s2_section(section_id)
```
Return one configured S2 section or fail before evidence acquisition.
##### validate_build_readiness { #aria_nbv.reporting.ScientificReportConfig.validate_build_readiness }
```python
reporting.ScientificReportConfig.validate_build_readiness(section_ids=())
```
Fail before client construction when selected source selectors are incomplete.
### ScientificReportError { #aria_nbv.reporting.ScientificReportError }
```python
reporting.ScientificReportError(code, message, result_id=None, source_id=None)
```
Contextual failure crossing the reporting interface.
#### Attributes {.doc-section .doc-section-attributes}
| Name | Type | Description |
|-----------|----------------------------------------------------------------|-------------------------------------------------------------|
| code | [ReportErrorCode](`aria_nbv.reporting.errors.ReportErrorCode`) | Stable machine-readable category. |
| message | [str](`str`) | Human-readable failure detail. |
| result_id | [str](`str`) \| None | Optional result whose construction or export failed. |
| source_id | [str](`str`) \| None | Optional source whose acquisition or identity check failed. |
### SourceIdentity { #aria_nbv.reporting.SourceIdentity }
```python
reporting.SourceIdentity(id, kind, sha256, provenance)
```
Frozen identity and provenance for one materialized evidence source.
#### Attributes
| Name | Description |
| --- | --- |
| [id](#aria_nbv.reporting.SourceIdentity.id) | Stable recipe-local source identifier. |
| [kind](#aria_nbv.reporting.SourceIdentity.kind) | Owning source family. |
| [sha256](#aria_nbv.reporting.SourceIdentity.sha256) | Digest of the normalized source identity and acquired evidence. |
| [provenance](#aria_nbv.reporting.SourceIdentity.provenance) | Sorted non-secret provenance key/value pairs. |
### VerifiedReportBundle { #aria_nbv.reporting.VerifiedReportBundle }
```python
reporting.VerifiedReportBundle(snapshot, manifest_sha256, file_bytes)
```
A cold-verified snapshot and exact bundle bytes for static consumers.
The file set is captured in the same read transaction that validates the
manifest, paths, asset digests, and snapshot. Consumers can publish HTML
and static fallbacks without reopening the source bundle or raw evidence.
#### Attributes
| Name | Description |
| --- | --- |
| [snapshot](#aria_nbv.reporting.VerifiedReportBundle.snapshot) | Typed snapshot reconstructed from the validated bundle bytes. |
| [manifest_sha256](#aria_nbv.reporting.VerifiedReportBundle.manifest_sha256) | SHA-256 of the exact ``manifest.json`` bytes in ``file_bytes``. |
| [file_bytes](#aria_nbv.reporting.VerifiedReportBundle.file_bytes) | Sorted bundle-relative POSIX paths and captured bytes for every file. |
## Functions
| Name | Description |
| --- | --- |
| [read_report_bundle](#aria_nbv.reporting.read_report_bundle) | Verify a current report bundle and reconstruct its sealed snapshot. |
| [read_report_bundle_with_assets](#aria_nbv.reporting.read_report_bundle_with_assets) | Read a verified report with its exact files for source-free publishing. |
| [theory_for_initial_metric](#aria_nbv.reporting.theory_for_initial_metric) | Return canonical references for the first reward/reconstruction metrics. |
| [write_report_snapshot](#aria_nbv.reporting.write_report_snapshot) | Atomically export the exact supplied snapshot without source access. |
### read_report_bundle { #aria_nbv.reporting.read_report_bundle }
```python
reporting.read_report_bundle(path)
```
Verify a current report bundle and reconstruct its sealed snapshot.
Verification rejects unknown schema versions, non-canonical JSON, unsafe
or duplicate paths, symlinks and special files, undeclared or missing
files, digest mismatches, and malformed report values. The reconstructed
:class:`ReportSnapshot` then verifies the report's ``snapshot_sha256``
against the exact recipe, quantities, tables, sources, and Plotly bytes.
#### Parameters {.doc-section .doc-section-parameters}
| Name | Type | Description | Default |
|--------|----------------------------------------|------------------------------------------------------|------------|
| path | [Path](`pathlib.Path`) \| [str](`str`) | Directory produced by :func:`write_report_snapshot`. | _required_ |
#### Returns {.doc-section .doc-section-returns}
| Name | Type | Description |
|--------|---------------------------------------------------------------|------------------------------------------------------------|
| | [ReportSnapshot](`aria_nbv.reporting.results.ReportSnapshot`) | The immutable snapshot represented by the verified bundle. |
#### Raises {.doc-section .doc-section-raises}
| Name | Type | Description |
|--------|----------------------------------------------------------------------------|-----------------------------------------------|
| | [ScientificReportError](`aria_nbv.reporting.errors.ScientificReportError`) | If the path is not a complete current bundle. |
### read_report_bundle_with_assets { #aria_nbv.reporting.read_report_bundle_with_assets }
```python
reporting.read_report_bundle_with_assets(path)
```
Read a verified report with its exact files for source-free publishing.
### theory_for_initial_metric { #aria_nbv.reporting.theory_for_initial_metric }
```python
reporting.theory_for_initial_metric(metric)
```
Return canonical references for the first reward/reconstruction metrics.
The identifiers select definitions from the generated registry. Formulas
remain owned by ``docs/typst/shared`` and are never copied into Python.
### write_report_snapshot { #aria_nbv.reporting.write_report_snapshot }
```python
reporting.write_report_snapshot(
snapshot,
destination,
*,
width=1400,
height=900,
scale=2.0,
two_dimensional_format='svg',
webgl_format='png',
transparent_background=False,
renderer=None,
)
```
Atomically export the exact supplied snapshot without source access.
Ordinary 2D figures use SVG by default. WebGL/3D figures use high-
resolution PNG because vector containers rasterize their WebGL layers.
``transparent_background`` applies a renderer-only transparent canvas to
PNG assets while preserving the canonical Plotly specification verbatim.
A render or validation failure removes only the staging directory and keeps
the previously published destination intact. An existing corrupt bundle
raises its admission error and remains untouched; it is never a cache miss.