Skip to content

feat(rust): validate @c4 uses against real crate deps via cargo metadata - #7

Open
nightscape wants to merge 1 commit into
GitSmart86:mainfrom
nightscape:feat/relationship-validation
Open

nightscape wants to merge 1 commit into
GitSmart86:mainfrom
nightscape:feat/relationship-validation

Conversation

@nightscape

Copy link
Copy Markdown

What

Adds archidoc ir check-deps — validates the @c4 uses relationship arrows declared in a compiled IR against the real crate→crate dependency graph, read from cargo metadata (no extra tooling).

archidoc ir check-deps <ir.json> --manifest-dir <dir> [--ignore NAME] [--strict]

Reports two kinds of drift:

  • missing — a real dependency with no @c4 uses (prints a paste-ready //! @c4 uses … line)
  • stale — an @c4 uses with no real dependency

--strict exits 1 (CI gate). workspace-hack is ignored by default.

Why

cargo_modules.rs already contained ImportGraph + validate_relationships (both drift directions) + detect_orphans, but it was dead code: never wired into the CLI, and it depends on the external cargo-modules tool (module-level). This revives that machinery with:

  1. a workspace-native, tool-free edge source (cargo metadata --no-deps, crate-level — matches @c4 component granularity), and
  2. a CLI entry point.

@c4 uses arrows in the generated C4 diagrams can now be kept honest automatically instead of silently rotting as dependencies change.

How

  • adapters/archidoc-rust/src/cargo_metadata.rsworkspace_import_graph() builds the existing ImportGraph; validate_ir_relationships() diffs a compiled ArchitectureIR against it, reusing RelationshipWarning / WarningKind.
  • core/archidoc-cli — new ir check-deps subcommand.
  • 3 unit tests (clean / missing+stale / ignore-list).

Validated against a real 20+ crate workspace: a fully-declared IR passes; a perturbed IR correctly reports the injected missing + stale edges.

🤖 Generated with Claude Code

Add a workspace-native dependency source and a `ir check-deps` CLI command
that diffs declared `@c4 uses` arrows against the real crate→crate graph.

- adapters/archidoc-rust/cargo_metadata.rs: workspace_import_graph() reads
  `cargo metadata --no-deps` (no external tooling, unlike the cargo-modules
  path) into the existing ImportGraph; validate_ir_relationships() diffs a
  compiled IR's relationships against it, reusing RelationshipWarning.
- archidoc ir check-deps <ir> --manifest-dir <dir> [--ignore N] [--strict]:
  reports `missing` (real dep, no @C4 uses — prints paste-ready line) and
  `stale` (declared @C4 uses, no real dep). --strict exits 1 for CI.
- Revives the previously dead validate_relationships/ImportGraph machinery
  by giving it a tool-free, crate-level edge source and a CLI entry point.
- workspace-hack ignored by default. 3 unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new archidoc ir check-deps command to detect drift between declared @c4 uses relationships in compiled IR and actual Rust workspace crate dependencies using cargo metadata.

Changes:

  • Introduces IrCommand::CheckDeps and CLI handler to report missing vs stale @c4 uses edges (optionally CI-gating via --strict).
  • Adds a new archidoc-rust::cargo_metadata adapter for building crate-level graphs from cargo metadata and validating IR relationships.
  • Wires up the new adapter module and adds serde_json dependency for parsing metadata.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

File Description
core/archidoc-cli/src/main.rs Adds the ir check-deps subcommand and output/exit-code behavior for drift detection.
adapters/archidoc-rust/src/lib.rs Exposes the new cargo_metadata module publicly.
adapters/archidoc-rust/src/cargo_metadata.rs Implements dependency graph extraction from cargo metadata and validation against IR @c4 uses, with unit tests for validation.
adapters/archidoc-rust/Cargo.toml Adds serde_json for parsing Cargo metadata JSON.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +49 to +58
let packages = meta["packages"]
.as_array()
.ok_or("`cargo metadata` JSON has no `packages` array")?;

let members: HashSet<String> = packages
.iter()
.filter_map(|p| p["name"].as_str())
.map(str::to_string)
.filter(|n| !ignore.contains(n))
.collect();
Comment on lines +65 to +82
for pkg in packages {
let from = match pkg["name"].as_str() {
Some(n) if members.contains(n) => n.to_string(),
_ => continue,
};
let deps = match pkg["dependencies"].as_array() {
Some(d) => d,
None => continue,
};
for dep in deps {
// `kind` is null for normal deps, "dev"/"build" otherwise.
if !dep["kind"].is_null() {
continue;
}
let to = match dep["name"].as_str() {
Some(n) if members.contains(n) && n != from => n.to_string(),
_ => continue,
};
Comment on lines +83 to +86
let edge = (from.clone(), to);
if !graph.edges.contains(&edge) {
graph.edges.push(edge);
}
Comment on lines +263 to +269
/// Check declared `@c4 uses` relationships against real crate dependencies
///
/// Reads the actual crate→crate dependency graph from `cargo metadata`
/// (no extra tooling) and diffs it against the `@c4 uses` arrows declared
/// in a compiled IR. Reports two kinds of drift:
/// missing — a real dependency with no `@c4 uses` (add the arrow)
/// stale — an `@c4 uses` with no real dependency (remove the arrow)
Comment on lines +149 to +152
warnings.sort_by(|a, b| {
(&a.module, &a.target, a.kind.clone() as u8)
.cmp(&(&b.module, &b.target, b.kind.clone() as u8))
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants