Repository navigation
Conversation
🟢 Tier S · Ready to merge
Moves dependency discovery to abnegate-vcs and centralizes configured-path scanning and persistence. Configured paths now expand
📂 Walkthrough · 7
Reviewed |
abnegate-vcs's DependencyDiscovery was donated from claudear's repo/discovery.rs and has been hardened in the crate since, so claudear now uses the published crate (0.1.3, default features, no `github`) and drops its own copy. repo/mod.rs re-exports DependencyDiscovery, DiscoveredDependency and Manifest, so `claudear::DependencyDiscovery` and `claudear::repo::*` keep working. The crate's DiscoveredDependency names its fields repository, depends_on, manifest (an enum) and repository_path (a PathBuf), and its scans return the dependencies directly instead of a Result that could never be an error, so the unreachable "discovery failed" branches are gone. `repos index`, `repos sync` and the daemon's Watcher each carried the same scan, warn and count loop. It now lives in the repo domain: discover_configured scans the configured paths (still literally, as before) and save_discovered stores each dependency, warning on and skipping one that fails. `repos index`, `repos sync` and `repos discover` scan through discover_configured, and `repos index`, `repos sync` and the Watcher save through save_discovered. `repos discover --save` keeps its own loop because it also records each repository's path and stops at the first storage error. What is stored is now chosen by relationships::dependency_type, which maps a Manifest to the DependencyType a cascade loads back, so the string written is DependencyType::as_str() rather than the crate's naming. Manifest is non-exhaustive: a manifest kind claudear does not cascade through is logged and skipped where it would be saved. Behaviour that changes with the crate: - A package named in both require and require-dev (or dependencies and devDependencies, or as both @org/x and org/x) is reported once per manifest, and each manifest's dependencies come back sorted. - A Composer section PHP encoded as an empty list (`"require": []`) no longer makes the whole manifest unreadable, so require-dev and the manifest's name still count. - A manifest that is a symlink is skipped, and an unreadable manifest is logged as a warning instead of being ignored silently. - A leading `@` is stripped from Composer package names too, not only npm ones. - `repos discover --save` reports how many dependencies it saved rather than how many it found. - `repos index` and `repos sync` say "No dependencies found under auto_discover_paths." when the scan finds nothing, since they scan those paths rather than the indexed repositories. Tests pin what claudear relies on: every Manifest maps to a DependencyType whose string parses back; a configured directory of checkouts is read one level down, with names from composer.json, then package.json without its scope, then the directory; a configured repository that declares dependencies is not descended into; and the Watcher stores a discovered dependency as a row that loads back as a Composer DependencyType. Cargo.lock gains abnegate-vcs and abnegate-secret 0.1.3 and moves tokio to 1.53 (with mio, socket2, libc and zeroize), the minimum abnegate-vcs requires. tokio-macros is held at 2.7.0, because 2.7.2 pulls in syn 3. This adds second majors of dirs (7), base64 (0.23), and abnegate-secret's aes-gcm stack (aes-gcm 0.11, aes 0.9, aead 0.6, cipher 0.5, ctr 0.10, ghash 0.6, polyval 0.7, universal-hash 0.6, inout 0.2), plus nix 0.31. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ncies The dependency scanner takes paths literally, and so did claudear's own copy before it, while build_repo_index expands `~`. With the documented `auto_discover_paths = ["~/Local"]`, `repos index` and `repos sync` indexed the repositories under the home directory but scanned a relative `~/Local` that does not exist, and found no dependencies. The same was true of `repos discover` with no `--paths`, or with a quoted `--paths '~/Local'` that the shell leaves alone. The daemon was not affected, because it scans the absolute paths of the repositories it indexed. discover_configured now resolves `~` the way the index does, through the shared expand_path_in, before it scans. With `~/Local` resolved, those commands now read every checkout one level below it. Forks and third-party projects that depend on a known organisation therefore become downstream rows too. That does no harm: a cascade skips a downstream it cannot resolve to a repository, and logs it. expand_path used to treat any leading `~` as the current user's home, so `~other/projects` became `$HOME/other/projects`. It now expands only `~` and `~/...` and leaves another user's home as written. `~//x` no longer joins as the absolute path `/x`. The home directory can be injected, so the tests no longer read or write under the real home. The regression test scans a configured `~/Local` under a temporary home. Scanning the paths literally again inside discover_configured turns it red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User-visible changes
~inauto_discover_pathsnow works for dependency discovery.claudear repos indexandclaudear repos syncscanned the documentedauto_discover_paths = ["~/Local"]as the literal relative path~/Local. They indexed the repositories, becausebuild_repo_indexexpands~, but found no dependencies.repos discoverbehaved the same with no--paths, or with a quoted--paths '~/Local'. All three now expand~the way the index does. The daemon was not affected, because it scans the absolute paths of indexed repositories.~/Localresolved,repos indexandrepos syncread every checkout one level below it. Forks and third-party projects that depend on a known organisation become downstream rows as well. This does no harm: a cascade skips a downstream it cannot resolve to an indexed repository, and logs it.~user/...is no longer expanded to$HOME/user/.... Only~and~/...are expanded. This affectsbuild_repo_indexas well.repos indexandrepos syncprint "No dependencies found under auto_discover_paths." (was "No dependencies found between indexed repos.").repos discover --savenow reports how many dependencies it saved rather than how many it found.auto_discover_pathsis still a list of strings.Commits
refactor(analysis): discover dependencies through abnegate-vcsmoves to the crate and keeps the old literal-path behaviour.fix(cli): expand ~ in auto_discover_paths before scanning for dependenciesadds the expansion and its regression test. The test is red without the fix, as described under Tests.What changed
crates/claudear-analysis/src/repo/discovery.rs. Dependency discovery now comes from the publishedabnegate-vcs = "0.1.3"(default features, nogithub). claudear donated this code to the crate, which has hardened it since.repo/mod.rsre-exportsDependencyDiscovery,DiscoveredDependencyandManifestfromabnegate_vcs, soclaudear::DependencyDiscovery,claudear::DiscoveredDependencyandclaudear::repo::*resolve as before.repo/dependencies.rsholds the repo-domain functions that replace three copies of one scan, warn and count loop:discover_configured(known_orgs, paths)scans configured path strings, with~expanded (commit 2).save_discovered(tracker, dependencies) -> usizestores each dependency, and warns on and skips any it cannot save.repos index,repos syncandrepos discoverscan throughdiscover_configured.repos index,repos syncandWatcher::discover_dependenciessave throughsave_discovered.repos discover --savekeeps its own loop, because it also records each repository's path and stops at the first storage error.relationships::dependency_type(Manifest) -> Option<DependencyType>decides what is stored, and the stored string is nowDependencyType::as_str(). For Composer and npm that is the same"composer"/"npm"as before.Manifestis#[non_exhaustive], so a kind claudear does not cascade through is logged and skipped wherever it would be saved.repo/index.rs:expand_pathdelegates toexpand_path_in(path, home)(commit 2), so tests can inject the home directory.repo→repositorydep_type: String→manifest: Manifestrepo_path: String→repository_path: PathBufVecrather than aResultthat could never be an error, so the unreachable "dependency discovery failed" branches are gone.index.rs,relationships.rsand therepos indexarm;repo_paths→repository_paths,dep_pb→dependency_progress;db_tracker→trackeracross thereposcommand block.abnegate-vcsandabnegate-secret0.1.3.tokio-macrosat 2.7.0, because 2.7.2 pulls in syn 3.dirs7,base640.23, and abnegate-secret's aes-gcm stack (aes-gcm0.11,aes0.9,aead0.6,cipher0.5,ctr0.10,ghash0.6,polyval0.7,universal-hash0.6,inout0.2).nix0.31.Why the config field stays
Vec<String>The plan proposed turning
auto_discover_pathsintoVec<PathBuf>. This PR converts only where the crate needs a path, insidediscover_configured. The field holds paths as a user writes them,~included. Changing its type would have moved the expansion into claudear-config at load time. It would also have changedbuild_repo_index,build_repo_index_with_fallback,RepoInferrer::with_discovery, the e2e builder and the config tests, and none of that gains anything.Behaviour differences
~in configured or--pathspaths~and~/...expanded before the scan (commit 2)~user/...$HOME/user/...(index only)requireandrequire-dev, or in bothdependenciesanddevDependencies, or written as both@org/xandorg/x, was reported twiceON CONFLICT. Therepos discovercount and listing shrinkHashMaporder. Composer before npmread_dirorder"require": [](PHP's empty object)composer.jsonfailed to parse, losingrequire-devandnamewarnlogwarnlog@@)dep_typestringDependencyType::as_str()viadependency_type. Same strings for Composer and npmcomposer.json(require,require-dev),package.json(dependencies,devDependencies)name, then thepackage.jsonnamewithout@, then the directory name/Tests
These are claudear-level tests through claudear's own functions. Tests that duplicated the crate's own suite were not ported: private helpers, struct construction, the PHP empty-list section, and empty or missing paths.
relationships::test_every_manifest_maps_to_a_dependency_type_stored_as_it_parses_back: the string contract between saving and the cascade loader.dependencies::test_a_configured_directory_of_checkouts_is_read_one_level_down: an~/Local-style root covering:requireandrequire-dev, with a duplicate collapsed;repository_pathvalues.dependencies::test_a_configured_repository_that_declares_dependencies_is_not_read_one_level_downdependencies::test_a_configured_home_relative_path_is_scanned_in_the_home_directory(commit 2): scans a configured~/Localunder aTempDirhome, so nothing is written under the real home. With the expansion insidediscover_configured_inreverted to a literalPathBuf::from, this test fails (0 dependencies found instead of 1). Re-checked after the rebase.index::test_expand_path_home,test_expand_path_leaves_another_users_home_as_writtenandtest_expand_path_without_a_home_leaves_the_path_as_written(commit 2).claudear-engine,watcher::test_discover_dependencies_stores_what_the_cascade_loads: runsWatcher::discover_dependenciesover an indexed checkout. It checks the stored row'supstreamanddownstream, and that itsdep_typeparses asDependencyType::Composer. The duplicate is stored once.How it was verified
After rebasing onto
mainat 95fab34 (#154, #160 and #166 merged), each commit was checked on its own. The runs were local on macOS from themigrate/clhworktree, with--features sqlitefor the member crates. CI uses--all-features, which addscuda. The environment wasFASTEMBED_CACHE_DIR/HF_HOME/CLAUDEAR_EMBEDDING_CACHE_DIRpointed at a local copy of the nomic model, andCLAUDEAR_VECTORLITE_PATH=/opt/homebrew/lib/vectorlite.dylib, so no test was skipped.cargo fmt --all -- --checkcargo check --workspace --all-targetscargo clippy --workspace --all-targets -- -D warnings -A clippy::double_must_usecargo test -p claudear-analysis --features sqlitecargo test -p claudear-engine --features sqlitecargo test -p claudear --features sqlitee2e_real_repo2,retries1,shutdown13 passedBefore the rebase, clippy and the three test suites also passed on commit 1 on its own. The regression test was re-checked at head by reverting the expansion to a literal
PathBuf::from: it fails, and passes again with the fix.Cargo.lockwas rebuilt frommain's lock withcargo metadata, thencargo update -p tokio-macros --precise 2.7.0. The result is identical to the auto-merged lock: registry sources only, and nosyn3.Not verified
--all-features(thecudafeature) was not built locally.repos index,repos syncandrepos discoverwere not run against a real~/Local. The scan input is covered by the unit tests above.Overlapping open PRs (by file)
Rebased on #154, #160 and #166. Overlaps are the intersection of this PR's files with each open PR's files.
Cargo.toml,Cargo.lock,crates/claudear-analysis/Cargo.tomlandcrates/claudear-engine/src/watcher.rs.abnegate-httppin sits next to this PR'sabnegate-vcspin in bothCargo.tomlfiles.tokio-macrosheld at 2.7.0 in the lock.RetryOutcomeenum and one test near line 5963) do not touchdiscover_dependenciesor its tests.crates/claudear-engine/src/watcher.rs. Its hunks (source workers and their tests) do not touchdiscover_dependenciesor its tests.crates/claudear-engine/src/watcher.rs. Its hunks do not touchdiscover_dependenciesor its tests.Cargo.toml,Cargo.lockandcrates/claudear-analysis/Cargo.toml. Itsabnegate-learnpins sit next to this PR'sabnegate-vcspins.Cargo.toml(theabnegate-configpin sits next to this one) andCargo.lock. Both PRs addabnegate-secret0.1.3 to the lock.Cargo.toml,Cargo.lock,watcher.rsandsrc/main.rs.🤖 Generated with Claude Code