feat(linker): workspace-aware default — Bun-parity heuristic#37
Merged
Conversation
Single-package projects keep `Hoisted` (npm-compat fast path). Workspace projects (npm/yarn `workspaces` field OR `pnpm-workspace.yaml`, walking up from `project_dir`) auto-resolve to `Isolated` so phantom-dep regressions stay contained. Mirrors Bun's recently-shipped heuristic without changing any existing override surface. Precedence chain (in order): 1. `--linker` CLI flag 2. `~/.lpm/config.toml > linker` 3. `LPM_LINKER` env var 4. `package.json > lpm > linker` 5. *new:* workspace auto-detection → Isolated 6. default → Hoisted Implementation: - `resolve_effective_linker` + `_from_bytes` gain a `project_dir: &Path` arg. Three call sites updated (`commands/install.rs`, two in `install_state.rs`). `lpm_workspace::discover_workspace` already walks up + handles npm/yarn `workspaces` AND `pnpm-workspace.yaml`, so we just check `Ok(Some(_))`. I/O failures fall through silently to the default — Hoisted still works correctly, so a recoverable blip should not be a hard install error. - Resolved linker mode is already folded into the install-hash, so adding/removing a workspace globs file invalidates "up to date" and triggers a re-link on the next install — no manual cache bust. - New `LinkerModeSource` enum + `resolve_effective_linker_with_source` variant report which surface won the precedence chain. Install pipeline still calls the source-discarding fn (lean signature). - `lpm doctor` gains a `linker_mode_resolved` check (Pass severity, informational) showing both the resolved mode and its source so users can answer "why is my linker mode X?" without re-deriving the chain. - Old `resolve_environment_linker_override` helper deleted — its logic inlined into `resolve_effective_linker_with_source` so the source can be disambiguated between `GlobalConfig` and `EnvVar`. Tests migrated to drive `resolve_effective_linker_with_source` directly with empty single-package fixtures. Tests: 11 unit tests in `linker_config::tests` cover the precedence chain plus single-package + npm-yarn-workspaces + pnpm-workspace.yaml + workspace-member-walk-up paths. Workspace 5752/5752 pass (was 5745 + 7 new tests). audit-fixtures: same 16 PASS / 1 SKIP / 1 FAIL as main, including `workspace/monorepo-basic` which now hits Isolated by default (PASS/PASS confirms the default flip is benign). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
workspacesfield ORpnpm-workspace.yaml, walking up fromproject_dir) auto-resolve toIsolated. Single-package projects keep the existingHoisteddefault. Mirrors Bun's recently-shipped heuristic — strict per-package dep boundaries pay off in monorepos where phantom-dep regressions are most expensive; npm-compat fast path stays for typical single-package apps.--linkerflag >~/.lpm/config.toml>LPM_LINKERenv >package.json > lpm > linker> workspace auto-detection > default.lpm doctornow surfaces the resolved linker mode + which surface won the precedence chain (linker_mode_resolvedcheck, Pass severity).LinkerMode, so adding/removing a workspace globs file invalidates "up to date" and triggers a re-link — no manual cache bust.Test plan
linker_config::testscover npm/yarn workspaces,pnpm-workspace.yaml, walk-up from a member dir, and override precedence (CLI / env / package.json beat detection)resolve_effective_linker_with_sourceto assert the rightLinkerModeSourcecargo clippy --workspace --all-targets -- -D warningscleancargo fmt --checkcleancargo nextest run --workspace --exclude lpm-integration-tests— 5752/5752 passbench/audit-fixtures/run-all.sh— 16 PASS / 1 SKIP / 1 FAIL (native/esbuild-prebuiltconfirmed pre-existing).workspace/monorepo-basicPASS/PASS confirms the default flip is benign.🤖 Generated with Claude Code