AGENTS.md@src/gnn/execute/stan · git:20260906.e62b9e9 · 2026-09-06 · sha256 2b8737ce155b3191

AGENTS.md@src/gnn/execute/stan git:20260906.e62b9e9A

Immutable. This exact content is served forever at /api/v1/blob/2b8737ce155b3191.

# Stan Executor (`src/gnn/execute/stan/`)

## Purpose

Execute the Stan artifacts produced by `src/gnn/render/stan/`. Each rendered model
ships a `<stem>_stan.stan` program and a sibling `<stem>_stan.py` cmdstanpy
driver. Step 12 discovers the driver like any other Python framework script
(framework directory `stan/`, output env var `STAN_OUTPUT_DIR`) and runs it.

## What the driver does

1. Simulates a trajectory from the GNN generative model with a fixed seed
   (discrete: A/B/D with a uniform-random exploratory policy; continuous:
   LGSSM with an in-loop Kalman filter and optional closed-loop control).
2. Writes `<stem>_stan_data.json`, compiles the `.stan` program with CmdStan
   (`cmdstanpy.CmdStanModel`), then samples with NUTS (1 chain, 300 warmup,
   300 draws, seeded) or, for discrete models with more than
   `stan_nuts_param_budget` (default 1024) simplex parameters, fits the MAP
   with L-BFGS.
3. Writes `simulation_results.json` — discrete: filtered beliefs (T×S),
   learned `A_posterior_mean` (O×S), `rhat_max_A_est`; continuous: posterior
   means/covariances, `obs_noise_scale_posterior_mean`, `rmse_vs_true`.
   Exit code 0 iff `validation.all_valid`.

## Dependency gating

`utils.framework_availability` maps `stan` → `cmdstanpy`. When it is not
importable Step 12 marks the script **skipped** with the reason
`uv sync --extra stan`. CmdStan itself is installed with
`python -c "import cmdstanpy; cmdstanpy.install_cmdstan()"`.

## Public API

| Symbol | Purpose |
|---|---|
| `is_stan_available()` | cmdstanpy importable and CmdStan toolchain found |
| `find_stan_scripts(render_dir)` | every `*_stan.py` driver under a render tree |
| `execute_stan_script(script, out_dir)` | run one driver with `STAN_OUTPUT_DIR` set |
| `run_stan_scripts(render_dir, out_dir)` | run all drivers, or skip all with a reason |

## Tests

`tests/execute/test_execute_stan.py` (skips when CmdStan is absent).