fix(linker): link workspace bins into dependent packages#353
Conversation
When workspace package A declares `bin` and B depends on A via `workspace:*`, pnpm symlinks A's bin into B/node_modules/.bin so B's npm scripts can call it. aube skipped these because workspace deps have no `.aube/<dep_path>/<name>/` materialization — the linker symlinks them straight into the importer's `node_modules/`, so `link_bins_for_dep` reads `package.json` from a path that doesn't exist and returns Ok(None). Route workspace deps through a new `link_bins_for_workspace_dep` helper that reads `package.json` from the workspace package's own directory (already known via `ws_dirs`) and shims each bin entry. Both the root pass (`link_bins`) and the per-importer workspace loop pick up the change. Reported in #352.
Greptile SummaryFixes missing bin shims for Confidence Score: 5/5Safe to merge; the fix is well-scoped to the install/bin-linking path and covered by a new integration test. Only P2 findings present — no logic errors or security concerns in the implementation. The sole issue is test portability of the test/workspace.bats — the Important Files Changed
Reviews (2): Last reviewed commit: "fix(linker): cache workspace package.jso..." | Re-trigger Greptile |
`link_bins_for_workspace_dep` was reading and parsing the workspace package's `package.json` once per consumer. In a monorepo where a shared tooling package with bins is a `devDependency` of dozens of workspace members (the discussion #352 reporter cites ~100), that multiplies into N redundant reads per install. Add a per-install `WsPkgJsonCache` keyed by `ws_dir`, threaded through `link_bins` and the per-importer loop alongside the existing `PkgJsonCache`. Updates the bats test to install two consumers of the same workspace bin so the cache path is exercised.
Summary
When workspace package A declares
binand B depends on A viaworkspace:*, pnpm symlinks A's bin intoB/node_modules/.bin/so B's npm scripts can call it. aube didn't, breaking any workspace package that runs a bin provided by another workspace package.Root cause: workspace deps have no
.aube/<dep_path>/<name>/materialization — the linker symlinks them straight into the importer'snode_modules/, solink_bins_for_depreadspackage.jsonfrom a path that doesn't exist and returnsOk(None)silently.Fix: route workspace deps through a new
link_bins_for_workspace_dephelper that readspackage.jsonfrom the workspace package's own directory (already known viaws_dirs) and shims each bin entry. Both the root pass (link_bins) and the per-importer workspace loop pick up the change.Reported in #352 (item 6,
workspace-bin-not-linked).Test plan
cargo clippy --all-targets -- -D warningscargo test --package aube install::bin_linking./test/bats/bin/bats test/workspace.bats— all 17 tests pass, including new "workspace dep bins land in dependent's node_modules/.bin"test/root_bin.bats,test/workspace_member_install_walks_up.bats,test/optimistic_and_bin_settings.batsall passNote
Medium Risk
Changes bin-linking behavior during installs by adding a separate code path for
workspace:dependencies, which could affect which executables appear in.binacross workspaces. Risk is moderate due to touching core install/linking logic but is localized and covered by a new integration test.Overview
Fixes aube installs to link executables (
binentries) fromworkspace:dependencies into each dependent package’snode_modules/.bin, matching pnpm behavior (previously skipped because workspace deps aren’t materialized under.aube/<dep_path>).Adds a dedicated
link_bins_for_workspace_dephelper that reads the workspace package’s ownpackage.json, shims itsbinentries, and uses a per-installWsPkgJsonCacheto avoid repeated reads across multiple importers; wires this path into both the root bin-link pass and the per-workspace-importer bin-link loop, and adds a bats test asserting the bins land in multiple consumers.Reviewed by Cursor Bugbot for commit 5c17f3e. Bugbot is set up for automated code reviews on this repo. Configure here.