use std::path::Path;
use crate::rules::{Evidence, Examine, Finding, Rule, Stance, Trend};
use crate::shell::Parsed;
pub const RULE: Rule = Rule {
id: "agent-guidance-written",
default_stance: Stance::Advise,
max_stance: Stance::Advise,
evidence: Evidence {
per_1000: 0.66,
measured: "2026-10-13",
trend: Trend::Rare,
},
examine: Examine::Legacy(examine),
confirm: None,
};
fn examine(_parsed: &Parsed) -> Option<Finding> {
None
}
pub fn is_guidance(path: &Path) -> bool {
let Some(name) = path.file_name().and_then(|n| n.to_str()) else {
return false;
};
if matches!(
name,
"SKILL.md" | "CLAUDE.md" | "CLAUDE.md.tmpl" | "AGENTS.md" | "MEMORY.md"
) {
return true;
}
if !name.ends_with(".md") {
return false;
}
let mut parents = path.components().rev().skip(1);
let dir = parents.next().and_then(|c| c.as_os_str().to_str());
let up = parents.next().and_then(|c| c.as_os_str().to_str());
dir == Some("agents") && matches!(up, Some(".claude") | Some("dot_claude"))
}
pub fn phrase(shown: &str) -> String {
let file = Path::new(shown)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or(shown);
crate::decision::phrase(
RULE.id,
&format!("`{file}` is agent guidance: the `guidance.*` and `prose.*` rules apply (ADR-0026, ADR-0032)."),
&format!("`aval relevant --path {shown}` lists them."),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn guidance_paths_are_recognised() {
for p in [
"a/SKILL.md",
"CLAUDE.md",
"dot_claude/CLAUDE.md.tmpl",
"r/AGENTS.md",
"m/MEMORY.md",
"r/.claude/agents/reviewer.md",
"r/dot_claude/agents/reviewer.md",
] {
assert!(is_guidance(Path::new(p)), "{p}");
}
}
#[test]
fn other_files_are_not_guidance() {
for p in [
"src/main.rs",
"m/feedback_x.md",
"README.md",
"r/agents/reviewer.md",
".claude/agents/notes.txt",
".claude/agents",
] {
assert!(!is_guidance(Path::new(p)), "{p}");
}
}
#[test]
fn the_advice_names_the_file_the_adrs_and_the_command() {
let t = phrase("/r/skills/x/SKILL.md");
assert!(t.contains("`SKILL.md`"), "{t}");
assert!(t.contains("ADR-0026") && t.contains("ADR-0032"), "{t}");
assert!(
t.contains("aval relevant --path /r/skills/x/SKILL.md"),
"{t}"
);
}
}