5c2ac982bc
The shell no longer defines what an aura backtest is. Tasks 1-9 of the shell-boundary cycle — structural extraction, behaviour byte-identical: - aura-runner (new; the C28 assembly position): input binding (the C26 module, moved whole), the C1-load-bearing param<->config translators, harness assembly (wrap_r / run_signal_r / run_blueprint_member and the probe/reopen cluster), axis + risk-regime conventions (bind_axes et al.), the campaign family builders + MC guards, reproduce (process::exit -> RunnerError, shell remaps to identical bytes), the measurement-run orchestration, project loading (Env / cdylib load / charter / staleness, moved whole), the coverage gap-walk (deduplicated onto interior_gap_months), and DefaultMemberRunner — the public implementation of aura_campaign::MemberRunner (ex CliMemberRunner). The MemberRunner trait stays in aura-campaign; the column still imports no harness/data-binding machinery. - aura-measurement (new; seeds C28 rung 3): the IcMetrics/IcKey vocabulary + information_coefficient, verbatim incl. serde derives (#294 duplicate-timestamp semantics move as-is, unresolved). - aura-backtest: the pure per-run scaffold (point_from_params, wf_ms_sizes / fit_wf_ms_sizes, intersect_shared_window). - shell residue: main.rs / campaign_run.rs keep argv/dispatch, argv->document translation, and presentation only; walkforward_summary_json_from_reports now calls the public aura_engine::param_stability instead of its inline twin. - worked example (crates/aura-runner/examples/world_member_run.rs): a World program runs a member backtest through the library alone. Held quality findings, adjudicated: the plan's literal pub-visibility list for binding.rs kept (cosmetic); ~20 refusal sites inside aura-runner (family/member/measure/translate) still process::exit — behaviour-identical today, conversion to RunnerError is filed forward (refs #297); rustfmt line-width drift on re-pathed call sites left for a repo-wide fmt decision. Verification: cargo test --workspace green (1471 passed, 0 failed); cargo clippy --workspace --all-targets -D warnings clean. Byte-identity is pinned by the untouched shell E2E suites (cli_run, measure_ic, run_measurement, research_docs, run_refuses_unrunnable_blueprint, tap_recording — zero assertion edits). Remaining in this cycle: full-workspace c28_layering + shell-content check, ledger amendments (C28 assembly position, C25/C14 control-surface consequence, C26 realization note). refs #295
63 lines
2.8 KiB
Rust
63 lines
2.8 KiB
Rust
//! Capture the git HEAD sha at compile time and expose it as `AURA_COMMIT`, so
|
|
//! `member::sim_optimal_manifest`'s `RunManifest.commit` is self-identifying
|
|
//! (C8/C18 audit trail: this run = this commit) even when aura-runner is
|
|
//! consumed by a downstream World program with no `aura` binary involved.
|
|
//! `cargo:rustc-env` is per-compilation-unit (aura-cli's own `build.rs` does
|
|
//! not propagate its env to this crate's `option_env!("AURA_COMMIT")`), so
|
|
//! aura-runner needs this identical capture rather than inheriting the
|
|
//! shell's. When there is no git (e.g. a packaged source tree), `AURA_COMMIT`
|
|
//! is left unset and `member.rs`'s `option_env!(...)` fallback to `"unknown"`
|
|
//! holds.
|
|
//!
|
|
//! Zero runtime/build dependency by commitment (C14/C18): we shell out to the
|
|
//! `git` already in PATH rather than pulling in a libgit crate. Verbatim twin
|
|
//! of `aura-cli/build.rs` (#295) — same repo-root depth (`crates/aura-runner`
|
|
//! sits beside `crates/aura-cli`), same capture logic, so the two crates'
|
|
//! `AURA_COMMIT` cannot disagree within one build.
|
|
|
|
use std::path::Path;
|
|
use std::process::Command;
|
|
|
|
fn main() {
|
|
// build.rs runs with CWD = the crate dir (crates/aura-runner); the repo
|
|
// root, which owns `.git`, is two levels up.
|
|
let repo_root = Path::new("../..");
|
|
let git_dir = repo_root.join(".git");
|
|
|
|
if !git_dir.exists() {
|
|
// No git: emit nothing; the `"unknown"` fallback in member.rs holds.
|
|
return;
|
|
}
|
|
|
|
// Re-run when HEAD moves or its working tree changes so AURA_COMMIT never
|
|
// goes stale across commits. `.git/logs/HEAD` grows on every HEAD move
|
|
// (commit, checkout, reset), covering branch switches without resolving the
|
|
// current branch's ref file by hand.
|
|
println!("cargo:rerun-if-changed=../../.git/HEAD");
|
|
println!("cargo:rerun-if-changed=../../.git/logs/HEAD");
|
|
|
|
let head = run_git(repo_root, &["rev-parse", "HEAD"]);
|
|
let Some(head) = head else { return };
|
|
|
|
// Append `-dirty` when the working tree has uncommitted changes, so a run
|
|
// built off an unclean tree is not silently attributed to the clean HEAD.
|
|
let dirty = run_git(repo_root, &["status", "--porcelain"])
|
|
.map(|s| !s.is_empty())
|
|
.unwrap_or(false);
|
|
|
|
let commit = if dirty { format!("{head}-dirty") } else { head };
|
|
println!("cargo:rustc-env=AURA_COMMIT={commit}");
|
|
}
|
|
|
|
/// Run `git <args>` in `dir`, returning trimmed stdout on success, `None` on any
|
|
/// failure (git missing, non-zero exit, non-utf8). Never panics: a build must
|
|
/// not fail because git is unavailable.
|
|
fn run_git(dir: &Path, args: &[&str]) -> Option<String> {
|
|
let out = Command::new("git").current_dir(dir).args(args).output().ok()?;
|
|
if !out.status.success() {
|
|
return None;
|
|
}
|
|
let s = String::from_utf8(out.stdout).ok()?;
|
|
Some(s.trim().to_string())
|
|
}
|