v0.2.9
This release changes the default node_modules layout to isolated for npm, Yarn, and Bun projects, alongside install-performance and diagnostics work.
Important
The default node_modules layout is now isolated. npm, Yarn, Bun, and pnpm incumbents — and fresh projects — now install with the isolated linker backed by a global virtual store, instead of the flat hoisted tree. The first nub install after upgrading does a one-time clean reinstall of node_modules (the layout flip wipes and relinks it once, cleanly). To keep the flat npm-style layout, add one line to .npmrc:
node-linker=hoistedThe --node-linker hoisted flag does the same for a single command.
Default node_modules layout
Every incumbent now defaults to isolated — npm, Yarn, and Bun join pnpm and Nub-identity projects. Isolated links each package into a global virtual store and symlinks the declared dependency graph into node_modules, so only declared dependencies are reachable. A project that relies on phantom (undeclared) dependencies opts into the flat layout with node-linker=hoisted in .npmrc. When an undeclared package fails to resolve at runtime, the error names it and points at this opt-out. (#238)
next, nuxt, and parcel default to strict isolated with the global virtual store auto-disabled, matching how those toolchains expect node_modules to be laid out.
pnpm compatibility note. Nub now sets hoist=false for pnpm incumbents as well, so a pnpm project that depended on packages reachable only through pnpm's hidden .pnpm/node_modules hoist tree may hit a phantom-dependency miss it did not see under pnpm. The .npmrc opt-out and the runtime hint above mitigate it; the change favors correct, declared-only resolution by default.
Install performance
| Area | What changed | PR |
|---|---|---|
| Warm installs | A fully-satisfied, unchanged tree now exits "Already up to date" without re-running resolve/fetch/link, even under the default no-downgrade trust policy. The trust gate still fires on any install that does real work. | #234 |
| Isolated installs | The isolated materialize step now overlaps with package fetch instead of running after it. | #235 |
Diagnostics
| Area | What changed | PR |
|---|---|---|
| Diagnostics layer | The engine's diagnostics layer is now reachable under Nub via NUB_DIAG_* environment variables. |
#233 |
| Phase output | Install phase debug lines are annotated with work counts and a no-work marker, so a warm no-op install is legible in the phase output. | #236 |
Release pipeline
Docker images are now published on every release via a reusable workflow. (#237)
Commits in this release
- skill: add benchmarking methodology for comparative install benches (
fd4181bf) - skill(benchmarking): gate on quiet-machine load, not load-robust-on-busy-host (
2ce94414) - scripts: share one CARGO_TARGET_DIR across worktrees (
20df6043) - dev-loop: throttle agent builds on the shared dev host (job cap + background QoS) (
dbbff24a) - skill(benchmarking): process hygiene — reap install children, tear down dev servers, docker --rm (
074ea16c) - skill(benchmarking): trim process-hygiene to the real lesson (tear down dev servers); drop the self-reaping-children noise (
904ffe54) - untrack the local-only wiki corpus symlink (was a corrupt self-loop); gitignore the bare
wikipath (41ac7d43) - pm: expose the aube diagnostics layer under nub via NUB_DIAG_* (#233,
878d7530) - perf(install): short-circuit a warm-satisfied install under no-downgrade (#234,
7ca4a26d) - perf(install): overlap the default isolated materialize with fetch (#235,
14273751) - aube: annotate install phase debug lines with work counts + no-work marker (#236,
67bd6664) - ci(release): publish Docker images on every release via reusable workflow (#237,
3565b0c7) - feat(install): default npm/yarn/bun incumbents to isolated + GVS (#238,
2e63f1cb) - fray(hooks): self-contained non-blocking notify-surface stop hook (
b7e21613)
Full Changelog: v0.2.8...v0.2.9