-
-
Notifications
You must be signed in to change notification settings - Fork 20
Comparing changes
Open a pull request
base repository: endevco/aube
base: v1.4.0
head repository: endevco/aube
compare: v1.5.0
- 10 commits
- 55 files changed
- 4 contributors
Commits on Apr 29, 2026
-
fix(lockfile): hoist npm workspace links to root importer deps (#374)
## Summary - npm symlinks every workspace member into the root `node_modules/` regardless of whether the root `package.json` declares it as a dep — recorded in `package-lock.json` as `node_modules/<name>: { link: true, resolved: "<rel>" }`. Aube was seeding the root importer only from `dependencies`/`devDependencies`/`optionalDependencies`, so undeclared workspace projects never got a top-level `node_modules/<ws-pkg>` symlink and Angular CLI / Nx / similar tooling that resolves workspace libraries from the repo root broke when migrating npm-managed monorepos to aube. - Surface every top-level link entry (plain or scoped, no nested `/node_modules/` segment) as a direct dep of the root importer in the npm-lockfile parser. Existing `already_added` dedupe preserves explicit `dependencies: { "@scope/x": "file:packages/x" }` declarations; entries are appended sorted by name for deterministic output. Reported in #345 (comment) (siemens/element). ## Test plan - [x] `cargo test -p aube-lockfile` (new test `test_parse_workspace_links_undeclared_in_root_deps` + existing `test_parse_workspace_links` to confirm no double-add when the workspace IS in root deps) - [x] `cargo test` workspace-wide - [x] Manual smoke: minimal repro repo with `workspaces: ["projects/foo", "projects/bar"]`, neither declared in root `dependencies`, package-lock.json with `node_modules/@scope/foo` + `node_modules/@scope/bar` link entries → `aube install` produces `node_modules/@scope/foo` and `node_modules/@scope/bar` symlinks pointing at `../../projects/<name>` 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes how npm lockfiles are interpreted to seed root direct dependencies, which can affect install layout and hoisting behavior for workspace/linked packages. > > **Overview** > Ensures npm-managed workspaces that are **not declared in the root `package.json` deps** still get their top-level `node_modules/<workspace>` symlinks recreated by `aube install`. > > The npm lockfile parser now scans `package-lock.json` `packages` for top-level `node_modules/*` entries with `link: true`, de-dupes against already-declared direct deps, sorts them deterministically, and appends them to the root importer’s direct deps. Adds a regression test covering undeclared workspace members being surfaced as root direct deps and round-tripping as `LocalSource::Link`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c98805f. 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>Configuration menu - View commit details
-
Copy full SHA for 7dc3692 - Browse repository at this point
Copy the full SHA 7dc3692View commit details -
fix(resolver): bound resolved package stream (#377)
## Summary - replace the resolver resolved-package stream with a bounded Tokio channel - size the install streaming buffer from the same network concurrency used by fetch workers - await stream sends so resolver/fetch overlap applies backpressure instead of growing an unbounded queue - move an existing install test module below helper items so current all-targets clippy stays green ## Validation - cargo check -p aube-resolver -p aube - cargo fmt --check - cargo clippy --all-targets -- -D warnings - cargo test -p aube-resolver *This PR was generated by Codex.* <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes async streaming semantics (`send().await`) between resolver and installer, which can affect throughput and introduce stalls if the receiver isn’t drained as expected. Scope is contained to the streaming resolution/fetch overlap path. > > **Overview** > The resolver’s resolved-package stream is now **bounded**: `Resolver::with_stream` uses a fixed default capacity and a new `with_stream_capacity` constructor, and `resolved_tx` switches from `mpsc::UnboundedSender` to `mpsc::Sender`. > > All resolver streaming `send` call sites now `await` to apply **backpressure** instead of accumulating an unbounded queue, and `install` sizes the stream buffer from the same network concurrency used by tarball fetch workers. A small test-module move keeps `--all-targets` clippy passing. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7b20f7b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Configuration menu - View commit details
-
Copy full SHA for a179f9b - Browse repository at this point
Copy the full SHA a179f9bView commit details -
fix(lockfile): preserve pnpm registry tarball urls (#378)
## Summary - preserve pnpm registry packages as registry packages when `lockfileIncludeTarballUrl` records a tarball URL - add an adversarial pnpm roundtrip test covering aliases, catalogs, overrides, patches, skipped optionals, peer metadata, platform optionals, and section ordering together ## Root Cause The pnpm parser classified any `resolution.tarball` HTTP URL as a remote-tarball dependency. That is only correct for URL-keyed package entries; ordinary `name@version` registry entries can also carry tarball URLs when `lockfileIncludeTarballUrl=true`. ## Validation - `cargo fmt --check` - `cargo test -p aube-lockfile` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches pnpm lockfile parsing/classification used by the installer; misclassification fixes are targeted but can change how dependencies are fetched/resolved for some lockfiles. > > **Overview** > Preserves pnpm registry dependencies as *registry-sourced* even when `lockfileIncludeTarballUrl` adds an HTTP `resolution.tarball`, by only treating `RemoteTarball` as `local_source` for URL-keyed entries. > > Adds an adversarial pnpm v9 parse→write→reparse test that exercises multiple native lockfile features together (overrides, catalogs, patched deps, aliasing, skipped/ignored optionals, peer metadata, platform constraints) and asserts top-level section ordering and tarball URL retention. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e94a504. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Configuration menu - View commit details
-
Copy full SHA for 97cf455 - Browse repository at this point
Copy the full SHA 97cf455View commit details -
test(lockfile): add property roundtrip coverage (#376)
## Summary Adds property-based lockfile roundtrip coverage for generated registry-only graphs across pnpm, npm, Bun, Yarn classic, and Yarn Berry lockfile writers/parsers. The tests normalize dependency edges before comparing so they focus on structural graph preservation across each format. ## Validation - cargo fmt --check - cargo test -p aube-lockfile --test proptest - cargo test -p aube-lockfile - cargo clippy -p aube-lockfile --all-targets -- -D warnings *This PR was generated by Codex.* <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only changes plus a new dev-dependency; no production code paths are modified. > > **Overview** > Adds property-based roundtrip tests in `aube-lockfile` that generate small registry-only dependency graphs, write them as each supported lockfile format (pnpm/npm/bun/yarn classic/yarn berry), re-parse them, and compare a normalized representation to ensure structural preservation. > > Introduces `proptest` as a dev-dependency (and updates `Cargo.lock`) to support this new randomized/parametric test coverage. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 499374f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Configuration menu - View commit details
-
Copy full SHA for f9c6c74 - Browse repository at this point
Copy the full SHA f9c6c74View commit details -
fix(resolver): require structured trust evidence (#379)
## Summary - require npm trusted-publisher evidence to include a structured non-empty `id` - require provenance evidence to include an SLSA `predicateType` - update trust policy docs and regenerated settings docs ## Why The trust downgrade policy previously treated arbitrary truthy registry values as trust evidence. That matched pnpm-style boolean checks, but it meant malformed or hostile packument metadata such as `{}` or `"oidc"` could satisfy aube's trust policy. This keeps the existing metadata-based policy but narrows the accepted shapes to the structured metadata npm emits after registry-side checks. ## Validation - `cargo run -p aube-settings --bin generate-settings-docs` - `cargo fmt --check` - `cargo test -p aube-resolver trust::tests` - `cargo test -p aube-registry provenance` - `cargo clippy -p aube-resolver -p aube-registry --all-targets -- -D warnings` *This pull request was generated by Codex.* <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes security enforcement logic for installs, which could newly reject packages with malformed/nonstandard registry metadata or alter downgrade decisions; behavior is well-covered by updated tests and docs. > > **Overview** > Tightens trust-policy evidence detection so `_npmUser.trustedPublisher` only counts when it is an object with a non-empty `id`, and `dist.attestations.provenance` only counts when it is an object whose `predicateType` matches an SLSA provenance URI (e.g. `https://slsa.dev/provenance/v1`). > > Updates resolver/unit tests and documentation/settings text to reflect the new structured-shape requirements and clarify that this is *metadata validation* (not cryptographic attestation verification). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e4a5bb0. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->Configuration menu - View commit details
-
Copy full SHA for abbe949 - Browse repository at this point
Copy the full SHA abbe949View commit details -
feat(cli): add dependency graph query command (#380)
## Summary - add `aube query` for local selector-based dependency graph inspection inspired by vlt's dependency selector model - support package/name/version/source/license selectors plus direct/transitive flags and JSON/parseable output - regenerate usage docs and add BATS coverage for the CLI path ## Validation - `cargo fmt --check` - `cargo test -p aube query::tests` - `cargo test -p aube cli_ordering_tests::test_cli_ordering` - `cargo clippy -p aube --bin aube --bin aubr --bin aubx -- -D warnings` - `mise run test:bats test/query.bats` - `mise run render` Note: `cargo clippy --all-targets -- -D warnings` still reports the existing `items_after_test_module` warning in `crates/aube/src/commands/install/mod.rs`. *This PR was generated by Codex.* <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Additive CLI feature that only reads existing lockfile data and adds new parsing/output paths; minimal impact on existing commands aside from command dispatch and docs regeneration. > > **Overview** > Adds a new `aube query` command that reads the local lockfile, walks the reachable dependency graph (optionally scoped by workspace `--filter` and `--prod`/`--dev` roots), and filters packages via a selector expression supporting attribute predicates and pseudo-selectors like `:scripts`, `:bin`, `:peer`, `:type(...)`, and `:license(...)`. > > The command can emit human-readable output, tab-separated `--parseable` rows, or `--json` output; CLI wiring, usage spec/docs generation (`aube.usage.kdl`, `docs/cli/*`), and new BATS coverage are included. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 780bcad. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Configuration menu - View commit details
-
Copy full SHA for 038e339 - Browse repository at this point
Copy the full SHA 038e339View commit details -
fix(workspace): default-write aube-workspace.yaml instead of pnpm-wor…
…kspace.yaml (#382) ## Summary When `aube approve-builds` (or the install-time auto-seed of unreviewed build scripts) needs to create a workspace yaml from scratch, aube was writing `pnpm-workspace.yaml`. The lockfile companion is `aube-lock.yaml` — having the workspace yaml stay pnpm-prefixed is an asymmetry: a fresh `aube install` on a solo project produces a filesystem layout with both names sitting next to each other, mixing vendor namespaces. Switches the **default write** filename to `aube-workspace.yaml` so the two aube-generated files share a naming scheme. ## Backward compat Unchanged. The read path already prefers `aube-workspace.yaml` and falls back to `pnpm-workspace.yaml` (constant `WORKSPACE_YAML_NAMES = ["aube-workspace.yaml", "pnpm-workspace.yaml"]` in `crates/aube-manifest/src/workspace.rs:6`). The write path's existing-file precedence is unchanged too: a project that already ships `pnpm-workspace.yaml` keeps mutating that file in place. The only behavior change is the **fallback** when neither file exists — that branch now creates the aube-prefixed name. | State | Before this PR | After this PR | |---|---|---| | `aube-workspace.yaml` present | mutate it | mutate it (unchanged) | | `pnpm-workspace.yaml` present | mutate it | mutate it (unchanged) | | Both present | mutate `aube-workspace.yaml` | mutate `aube-workspace.yaml` (unchanged) | | Neither present | **create `pnpm-workspace.yaml`** | **create `aube-workspace.yaml`** ← change | ## Test coverage - Renames the existing `add_to_allow_builds_creates_pnpm_workspace_when_no_yaml` test to its new behavior (`add_to_allow_builds_creates_aube_workspace_when_no_yaml`). - Adds a companion `add_to_allow_builds_writes_to_existing_pnpm_workspace` that pins the backward-compat branch — a project with an existing `pnpm-workspace.yaml` keeps using it; no `aube-workspace.yaml` is created alongside. ## Test plan - [x] `cargo test -p aube-manifest workspace` — 24 pass (including the 2 covered above) - [x] `cargo test --workspace --all-targets` — all green (~1500 tests) - [x] `cargo clippy --workspace --all-targets -- -D warnings` — clean - [x] `cargo fmt --check` — clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Behavior change is limited to the fallback filename used when creating a new workspace YAML; existing files and build-policy logic remain unchanged. > > **Overview** > Changes the default workspace YAML write target for `allowBuilds` updates: when neither `aube-workspace.yaml` nor `pnpm-workspace.yaml` exists, aube now creates `aube-workspace.yaml` instead of `pnpm-workspace.yaml` (while still mutating an existing `pnpm-workspace.yaml` in place for backward compatibility). > > Updates `approve-builds`/lifecycle-script documentation, CLI help text, and bats/unit tests to reflect the new filename and to add coverage that existing `pnpm-workspace.yaml` files are not “forked” into a new `aube-workspace.yaml`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f353258. 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>
Configuration menu - View commit details
-
Copy full SHA for d6f9a4d - Browse repository at this point
Copy the full SHA d6f9a4dView commit details -
perf(bench): add install phase timings (#381)
## Summary - add an opt-in `AUBE_BENCH_PHASES_FILE` JSONL sink for install phase timings - sample aube install-shaped benchmark scenarios after the hyperfine matrix - generate markdown and JSON phase timing summaries from the sampled JSONL ## Validation - `cargo fmt --check` - `bash -n benchmarks/bench.sh` - `node --check benchmarks/generate-phase-results.mjs` - `cargo check -p aube` - smoke-tested `benchmarks/generate-phase-results.mjs` with sample JSONL <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes touch core install code, but the new timing collection and file I/O are gated behind `AUBE_BENCH_PHASES_FILE`, so normal installs should be unaffected aside from minimal added timing calls. > > **Overview** > Adds an opt-in install phase timing sink to `aube install`: when `AUBE_BENCH_PHASES_FILE` is set, the installer records per-phase durations (e.g. resolve/fetch/link/scripts/state/sweep) and appends a JSONL summary including counts and an optional `AUBE_BENCH_SCENARIO` label. > > Extends `benchmarks/bench.sh` to run one extra aube-only sample per install-shaped scenario that writes phase timings, and adds `benchmarks/generate-phase-results.mjs` to convert the collected JSONL into a Markdown table plus a structured JSON artifact. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0714efd. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Configuration menu - View commit details
-
Copy full SHA for b5674b3 - Browse repository at this point
Copy the full SHA b5674b3View commit details -
fix(cli,linker,lockfile): patch-commit destination, CRLF patches, npm…
…-alias catalog (#384) ## Summary Three bug fixes for [#383](#383) plus the supporting refactors that fell out of code review. ### Bug fixes - **Patches against CRLF text files** — tarballs published from Windows editors ship CRLF (e.g. `gifuct-js@2.1.2/index.d.ts`), but git/pnpm-style patches always emit LF. Diffy is byte-exact and refused to match CRLF context against LF hunks, so a clean patch failed with `error applying hunk #1`. Normalize the original to LF before apply and restore CRLF on write — same approach pnpm uses. The CRLF restore also collapses any `\r\r\n` so a patch line containing a literal `\r` byte mid-line doesn't gain a second carriage return. - **`aube patch-commit` destination** — previously wrote unconditionally to `pnpm.patchedDependencies` in `package.json`, even on projects already using the pnpm v10+ workspace-yaml home. Now follows the unified rule below. `aube patch-remove` now strips entries from every place they could live (both yaml and both `pnpm.*` / `aube.*` namespaces) and reports the actual files rewritten in its status output. - **npm-aliased catalog deps from pnpm-generated lockfiles** ([discussioncomment](#383 (comment))) — `aube install --frozen-lockfile` accepted a pnpm lockfile with `beamcoder: npm:beamcoder-prebuild@…` (declared via `pnpm-workspace.yaml#catalog`) and silently produced an empty `node_modules`. The importer's `specifier:` was `'catalog:'`, but the alias detection only fired on `specifier.starts_with("npm:")`. Now detects aliases purely from the `version:` shape (the canonical `<real>@<resolved>` form pnpm always uses), with a peer-suffix strip so `version: 18.2.0(react@18.2.0)` doesn't get misclassified. ### Refactor: unified workspace-config writer One rule applies to every command that mutates a setting which can live in either the workspace yaml or `package.json#{pnpm,aube}.<key>` (`aube patch-commit`, `aube patch-remove`, `aube approve-builds`, install-time auto-deny seeding, future settings): 1. If a workspace yaml exists on disk → write there. 2. Otherwise, if `package.json#pnpm` is already declared → write `pnpm.<key>` (preserve the user's chosen namespace). 3. Otherwise → write `aube.<key>` (aube's native namespace; the read side already gives `aube.*` precedence over `pnpm.*`). New helpers in `aube_manifest::workspace`: - `ConfigWriteTarget` + `config_write_target(dir)` — picks step 1 vs steps 2/3. - `edit_workspace_yaml(path, f)` — yaml writer; **skips the rewrite when the closure produces no structural change**, so user comments survive every no-op write. Used by allowBuilds, patchedDependencies, and catalog cleanup. - `edit_setting_map(cwd, key, f)` — `package.json` writer; picks namespace per steps 2/3, also skips no-op rewrites. - `remove_setting_entry(cwd, key, entry_key)` — strips an entry from both `pnpm.<key>` and `aube.<key>` so a one-namespace removal doesn't leave a stale duplicate behind on the read merge. Migrated callers: `aube approve-builds` (and the install-time auto-deny seed), `aube patch-commit`, `aube patch-remove`, catalog cleanup. The `PatchDestination` enum and `edit_patched_dependencies` helper that lived in `aube/src/patches.rs` are gone. ### Refactor: workspace-yaml file selection Centralized the `aube-workspace.yaml` → `pnpm-workspace.yaml` precedence walk into `aube_manifest::workspace::workspace_yaml_existing`. `workspace_yaml_target` is now a one-liner over it. Removed three duplicates of the same loop (`catalogs.rs`, `find_workspace_root`, `find_workspace_yaml_root`). ## Test plan - [x] `cargo test` (1185 passing — new coverage spans CRLF apply + embedded-`\r` restore in `aube-linker`; helper-level + per-writer no-op-skip tests for allowBuilds, patchedDependencies, and catalog cleanup; `ConfigWriteTarget` + namespace-picking cases; pnpm-lockfile catalog alias) - [x] `cargo clippy --all-targets -- -D warnings` - [x] `cargo fmt --check` - [x] End-to-end repros from the discussion: `aube install` against `patch-application-failure` succeeds with CRLF preserved; `aube install --frozen-lockfile` against `catalog-npm-alias` installs `beamcoder` (resolved to `beamcoder-prebuild`) into `packages/app/node_modules/` 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches install/patch/config persistence paths and changes where settings are written (`workspace` YAML vs `package.json`), which can affect real projects’ config layout; mitigated by extensive new tests and largely additive helpers. > > **Overview** > Fixes patch application on CRLF-backed files by normalizing input to LF for diff matching and restoring CRLF on write (with protection for embedded literal `\r`), plus adds regression tests. > > Unifies how workspace-level settings are written: if a workspace yaml exists, write there; otherwise write to `package.json` under `aube.*` unless `pnpm` already exists. This refactor is applied to `allowBuilds` seeding/approval, `patch-commit`/`patch-remove` (including removing entries from all possible locations and reporting the actual files changed), and catalog cleanup (now skips no-op YAML rewrites to avoid stripping comments). > > Fixes pnpm lockfile parsing to detect npm-aliased dependencies based on the `version:` field shape (including catalog-declared aliases and peer suffix handling), with new tests. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 74cbd4d. 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>
Configuration menu - View commit details
-
Copy full SHA for 2f44140 - Browse repository at this point
Copy the full SHA 2f44140View commit details -
## 🤖 New release: `v1.5.0` This PR bumps the workspace to `v1.5.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>
Configuration menu - View commit details
-
Copy full SHA for c9a98ab - Browse repository at this point
Copy the full SHA c9a98abView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v1.4.0...v1.5.0