AGENTS.md@src/gnn/execute/stan · git:20261002.4fbe8e4 · 2026-10-02 · sha256 bc21ca8c4276675e
AGENTS.md@src/gnn/execute/stan git:20261002.4fbe8e4A
Immutable. This exact content never changes and is served at /api/v1/blob/bc21ca8c4276675e.
# 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 `gnn.utils.runtime_safety.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 | Both runner functions accept an optional `cancel_token`. Preconditions precede availability probes; readiness uses the shared bounded child probe in the selected Python interpreter. The shared script security gate also precedes readiness and execution; blocked scripts retain findings and never run. Missing dependencies and toolchains produce skipped receipts, while probe failures retain their cause as failed work. Cancellation and timeout use the shared subprocess envelope; per-driver receipts preserve the original error category, partial streams, and observed process cleanup evidence. The invocation deadline bounds all work; a standalone driver's timeout applies to its command and separately caps its readiness probe. ## Tests `tests/execute/test_execute_stan.py` covers discovery and actual child-process cancellation/timeout without CmdStan. Native compilation and sampling use the explicit `needs_cmdstan` integration test.