use std::collections::BTreeSet;
use std::path::PathBuf;
const SPEC: &str = "docs/architecture/SPEC-PR-Gate-Outputs-v1.md";
fn workspace_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..")
}
fn read(rel: &str) -> String {
let path = workspace_root().join(rel);
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()))
}
fn emittable_codes() -> BTreeSet<String> {
let src = read("crates/assay-cli/src/exit_codes.rs");
let body = after(&src, "pub fn as_str(&self) -> &'static str {");
let body = before(body, "\n }");
let mut found = BTreeSet::new();
for line in body.lines() {
let line = line.trim();
let Some(rest) = line.strip_prefix("ReasonCode::") else {
continue;
};
let Some((_variant, value)) = rest.split_once("=>") else {
continue;
};
let value = string_literal(value)
.unwrap_or_else(|| panic!("`as_str` arm is not a string literal: {line}"));
if value.is_empty() {
continue;
}
assert!(
found.insert(value.clone()),
"duplicate as_str value {value:?}"
);
}
assert!(
found.len() > 10,
"parsed only {} codes; the `as_str` shape moved",
found.len()
);
found
}
fn registered(section: &str) -> BTreeSet<String> {
let spec = read(SPEC);
let body = after(&spec, &format!("### {section}"));
let body = before(body, "\n### ");
body.lines()
.filter_map(|line| line.strip_prefix('|'))
.filter_map(|line| line.split('|').next())
.flat_map(|cell| cell.split(','))
.map(str::trim)
.filter(|token| is_code_shaped(token))
.map(str::to_owned)
.collect()
}
fn is_code_shaped(token: &str) -> bool {
!token.is_empty()
&& token.starts_with(|c: char| c.is_ascii_uppercase())
&& token
.chars()
.all(|c| c.is_ascii_uppercase() || c == '_' || c.is_ascii_digit())
}
fn after<'a>(haystack: &'a str, needle: &str) -> &'a str {
let idx = haystack
.find(needle)
.unwrap_or_else(|| panic!("not found: {needle}"));
&haystack[idx + needle.len()..]
}
fn before<'a>(haystack: &'a str, needle: &str) -> &'a str {
haystack
.split_once(needle)
.map(|(a, _)| a)
.unwrap_or(haystack)
}
fn string_literal(s: &str) -> Option<String> {
let start = s.find('"')? + 1;
let end = s[start..].find('"')? + start;
Some(s[start..end].to_owned())
}
fn remediation_matched_codes() -> BTreeSet<String> {
let src = read("crates/assay-core/src/agentic/builder.rs");
let mut found = BTreeSet::new();
for line in src.lines() {
let trimmed = line.trim();
if !trimmed.ends_with("=> {") || !trimmed.starts_with('"') {
continue;
}
for part in trimmed.trim_end_matches("=> {").split('|') {
if let Some(code) = string_literal(part) {
found.insert(code);
}
}
}
assert!(
!found.is_empty(),
"parsed no remediation match arms; the builder's shape moved"
);
found
}
fn all_registered() -> BTreeSet<String> {
["5.1", "5.2", "5.3", "5.4", "5.5"]
.iter()
.flat_map(|s| registered(s))
.collect()
}
#[test]
fn every_emittable_code_is_registered() {
let unregistered: Vec<String> = emittable_codes()
.difference(&all_registered())
.cloned()
.collect();
assert!(
unregistered.is_empty(),
"`ReasonCode::as_str` can emit these, and {SPEC} §5 registers none of them: {unregistered:?}. \
§5's normative rule requires reason_code to be a registered value, so an unregistered \
emittable code makes the CLI violate its own spec."
);
}
#[test]
fn every_registered_code_is_emittable_or_reserved() {
let emittable = emittable_codes();
let reserved = registered("5.4");
let policy_engine = registered("5.5");
let orphans: Vec<String> = ["5.1", "5.2", "5.3"]
.iter()
.flat_map(|s| registered(s))
.filter(|code| {
!emittable.contains(code) && !reserved.contains(code) && !policy_engine.contains(code)
})
.collect();
assert!(
orphans.is_empty(),
"{SPEC} registers these in an exit-code table, but nothing emits them and §5.4 does not \
list them as reserved: {orphans:?}. Either wire the code up, or record it as reserved — \
§175 forbids deleting it outright."
);
}
#[test]
fn every_remediation_branch_keys_on_a_registered_code() {
let known = all_registered();
let diagnostic_codes: BTreeSet<String> = {
let src = read("crates/assay-core/src/errors/diagnostic.rs");
let body = before(after(&src, "pub mod codes {"), "\n}");
body.lines()
.filter(|l| l.trim().starts_with("pub const "))
.filter_map(|l| l.split_once('=').and_then(|(_, v)| string_literal(v)))
.collect()
};
let unknown: Vec<String> = remediation_matched_codes()
.into_iter()
.filter(|code| !known.contains(code) && !diagnostic_codes.contains(code))
.collect();
assert!(
unknown.is_empty(),
"`agentic::builder` picks a remediation for these codes, and no registry knows them: \
{unknown:?}. A branch keyed on a code nothing emits and nothing registers cannot fire and \
cannot be reviewed — register it (§5.4 reserved is enough) or delete the arm."
);
}
fn variant_by_code() -> std::collections::BTreeMap<String, String> {
let src = read("crates/assay-cli/src/exit_codes.rs");
let body = after(&src, "pub fn as_str(&self) -> &'static str {");
let body = before(body, "\n }");
let mut map = std::collections::BTreeMap::new();
for line in body.lines() {
let Some(rest) = line.trim().strip_prefix("ReasonCode::") else {
continue;
};
let Some((variant, value)) = rest.split_once("=>") else {
continue;
};
if let Some(code) = string_literal(value) {
map.insert(code, variant.trim().to_owned());
}
}
map
}
fn walk_rust_sources() -> Vec<String> {
fn visit(dir: &std::path::Path, root: &std::path::Path, out: &mut Vec<String>) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
visit(&path, root, out);
} else if path.extension().is_some_and(|e| e == "rs") {
if let Ok(rel) = path.strip_prefix(root) {
out.push(rel.to_string_lossy().into_owned());
}
}
}
}
let root = workspace_root();
let mut out = Vec::new();
visit(&root.join("crates"), &root, &mut out);
assert!(
out.len() > 100,
"walked only {} source files; the layout moved",
out.len()
);
out
}
#[test]
fn the_reserved_section_claims_nothing_a_variant_construction_contradicts() {
let variants = variant_by_code();
let sources = walk_rust_sources();
let mut live = Vec::new();
for code in registered("5.4") {
let Some(variant) = variants.get(&code) else {
continue;
};
let needle = format!("ReasonCode::{variant}");
for path in &sources {
if path.contains("exit_codes.rs") || path.contains("tests/") {
continue;
}
if read(path).contains(&needle) {
live.push(format!("{code} ({needle} in {path})"));
break;
}
}
}
assert!(
live.is_empty(),
"§5.4 calls these reserved, and something constructs the variant: {live:?}. A consumer told \
a code may start appearing, about a code already appearing, has been misled in the \
direction that matters."
);
}
#[test]
fn the_boundary_names_error_codes_that_still_exist_in_assay_evidence() {
let errors = read("crates/assay-evidence/src/bundle/writer_next/errors.rs");
let boundary = read(BOUNDARY);
for code in [
"IntegrityManifestHash",
"IntegrityEventHash",
"IntegrityFileSizeMismatch",
"IntegrityRunRootMismatch",
"IntegrityIo",
"IntegrityGzip",
"IntegrityTar",
] {
assert!(
boundary.contains(code),
"{code} is checked here and the boundary no longer names it; update this list in the \
same change that drops it, and say why"
);
assert!(
errors.contains(code),
"the boundary names `ErrorCode::{code}` and `assay-evidence` no longer declares it. A \
normative MUST pointing at a renamed variant is worse than one pointing at none."
);
}
}
#[test]
fn the_reserved_section_claims_nothing_that_is_live() {
let src = read("crates/assay-core/src/policy_engine.rs");
let live_policy_codes: BTreeSet<String> = src
.lines()
.map(str::trim)
.filter(|l| !l.starts_with("//") && !l.starts_with("pub reason_code"))
.filter_map(|l| l.strip_prefix("reason_code:"))
.filter_map(string_literal)
.collect();
let contradictions: Vec<String> = registered("5.4")
.into_iter()
.filter(|code| live_policy_codes.contains(code))
.filter(|code| code != "E_ARG_SCHEMA" && code != "E_SEQUENCE_VIOLATION")
.collect();
assert!(
contradictions.is_empty(),
"§5.4 lists these as reserved, but `policy_engine` constructs them: {contradictions:?}"
);
}
const BOUNDARY: &str = "crates/assay-cli/src/exit_codes/evidence_integrity_boundary.md";
fn flowed(text: &str) -> String {
text.split_whitespace().collect::<Vec<_>>().join(" ")
}
fn spec_description(section: &str, code: &str) -> String {
let spec = read(SPEC);
let body = after(&spec, &format!("### {section}"));
let body = before(body, "\n### ");
let prefix = format!("| {code} ");
let row = body
.lines()
.find(|line| line.starts_with(&prefix))
.unwrap_or_else(|| panic!("§{section} has no row for {code}"));
let cells: Vec<&str> = row.trim_matches('|').split('|').collect();
assert_eq!(
cells.len(),
2,
"§{section}'s row for {code} has {} cells, not the code/description pair this reads: {row}",
cells.len()
);
flowed(cells[1])
}
#[test]
fn the_evidence_integrity_boundary_reads_the_same_in_the_spec_and_the_code() {
assert_eq!(
spec_description("5.1", "E_EVIDENCE_INTEGRITY"),
flowed(&read(BOUNDARY)),
"the §5.1 registry row is no longer the text of {BOUNDARY}. That file is the boundary; the \
row and the `ReasonCode::EEvidenceIntegrity` doc comment transport it. Edit the file and \
reflow it into the row rather than editing the row."
);
}
const REGISTRY_HEADER: &str = "pub enum ReasonCode {";
const INTEGRITY_DECL: &str = "\n EEvidenceIntegrity,";
const BOUNDARY_INCLUDE: &str =
"#[doc = include_str!(\"exit_codes/evidence_integrity_boundary.md\")]";
fn code_of(text: &str) -> Option<(String, i32)> {
let mut code = String::with_capacity(text.len());
let mut depth = 0i32;
let mut chars = text.chars();
while let Some(c) = chars.next() {
match c {
'"' => loop {
match chars.next()? {
'\\' => {
chars.next()?;
}
'"' => break,
_ => {}
}
},
'(' | '[' | '{' => {
depth += 1;
code.push(c);
}
')' | ']' | '}' => {
depth -= 1;
if depth < 0 {
return None;
}
code.push(c);
}
_ => code.push(c),
}
}
Some((code, depth))
}
fn identifiers(code: &str) -> Vec<&str> {
code.split(|c: char| !c.is_ascii_alphanumeric() && c != '_')
.filter(|token| !token.is_empty())
.collect()
}
fn cannot_document(unit: &str) -> bool {
let unit = unit.trim();
if unit.is_empty() {
return true;
}
if unit.starts_with("//") {
return !unit.starts_with("///") && !unit.starts_with("//!");
}
let Some(attribute) = unit
.strip_prefix("#[")
.and_then(|rest| rest.strip_suffix(']'))
else {
return false;
};
let Some((code, 0)) = code_of(attribute) else {
return false;
};
let tokens = identifiers(&code);
match tokens.first() {
Some(&"doc") => tokens == ["doc", "alias"],
Some(&"deprecated") => false,
Some(&"cfg_attr") => !tokens
.iter()
.any(|token| *token == "doc" || *token == "deprecated"),
Some(_) => true,
None => false,
}
}
fn source_units(lines: &[&str]) -> Vec<(usize, String)> {
let mut units = Vec::new();
let mut start = 0;
while start < lines.len() {
let mut last = start;
let mut text = lines[start].trim().to_string();
if text.starts_with("#[") {
while code_of(&text).map(|(_, depth)| depth) != Some(0) && last + 1 < lines.len() {
last += 1;
text.push(' ');
text.push_str(lines[last].trim());
}
}
units.push((last, text));
start = last + 1;
}
units
}
fn declares_a_variant(line: &str) -> bool {
let code = match line.find("//") {
Some(at) => &line[..at],
None => line,
};
let Some(name) = code.trim().strip_suffix(',') else {
return false;
};
name.starts_with(|c: char| c.is_ascii_uppercase()) && name.chars().all(char::is_alphanumeric)
}
#[test]
fn nothing_but_the_boundary_include_documents_the_integrity_variant() {
let src = read("crates/assay-cli/src/exit_codes.rs");
assert_eq!(
src.matches(REGISTRY_HEADER).count(),
1,
"`{REGISTRY_HEADER}` occurs more than once in crates/assay-cli/src/exit_codes.rs, so the \
slice read below is not necessarily the registry"
);
let body = src
.split_once(REGISTRY_HEADER)
.and_then(|(_, body)| body.split_once("\n}"))
.map(|(body, _)| body)
.expect("`pub enum ReasonCode` has no closing brace");
assert_eq!(
body.matches(INTEGRITY_DECL).count(),
1,
"`EEvidenceIntegrity,` occurs {} times in the `ReasonCode` body; the declaration this reads \
is then not necessarily the one it names",
body.matches(INTEGRITY_DECL).count()
);
let head = body
.split_once(INTEGRITY_DECL)
.map(|(above_decl, _)| above_decl)
.expect("no `EEvidenceIntegrity` variant in `ReasonCode`");
let lines: Vec<&str> = head.lines().collect();
let units = source_units(&lines);
let previous_variant = units
.iter()
.rposition(|(_, unit)| !(cannot_document(unit) || unit.as_str() == BOUNDARY_INCLUDE));
let own_text: &[&str] = match previous_variant {
Some(index) => {
let (last_line, unit) = &units[index];
assert!(
declares_a_variant(unit),
"`EEvidenceIntegrity`'s own text reaches back to {unit:?}, which does not declare \
the previous variant. Every line between the two variants documents this one, so \
anything there that is not the boundary include is a second copy of the rule, \
free to contradict it while the §5.1 row stays correct. Blank lines, `//` \
comments, and attributes whose path is neither `doc` nor `deprecated` — on one \
line or broken across several — carry no text and are fine on either side of the \
include; a `///` or `/** */` comment, a `#[doc = ...]`, a `#[deprecated]` note, \
any `cfg_attr` naming either path, and any attribute whose brackets do not \
balance are refused here rather than guessed at."
);
&lines[last_line + 1..]
}
None => &lines,
};
assert_eq!(
own_text
.iter()
.filter(|line| line.trim() == BOUNDARY_INCLUDE)
.count(),
1,
"`EEvidenceIntegrity` is documented by {own_text:?} rather than by including {BOUNDARY} \
exactly once"
);
}
#[test]
fn the_boundary_states_the_canonical_flat_digest_formula() {
let boundary = flowed(&read(BOUNDARY));
assert!(
boundary.contains(
"`run_root` is SHA-256 over newline-delimited event content-hash strings, with a \
trailing newline, in event sequence order."
),
"{BOUNDARY} must state the canonical run_root formula"
);
assert!(
boundary.contains("flat digest"),
"{BOUNDARY} must identify run_root as a flat digest"
);
assert!(
!boundary.contains("hash chain")
&& !boundary.contains("integrity chain")
&& !boundary.contains("concatenated"),
"{BOUNDARY} must not describe run_root as a chain or delimiter-free concatenation"
);
assert!(
!boundary.contains("Merkle"),
"{BOUNDARY} must not name a structure the verifier does not build"
);
}