# C13 — Hot-reload is authoring-only; deploy is frozen **Guarantee.** A node/strategy is authored as a native Rust `cdylib`, hot-reloaded during the authoring loop (Rust-ABI; host and node built with the same toolchain). The live/deploy bot is a statically-linked, versioned, frozen artifact. **Forbids.** Hot-swapping a running live bot; loading third-party / foreign- toolchain plugins. **Why.** Hot-reload makes the research loop fast; a live artifact must be frozen and reproducible (audit trail: this bot = this commit). A sweep pays no hot-reload tax — params are runtime data ([C12](c12-atomic-sim-unit.md)), so the cdylib loads once. ## Current state The authoring-loop half is realized; the frozen live/deploy artifact is not yet built. A research project compiles to an external cdylib exporting one symbol, `AURA_PROJECT`, a two-tier `#[repr(C)]` `ProjectDescriptor` (`aura-core::project`, `crates/aura-core/src/project.rs`, emitted by the `aura_project!` macro). A **C tier** — `magic` (`AURAPROJ`), `descriptor_version`, the rustc-version and aura-core-version stamps, the namespace, all C-compatible field types — is validated **before** any Rust-ABI field is touched; a **Rust tier** — the vocabulary resolver `fn(&str) -> Option` and the enumerable type-id list — is read only once both stamps match. The stamp cannot certify the channel it rides on, so it does not depend on the Rust ABI it certifies; both stamps are baked at *aura-core* compile time (build.rs, per consuming build), so host and dylib each carry their own side's truth. "Hot-reload" reads, in v1, as **per-invocation load of the freshest build**: the author runs `cargo build`, and the next `aura` invocation locates the artifact via `cargo metadata` (debug default, `--release` opt-in) and loads it **load-and-hold** — the `Library` is leaked, never unloaded, so its `'static` strings and fn-pointers stay valid (`aura-runner::project::load`, `crates/aura-runner/src/project.rs`). `validate_c_tier` checks the four stamps front-to-back; a mismatch of either version stamp refuses with exit 1 naming both sides (`ProjectError::Incompatible`). The project vocabulary is charter-checked at load (`check_charter`): non-empty namespace, every id `::`-prefixed, no duplicate, no collision against the std vocabulary, list↔resolver cross-check — the invariant-9 data-plane discipline (the [C24](c24-blueprint-data.md) enforcement-shift note) enforced at this one seam. **Scope boundary.** Load-and-hold is trivially sound only because the CLI is a one-shot process. A future long-running host — the local-server thread ([C22](c22-playground-traces.md)) — must re-solve reload by host restart or subprocess isolation, never in-process unload. ## See also - [C12](c12-atomic-sim-unit.md) — params are runtime data, so the cdylib loads once across a sweep - [C16](c16-engine-project-split.md) — engine/project separation; the per-case dependency policy the cdylib boundary serves - [C22](c22-playground-traces.md) — the long-running host that must re-solve reload - [C24](c24-blueprint-data.md) — the enforcement-shift note whose data-plane discipline the charter check applies > History: [c13-hot-reload-frozen-deploy.history.md](c13-hot-reload-frozen-deploy.history.md)