Files
peltier.io/crates/diff-test/src/target.rs
T
Claude 014e3b11d1 phase3: generalize trust layer for C/C++; wire cJSON target
Trust-layer generalization (zero-regression verified on tokei):
- TargetSpec [build] uses an explicit {out} isolation-dir placeholder
  instead of injected CARGO_TARGET_DIR, plus optional sanitizer/
  sanitizer_binary templates. Nothing assumes cargo anymore.
- verdict rebuild_pristine_baseline, sanitizer_check, and harnessd
  run_verdict candidate build all use {out} substitution. A target with
  no sanitizer build caps accepts at needs-human-review.
- tokei/comrak target.toml migrated to the {out} form (CARGO_TARGET_DIR=
  {out} + nightly ASan sanitizer command).

cJSON C target (v1.7.19, MIT):
- harness.c bench/golden driver (trust-layer; agent can patch workspace
  cJSON.c but not the rig), compiled with clang against the patched tree.
- 5.6 MB deterministic corpus (gen-corpus.sh) + MANIFEST/GOLDEN pins.
- gates = hermetic Unity/CTest suite (19 tests pass); sanitizer =
  ASan+UBSan; scripts/diff-fuzz-cjson.py for differential fuzzing.

coz causal profiler integration (SPEC §12):
- harness.c optional -DHOTPATH_COZ throughput progress point.
- scripts/install-coz.sh, coz-profile.sh, coz-summary.py; just coz/install-coz.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EcKPWQ3MQD4NdEHwar96u2
2026-07-11 18:17:26 +00:00

103 lines
3.5 KiB
Rust

//! Per-target spec (`targets/<name>/target.toml`). All commands and
//! paths are relative to the repository root; `{binary}` in commands is
//! substituted with the built binary path.
use serde::Deserialize;
use std::path::{Path, PathBuf};
#[derive(Debug, Deserialize)]
pub struct TargetSpec {
pub source: Source,
pub build: Build,
pub bench: Bench,
pub gates: Gates,
pub corpus: Corpus,
}
#[derive(Debug, Deserialize)]
pub struct Bench {
/// Bench command; `{binary}` substituted per side. Run from repo root.
pub command: String,
/// Human-readable workload statement, printed with every number.
pub workload: String,
}
#[derive(Debug, Deserialize)]
pub struct Source {
pub repo: String,
pub commit: String,
pub license: String,
#[serde(default)]
pub submodules: toml::value::Table,
}
#[derive(Debug, Deserialize)]
pub struct Build {
/// Build command, run from repo root. `{out}` is substituted with an
/// isolation directory the harness provides (per-baseline, per-
/// candidate, per-sanitizer) — the command MUST place all artifacts
/// under it. A cargo target sets `CARGO_TARGET_DIR={out}`; a make
/// target builds and copies the binary to `{out}`. Language-agnostic:
/// nothing here assumes cargo.
pub baseline: String,
/// Built binary path with `{out}` substituted — where `baseline`
/// leaves the binary given an isolation dir.
pub binary: String,
/// ASan+LSan (or ASan+UBSan for C/C++) build command; `{out}`
/// substituted. Run on every would-be accept (SPEC §8). If absent,
/// an accept cannot be sanitizer-verified and is capped at
/// needs-human-review.
#[serde(default)]
pub sanitizer: Option<String>,
/// Sanitizer binary path with `{out}` substituted.
#[serde(default)]
pub sanitizer_binary: Option<String>,
}
/// Substitute the `{out}` isolation-dir placeholder in a build command or
/// binary-path template.
pub fn subst_out(template: &str, out_dir: &str) -> String {
template.replace("{out}", out_dir)
}
#[derive(Debug, Deserialize)]
pub struct Gates {
/// Upstream test suite command, run from repo root.
pub tests: String,
/// Golden replay command; stdout is hashed. `{binary}` substituted.
pub golden: String,
}
#[derive(Debug, Deserialize)]
pub struct Corpus {
/// sha256sum-format manifest of the corpus inputs.
pub manifest: PathBuf,
/// Directory the manifest's relative paths resolve against.
pub root: PathBuf,
/// File whose last whitespace-delimited-first-field line is the
/// expected sha256 of the golden command's stdout.
pub golden_sha256: PathBuf,
}
impl TargetSpec {
pub fn load(repo_root: &Path, name: &str) -> anyhow::Result<Self> {
let path = repo_root.join("targets").join(name).join("target.toml");
let raw = std::fs::read_to_string(&path)
.map_err(|e| anyhow::anyhow!("cannot read {}: {e}", path.display()))?;
Ok(toml::from_str(&raw)?)
}
}
/// Parse the expected stdout hash out of a GOLDEN.sha256 file
/// (comment lines starting with '#' ignored).
pub fn expected_golden_hash(path: &Path) -> anyhow::Result<String> {
let raw = std::fs::read_to_string(path)?;
raw.lines()
.map(str::trim)
.filter(|l| !l.is_empty() && !l.starts_with('#'))
.filter_map(|l| l.split_whitespace().next())
.next_back()
.map(str::to_string)
.ok_or_else(|| anyhow::anyhow!("no hash entry in {}", path.display()))
}