fix(scripts): close 3 lifecycle parity gaps with pnpm#421
Conversation
Adds three green ports of pnpm/test/install/lifecycleScripts.ts — preinstall/postinstall/prepare echo reaches the user — and three skip tests documenting parity gaps surfaced by porting the suite: npm_config_user_agent not exported, root postinstall fires on `aube add <pkg>`, root prepare fires on `aube add <pkg>`. Each skip cites the pnpm source line and the underlying contract so a future PM-side fix knows what to enable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR closes three pnpm lifecycle parity gaps: exports Confidence Score: 5/5Safe to merge; all InstallOptions construction paths correctly set skip_root_lifecycle and the gate logic is straightforward. Only P2 findings: the simplified npm_config_user_agent format (missing node/ field) and an incomplete arch allowlist in one unit test. No logic errors, no missing guards on hot paths, and the previous P1 about remove/update not inheriting the flag is correctly resolved by making with_mode() the authoritative default. crates/aube-scripts/src/lib.rs — user-agent format and test arch allowlist are worth a second look before future tool-compatibility claims are made. Important Files Changed
Reviews (6): Last reviewed commit: "fix(scripts): add ppc/ppc64/loong64 mapp..." | Re-trigger Greptile |
- Export npm_config_user_agent to every lifecycle script so dep postinstalls (husky, unrs-resolver, node-pre-gyp, etc.) can detect the running PM. Format mirrors pnpm: "aube/<version> <os> <arch>". - Gate the root preinstall/install/postinstall/prepare hooks behind a new InstallOptions.skip_root_lifecycle flag and set it on `aube add` (single-project + workspace paths). Matches pnpm's contract: hooks fire only on argumentless `aube install`, not on `aube install <pkg>` / `aube add`. Removes the perf hit of re-running an expensive root postinstall on every incremental add. - Drop the corresponding skip-with-citation tests from test/lifecycle_scripts.bats — all 3 ports now pass green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Benchmark changesVersions:
Public ratios: warm installs vs Bun 3x -> 4x; warm installs vs pnpm 9x -> 9x.
3a16e90 vs 113eb8b | aube/bun/pnpm | 3 scenarios | 3 runs | 500mbit/50ms | generated by Codex. |
Greptile flagged that the previous fix only covered \`aube add\`. The contract is broader: pnpm fires root lifecycle hooks only on the literal argumentless \`pnpm install\`, never on any other command. Flip \`InstallOptions::with_mode()\` (the chained-call constructor) to default \`skip_root_lifecycle: true\`. Every chained-call site already goes through that constructor — \`add\`, \`remove\`, \`update\`, \`dedupe\`, \`dlx\`, patch tooling, the \`ensure_installed\` auto-install before \`run\`/\`test\`, and nested git-prepare installs — so the parity contract is now enforced uniformly. The argumentless \`aube install\` path (\`InstallArgs::into_options\`) and the literal-struct constructions in \`ci.rs\` / \`deploy.rs\` keep \`false\`, which are the only sites that should still run hooks. Drop the now-redundant explicit \`skip_root_lifecycle = true\` lines from add.rs and add bats tests covering \`aube remove\` and \`aube update\` to lock in the broader contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous commit flipped \`with_mode()\` to default \`skip_root_lifecycle: true\` and broke three \`git_deps.bats\` tests that exercise git deps with a \`prepare\` script. The nested install spawned by \`git_prepare.rs\` is special: its "root" IS the cloned git dep itself, and running that dep's preinstall/postinstall/prepare is the entire point of git-dep preparation — equivalent to an argumentless \`aube install\` against the dep's clone directory, not a chained call from the user's perspective. Override the chained-call default explicitly in \`git_prepare.rs\` and update the field doc to call out the exception. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…on install-test Two follow-up fixes from PR review: - Map Rust's std::env::consts::OS/ARCH (macos/windows, x86_64/aarch64) to Node's process.platform/arch vocabulary (darwin/win32, x64/arm64) in npm_config_user_agent so dep build scripts that parse the full string identify the platform the same way npm/yarn/pnpm do. Add a unit test that asserts the emitted tokens match Node's set. - aube install-test (pnpm-compat alias for install && test) is the explicit install entry point, so its install phase needs root lifecycle hooks. Override the chained-call default that with_mode() sets back to false on this one path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e5b0476. Configure here.
Cursor flagged that the user_agent test asserts \`ppc64\` is a valid arch token but the mapping function fell through to Rust's raw \`powerpc64\` for that target — the test would fail on a ppc64 build. Add explicit mappings for the rare arches that disagree between Rust and Node (powerpc → ppc, powerpc64 → ppc64, loongarch64 → loong64) and align the test allowlist with the values \`node_arch\` can actually produce. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary - Check off Phase 0 — `@pnpm.e2e/*` fixtures ([#424](#424)) and `add_dist_tag` helper ([#422](#422)) both landed. - Record `lifecycleScripts.ts` 8/21 ported via [#421](#421) with a done/remaining split. - Relabel Phase 2 as unblocked (was "depends on add_dist_tag helper"). - Refresh the conventions note now that the `@pnpm.e2e/*` fixtures are in-tree. ## Test plan - [ ] doc-only — render check on GitHub 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Documentation-only updates to the pnpm test-import tracking doc; no runtime or test behavior changes. > > **Overview** > Updates `test/PNPM_TEST_IMPORT.md` to mark Phase 0 infrastructure work as complete (mirrored `@pnpm.e2e/*` fixtures and the `add_dist_tag` helper), and records current Tier 1 progress for `lifecycleScripts.ts` (8/21 ported with done/remaining notes). > > Renames Phase 2 as *unblocked* now that `add_dist_tag` exists, and refreshes the translation conventions to prefer using the in-tree `@pnpm.e2e/*` fixtures when specific package shapes are required. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 270cfc9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Summary
Ports the relevant tests from pnpm/test/install/lifecycleScripts.ts into test/lifecycle_scripts.bats, per the plan in test/PNPM_TEST_IMPORT.md (#416), and closes the parity gaps surfaced by the port.
Test ports
3 green ports — orthogonal stdout-visibility checks that complement aube's existing filesystem-marker tests by proving the script's echoed output reaches the user through aube's progress UI:
3 ports that previously documented parity gaps, now green:
npm_config_user_agentexported to lifecycle scripts (pnpm L29)postinstallis NOT triggered when adding a named dep (pnpm L69)prepareis NOT triggered when adding a named dep (pnpm L82)2 extra coverage tests for
aube remove/aube update— the same pnpm contract extended to all chained-call commands (added in response to PR review).Gap fixes
1.
npm_config_user_agentexportedcrates/aube-scripts/src/lib.rs— addsaube_user_agent()returning"aube/<version> <os> <arch>"(mirrors pnpm's format) and sets it viaapply_script_settings_env, which covers root + dep, jailed + non-jailed paths. Dep build scripts that sniff this env var to detect the running PM (husky, unrs-resolver, node-pre-gyp) now recognize aube instead of falling back to npm-mode.2. Root hooks gated to argumentless
aube installonlypnpm's contract: root lifecycle hooks fire only on the literal
pnpm installinvocation (no package args). Every other entry point —add,remove,update,dedupe,dlx, patch tooling, theensure_installedauto-install beforerun/test, nested git-prepare installs — must skip them.crates/aube/src/commands/install/mod.rs— addsInstallOptions.skip_root_lifecycle: booland gates bothrun_root_lifecycleblocks on it. The chained-call constructorwith_mode()defaults totrueso every chained site (every command except argumentlessinstall) inherits the correct behavior automatically. Argumentlessaube install(viaInstallArgs::into_options) andci.rs/deploy.rs(literal struct) keepfalse.Test plan
mise run test:bats test/lifecycle_scripts.bats— 21 ok, no skipscargo test -p aube-scripts— 29 ok🤖 Generated with Claude Code
Note
Medium Risk
Changes when root lifecycle hooks run across multiple commands and adds a new env var for all lifecycle scripts, which may affect projects relying on prior hook behavior or script environment.
Overview
Improves pnpm parity for lifecycle scripts by exporting
npm_config_user_agent(Node-style platform/arch) to all spawned scripts so dependency postinstalls can correctly detect aube.Updates the install pipeline to skip root
preinstall/install/postinstall/preparehooks for chained installs (e.g.add/remove/update), while keeping them enabled for argumentlessaube install,ci,deploy, and nested git-depprepareinstalls.Ports/extends pnpm lifecycle tests in
test/lifecycle_scripts.batsand adds a unit test for the new user-agent formatting.Reviewed by Cursor Bugbot for commit 3a16e90. Bugbot is set up for automated code reviews on this repo. Configure here.