phase3: diff-test resolves {out}-templated binary; CI gates cjson

diff-test standalone (just gates / CI target-gates) passed the now-
templated build.binary into golden replay verbatim — literal {out}.
It now builds the current tree to targets/<t>/gates-build and tests
that, with a --binary override. CI's target-gates-no-net job gains
clang/cmake, fetches+gates the cjson C target (clang build -> Unity/
CTest -> golden replay) alongside tokei.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcKPWQ3MQD4NdEHwar96u2
This commit is contained in:
Claude
2026-07-11 18:20:08 +00:00
parent 014e3b11d1
commit fd6f963829
2 changed files with 33 additions and 3 deletions
+26 -2
View File
@@ -5,7 +5,7 @@
use anyhow::Result;
use clap::Parser;
use diff_test::orchestrate::run_core_gates;
use diff_test::target::TargetSpec;
use diff_test::target::{subst_out, TargetSpec};
use diff_test::{all_passed, GateOutcome};
use std::path::PathBuf;
@@ -17,13 +17,37 @@ struct Cli {
/// Repository root (defaults to current directory).
#[arg(long, default_value = ".")]
root: PathBuf,
/// Binary to test in golden replay. If omitted, the current working
/// tree is built to targets/<name>/gates-build and that is tested.
#[arg(long)]
binary: Option<String>,
}
fn main() -> Result<()> {
let cli = Cli::parse();
let root = cli.root.canonicalize()?;
let spec = TargetSpec::load(&root, &cli.target)?;
let results = run_core_gates(&root, &spec, &spec.build.binary)?;
// build.binary is an {out}-templated path now; resolve it to a real
// binary either from --binary or by building the current tree into an
// isolation dir (so `just gates` tests what's on disk, self-contained).
let binary = match &cli.binary {
Some(b) => b.clone(),
None => {
let out = root
.join(format!("targets/{}/gates-build", cli.target))
.to_string_lossy()
.into_owned();
println!("building current tree for gates -> {out}");
let status = std::process::Command::new("sh")
.arg("-c")
.arg(subst_out(&spec.build.baseline, &out))
.current_dir(&root)
.status()?;
anyhow::ensure!(status.success(), "gates build failed");
subst_out(&spec.build.binary, &out)
}
};
let results = run_core_gates(&root, &spec, &binary)?;
for (layer, outcome) in &results {
match outcome {
GateOutcome::Passed => println!("{layer:?}: PASS"),