From bec76fc97150b706f329c5dcf3a215f5cf4dbb27 Mon Sep 17 00:00:00 2001 From: Yuanhao Li Date: Fri, 28 Aug 2026 13:19:23 +0200 Subject: [PATCH] chore: read the fold version from the linked crate, not the lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit yoagent-state 0.5.2 exports VERSION, baked in at its own compile time. That reports what the checker actually LINKED rather than what a lockfile resolved — strictly stronger, since a stale lockfile entry cannot drift from it — and it needs no build script. Deletes build.rs, which shipped three bugs in a day: - packaged builds printed "unknown": cargo package puts Cargo.lock beside build.rs, not one level up, so it worked in the workspace and failed in every installed build - a two-version lockfile reported the LOWEST, naming 0.4.0 while linking 0.5.1 — the exact skew the line exists to expose, backwards - collecting every match over-collected [[patch.unused]], so a local [patch.crates-io] override reported a single resolved version as ambiguous Fifty lines of string parsing over a format we do not own, replaced by one const. Verified where build.rs failed: an extracted .crate now reports 0.5.2 rather than "unknown". Floors the dependency at 0.5.2, since VERSION lands there. 23 passed. Real store still 7/7 with the skip named. --- Cargo.lock | 4 +- conformance-check/Cargo.toml | 2 +- conformance-check/build.rs | 78 ----------------------------------- conformance-check/src/main.rs | 2 +- 4 files changed, 4 insertions(+), 82 deletions(-) delete mode 100644 conformance-check/build.rs diff --git a/Cargo.lock b/Cargo.lock index cc536a8..bfe16f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -603,9 +603,9 @@ dependencies = [ [[package]] name = "yoagent-state" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7384e9ee74b278cbbbf4fa6d5870133c97df202e74a4e89bb9bef54a85ab229e" +checksum = "2dd8927d9d65826f646e7a674064904baa56f10b485301b91a65652b50c6ca32" dependencies = [ "async-trait", "chrono", diff --git a/conformance-check/Cargo.toml b/conformance-check/Cargo.toml index 14d3491..17c5759 100644 --- a/conformance-check/Cargo.toml +++ b/conformance-check/Cargo.toml @@ -6,7 +6,7 @@ description = "GASP conformance checker — verifies an agent repo against Part license = "MIT" [dependencies] -yoagent-state = "0.5" +yoagent-state = "0.5.2" serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = "0.10" diff --git a/conformance-check/build.rs b/conformance-check/build.rs deleted file mode 100644 index 733ef37..0000000 --- a/conformance-check/build.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! Records which `yoagent-state` the checker folds with, so the report can say so. -//! -//! The checker answers "can a conformant runtime fold and restore this store?" -//! by folding the store itself. That answer is only meaningful if the fold it -//! uses matches the fold runtimes use — and when it drifted, the skew was -//! discoverable only by reading two lockfiles. -//! -//! A certificate that does not say what produced it cannot be audited. -//! -//! Reads the workspace lockfile rather than guessing: cargo exposes no env var -//! for a dependency's resolved version, and the requirement in `Cargo.toml` -//! ("0.5") is not what was actually built. - -use std::path::PathBuf; - -fn main() { - // Both layouts, in this order. `cargo package` ships the lockfile at the - // *package* root, beside this build script — so looking only at the - // workspace parent worked in development and printed "unknown" for every - // installed build, which is the one place the line has to work. Cargo also - // regenerates the workspace lock before build scripts run, so the failure - // was unreachable in-tree. - let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let lock = [manifest.join("Cargo.lock"), manifest.join("../Cargo.lock")] - .into_iter() - .find(|p| p.exists()); - - let version = lock - .as_ref() - .and_then(|p| std::fs::read_to_string(p).ok()) - .and_then(|body| resolved_version(&body, "yoagent-state")) - // Not a build failure: a missing or restructured lockfile should not - // stop the checker from running, only from naming its fold version. - .unwrap_or_else(|| "unknown".to_string()); - - println!("cargo:rustc-env=GASP_STATE_VERSION={version}"); - if let Some(p) = lock { - println!("cargo:rerun-if-changed={}", p.display()); - } -} - -/// Every `version = "x"` following a `name = ""` in a Cargo.lock. -/// -/// All of them, not the first. Cargo sorts by name then version ascending, so -/// taking the first reports the *lowest* when two versions resolve — and this -/// line exists precisely because 0.4 and 0.5 fold differently, so naming the -/// wrong one is worse than naming none. Ambiguity is reported as such. -fn resolved_version(lock: &str, crate_name: &str) -> Option { - let needle = format!("name = \"{crate_name}\""); - let mut found: Vec = Vec::new(); - let lines: Vec<&str> = lock.lines().collect(); - let mut in_package = false; - for (i, line) in lines.iter().enumerate() { - let trimmed = line.trim(); - // Only `[[package]]` entries describe what was resolved. Cargo also - // emits `[[patch.unused]]` in the same shape, so collecting every - // matching name reported `ambiguous(...)` when a single version had - // resolved — reachable with `[patch.crates-io] yoagent-state = { path - // = ... }`, which is the obvious way to test a local fix. - if trimmed.starts_with("[[") { - in_package = trimmed == "[[package]]"; - } - if !in_package || trimmed != needle { - continue; - } - if let Some(v) = lines - .get(i + 1) - .and_then(|l| l.trim().strip_prefix("version = ")) - { - found.push(v.trim_matches('"').to_string()); - } - } - match found.len() { - 0 => None, - 1 => found.pop(), - _ => Some(format!("ambiguous({})", found.join(","))), - } -} diff --git a/conformance-check/src/main.rs b/conformance-check/src/main.rs index f5b4f40..f935149 100644 --- a/conformance-check/src/main.rs +++ b/conformance-check/src/main.rs @@ -37,7 +37,7 @@ fn main() -> ExitCode { println!( "conformance-check {} — folding with yoagent-state {}", env!("CARGO_PKG_VERSION"), - env!("GASP_STATE_VERSION"), + yoagent_state::VERSION, ); let mut failed = false;