Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: endevco/aube
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.3.0
Choose a base ref
...
head repository: endevco/aube
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.4.0
Choose a head ref
  • 20 commits
  • 105 files changed
  • 7 contributors

Commits on Apr 27, 2026

  1. fix(packaging): include README on published aube crate (#349)

    ## Summary
    - Add `readme = \"README.md\"` to `[workspace.package]` and inherit it
    on the aube binary crate so crates.io renders the project README.
    Currently the [crates.io page](https://crates.io/crates/aube) has no
    README because the binary crate's `include` whitelist
    (`[\"src/**/*.rs\", \"build.rs\"]`) excluded it and no `readme` field
    was set.
    - Cargo always bundles the README when `readme` is set, regardless of
    `include`; verified with `cargo package --list -p aube` (README.md now
    appears in the file list).
    - Takes effect on the next publish (1.3.0+); 1.2.1 is already up without
    one.
    
    ## Test plan
    - [x] `cargo package --list -p aube --no-verify` shows `README.md` in
    the tarball
    - [ ] After release-plz publishes the next version, confirm the README
    renders on crates.io
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Low Risk**
    > Low risk: this only adjusts Cargo package metadata for publishing and
    should not affect runtime behavior or dependencies.
    > 
    > **Overview**
    > Ensures crates published from this workspace include and render the
    repository `README.md` by setting `readme = "README.md"` in
    `[workspace.package]` and having each crate inherit it via
    `readme.workspace = true` (including the `aube` binary crate that
    previously whitelisted files via `include`).
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    3134282. 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>
    jdx and claude authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    e5f1f44 View commit details
    Browse the repository at this point in the history
  2. fix(linker): link workspace bins into dependent packages (#353)

    ## Summary
    
    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 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's
    `node_modules/`, so `link_bins_for_dep` reads `package.json` from a path
    that doesn't exist and returns `Ok(None)` silently.
    
    Fix: 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 (item 6, `workspace-bin-not-linked`).
    
    ## Test plan
    
    - [x] `cargo clippy --all-targets -- -D warnings`
    - [x] `cargo test --package aube install::bin_linking`
    - [x] `./test/bats/bin/bats test/workspace.bats` — all 17 tests pass,
    including new "workspace dep bins land in dependent's node_modules/.bin"
    - [x] Related: `test/root_bin.bats`,
    `test/workspace_member_install_walks_up.bats`,
    `test/optimistic_and_bin_settings.bats` all pass
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Changes bin-linking behavior during installs by adding a separate code
    path for `workspace:` dependencies, which could affect which executables
    appear in `.bin` across 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 (`bin` entries) from
    `workspace:` dependencies** into each dependent package’s
    `node_modules/.bin`, matching pnpm behavior (previously skipped because
    workspace deps aren’t materialized under `.aube/<dep_path>`).
    > 
    > Adds a dedicated `link_bins_for_workspace_dep` helper that reads the
    workspace package’s own `package.json`, shims its `bin` entries, and
    uses a per-install `WsPkgJsonCache` to 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.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    5c17f3e. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 27, 2026
    Configuration menu
    Copy the full SHA
    55f1db4 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    9d50f3a View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    6ff9297 View commit details
    Browse the repository at this point in the history

Commits on Apr 28, 2026

  1. fix(lockfile): store bun dependency tails (#355)

    ## Summary
    
    - Store Bun package dependency values as dep-path tails instead of full
    `name@version` strings.
    - Keep workspace-link dependency emission compatible with the tail form.
    - Update Bun lockfile tests to assert the shared
    `LockedPackage.dependencies` contract.
    
    ## Why
    
    Bun lockfile imports were producing dependency entries like
    `node-gyp-build -> node-gyp-build@node-gyp-build@4.8.4`, which broke
    transitive sibling links and dep-local `.bin` generation. Approved
    postinstall scripts could then fail after migrating from `bun install`
    to `aube install`, because tools such as `node-gyp-build` and packages
    such as `@electron/get` were not resolvable from the virtual store
    package.
    
    ## Validation
    
    - `cargo fmt --check`
    - `cargo test -p aube-lockfile bun::tests`
    - `cargo test -p aube-lockfile`
    - Reproduced the reported Bun-to-Aube install with `bufferutil@4.0.9`,
    `electron@39.2.7`, and `fs-extra@10.1.0`; verified `aube install
    --no-side-effects-cache` now exits successfully.
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Changes Bun lockfile parsing/writing semantics for
    `LockedPackage.dependencies`, which affects downstream linking and
    script/bin resolution; regressions could break installs if any consumer
    still expects full `name@version` dep values.
    > 
    > **Overview**
    > **Bun lockfile parsing now stores transitive dependency values as
    dep-path tails** (e.g. `"3.1.0"` instead of `"nested@3.1.0"`), using the
    shared `npm::dep_path_tail` helper so downstream consumers see the same
    dependency-map shape across lockfile formats.
    > 
    > **Bun workspace package emission was updated to match the tail form**,
    fixing reachability checks for workspace-link targets by comparing
    against canonical keys rather than raw dep values.
    > 
    > Tests were updated/added to assert the new contract (including a
    regression covering lifecycle-script-related deps like `node-gyp-build`
    and `@electron/get`).
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    9483919. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    d8f260a View commit details
    Browse the repository at this point in the history
  2. fix(registry): request identity encoding for tarballs (#356)

    ## Summary
    
    - Send `Accept-Encoding: identity` for tarball downloads.
    - Keep metadata requests unchanged, so packuments can still use normal
    HTTP compression.
    - Add a registry retry test that asserts tarball requests use identity
    encoding.
    
    ## Why
    
    A user reported intermittent GitHub Actions failures in `aube ci` where
    larger native tarballs stalled and eventually failed with `HTTP error:
    error decoding response body`. Tarballs are already `.tgz` archives, so
    asking CDNs or proxies for another HTTP content-encoding layer adds an
    avoidable decode failure mode without reducing useful payload size.
    
    Current `main` already retries tarball body read/decode failures and
    surfaces retry warnings; this change reduces the chance of hitting HTTP
    content-encoding decode errors in the first place.
    
    ## Validation
    
    - `cargo fmt --check`
    - `cargo test -p aube-registry retry_tests`
    - `cargo test -p aube-registry`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Low Risk**
    > Low risk: a narrow HTTP header change affecting only tarball GETs,
    plus a test asserting the new behavior; could only impact unusual
    registries that rely on content-encoding for tarballs.
    > 
    > **Overview**
    > Tarball downloads now send `Accept-Encoding: identity` in
    `fetch_tarball_bytes` to prevent proxies/CDNs from applying an
    additional HTTP content-encoding layer on already-`.tgz` payloads.
    > 
    > Adds a `wiremock` retry test that asserts tarball GETs include the
    identity encoding header, while keeping packument/metadata request
    behavior unchanged.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    f527fa0. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    7942bd1 View commit details
    Browse the repository at this point in the history
  3. fix(store): repair truncated CAS entries (#357)

    ## Summary
    
    - Verify an existing content-addressed file has the expected byte length
    when importing bytes into the store.
    - Remove and rewrite stale truncated CAS files before returning store
    metadata.
    - Add a regression test that seeds an empty CAS file for a package
    manifest-shaped payload and confirms import repairs it.
    
    ## Why
    
    A discussion report showed a valid npm tarball failing package
    validation with an empty `package.json` parse error. The upstream
    tarball and integrity for `@babel/helper-string-parser@7.27.1` are
    valid, which points to reuse of a stale zero-byte or truncated CAS file
    during import.
    
    ## Validation
    
    - `cargo fmt --check`
    - `cargo test -p aube-store
    test_import_bytes_repairs_truncated_existing_cas_entry`
    - `cargo test -p aube-store`
    - `cargo clippy -p aube-store --all-targets -- -D warnings`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Touches CAS import and cache-staleness detection paths; incorrect size
    checks or rewrite logic could cause unnecessary rewrites or new I/O
    errors during installs, but changes are localized and covered by a
    regression test.
    > 
    > **Overview**
    > Prevents reuse of **truncated/zero-byte CAS files** by verifying
    on-disk byte length against the expected `StoredFile.size` and treating
    mismatches as stale.
    > 
    > `import_bytes` now **rechecks the stored file length after creation**,
    and if it’s wrong it deletes and rewrites the CAS entry (failing with a
    detailed I/O error if the second attempt is still wrong). A new
    regression test seeds an empty CAS file and asserts that a subsequent
    import repairs it.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    206edfc. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    1ac4869 View commit details
    Browse the repository at this point in the history
  4. docs: require AI disclosure in GitHub comments (#359)

    ## Summary
    
    - Add a `github_interactions` rule to the shared agent instructions.
    - Require GitHub PR and Discussion comments to disclose which AI
    assistant generated them.
    - Include examples for Codex and Claude.
    
    ## Validation
    
    - `git diff --check`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Low Risk**
    > Low risk: documentation/instruction-only change that does not affect
    runtime behavior or build output.
    > 
    > **Overview**
    > Adds a new `github_interactions` section to `.rules` requiring that
    any GitHub PR/Discussion comments include an explicit disclosure of
    which AI assistant generated the comment, with example disclosures for
    Codex and Claude.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    8df117e. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    9b32166 View commit details
    Browse the repository at this point in the history
  5. fix(resolver): exclude provenance churn packages (#360)

    ## Summary
    
    - Add built-in `trustPolicyExclude` entries for npm packages with known
    provenance metadata churn that caused benchmark fixture resolution to
    fail.
    - Merge user-provided `trustPolicyExclude` entries on top of the
    built-in defaults.
    - Add a focused vlt benchmark fixture regression test using the cheaper
    `svelte` fixture. Heavier `next`, `vue`, `large`, and `babylon` cases
    were removed after they pushed serial BATS past the 20-minute CI
    timeout.
    
    ## Validation
    
    - `cargo test -p aube-resolver trust`
    - `cargo build`
    - `mise run test:bats test/vlt_benchmarks.bats`
    - Commit hook: `cargo fmt --check`, targeted `cargo clippy`, `shfmt`,
    `shellcheck`
    
    ## CI note
    
    The previous run timed out in `bats-serial`: `next` took about 3.7-3.9
    minutes, `vue` about 3.1-4.2 minutes, and `large` about 3.5-5.3 minutes
    before the job was cancelled. The reduced fixture keeps coverage for the
    benchmark install variations without carrying those expensive cases in
    serial CI.
    
    ---------
    
    Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
    jdx and autofix-ci[bot] authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    2c617a4 View commit details
    Browse the repository at this point in the history
  6. fix(linker): expose hidden hoist from global store (#358)

    ## Summary
    
    - Expose hidden-hoist links from the shared global virtual-store root so
    packages reached through canonical `~/.cache/aube/virtual-store/...`
    paths can still resolve hoisted packages.
    - Keep project-local `.aube/node_modules` behavior unchanged for
    non-canonicalized paths.
    - Clean only dead or junk GVS hidden-hoist entries and reconcile
    current-project names, preserving live links written by other projects.
    - Add regression tests for GVS hidden-hoist resolution, shared cleanup
    behavior, hoist-disabled shared installs, and stale scope-shaped
    entries.
    
    ## Root Cause
    
    Some toolchains resolve package files through their real GVS path
    instead of the project-local `.aube/<dep_path>` symlink. From that real
    path, Node's upward `node_modules` walk cannot reach
    `node_modules/.aube/node_modules`, so packages that rely on hidden
    hoisting for undeclared imports fail. The reported `@ngx-translate/core`
    / `rxjs` failure is one instance of that shape.
    
    ## Tradeoffs
    
    Packages with undeclared imports should fix their manifests upstream.
    This PR does not add package-specific exceptions; it makes GVS preserve
    the same hidden-hoist compatibility behavior that aube already provides
    in the project-local virtual store.
    
    Because the GVS hidden hoist is shared across projects, cleanup is
    intentionally conservative. Live links are preserved even when they are
    not in the current project graph; a current install only removes dead
    targets or junk entries before reconciling the names it owns.
    
    ## Validation
    
    - `cargo fmt --check`
    - `cargo test -p aube-linker test_global_virtual_store_hidden_hoist --
    --nocapture`
    - `cargo test -p aube-linker`
    - `cargo clippy -p aube-linker --all-targets -- -D warnings`
    - `git diff --check`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Changes filesystem linking/cleanup behavior for hidden-hoist entries
    in global-virtual-store mode; mistakes could break module resolution or
    delete shared links across projects.
    > 
    > **Overview**
    > Fixes hidden-hoist resolution in *global virtual store (GVS)* mode by
    **mirroring the hidden-hoist symlinks into
    `virtual_store/node_modules/`** in addition to the existing
    project-local `.aube/node_modules/`, so canonicalized package paths can
    still resolve hoisted undeclared deps.
    > 
    > Refactors hidden-hoist linking into `link_hidden_hoist_at` and adds
    **shared-safe cleanup** via `sweep_dead_hidden_hoist_entries`, which
    only removes dangling links/non-link junk in the shared GVS directory
    (while project-local installs still fully wipe/rebuild). Adds regression
    tests covering GVS hidden-hoist creation, dead-entry pruning, and
    preservation of live shared links when hoist is disabled.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    9f4f334. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    44400c7 View commit details
    Browse the repository at this point in the history
  7. fix: roundup of critical/high audit findings (#361)

    ## Audited
    
    Six critical/high bugs found via targeted code-review pass over
    `aube-resolver`, `aube-lockfile`, `aube-store`, `aube-linker`,
    `aube-scripts`, `aube-registry`, `aube-workspace`, `aube-manifest`,
    `aube-settings`, and the install pipeline. Workspace traversal
    verified empirically with a repro repo, others verified by code read.
    
    ## Fixed
    
    ### `fix(scripts): expand seccomp denylist + drop /tmp from landlock`
    
    Old seccomp filter denied AF_INET and AF_INET6, left every other
    family open. Now denies AF_INET, AF_INET6, AF_NETLINK, AF_PACKET,
    AF_VSOCK, AF_XDP, AF_ALG, AF_BLUETOOTH, AF_RDS, AF_CAN, AF_TIPC,
    AF_IB, AF_NFC. Strict superset of original.
    
    AF_UNIX stays allowed (node and node-gyp IPC). True default-deny on
    the family axis is not implementable with seccompiler today since
    its `mismatch_action` is global, setting it to `Errno` kills every
    non-socket syscall. Documented in the source.
    
    Known residual gap: AF_UNIX `connect()` to filesystem socket paths
    (e.g. `/var/run/docker.sock`) is not bounded by Landlock ABI v2.
    v2 only filters VFS open/write hooks, the unix socket connect path
    bypasses them by passing `sun_path` inline.
    `LANDLOCK_ACCESS_FS_CONNECT_UNIX`
    arrives in v5 (kernel 6.10+). The policy pins v2 for LTS-kernel
    coverage (Ubuntu 22.04, Debian 12, RHEL 9). On hosts with a sensitive
    unix socket and a kernel below 6.10, install in a namespace that
    bind-mounts the socket away.
    
    Same commit drops `/tmp` from the landlock full-access list. `home`
    already covers writable scratch and `apply_jail_env` redirects
    TMPDIR/TMP/TEMP there. Granting `/tmp` let scripts seed symlink races
    on shared CI hosts and read other tenants' tmp files.
    
    ### `fix(workspace): reject pnpm-workspace patterns escaping project
    root`
    
    `glob_workspace_pattern` pushed match parents without containment
    check. Pattern `../sibling` lexically starts with the project prefix
    but escapes via parent components, leaking foreign dirs into the
    workspace package list (linker, resolver, bin wiring all consume it).
    
    Repro before fix:
    
    ```yaml
    # pnpm-workspace.yaml
    packages:
      - "../sibling"
    ```
    
    ```
    packages: Ok([ "C:\...\project\..\sibling" ])
    ```
    
    After: empty result, valid `packages/*` patterns still resolve.
    
    Adds `is_under_project` helper, canonicalize both sides, fall back
    to lexical compare when paths do not exist yet (combined with
    `starts_with(project_dir)` guard so the fallback is also
    containment-checked).
    
    ### `fix(resolver): include dep tails in peer-context convergence hash`
    
    Old `key_set_hash` covered package keys only. Peer-context iteration
    can rewrite a dep value to point at an existing key without adding
    a new key, so convergence fired with partially rewritten tails.
    Linker reads tails directly to locate sibling symlink targets, stale
    tails ship broken `node_modules` silently.
    
    New `graph_hash` walks `(key, [(dep_name, dep_tail)...])` for every
    package. Same `ordered_seq_hash` infra, no extra deps. Capacity hint
    is exact (`len*3 + total_deps*2`), explicit `\x1f`/`\x1e` framing.
    
    ### `fix(cli): make patch-commit atomic, roll back on manifest failure`
    
    Old order: write `.patch` file, then `upsert_patched_dependency`.
    If the manifest write failed (Windows file lock, disk full,
    concurrent writer) the patch lived on disk but `package.json` had no
    entry. `load_patches` reads `package.json`, so the patch was invisible
    to every future install.
    
    Switch to `aube_util::fs_atomic::atomic_write` for the patch, snapshot
    the prior bytes (re-patch path), restore them on failure or remove
    the orphan if no prior patch existed.
    
    ### `fix(install): hash user-level npmrc in install state digest`
    
    `hash_settings` raw-bytes segment only hashed `<project>/.npmrc`.
    A token swap or `registry=` change in `~/.npmrc` left the fast-path
    state hash green, so `aube install` reported "Already up to date"
    while the source of truth for tarball URLs and auth had changed.
    Fresh checkouts after the change would install from the wrong
    registry.
    
    Includes user-level `~/.npmrc` via `aube_util::env::home_dir()`.
    
    ## Verified
    
    - `cargo build --all` clean
    - `cargo test --workspace` 1145 passed, 0 failed
    - 5 frameworks x 8 install scenarios = 40/40 PASS:
    
    | project | clean | nm | cache | cache+nm | cache+lock | cache+lock+nm |
    lock | lock+nm |
    |---|---|---|---|---|---|---|---|---|
    | next | OK | OK | OK | OK | OK | OK | OK | OK |
    | vue | OK | OK | OK | OK | OK | OK | OK | OK |
    | svelte | OK | OK | OK | OK | OK | OK | OK | OK |
    | astro | OK | OK | OK | OK | OK | OK | OK | OK |
    | babylon | OK | OK | OK | OK | OK | OK | OK | OK |
    
    Frozen fast path on warm state stays under 100ms across the matrix.
    pnpm v9 lockfile roundtrip works. `workspace:*` protocol resolves.
    Valid workspace patterns (`packages/*`) still match correctly.
    
    ## Skipped
    
    - Optional-peer drop after rewrite (lower confidence, tighter repro
      needed)
    - CAS integrity bypass in `import_tarball` (latent, every current
      caller verifies. Worth tightening to enforceable later)
    imjustprism authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    070545b View commit details
    Browse the repository at this point in the history
  8. feat(pnpmfile): support esm pnpmfiles (#362)

    ## Summary
    
    - prefer `.pnpmfile.mjs` over `.pnpmfile.cjs` during default pnpmfile
    discovery
    - load ESM pnpmfiles with dynamic import while preserving CommonJS
    `require()` support
    - document the new default lookup order and cover `.mjs`
    afterAllResolved/readPackage hooks
    
    ## Validation
    
    - `cargo test -p aube pnpmfile::tests`
    - `cargo build -p aube`
    - `mise run test:bats test/pnpmfile.bats`
    - `mise run docs:build`
    - `cargo fmt --check`
    - `git diff --check`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Changes how pnpmfile hooks are discovered and executed (including
    dynamic ESM loading), which can affect dependency resolution behavior
    during installs if projects rely on existing hook semantics.
    > 
    > **Overview**
    > Adds support for ESM pnpmfiles by **discovering and preferring**
    `.pnpmfile.mjs` over `.pnpmfile.cjs`, while still honoring
    `pnpmfilePath` overrides.
    > 
    > Updates the Node hook shims to **dynamically load** `.mjs` via
    `import()` (and `.cjs` via `require()`), including a fallback when an
    ESM default export lacks `hooks`. Documentation/CLI help text and
    bats/unit tests are updated to reflect the new lookup order and to cover
    `.mjs` for both `afterAllResolved` and `readPackage`.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    38f6eb1. 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: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
    jdx and autofix-ci[bot] authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    8095b6b View commit details
    Browse the repository at this point in the history
  9. feat(install): adopt pnpm 11 allowBuilds reviews (#364)

    ## Summary
    
    - Switch build approval writes from `onlyBuiltDependencies` to pnpm
    11-style `allowBuilds` entries.
    - Auto-seed unreviewed dependency builds into workspace `allowBuilds` as
    `false`, and have `aube approve-builds` flip selected entries to `true`.
    - Keep legacy `onlyBuiltDependencies` / `neverBuiltDependencies` as
    read-compatible inputs, and update docs, generated CLI help, and BATS
    coverage.
    
    ## Validation
    
    - `cargo fmt --check`
    - `cargo test -p aube-manifest workspace::tests::add_to_allow_builds --
    --nocapture`
    - `cargo test -p aube --bin aube`
    - `cargo clippy --all-targets -- -D warnings`
    - `mise run test:bats test/approve_builds.bats`
    - `mise run test:bats test/lifecycle_scripts.bats`
    - `mise run test:bats test/global_install.bats`
    - `mise run docs:build`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Changes dependency-build approval persistence and makes `install`
    write/update `pnpm-workspace.yaml`, which could affect build-script
    execution behavior and create new files in repos. Logic is localized but
    touches install-time safety gates and policy state transitions.
    > 
    > **Overview**
    > Switches build-script review/approval persistence to pnpm v11’s
    `allowBuilds` *review map* (writing `true`/`false` entries) instead of
    appending to `onlyBuiltDependencies`.
    > 
    > `aube install` now auto-seeds unreviewed build-script packages into
    workspace `allowBuilds` as `false` (and errors/warns accordingly), while
    `aube approve-builds` flips selected entries to `true`; when no
    workspace YAML exists, the code now creates `pnpm-workspace.yaml` rather
    than writing to `package.json`.
    > 
    > Updates CLI help text, settings/docs, and BATS/unit tests to reflect
    the new review workflow and file-writing behavior.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    f76b880. 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: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
    jdx and autofix-ci[bot] authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    94635b5 View commit details
    Browse the repository at this point in the history
  10. feat(audit): support update fix mode (#363)

    ## What changed
    
    - Adds pnpm-compatible `aube audit --fix=update` to update vulnerable
    packages through the lockfile instead of writing overrides.
    - Changes `--fix` into pnpm's optional method form: bare `--fix`
    defaults to `override`, and `--fix=override` / `--fix=update` are
    accepted.
    - Allows `aube audit -i` to default into override fix mode, matching
    pnpm's interactive behavior.
    - Adds resolver support for advisory ranges so audit update mode avoids
    vulnerable versions during sibling reuse, lockfile reuse, and version
    picking.
    
    ## Why
    
    pnpm 11 added `audit --fix=update` as the user-visible path for fixing
    advisories without generating override entries. Aube's previous audit
    fix path was override-only, so users coming from pnpm 11 got the wrong
    behavior.
    
    ## Validation
    
    - `cargo check -q`
    - `cargo build -q`
    - `cargo clippy --all-targets -- -D warnings`
    - `cargo test -p aube-resolver test_pick_version_prefers_locked --
    --nocapture`
    - `mise run test:bats test/audit.bats`
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Changes `aube audit` from read-only to optionally rewriting
    `package.json` and the lockfile, and alters resolver version-picking
    behavior when vulnerable ranges are provided; this can impact dependency
    graphs and reproducibility if the avoidance logic is wrong.
    > 
    > **Overview**
    > Adds pnpm-compatible audit fixing modes: `--fix` now accepts optional
    values (`override` default, `update` to refresh the lockfile) and
    introduces `-i/--interactive` to select which advisories to fix.
    > 
    > Implements `--fix=update` by re-running resolution while steering
    specific packages away from advisory semver ranges, then writing updated
    `aube-lock.yaml` and (when needed) adjusting direct dependency
    specifiers to match the new resolved versions.
    > 
    > Extends the resolver with `vulnerable_ranges` support so sibling
    reuse, lockfile reuse, and version picking prefer non-vulnerable
    versions when available, while falling back to the original pick if no
    safe version exists; updates CLI docs/usage metadata and expands
    bats/unit tests to cover the new behaviors.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    9a3a439. 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: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
    jdx and autofix-ci[bot] authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    b431a98 View commit details
    Browse the repository at this point in the history
  11. test(import): add messy Bun lockfile install smoke (#367)

    ## Motivation
    
    Recent changes showed that `aube install` could use a broader smoke
    coverage for projects that already carry a package-manager-native
    lockfile. The existing Bun coverage used a small fixture, but it did not
    stress the messy workspace shapes that tend to expose lockfile import
    and format-preservation bugs.
    
    ## Changes
    
    - Add a messy Bun workspace fixture with catalogs, overrides, patches,
    trusted and untrusted lifecycle script packages, local folder and
    tarball deps, npm aliases, remote tarball deps, GitHub git specifiers,
    and workspace dependency variations.
    - Regenerate the fixture `bun.lock` with Bun against the repo Verdaccio
    registry for normal registry packages.
    - Add `aube-test-builds-marker-2` to the Verdaccio fixture registry so
    the messy fixture can cover both trusted and untrusted lifecycle script
    deps without pulling large public packages into the test path.
    - Add a high-level BATS smoke test that copies the fixture, runs `aube
    install`, and asserts `bun.lock` stays byte-for-byte unchanged.
    
    ## Validation
    
    - `mise run test:bats test/import.bats`
    
    *PR description created with GPT 5.5*
    johnpyp authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    0688341 View commit details
    Browse the repository at this point in the history
  12. fix(npm): preserve extensionless bin shims (#369)

    ## Summary
    
    - Keep the root npm package's published `bin` entries stable and
    extensionless: `./bin/aube`, `./bin/aubr`, and `./bin/aubx`.
    - On Unix, continue copying or hardlinking the selected native binaries
    directly to those extensionless paths.
    - On Windows, copy or hardlink native binaries to sibling `.exe` files,
    then write the extensionless `bin/<name>` files as tiny shebang files
    pointing at those native `.exe` files. This gives npm's generated `.cmd`
    shims a stable target without adding a Node wrapper.
    - Normalize npm's Windows interpreter-shim argv shape in the native CLI,
    so `aube.exe bin/aube ...` parses as the intended `aube ...`, and `aubr`
    / `aubx` multicall dispatch still works.
    
    ## Why
    
    The current published npm package downloads/copies the platform binary
    during `preinstall`, then rewrites `package.json` from `./bin/aube` to
    `./bin/aube.exe` on Windows. npm/npx appear to resolve executable
    metadata before that rewrite matters, so global installs and fresh-cache
    `npx` installs can leave no runnable `aube` command.
    
    This keeps the published bin paths stable for npm/npx while preserving
    extensionless command targets on Unix and keeping the runtime path
    native-only.
    
    ## Validation
    
    - `git diff --check`
    - `node -c npm/installArchSpecificPackage.js`
    - `rustup run 1.93.0 cargo test -p aube multicall_tests --bin aube`
    - `rustup run 1.93.0 cargo build -p aube --bin aube --bin aubr --bin
    aubx`
    - Windows global-prefix smoke using a temp root package and temp local
    `@endevco/aube-win32-x64` package built from the updated debug binaries:
    `npm.cmd install --global --prefix <tmp> --ignore-scripts=false <pkg>`,
    then `<tmp>\\aube.cmd --version`, `<tmp>\\aubr.cmd --version`, and
    `<tmp>\\aubx.cmd --version` all printed `1.3.0-DEBUG windows-arm64
    (2026-04-28)`.
    - Windows npx smoke using a fresh cache and temp local platform package:
    `npx.cmd --yes --package <fixed local package> aube --version` printed
    `1.3.0-DEBUG windows-arm64 (2026-04-28)`.
    
    ---------
    
    Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
    jdx and autofix-ci[bot] authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    5946c78 View commit details
    Browse the repository at this point in the history
  13. docs: warn about npm install caveats (#368)

    ## Summary
    
    - Add an installation-page warning that the npm package depends on
    lifecycle scripts and can fail to expose commands when scripts are
    disabled or PowerShell blocks `npm.ps1`.
    - Add a mise tip explaining why it remains the recommended path and how
    to enable idiomatic Node version files with
    `idiomatic_version_file_enable_tools`.
    - Mirror the npm caveat and mise Node-version note in the README install
    section.
    
    ## Validation
    
    - `git diff --check`
    - `npm.cmd run docs:build` *(fails before docs render: active toolchain
    is `rustc 1.88.0-beta.3`, but `aube-settings` requires rustc 1.93)*
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Low Risk**
    > Low risk documentation-only changes; no product logic is modified, but
    incorrect guidance could impact install success for npm users.
    > 
    > **Overview**
    > Updates the install docs to further **recommend mise** by calling out
    Node runtime/version-file management, including the `mise settings add
    idiomatic_version_file_enable_tools node` guidance.
    > 
    > Clarifies **npm install caveats** by switching examples to pass
    `--ignore-scripts=false` and adding warnings that the npm package
    depends on its `preinstall` lifecycle script to fetch the native binary
    and wire up `aube`/`aubr`/`aubx` commands (mirrored in both `README.md`
    and `docs/installation.md`).
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    c2fa685. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    3980ff3 View commit details
    Browse the repository at this point in the history
  14. fix(resolver): trust benchmark fixture churn packages (#370)

    ## Summary
    
    - add built-in trustPolicy exclusions for eslint-config-prettier,
    react-redux, and reselect
    - keep the no-downgrade algorithm unchanged; these packages are registry
    provenance metadata churn cases surfaced by the benchmark fixture
    
    ## Validation
    
    - cargo fmt --check
    - cargo test -p aube-resolver trust::tests
    - cargo build -p aube
    - cargo clippy -p aube-resolver --all-targets -- -D warnings
    - fresh-cache benchmark fixture install: `aube
    --disable-global-virtual-store install --no-side-effects-cache`
    
    ## Notes
    
    `cargo clippy --all-targets -- -D warnings` currently fails outside this
    change on `clippy::items-after-test-module` in
    `crates/aube/src/commands/install/mod.rs`.
    
    *This PR description was generated by Codex.*
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Medium Risk**
    > Adjusts default trust-policy enforcement by globally excluding three
    additional packages, which can bypass downgrade failures for those
    dependencies. Low code complexity, but it touches a security-related
    guardrail and changes install acceptance for affected packages.
    > 
    > **Overview**
    > Expands the built-in `DEFAULT_TRUST_POLICY_EXCLUDES` list to also
    exclude `eslint-config-prettier`, `react-redux`, and `reselect` from
    trust-downgrade checks, reducing benchmark/fixture churn caused by
    registry provenance metadata changes.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    8b11a39. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    3eba9f7 View commit details
    Browse the repository at this point in the history
  15. fix(bench): support macos bash in benchmark script (#371)

    ## Summary
    
    - replace the benchmark script's Bash 4 associative-array command map
    with a Bash 3-compatible `case` helper
    - leave the benchmark task tool providers unchanged, including
    `aqua:pnpm/pnpm@latest`
    
    ## Why
    
    macOS still ships Bash 3.2 by default, so `benchmarks/bench.sh` failed
    on `declare -A` before it could run the hyperfine matrix. This keeps the
    same per-scenario commands while making the dispatch portable to the
    default macOS shell.
    
    ## Validation
    
    - `bash -n benchmarks/bench.sh`
    - `git diff --check`
    
    I also confirmed the earlier one-run smoke got past pnpm 11 provisioning
    when using `npm:pnpm@11`, but reverted that provider change per
    follow-up because `aqua:pnpm/pnpm@latest` is expected to work again
    later.
    
    *This PR was generated by Codex.*
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > **Low Risk**
    > Low risk: this is a refactor of benchmark command dispatch to avoid
    Bash 4-only associative arrays, with no production/runtime impact beyond
    the benchmarking harness.
    > 
    > **Overview**
    > Makes `benchmarks/bench.sh` compatible with macOS’s default Bash (3.2)
    by **replacing the Bash 4 `declare -A` scenario/tool command map** with
    a `cmd_template` `case` helper.
    > 
    > Updates `run_bench` and `run_bench_preinstall` to fetch per-scenario
    commands via `cmd_template`, keeping the underlying benchmark commands
    and hermetic env flags effectively the same while improving portability.
    > 
    > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
    e51dc9a. Bugbot is set up for automated
    code reviews on this repo. Configure
    [here](https://www.cursor.com/dashboard/bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    jdx committed Apr 28, 2026
    Configuration menu
    Copy the full SHA
    a2c8113 View commit details
    Browse the repository at this point in the history
  16. chore: release v1.4.0 (#351)

    ## 🤖 New release: `v1.4.0`
    
    This PR bumps the workspace to `v1.4.0` and regenerates CHANGELOG
    entries, `aube.usage.kdl`, the CLI docs, and the benchmark results.
    
    See the diff for the full set of changes, or the per-crate
    `CHANGELOG.md` files for the release notes that will ship.
    
    ---
    Generated by the `release-plz-pr` workflow.
    
    Co-authored-by: release-plz[bot] <release-plz+bot@users.noreply.github.com>
    mise-en-dev and release-plz[bot] authored Apr 28, 2026
    Configuration menu
    Copy the full SHA
    fa69f13 View commit details
    Browse the repository at this point in the history
Loading