use std::path::{Path, PathBuf};
const SCANNED: &[&str] = &[
"crates/codelore-lib/src",
"crates/codelore-lib/tests",
"crates/codelore-cli/src",
"crates/codelore-cli/tests",
];
fn workspace_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(2)
.expect("workspace root two levels above crates/codelore-lib")
.to_path_buf()
}
fn collect_source_files(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_source_files(&path, out);
} else if matches!(
path.extension().and_then(|e| e.to_str()),
Some("rs" | "sql")
) {
out.push(path);
}
}
}
fn is_id_token(token: &str, prefix: u8) -> bool {
let bytes = token.as_bytes();
matches!(bytes.len(), 2..=4) && bytes[0] == prefix && bytes[1..].iter().all(u8::is_ascii_digit)
}
fn is_task_id(token: &str) -> bool {
is_id_token(token, b'F')
}
fn line_has_task_id(line: &str) -> bool {
line.split(|c: char| !(c.is_ascii_alphanumeric() || c == '_'))
.any(is_task_id)
}
fn stem_opens_with_task_id(stem: &str) -> bool {
let head = stem.split('_').next().unwrap_or(stem);
is_task_id(&head.to_ascii_uppercase())
}
const PHASE_KEYWORDS: &[&str] = &["Plan", "Task", "DEEP"];
fn line_has_plan_marker(line: &str) -> bool {
PHASE_KEYWORDS
.iter()
.any(|keyword| line_has_keyword_number(line, keyword))
}
fn line_has_keyword_number(line: &str, keyword: &str) -> bool {
let bytes = line.as_bytes();
line.match_indices(keyword).any(|(start, _)| {
if start > 0 && (bytes[start - 1].is_ascii_alphanumeric() || bytes[start - 1] == b'_') {
return false;
}
let rest = line[start + keyword.len()..].trim_start_matches(' ');
let rest = rest.strip_prefix(['-', '_']).unwrap_or(rest);
rest.starts_with(|c: char| c.is_ascii_digit())
})
}
fn line_has_ticket_id(line: &str) -> bool {
line.split(|c: char| !(c.is_ascii_alphanumeric() || c == '_' || c == '}'))
.any(|token| is_id_token(token, b'T'))
}
fn scanned_files() -> Vec<PathBuf> {
let root = workspace_root();
let mut files = Vec::new();
for rel in SCANNED {
collect_source_files(&root.join(rel), &mut files);
}
assert!(
!files.is_empty(),
"scanned zero source files — source-path resolution is broken"
);
files
}
#[test]
fn no_task_id_references_in_code() {
let root = workspace_root();
let files = scanned_files();
let mut violations = Vec::new();
for file in &files {
let rel = file.strip_prefix(&root).unwrap_or(file);
if let Some(stem) = file.file_stem().and_then(|s| s.to_str())
&& stem_opens_with_task_id(stem)
{
violations.push(format!("{}: task ID in the file name", rel.display()));
}
let text = std::fs::read_to_string(file).expect("read source file");
for (line_idx, line) in text.lines().enumerate() {
if line_has_task_id(line) || line_has_ticket_id(line) {
violations.push(format!(
"{}:{}: {}",
rel.display(),
line_idx + 1,
line.trim()
));
}
}
}
assert!(
violations.is_empty(),
"found {} finding/task-ID reference(s) in .rs/.sql source (comment, string, DDL, \
or file name). Drop the ID and keep the rationale — audit history lives in \
CHANGELOG.md and the findings report, not in the code:\n{}",
violations.len(),
violations.join("\n"),
);
}
#[test]
fn no_plan_phase_markers_in_code() {
let root = workspace_root();
let files = scanned_files();
let mut violations = Vec::new();
for file in &files {
let text = std::fs::read_to_string(file).expect("read source file");
for (line_idx, line) in text.lines().enumerate() {
if line_has_plan_marker(line) {
let rel = file.strip_prefix(&root).unwrap_or(file);
violations.push(format!(
"{}:{}: {}",
rel.display(),
line_idx + 1,
line.trim()
));
}
}
}
assert!(
violations.is_empty(),
"found {} phase-number marker(s) in .rs/.sql source (comment, string, or DDL). \
Describe the current state and drop the marker — which release a feature shipped \
in is history for CHANGELOG.md, not the code:\n{}",
violations.len(),
violations.join("\n"),
);
}
#[test]
fn the_hygiene_predicates_discriminate() {
let t = |n: u32| format!("T{n}");
for line in [
format!("// {}: an author is considered departed", t(8)),
format!("// {} (foo): bar", t(42)),
format!("//! ({}) emitter note", t(11)),
format!("// {} regression guard", t(9)),
format!("// {}+{} exact match", t(1), t(2)),
] {
assert!(line_has_ticket_id(&line), "must flag a task ID: {line:?}");
}
for line in [
r#"let d = format!("2026-01-{day:02}T10:00:00Z");"#.to_string(),
format!("// INT8_C and {}_suffix identifiers", t(9)),
] {
assert!(
!line_has_ticket_id(&line),
"must NOT flag a non-ID shape: {line:?}"
);
}
assert!(line_has_plan_marker(&format!("// tracked in Plan {}", 6)));
assert!(line_has_plan_marker(&format!("// see Task {} for more", 9)));
assert!(
!line_has_plan_marker("// the plan is documented in the roadmap"),
"lowercase prose is not a marker"
);
assert!(
!line_has_plan_marker("// Task list lives in the roadmap"),
"the keyword without a number is not a marker"
);
for keyword in PHASE_KEYWORDS {
for joiner in ['-', '_', ' '] {
let line = format!("// {keyword}{joiner}{} under compat", 3);
assert!(
line_has_plan_marker(&line),
"must flag a joined marker: {line:?}"
);
}
assert!(
!line_has_plan_marker(&format!("// {keyword}-driven review notes")),
"the keyword joined to a word rather than a number is not a marker"
);
}
let f = format!("F{}", 12);
assert!(line_has_task_id(&format!("// {f}: the original shape")));
assert!(
!line_has_task_id(&format!("// _{f} stays an identifier")),
"an underscored identifier is one token and is not an ID"
);
}