Repository navigation
Fix vendor in a workspace member exiting 0 (#1921) - #1928
Mikola Lysenko (mikolalysenko) wants to merge 4 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Hosted scan's governing-root check already finds the workspace root whose lock installs a member directory (npm, yarn, Bun, pnpm, vlt). Move that branch into npm_family_governing_root so vendored commands can ask the same question. Hosted behavior is unchanged. Refs #1921 Assisted-by: Claude Code:claude-opus-5-5
vendor, vendor --revert and vendor --check read only --cwd. From a workspace member directory (no lock, manifest or ledger of its own) they found nothing and exited 0: the eject said "nothing to vendor" while the root lock held hosted pins, and --check passed even when the root's committed artifact was tampered, so a per-package CI job could never fail. These forms now refuse with vendor_lockfile_missing (exit 1) and name the workspace root to run from, matching hosted and vendored scan. A standalone project keeps the calm no-manifest exit 0. Fixes #1921 Assisted-by: Claude Code:claude-opus-5-5
Review follow-ups for the workspace-member refusal: - Only refuse in an npm project (a directory with package.json), so a Python or other service under a pnpm workspace keeps its exit 0. - vendor --check now asks after reading the manifest, so a manifest it cannot read reports that error instead of the member refusal. - vendor --revert is not refused when the member has its own manifest. - Name the pnpm root by its canonical path, like the other roots. - The message no longer claims a member has no lock, since one with a stray lock its manager ignores is refused too. Refs #1921 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 1dff586. Configure here.
|
[burn-down agent] Labeled Ready for review at 1dff586.
Generated by Claude Code |
Final review briefWhat it does: Running Risk: low. The guard is narrow and runs before any lock is taken or file is written. Core's hosted refusal codes and messages are unchanged. The only behaviour change in core is that the pnpm directory is now canonicalized before it is returned. Look here:
Verified:
Changes I made: none. Open questions (non-blocking):
Auto-merge is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
|
[agent] Answers to the review brief's open questions, from the diff:
Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1921
Summary
vendor(eject),vendor --revertandvendor --checkrun from an npm-family workspace member directory (or with--cwd packages/a) used to look only at that directory. They found nothing and exited 0, so a per-package CIvendor --checkpassed even when the root's committed artifact was tampered. Now they refuse withvendor_lockfile_missing(exit 1) and name the workspace root to run from. That matches hostedscanand the vendored refusal docs/ecosystems.md already describes.Root cause
None of the three forms asked whether an ancestor workspace root governs
--cwd. Hostedscanalready asks, throughhosted::governing_root::refusal, which finds npm/yarn/Bunpackage.jsonworkspaces, pnpm workspaces andlockfile-dir, and vlt workspaces. The vendor command never called it.Change
core
hosted/governing_root.rs: the npm-family branch ofrefusalmoves into a publicnpm_family_governing_root(dir) -> Option<(root, Refusal)>. Hosted behavior is unchanged, except that the pnpm root it returns is now canonical (a relativelockfile-dirno longer yields a..path). The hosted refusal message is unchanged.cli
commands/vendor.rs: a newmember_refusal(dir, form)refuses only when all of these hold:package.json;It is wired into the no-manifest eject arm, into
--revert(when there is no manifest), and into--check(afterread_manifestreturns no manifest, so a manifest read error keeps its own code).CLI_CONTRACT.md: documents the refusal in the vendor section.
Tests (red → green)
New tests in
crates/socket-patch-cli/tests/vendor/vendor_failure_paths.rs:vendor_check_from_workspace_member_refuses_and_names_root: root vendored, then its tgz tampered;--checkfrom the member (absolute--cwd, relative--cwd packages/a, and human mode)vendor_lockfile_missing, names rootvendor_eject_from_workspace_member_refuses_and_names_root: root lock hosted-pinned; eject from member (json + human).socket/in membervendor_revert_from_workspace_member_refuses_and_names_rootvendor_outside_a_workspace_keeps_the_no_manifest_exitnoManifest, exit 0)vendor_in_a_non_npm_dir_under_a_pnpm_workspace_is_not_refusedvendor_revert_in_a_member_with_its_own_manifest_is_not_refusedPer-issue checklist:
vendorandvendor --checkrun from an npm workspace member directory exit 0 without looking at the root lock: the eject says "nothing to vendor" and the check passes over a tampered artifact #1921vendorfrom a member:vendor_eject_from_workspace_member_refuses_and_names_rootvendorandvendor --checkrun from an npm workspace member directory exit 0 without looking at the root lock: the eject says "nothing to vendor" and the check passes over a tampered artifact #1921vendor --checkfrom a member, including--cwd packages/afrom the root:vendor_check_from_workspace_member_refuses_and_names_rootLocal runs:
cargo fmt --all -- --check: ok.cargo clippy --workspace --all-features -- -D warnings: ok.cargo test -p socket-patch-cli --all-features --test vendor: 157 passed.cargo test -p socket-patch-cli --all-features --lib: 940 passed.cargo test -p socket-patch-core --all-features --lib: 6995 passed, 4 failed. All 4 failures are permission fault-injection tests (copy_tree,vlt_heal,pypi_poetry,pypi_requirements) that can't fail as root in this container, and none is in a touched file.cargo test --workspacedidn't fit the container's disk; CI runs it.Review notes (
/code-review high)Fixed:
--revertrefusing a member that has its own manifest.Not fixed:
member_refusalfor no behavior change.vendor --check/--revert. They're out of scope for this npm issue and a candidate follow-up;governing_rootalready hascargo_member_refusalandgoverning_uv_workspaceto reuse.Yarn and Bun members go through the same
package.jsonworkspace lookup, and pnpm and vlt through their own branches. Only npm was exercised end to end.https://claude.ai/code/session_011f9aeRgLZEtRSKeWxfgoZ3
Generated by Claude Code