Skip to content

Commit 3d7333b

Browse files
authored
fix: make parity test resilient with workspace_root() helper (#153)
* fix: make parity test resilient with workspace_root() helper Closes #90 * docs: add CHANGELOG entry for parity test resilience * fix: add clearer error messages for file reads in parity test Addresses Copilot review feedback.
1 parent bdf49ce commit 3d7333b

2 files changed

Lines changed: 35 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
- Backward compatibility maintained - old configs with these fields still parse correctly
2121

2222
### Fixed
23+
- CLAUDE/AGENTS parity test now resilient to different directory structures (worktrees, symlinks)
24+
- Replaced brittle `.ancestors().nth(2)` with dynamic workspace root detection
25+
- New `workspace_root()` helper searches for `[workspace]` in ancestor Cargo.toml files
2326
- JSON output `files_checked` now correctly reports total validated files, not just files with diagnostics
2427
- CLI `--target` flag now validates values instead of silently falling back to "generic"
2528
- Invalid values rejected with helpful error message showing valid options

crates/agnix-core/src/lib.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,28 @@ fn resolve_validation_root(path: &Path) -> PathBuf {
485485
mod tests {
486486
use super::*;
487487

488+
fn workspace_root() -> &'static Path {
489+
use std::sync::OnceLock;
490+
491+
static ROOT: OnceLock<PathBuf> = OnceLock::new();
492+
ROOT.get_or_init(|| {
493+
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
494+
for ancestor in manifest_dir.ancestors() {
495+
let cargo_toml = ancestor.join("Cargo.toml");
496+
if let Ok(content) = std::fs::read_to_string(&cargo_toml) {
497+
if content.contains("[workspace]") || content.contains("[workspace.") {
498+
return ancestor.to_path_buf();
499+
}
500+
}
501+
}
502+
panic!(
503+
"Failed to locate workspace root from CARGO_MANIFEST_DIR={}",
504+
manifest_dir.display()
505+
);
506+
})
507+
.as_path()
508+
}
509+
488510
#[test]
489511
fn test_detect_skill_file() {
490512
assert_eq!(detect_file_type(Path::new("SKILL.md")), FileType::Skill);
@@ -539,14 +561,16 @@ mod tests {
539561

540562
#[test]
541563
fn test_repo_agents_md_matches_claude_md() {
542-
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
543-
let repo_root = manifest_dir
544-
.ancestors()
545-
.nth(2)
546-
.expect("Failed to locate repo root from CARGO_MANIFEST_DIR");
564+
let repo_root = workspace_root();
547565

548-
let claude = std::fs::read_to_string(repo_root.join("CLAUDE.md")).unwrap();
549-
let agents = std::fs::read_to_string(repo_root.join("AGENTS.md")).unwrap();
566+
let claude_path = repo_root.join("CLAUDE.md");
567+
let claude = std::fs::read_to_string(&claude_path).unwrap_or_else(|e| {
568+
panic!("Failed to read CLAUDE.md at {}: {e}", claude_path.display());
569+
});
570+
let agents_path = repo_root.join("AGENTS.md");
571+
let agents = std::fs::read_to_string(&agents_path).unwrap_or_else(|e| {
572+
panic!("Failed to read AGENTS.md at {}: {e}", agents_path.display());
573+
});
550574

551575
assert_eq!(agents, claude, "AGENTS.md must match CLAUDE.md");
552576
}
@@ -1499,13 +1523,7 @@ Run npm install and npm build.
14991523

15001524
/// Helper to locate the fixtures directory for testing
15011525
fn get_fixtures_dir() -> PathBuf {
1502-
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
1503-
manifest_dir
1504-
.ancestors()
1505-
.nth(2)
1506-
.expect("Failed to locate repo root")
1507-
.join("tests")
1508-
.join("fixtures")
1526+
workspace_root().join("tests").join("fixtures")
15091527
}
15101528

15111529
#[test]

0 commit comments

Comments
 (0)