fix: more strict check for registry to avoid false positives#2222
fix: more strict check for registry to avoid false positives#2222serrrfirat merged 4 commits intonearai:stagingfrom
Conversation
By default ironclaw gets installed in ~/.cargo/bin/ironclaw, if the user happens to try to compile anything (e.g. their own tool) then the ~/.cargo/registry folder gets created, which makes ironclaw think that it found an (empty) registry, and thus stops being able to do list or install tools from its internal registry
There was a problem hiding this comment.
Pull request overview
Fixes false-positive detection of an on-disk registry/ directory (notably ~/.cargo/registry) so ironclaw registry list/install continues to work by falling back to the embedded registry when a real internal registry isn’t present.
Changes:
- Replace
candidate.is_dir()checks with a stricteris_registry()predicate during registry discovery. - Add unit tests covering
is_registry()accept/reject cases. - Update
build.rsto add directory-levelcargo:rerun-if-changedentries for registry subdirectories.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/registry/catalog.rs | Introduces is_registry() and applies it in find_dir(); adds tests for the new predicate. |
| build.rs | Adds directory-level Cargo rerun triggers for registry subdirectories to detect add/remove changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// i.e. it contains `_bundles.json` or at least one of the known subdirectories | ||
| /// (`tools/`, `channels/`, `mcp-servers/`). This prevents accidentally matching | ||
| /// unrelated directories named "registry" such as `~/.cargo/registry/`. | ||
| fn is_registry(dir: &Path) -> bool { | ||
| if !dir.is_dir() { | ||
| return false; | ||
| } | ||
| dir.join("_bundles.json").is_file() | ||
| || dir.join("tools").is_dir() | ||
| || dir.join("channels").is_dir() | ||
| || dir.join("mcp-servers").is_dir() |
There was a problem hiding this comment.
The is_registry heuristic will treat any directory named registry that merely contains an empty tools/, channels/, or mcp-servers/ subdirectory as a valid registry. That can still lead to the original failure mode (finding a “valid” registry that contains no manifests) if a user/project happens to have registry/tools present but empty or unrelated. Consider tightening this to require _bundles.json OR at least one *.json manifest file under one of the known subdirectories (e.g., via read_dir + extension check).
| /// i.e. it contains `_bundles.json` or at least one of the known subdirectories | |
| /// (`tools/`, `channels/`, `mcp-servers/`). This prevents accidentally matching | |
| /// unrelated directories named "registry" such as `~/.cargo/registry/`. | |
| fn is_registry(dir: &Path) -> bool { | |
| if !dir.is_dir() { | |
| return false; | |
| } | |
| dir.join("_bundles.json").is_file() | |
| || dir.join("tools").is_dir() | |
| || dir.join("channels").is_dir() | |
| || dir.join("mcp-servers").is_dir() | |
| /// i.e. it contains `_bundles.json` or at least one manifest file in one of the | |
| /// known subdirectories (`tools/`, `channels/`, `mcp-servers/`). This prevents | |
| /// accidentally matching unrelated directories named "registry" such as | |
| /// `~/.cargo/registry/`. | |
| fn has_json_manifest(dir: &Path, subdir: &str) -> bool { | |
| let manifest_dir = dir.join(subdir); | |
| if !manifest_dir.is_dir() { | |
| return false; | |
| } | |
| let Ok(entries) = std::fs::read_dir(&manifest_dir) else { | |
| return false; | |
| }; | |
| entries.flatten().any(|entry| { | |
| entry.path().is_file() | |
| && entry | |
| .path() | |
| .extension() | |
| .and_then(|ext| ext.to_str()) | |
| .map(|ext| ext.eq_ignore_ascii_case("json")) | |
| .unwrap_or(false) | |
| }) | |
| } | |
| fn is_registry(dir: &Path) -> bool { | |
| if !dir.is_dir() { | |
| return false; | |
| } | |
| dir.join("_bundles.json").is_file() | |
| || Self::has_json_manifest(dir, "tools") | |
| || Self::has_json_manifest(dir, "channels") | |
| || Self::has_json_manifest(dir, "mcp-servers") |
There was a problem hiding this comment.
I actually do not agree with this. Hitting an empty registry/ folder was highly likely (I did it multiple times), hitting an empty registry/tools/ or registry/channels/ or registry/mcp-servers seams unlikely in the wild and thus, in case of doing so, should hint that there is actually an empty registry
with that being said, I do think that the real solution is to change the registry logic, and place it inside the config folder (e.g. ~/.ironclaw/registry), but that is work for a different PR
because of that, I assume that this fix is "good enough" as of right now, except if another human reviewer provides a different opinion
There was a problem hiding this comment.
Code Review
This pull request improves the registry directory detection logic by introducing a helper method is_registry that validates directory contents, preventing accidental matches with unrelated directories. It also updates the build script to include additional directory-level watches for registry subdirectories and adds unit tests to verify the new detection logic. I have no further feedback, except for a minor suggestion to convert a regular comment into a documentation comment for consistency.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
By default ironclaw gets installed in ~/.cargo/bin/ironclaw, if the user happens to try to compile anything (e.g. their own tool) then the ~/.cargo/registry folder gets created, which makes ironclaw think that it found an (empty) registry, and thus stops being able to do list or install tools from its internal registry
Change Type
Linked Issue
Closes #2221
Validation
cargo fmt --all -- --checkcargo testcargo clippy --all --benches --tests --examples --all-features -- -D warningscargo buildcargo test --features integrationif database-backed or integration behavior changedregistryfolder on parent directory, and tested thatironclaw registry liststill workedreview-prorpr-shepherd --fixwas run before requesting reviewSecurity Impact
None
Database Impact
None
Blast Radius
Registry load
Rollback Plan
Revert
is_registryto simply check foris_dirReview track: A or B