use std::path::{Path, PathBuf};
fn repo() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).to_path_buf()
}
fn agent_facing_documents() -> Vec<PathBuf> {
let mut found = vec![repo().join("AGENTS.md")];
for dir in [".claude/commands", ".claude/agents", ".claude/skills"] {
let mut here = Vec::new();
collect_markdown(&repo().join(dir), &mut here);
assert!(
!here.is_empty(),
"no markdown under {dir}: scanning nothing"
);
found.extend(here);
}
found
}
fn collect_markdown(dir: &Path, out: &mut Vec<PathBuf>) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
collect_markdown(&path, out);
} else if path.extension().is_some_and(|e| e == "md") {
out.push(path);
}
}
}
fn read(relative: &str) -> String {
std::fs::read_to_string(repo().join(relative))
.unwrap_or_else(|e| panic!("cannot read {relative}: {e}"))
}
fn backticked(text: &str) -> Vec<String> {
let mut prose = String::new();
let mut rest = text;
while let Some(start) = rest.find("```") {
prose.push_str(&rest[..start]);
let after = &rest[start + 3..];
match after.find("```") {
Some(end) => rest = &after[end + 3..],
None => {
rest = "";
break;
}
}
}
prose.push_str(rest);
prose
.split('`')
.skip(1)
.step_by(2)
.map(str::to_string)
.collect()
}
fn unwrapped(text: &str) -> String {
text.split_whitespace().collect::<Vec<_>>().join(" ")
}
fn section_from<'a>(text: &'a str, needle: &str, until: &str) -> &'a str {
let start = text
.find(needle)
.unwrap_or_else(|| panic!("this document has no `{needle}`"));
let rest = &text[start..];
match rest[needle.len()..].find(until) {
Some(offset) => &rest[..needle.len() + offset],
None => rest,
}
}
fn step_about<'a>(text: &'a str, about: &str) -> &'a str {
let heading = text
.lines()
.filter(|line| line.starts_with("## "))
.find(|line| line.to_ascii_lowercase().contains(about))
.unwrap_or_else(|| panic!("no step about `{about}`"));
section_from(text, heading, "\n## ")
}
fn number_word(word: &str) -> Option<usize> {
const WORDS: &[&str] = &[
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
];
let word = word.trim_matches(|c: char| !c.is_ascii_alphabetic());
let word = word.to_ascii_lowercase();
WORDS.iter().position(|w| *w == word)
}
fn number_in(sentence: &str) -> Option<usize> {
sentence.split_whitespace().find_map(number_word)
}
fn numbered_headings(text: &str) -> Vec<usize> {
text.lines()
.filter_map(|line| line.strip_prefix("## "))
.filter_map(|rest| rest.split('.').next()?.parse().ok())
.collect()
}
fn numbered_items(text: &str) -> Vec<usize> {
text.lines()
.filter_map(|line| {
let (head, rest) = line.split_once(". ")?;
if rest.starts_with("**") {
head.parse().ok()
} else {
None
}
})
.collect()
}
fn assert_contiguous(numbers: &[usize], what: &str) {
assert!(
!numbers.is_empty(),
"{what}: found no numbered steps at all"
);
let expected: Vec<usize> = (1..=numbers.len()).collect();
assert_eq!(
numbers,
expected,
"{what}: the steps are numbered {numbers:?}, which is not 1..{}",
numbers.len()
);
}
#[test]
fn implement_numbers_its_steps_in_order() {
let text = read(".claude/commands/implement.md");
assert_contiguous(&numbered_headings(&text), "/implement");
}
#[test]
fn agents_md_counts_the_steps_it_lists() {
let text = read("AGENTS.md");
let section = section_from(&text, "## Working on a change", "\n## ");
let steps = numbered_items(section);
assert_contiguous(&steps, "AGENTS.md");
let claim = section
.lines()
.find(|line| line.contains("does all "))
.expect("AGENTS.md never says how many steps /implement does");
let word = claim
.split("does all ")
.nth(1)
.and_then(|rest| rest.split(['.', ' ']).next())
.expect("cannot read the number out of that sentence");
let claimed =
number_word(word).unwrap_or_else(|| panic!("`{word}` is not a number this test knows"));
assert_eq!(
claimed,
steps.len(),
"AGENTS.md lists {} steps and then says /implement does all {word}",
steps.len()
);
}
#[test]
fn the_pull_request_template_asks_as_many_questions_as_it_says() {
let text = read(".github/pull_request_template.md");
let sections = text.lines().filter(|l| l.starts_with("## ")).count();
let claim = text
.lines()
.find(|line| line.contains(" questions"))
.expect("the template never says how many questions it asks");
let claimed =
number_in(claim).unwrap_or_else(|| panic!("no number this test knows in: {claim}"));
assert_eq!(
claimed, sections,
"the template has {sections} sections and says: {claim}"
);
}
#[test]
fn the_documentation_points_at_files_that_exist() {
let mut missing = Vec::new();
for doc in agent_facing_documents() {
let name = doc
.strip_prefix(repo())
.unwrap_or(&doc)
.display()
.to_string();
let text =
std::fs::read_to_string(&doc).unwrap_or_else(|e| panic!("cannot read {name}: {e}"));
for span in backticked(&text) {
let looks_like_a_path = span.contains('/')
&& !span.contains(' ')
&& (span.ends_with(".rs")
|| span.ends_with(".md")
|| span.ends_with(".toml")
|| span.ends_with(".yml")
|| span.ends_with('/'));
if !looks_like_a_path || span.starts_with("target/") {
continue;
}
let path = repo().join(span.trim_end_matches('/'));
if !path.exists() {
missing.push(format!(" {name}: `{span}`"));
}
}
}
assert!(
missing.is_empty(),
"documentation names {} path(s) that do not exist:\n{}",
missing.len(),
missing.join("\n")
);
}
#[test]
fn the_review_comes_after_the_commits() {
let text = read(".claude/commands/implement.md");
let step = |needle: &str| -> usize {
text.lines()
.filter_map(|line| line.strip_prefix("## "))
.find(|heading| heading.to_ascii_lowercase().contains(needle))
.and_then(|heading| heading.split('.').next()?.parse().ok())
.unwrap_or_else(|| panic!("/implement has no step about `{needle}`"))
};
let commit = step("commit");
let review = step("read by");
assert!(
review > commit,
"the review is step {review} and the commits are step {commit}: its \
criteria ask about commits that would not exist yet"
);
let cleanup = step("clean it up");
let harness = step("run the harness");
for (doc, name) in [(&text, "/implement"), (&read("AGENTS.md"), "AGENTS.md")] {
assert!(
doc.contains("`/simplify`"),
"{name} never names `/simplify`, so the cleanup is a heading with \
nothing behind it"
);
}
assert!(
cleanup < harness && cleanup < commit && cleanup < review,
"the cleanup is step {cleanup}, the harness {harness}, the commits \
{commit} and the review {review}: a pass that edits the code has to \
run before every pass that checks it"
);
}
#[test]
fn the_report_back_matches_the_template() {
let implement = read(".claude/commands/implement.md");
let template = read(".github/pull_request_template.md");
let claim = implement
.lines()
.find(|line| line.contains("report back, in "))
.expect("/implement never says how many lines to report back");
let claimed =
number_in(claim).unwrap_or_else(|| panic!("no number this test knows in: {claim}"));
let sections = template.lines().filter(|l| l.starts_with("## ")).count();
assert_eq!(
claimed, sections,
"the template asks {sections} questions and /implement says: {claim}"
);
}
#[test]
fn the_review_step_still_says_what_it_is_for() {
let implement = read(".claude/commands/implement.md");
let review_step = implement
.split("\n## ")
.find(|section| {
section
.lines()
.next()
.is_some_and(|heading| heading.to_ascii_lowercase().contains("read by"))
})
.expect("/implement has no step about having the change read");
assert!(
review_step.contains(".claude/agents/reviewer.md"),
"the review step keeps no copy of the criteria, so naming the file that \
holds them is the whole of it — and it does not"
);
assert!(
review_step.contains("One pass"),
"the review step does not say it is one pass, and a review with no \
stopping rule is a review that runs until somebody gets tired"
);
assert!(
review_step.contains("Blocks") && review_step.contains("Note"),
"the review step does not say what to do with each level of finding"
);
assert!(
review_step.contains("did not run"),
"the review step does not say what to do when the review does not run, \
and a review that did not run looks exactly like one that found nothing"
);
let template = read(".github/pull_request_template.md");
assert!(
template
.lines()
.any(|l| l.starts_with("## ") && l.contains("review")),
"the pull request template has no section asking what the review found"
);
let agents = read("AGENTS.md");
assert!(
agents.contains("`reviewer` subagent"),
"AGENTS.md's list of what a change goes through never mentions the \
reviewer, so the step exists only in the command"
);
}
#[test]
fn the_reviewer_and_the_command_use_the_same_levels() {
const LEVELS: [&str; 3] = ["Blocks", "Worth answering", "Note"];
let reviewer = read(".claude/agents/reviewer.md");
let implement = read(".claude/commands/implement.md");
for level in LEVELS {
assert!(
reviewer.contains(level),
"the reviewer never defines `{level}`, so nothing it reports can \
carry that level and the command sorts into an empty box"
);
assert!(
implement.contains(level),
"/implement never says what to do with `{level}`"
);
}
assert!(
reviewer.contains("how many block"),
"the reviewer gives no verdict, so `zero blocking findings is the pass` \
has nothing to read"
);
}
#[test]
fn researching_a_design_decision_is_asked_for_where_the_alternatives_are_written() {
let agents = unwrapped(&read("AGENTS.md"));
let spec = unwrapped(&read(".claude/commands/spec.md"));
const RULE: &str = "A design decision that is not obvious is researched before it is proposed.";
assert!(
agents.contains(RULE),
"AGENTS.md does not carry the research rule, so nothing states it"
);
assert!(
spec.contains(RULE),
"/spec is the command that writes alternatives down and does not ask \
for the research behind them — the rule would exist only in the \
contract, where nothing invokes it"
);
const SLOT: &str = "**Prior art**";
assert!(
spec.contains(SLOT),
"/spec asks for research and its issue body has no {SLOT} for the \
answer, so the sources have nowhere to go"
);
}
#[test]
fn a_new_thread_local_is_questioned_where_it_is_listed() {
let agents = unwrapped(&read("AGENTS.md"));
let reviewer = unwrapped(&read(".claude/agents/reviewer.md"));
const TEST: &str = "tests/ambient_state_inventory.rs";
const TABLE: &str = "**Ambient state**";
for (name, text) in [("AGENTS.md", &agents), ("the reviewer", &reviewer)] {
assert!(
text.contains(TEST) && text.contains(TABLE),
"{name} does not name both {TEST} and the {TABLE} table, so one half \
of the thread-local rule is missing from it"
);
}
assert!(
reviewer.contains("could carry the value"),
"the reviewer names the table but no longer asks whether the reason holds"
);
}
#[test]
fn what_is_left_undone_is_given_a_home_outside_the_pull_request() {
const RULE: &str = "gets an issue in the same act";
let agents = read("AGENTS.md");
let implement = read(".claude/commands/implement.md");
let template = read(".github/pull_request_template.md");
let step_seven = section_from(&agents, "**Open the pull request**", "\n\n");
for (name, section) in [
("AGENTS.md's step 7", step_seven),
(
"/implement's step about the pull request",
step_about(&implement, "pull request"),
),
(
"the template's `Left undone`",
section_from(&template, "## Left undone", "\n## "),
),
] {
assert!(
unwrapped(section).contains(RULE),
"{name} does not say that what is left undone `{RULE}`, so it is \
recorded only where a merged pull request keeps it"
);
}
assert!(
unwrapped(step_seven)
.to_ascii_lowercase()
.contains("left undone"),
"AGENTS.md's step 7 lists what the template asks and leaves out the one \
question whose answer points past this change"
);
}
#[test]
fn an_issue_is_what_clears_a_bar_rather_than_whatever_is_left_over() {
const TRIAGE: &str = "worse off";
let agents = read("AGENTS.md");
let reviewer = read(".claude/agents/reviewer.md");
let template = read(".github/pull_request_template.md");
for (name, section) in [
(
"AGENTS.md's step 7",
section_from(&agents, "**Open the pull request**", "\n\n## "),
),
(
"the template's `Left undone`",
section_from(&template, "## Left undone", "\n## "),
),
(
"the reviewer's `Note` level",
section_from(&reviewer, "- **Note.**", "\n\n"),
),
] {
assert!(
unwrapped(section).contains(TRIAGE),
"{name} does not ask who is `{TRIAGE}` today, so nothing separates \
the follow-up that earns an issue from the one that is a nit"
);
}
assert!(
!unwrapped(&reviewer).contains("the pull request or an issue"),
"the reviewer offers a note both homes and no criterion, which is the \
sentence the bar exists to replace"
);
}