use super::mock_harness_guard::reject_mock_harness_scaffolding;
use super::*;
mod coverage;
#[test]
fn is_snippet_coverage_manifest_path_matches_only_the_exact_ledger_name() {
assert!(is_snippet_coverage_manifest_path(Path::new(
"docs/snippets/.alef-snippet-coverage.json"
)));
assert!(is_snippet_coverage_manifest_path(Path::new(COVERAGE_MANIFEST)));
assert!(
!is_snippet_coverage_manifest_path(Path::new("docs/snippets/.alef-snippet-coverage.json.bak")),
"a name that merely contains the ledger name must not match"
);
assert!(
!is_snippet_coverage_manifest_path(Path::new("packages/php/composer.json")),
"an unrelated unmarkable manifest must not match"
);
}
const SNIPPET_HEADER: &str = "<!-- This file is auto-generated by alef — DO NOT EDIT. -->\n\
<!-- To regenerate: alef e2e generate -->\n\
<!-- To verify freshness: alef verify -->\n\n";
struct FixtureExtension {
body: &'static str,
}
impl crate::Extension for FixtureExtension {
fn name(&self) -> &str {
"fixture"
}
fn render_e2e_snippet(
&self,
_fixture: &Fixture,
_e2e_config: &E2eConfig,
_config: &ResolvedCrateConfig,
_language: &str,
_type_defs: &[TypeDef],
_enums: &[EnumDef],
) -> Result<Option<String>> {
Ok(Some(self.body.to_string()))
}
}
fn documented_fixture() -> Fixture {
Fixture {
id: "extension_owned".into(),
description: "Extension-owned example".into(),
docs: Some(FixtureDocs {
topic: "api".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: SideEffectClass::Safe,
coverage_exceptions: BTreeMap::new(),
}),
..Fixture::default()
}
}
#[test]
fn mock_harness_scaffolding_is_rejected_for_every_language() {
let fixture = Fixture {
id: "rate_limit_429".into(),
..Fixture::default()
};
let leaks = [
"var url = System.getenv(\"MOCK_SERVER_URL\") + \"/fixtures/rate_limit_429\";",
"let url = std.c.getenv(\"MOCK_SERVER_RATE_LIMIT_429\");",
"var url = System.getProperty(\"mockServerUrl\");",
"let base = System.getProperty(\"mockServer.rate_limit_429\");",
"let hosts = process.env.MOCK_SERVERS;",
"let url = \"https://api.example.com/fixtures/rate_limit_429\";",
];
for leak in leaks {
let error = reject_mock_harness_scaffolding(leak, &fixture, "zig")
.expect_err("mock-server scaffolding must not reach a published snippet");
let message = format!("{error:#}");
assert!(message.contains("rate_limit_429"), "error omits the fixture: {message}");
assert!(message.contains("zig"), "error omits the language: {message}");
}
}
#[test]
fn a_reader_facing_snippet_passes_the_mock_harness_guard() {
let fixture = Fixture {
id: "rate_limit_429".into(),
..Fixture::default()
};
let body = "var apiKey = System.getenv(\"API_KEY\");\nvar client = Sample.createClient(apiKey, null);";
assert!(reject_mock_harness_scaffolding(body, &fixture, "java").is_ok());
}
fn snippet_report_for(fixture: Fixture, languages: &[&str], body: &'static str) -> Result<SnippetGenerationReport> {
let extensions: Vec<Box<dyn crate::Extension>> = vec![Box::new(FixtureExtension { body })];
let e2e = E2eConfig::default();
let crate_config = ResolvedCrateConfig::default();
let snippet_config = SnippetConfig {
output: "docs/snippets".into(),
..SnippetConfig::default()
};
let context = SnippetRenderContext {
e2e: &e2e,
crate_config: &crate_config,
type_defs: &[],
enums: &[],
functions: &[],
errors: &[],
};
let languages: Vec<String> = languages.iter().map(|language| (*language).to_string()).collect();
generate_snippet_report_with_extensions(&[fixture], &languages, &snippet_config, &context, &extensions)
}
#[test]
fn a_guard_rejected_snippet_is_a_reported_failure_not_a_silent_absence() {
let leaking_body = "var url = System.getenv(\"MOCK_SERVER_URL\") + \"/fixtures/extension_owned\";";
let error = snippet_report_for(documented_fixture(), &["java", "rust"], leaking_body)
.expect_err("a guard-rejected snippet must abort generation");
let message = format!("{error:#}");
assert!(
message.contains("rejected by the mock-harness guard"),
"the failure must name the guard: {message}"
);
assert!(
message.contains("2 documentation snippet(s)"),
"the failure must count every rejection: {message}"
);
assert!(
message.contains("\n java (1):"),
"the failure must attribute per language: {message}"
);
assert!(
message.contains("\n rust (1):"),
"the failure must attribute per language: {message}"
);
assert!(
message.contains("`MOCK_SERVER_URL` (1): extension_owned"),
"the failure must attribute per reason and fixture: {message}"
);
}
#[test]
fn a_documented_coverage_exception_cannot_retire_a_guard_rejection() {
let mut fixture = documented_fixture();
fixture
.docs
.as_mut()
.expect("documented fixture has docs")
.coverage_exceptions
.insert(
"rust".into(),
crate::e2e::fixture::SnippetCoverageException {
reason: "the sample backend cannot express this recipe".into(),
documentation: "docs/limitations.md".into(),
},
);
let leaking_body = "let url = std::env::var(\"MOCK_SERVER_URL\").unwrap();";
let error = snippet_report_for(fixture, &["rust"], leaking_body)
.expect_err("a coverage exception must not absorb a guard rejection");
let message = format!("{error:#}");
assert!(
message.contains("rejected by the mock-harness guard"),
"the exception silently absorbed the rejection: {message}"
);
assert!(
message.contains("cannot retire a guard rejection"),
"the failure must explain why the exception did not apply: {message}"
);
}
#[test]
fn coverage_exception_declared_as_c_applies_to_ffi_backend() {
let mut fixture = documented_fixture();
fixture.requirements = vec!["feature:unavailable_in_c".into()];
fixture
.docs
.as_mut()
.expect("documented fixture has docs")
.coverage_exceptions
.insert(
"c".into(),
crate::e2e::fixture::SnippetCoverageException {
reason: "the C binding cannot express this recipe".into(),
documentation: "docs/limitations.md".into(),
},
);
let body = "int main(void) { return 0; }";
let report = snippet_report_for(fixture, &["ffi"], body)
.expect("a documented exception must retire the gap instead of failing the run");
assert!(
report.coverage.missing.is_empty(),
"the `c` exception must apply while the backend runs as `ffi`: {:?}",
report.coverage.missing
);
assert_eq!(report.coverage.documented_exceptions.len(), 1);
assert_eq!(
report.coverage.documented_exceptions[0].reason,
"the C binding cannot express this recipe"
);
}
#[test]
fn validate_coverage_exceptions_rejects_unknown_language() {
let mut fixture = documented_fixture();
fixture
.docs
.as_mut()
.expect("documented fixture has docs")
.coverage_exceptions
.insert(
"csharpp".into(),
crate::e2e::fixture::SnippetCoverageException {
reason: "typo'd language key".into(),
documentation: "docs/limitations.md".into(),
},
);
let error = validate_coverage_exceptions(&fixture).expect_err("an unknown language key must hard-fail");
let message = error.to_string();
assert!(message.contains("csharpp"), "error must name the bad key: {message}");
assert!(
message.contains("c (also accepted: c_ffi, ffi)"),
"error must name the C backend's accepted spellings: {message}"
);
assert!(
message.contains("rust (also accepted: core, rust_core)"),
"error must name the Rust backend's accepted spellings: {message}"
);
}
#[test]
fn validate_coverage_exceptions_accepts_alias_spellings() {
for alias in ["c", "c_ffi", "ffi", "rust", "core", "rust_core"] {
let mut fixture = documented_fixture();
fixture
.docs
.as_mut()
.expect("documented fixture has docs")
.coverage_exceptions
.insert(
alias.to_string(),
crate::e2e::fixture::SnippetCoverageException {
reason: "documented limitation".into(),
documentation: "docs/limitations.md".into(),
},
);
assert!(
validate_coverage_exceptions(&fixture).is_ok(),
"`{alias}` is an accepted spelling and must pass validation"
);
}
}
#[test]
fn a_clean_snippet_still_renders_while_the_guard_is_armed() {
let clean_body =
"let api_key = std::env::var(\"API_KEY\").unwrap();\nlet client = sample::create_client(api_key)?;";
let report =
snippet_report_for(documented_fixture(), &["rust"], clean_body).expect("a clean snippet must still render");
assert!(report.guard_rejections.is_empty());
assert!(report.coverage.missing.is_empty());
assert_eq!(report.coverage.generated, report.coverage.expected);
assert_eq!(report.snippets.len(), 1);
assert!(
report.snippets[0]
.file
.content
.contains("sample::create_client(api_key)?")
);
}
#[test]
fn capability_decision_reports_missing_requirements_deterministically() {
let fixture = Fixture {
requirements: vec!["service:api".into(), "feature:json".into()],
..Fixture::default()
};
let capabilities = BTreeSet::from(["feature:json".to_string()]);
assert_eq!(
snippet_inclusion(&fixture, &capabilities),
SnippetInclusion::Exclude {
missing_requirements: vec!["service:api".into()]
}
);
}
#[test]
fn snippet_paths_reject_traversal() {
let mut docs = FixtureDocs {
topic: "..".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: Default::default(),
coverage_exceptions: BTreeMap::new(),
};
assert!(
snippet_path(
"docs/snippets",
&docs,
"basic",
"python",
DocumentationLanguage::Binding(Language::Python)
)
.is_err()
);
docs.topic = "fallback".into();
docs.paths.insert("python".into(), "../escape.md".into());
assert!(
snippet_path(
"docs/snippets",
&docs,
"basic",
"python",
DocumentationLanguage::Binding(Language::Python)
)
.is_err()
);
}
#[test]
fn target_path_override_precedes_topic_and_stem() {
let docs = FixtureDocs {
topic: "fallback".into(),
stem: Some("fallback".into()),
paths: BTreeMap::from([("node".into(), "config/basic_usage.md".into())]),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: Default::default(),
coverage_exceptions: BTreeMap::new(),
};
assert_eq!(
snippet_path(
"docs/snippets",
&docs,
"fixture",
"node",
DocumentationLanguage::Binding(Language::Node)
)
.expect("safe target path"),
Path::new("docs/snippets/typescript/config/basic_usage.md")
);
}
#[test]
fn docs_path_target_must_be_configured() {
let mut fixture = documented_fixture();
fixture
.docs
.as_mut()
.expect("fixture docs")
.paths
.insert("wasm".into(), "browser/basic.md".into());
assert!(validate_docs_paths(&fixture, &["node".into()]).is_err());
assert!(validate_docs_paths(&fixture, &["node".into(), "wasm".into()]).is_ok());
}
#[test]
fn language_aliases_include_core_and_ffi_targets() {
assert_eq!(
parse_language("rust_core"),
Some(DocumentationLanguage::Binding(Language::Rust))
);
assert_eq!(parse_language("ffi"), Some(DocumentationLanguage::Binding(Language::C)));
assert_eq!(parse_language("brew"), Some(DocumentationLanguage::Shell));
assert_eq!(parse_language("homebrew"), Some(DocumentationLanguage::Shell));
assert_eq!(generator_name("rust_core"), "rust");
assert_eq!(generator_name("ffi"), "c");
}
#[test]
fn generated_docs_use_validator_canonical_language_identity() {
let docs = FixtureDocs {
topic: "api".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: SideEffectClass::Safe,
coverage_exceptions: BTreeMap::new(),
};
let cases = [
("node", Language::Node, "typescript", "typescript"),
("wasm", Language::Wasm, "typescript", "wasm"),
("kotlin_android", Language::KotlinAndroid, "kotlin", "kotlin-android"),
];
for (target_language, binding_language, canonical_name, output_slug) in cases {
let language = DocumentationLanguage::Binding(binding_language);
let fixture = documented_fixture();
let rendered = render_snippet_markdown("example()", &fixture, &docs, target_language, language);
let path =
snippet_path("docs/snippets", &docs, "example", target_language, language).expect("snippet path is valid");
assert_eq!(
rendered,
format!(
"---\nid: fixture_{target_language}_extension_owned\nlanguage: {canonical_name}\ntarget: {target_language}\nlevel: null\nrequires: []\nside_effect: safe\n---\n\n{SNIPPET_HEADER}Extension-owned example\n\n```{canonical_name} title=\"{}\"\nexample()\n```\n",
language.display_name()
)
);
assert_eq!(
path,
Path::new("docs/snippets").join(output_slug).join("api/example.md")
);
assert_ne!(
crate::snippets::types::Language::from_fence_tag(canonical_name),
crate::snippets::types::Language::Unknown
);
}
}
#[test]
fn frontmatter_fields_are_pinned_by_exact_equality() {
let render = |fixture: &Fixture, side_effects: SideEffectClass, target: &str| {
let docs = FixtureDocs {
topic: "api".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects,
coverage_exceptions: BTreeMap::new(),
};
render_snippet_markdown(
"example()",
fixture,
&docs,
target,
DocumentationLanguage::Binding(Language::Node),
)
};
let baseline = documented_fixture();
assert_eq!(
render(&baseline, SideEffectClass::Network, "node"),
format!(
"---\nid: fixture_node_extension_owned\nlanguage: typescript\ntarget: node\nlevel: typecheck\nrequires: []\nside_effect: network\n---\n\n{SNIPPET_HEADER}Extension-owned example\n\n```typescript title=\"TypeScript\"\nexample()\n```\n"
)
);
assert_eq!(
render(&baseline, SideEffectClass::Install, "node"),
format!(
"---\nid: fixture_node_extension_owned\nlanguage: typescript\ntarget: node\nlevel: typecheck\nrequires: []\nside_effect: install\n---\n\n{SNIPPET_HEADER}Extension-owned example\n\n```typescript title=\"TypeScript\"\nexample()\n```\n"
)
);
let required = Fixture {
requirements: vec!["feature:json".into(), "service:api".into()],
..documented_fixture()
};
assert_eq!(
render(&required, SideEffectClass::Safe, "node"),
format!(
"---\nid: fixture_node_extension_owned\nlanguage: typescript\ntarget: node\nlevel: null\nrequires: [\"feature:json\",\"service:api\"]\nside_effect: safe\n---\n\n{SNIPPET_HEADER}Extension-owned example\n\n```typescript title=\"TypeScript\"\nexample()\n```\n"
)
);
}
#[test]
fn safe_side_effects_snippet_is_not_level_capped() {
let docs = FixtureDocs {
topic: "api".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: SideEffectClass::Safe,
coverage_exceptions: BTreeMap::new(),
};
let rendered = render_snippet_markdown(
"example()",
&documented_fixture(),
&docs,
"node",
DocumentationLanguage::Binding(Language::Node),
);
assert!(
rendered.contains("\nlevel: null\n"),
"safe snippet must not declare a level cap, got: {rendered}"
);
let front_matter = rendered
.split("---\n")
.nth(1)
.expect("rendered snippet has front matter");
let metadata: crate::snippets::types::SnippetMetadata =
serde_yaml::from_str(front_matter).expect("front matter is valid YAML");
assert_eq!(metadata.level, None, "safe snippet must resolve to no declared level");
}
#[test]
fn unsafe_side_effects_snippet_keeps_the_typecheck_cap() {
for side_effects in [
SideEffectClass::Network,
SideEffectClass::Process,
SideEffectClass::Install,
SideEffectClass::Server,
] {
let docs = FixtureDocs {
topic: "api".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects,
coverage_exceptions: BTreeMap::new(),
};
let rendered = render_snippet_markdown(
"example()",
&documented_fixture(),
&docs,
"node",
DocumentationLanguage::Binding(Language::Node),
);
assert!(
rendered.contains("\nlevel: typecheck\n"),
"unsafe snippet ({side_effects:?}) must keep the typecheck cap, got: {rendered}"
);
let front_matter = rendered
.split("---\n")
.nth(1)
.expect("rendered snippet has front matter");
let metadata: crate::snippets::types::SnippetMetadata =
serde_yaml::from_str(front_matter).expect("front matter is valid YAML");
assert_eq!(
metadata.level,
Some(crate::snippets::types::ValidationLevel::TypeCheck),
"unsafe snippet ({side_effects:?}) must resolve to the typecheck cap"
);
}
}
fn rendered_snippet() -> String {
let docs = FixtureDocs {
topic: "api".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: SideEffectClass::Safe,
coverage_exceptions: BTreeMap::new(),
};
render_snippet_markdown(
"example()",
&documented_fixture(),
&docs,
"python",
DocumentationLanguage::Binding(Language::Python),
)
}
fn rendered_snippet_without_header() -> String {
let rendered = rendered_snippet();
let stripped = rendered.replace(SNIPPET_HEADER, "");
assert_ne!(stripped, rendered, "control must actually remove the header");
stripped
}
#[test]
fn rendered_snippet_carries_a_marker_the_read_side_recognises() {
assert!(crate::core::hash::content_has_alef_marker(&rendered_snippet()));
}
#[test]
fn read_side_does_not_recognise_a_snippet_without_the_header() {
assert!(!crate::core::hash::content_has_alef_marker(
&rendered_snippet_without_header()
));
}
#[test]
fn snippet_marker_lands_inside_the_read_side_scan_window() {
let rendered = rendered_snippet();
let marker_index = rendered
.lines()
.position(|line| line.contains("auto-generated by alef"))
.expect("rendered snippet carries the marker");
assert_eq!(marker_index, 9, "marker must stay on the last line of the scan window");
let widened = rendered.replacen("\nlevel: null\n", "\nlevel: null\nextra: value\n", 1);
assert!(
!crate::core::hash::content_has_alef_marker(&widened),
"one extra front-matter line must push the marker out of the scan window -- \
the budget this test guards is exactly zero lines"
);
}
#[test]
fn a_body_ending_in_a_newline_does_not_open_a_blank_line_before_the_closing_fence() {
let docs = FixtureDocs {
topic: "smoke".into(),
stem: None,
paths: BTreeMap::new(),
title: None,
description: None,
input: None,
shows: Vec::new(),
error: None,
presentation: None,
client: None,
side_effects: SideEffectClass::Safe,
coverage_exceptions: BTreeMap::new(),
};
let rendered = render_snippet_markdown(
"example()\n",
&documented_fixture(),
&docs,
"python",
DocumentationLanguage::Binding(Language::Python),
);
assert!(
rendered.ends_with("example()\n```\n"),
"closing fence must follow the last code line directly: {rendered:?}"
);
let blocks = crate::snippets::parser::extract_fenced_blocks(&rendered);
assert_eq!(blocks.len(), 1);
assert_eq!(blocks[0].code, "example()");
}
#[test]
fn snippet_header_preserves_frontmatter_and_fence_structure() {
let rendered = rendered_snippet();
assert!(rendered.starts_with("---\nid: fixture_python_extension_owned\n"));
assert_eq!(
crate::snippets::parser::frontmatter_status(&rendered),
crate::snippets::parser::FrontmatterStatus::Present
);
let blocks = crate::snippets::parser::extract_fenced_blocks(&rendered);
assert_eq!(blocks.len(), 1);
assert_eq!(blocks[0].lang, "python");
assert_eq!(blocks[0].code, "example()");
assert_eq!(
blocks[0].preceding_comment, None,
"the provenance block must not be read as a snippet annotation"
);
}
#[test]
fn snippet_marker_survives_hash_stamping() {
let rendered = rendered_snippet();
let stamped = crate::core::hash::inject_hash_line(&rendered, "abc123");
assert!(crate::core::hash::content_has_alef_marker(&stamped));
assert_eq!(crate::core::hash::extract_hash(&stamped).as_deref(), Some("abc123"));
assert!(stamped.contains("<!-- alef:hash:abc123 -->"));
assert_eq!(crate::core::hash::strip_hash_line(&stamped), rendered);
}
#[test]
fn generated_snippet_file_is_claimed_by_the_stamping_pass() {
let file = crate::core::backend::GeneratedFile {
path: PathBuf::from("docs/snippets/python/api/example.md"),
content: rendered_snippet(),
generated_header: false,
};
assert!(file.carries_alef_marker());
}
#[test]
fn write_guard_accepts_a_marked_snippet_and_refuses_an_unmarked_one() {
let relative = PathBuf::from("docs/snippets/python/api/example.md");
let updated = rendered_snippet().replace("example()", "updated_example()");
let write_over = |existing: &str| {
let directory = tempfile::tempdir().expect("temporary output directory");
let full_path = directory.path().join(&relative);
std::fs::create_dir_all(full_path.parent().expect("snippet parent")).expect("snippet directory");
std::fs::write(&full_path, existing).expect("pre-existing snippet");
let report = crate::cli::pipeline::write_scaffold_files_report(
&[crate::core::backend::GeneratedFile {
path: relative.clone(),
content: updated.clone(),
generated_header: false,
}],
directory.path(),
true,
)
.expect("scaffold write report");
(
report.changed_paths.contains(&full_path),
report.refused_paths.contains(&full_path),
std::fs::read_to_string(&full_path).expect("snippet still readable"),
)
};
let (marked_written, marked_refused, marked_content) = write_over(&rendered_snippet());
assert!(marked_written, "a marked snippet must be regenerable");
assert!(!marked_refused);
assert!(marked_content.contains("updated_example()"));
let unmarked_existing = rendered_snippet_without_header();
let (unmarked_written, unmarked_refused, unmarked_content) = write_over(&unmarked_existing);
assert!(!unmarked_written, "an unmarked snippet has no proof of authorship");
assert!(unmarked_refused);
assert_eq!(
unmarked_content, unmarked_existing,
"a refused file must be left byte-identical"
);
}
#[test]
fn write_guard_accepts_an_unmarked_snippet_the_previous_run_recorded_in_the_ledger() {
let relative = PathBuf::from("docs/snippets/python/api/example.md");
let sibling = PathBuf::from("docs/snippets/python/api/hand-written.md");
let updated = rendered_snippet().replace("example()", "updated_example()");
let existing = rendered_snippet_without_header();
let directory = tempfile::tempdir().expect("temporary output directory");
let root = directory.path().join("docs/snippets");
for path in [&relative, &sibling] {
let full = directory.path().join(path);
std::fs::create_dir_all(full.parent().expect("snippet parent")).expect("snippet directory");
std::fs::write(&full, &existing).expect("pre-existing snippet");
}
let key = SnippetCoverageKey {
fixture_id: "example".into(),
language: "python".into(),
};
let ledger = SnippetCoverageLedger {
format_version: COVERAGE_MANIFEST_VERSION,
generated_paths: vec![PathBuf::from("python/api/example.md")],
generated_metadata: vec![GeneratedSnippetMetadata {
key: key.clone(),
path: PathBuf::from("python/api/example.md"),
language: "python".into(),
target: "python".into(),
session: "python".into(),
requires: Vec::new(),
side_effect: SideEffectClass::Safe,
}],
expected: vec![key.clone()],
generated: vec![key],
missing: Vec::new(),
documented_exceptions: Vec::new(),
};
std::fs::write(
root.join(COVERAGE_MANIFEST),
serde_json::to_string(&ledger).expect("serialize ledger"),
)
.expect("write ledger");
super::ownership::snapshot_pre_run_ledger(&root);
let report = crate::cli::pipeline::write_scaffold_files_report(
&[
crate::core::backend::GeneratedFile {
path: relative.clone(),
content: updated.clone(),
generated_header: false,
},
crate::core::backend::GeneratedFile {
path: sibling.clone(),
content: updated.clone(),
generated_header: false,
},
],
directory.path(),
true,
)
.expect("scaffold write report");
let recorded = directory.path().join(&relative);
let unrecorded = directory.path().join(&sibling);
assert!(
report.changed_paths.contains(&recorded),
"a snippet the previous run recorded must be regenerable"
);
assert!(
report.refused_paths.contains(&unrecorded),
"a hand-written sibling under the same root has no record and must stay refused"
);
assert_eq!(
std::fs::read_to_string(&unrecorded).expect("sibling still readable"),
existing,
"a refused file must be left byte-identical"
);
}