Skip to content

Install gate, Phase 3 (lane 1): uv gate + yarn/pnpm named-only wrappers#113

Open
juangaitanv wants to merge 3 commits into
install-gate-phase-2from
install-gate-phase-3-uv
Open

Install gate, Phase 3 (lane 1): uv gate + yarn/pnpm named-only wrappers#113
juangaitanv wants to merge 3 commits into
install-gate-phase-2from
install-gate-phase-3-uv

Conversation

@juangaitanv

@juangaitanv juangaitanv commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR is Phase 3, lane 1 of the install-gate feature for the Corgea CLI.

Lane 1 expands package-manager breadth. It adds uv coverage, adds named-only wrappers for yarn and pnpm, and adds wrong-package-manager guards so installs are steered toward the manager that owns the project.

This lane remains public mode only and does not add --json output.

Stacked on #112. Base branch: install-gate-phase-2. Review this PR's diff in isolation; it contains the Phase 3 lane 1 slice.

What Phase 3 Lane 1 Includes

  • uv tree gating for uv pip install, uv add, and uv pip sync through uv pip compile, with --only-binary :all: and a temporary input file so the full resolved set is checked.
  • uv sync lockfile gating from the nearest ancestor uv.lock. Local/editable stanzas are skipped, registry packages are checked, unparsable locks refuse unless --force is used, and skipped non-registry pins are disclosed.
  • uv command classification behind global flags, including valued flags, so commands such as uv --project ./app sync and uv pip --quiet install x do not pass through ungated.
  • uv custom-index warning for flags such as --index, --default-index, and --find-links.
  • yarn and pnpm named-target gating with an explicit named-only warning. Bare installs execute unchecked behind an honest note because there is no safe dry-run tree resolver in this lane.
  • Bare yarn routing through yarn install semantics.
  • Wrong-package-manager guard for npm/yarn/pnpm using lockfiles, packageManager, package workspaces, and pnpm-workspace.yaml; and for pip/uv using uv.lock and requirements files.
  • Ungated-install disclosure for commands such as uv run, uv tool install, and yarn global add.
  • Docs in skills/corgea/SKILL.md for the new managers and limitations.

Deliberately Out Of Scope

Later lanes add:

  • --json machine-readable output
  • token auth and fail-closed enforcement

Exit Criteria - Met

uv install paths gate through uv pip compile; uv sync gates from uv.lock; yarn and pnpm named-only installs warn honestly about what is not covered.

Covered by tests/cli_uv_sync.rs and extensions to the install, tree, and bare-install suites. Confirmed live with corgea uv pip install mezzanine==6.0.0, which resolves a 24-package tree through real uv pip compile and blocks; also confirmed corgea pnpm add in an npm project refuses with a corrected command suggestion. ./harness check passes.

Comment thread src/precheck/parse.rs
Comment thread src/precheck/uv.rs
Comment thread src/precheck/tree.rs
Comment thread src/precheck/uv.rs Outdated
Comment thread src/precheck/detect.rs
@juangaitanv juangaitanv force-pushed the install-gate-phase-2 branch from 936d69a to dd4b575 Compare June 12, 2026 14:51
juangaitanv added a commit that referenced this pull request Jun 12, 2026
… guard

Addresses Cursor review on #113.

- uv commands are now classified after skipping leading global flags, so
  `uv --project ./app sync` / `uv --quiet add x` are gated instead of
  falling through to ungated passthrough.
- the custom-index warning (from Phase 1) now fires for uv install/add/sync
  too, listing uv's index flags (--index, --default-index, --find-links, …).
- the pip↔uv wrong-manager guard is applied consistently: it stays on
  `uv add` (project management, writes pyproject) but NOT `uv pip install` /
  `uv pip sync` — those are uv's pip-compatible interface, correct to use in
  a requirements project, and already fully gated by the tree pass. (Partial
  decline of the review's ask, with the reasoning above.)
- parse_uv_lock now verdicts ONLY registry-sourced packages: git/url direct
  artifacts are skipped (their name@version is not a PyPI identity), and a
  registry package missing a version fails closed instead of being silently
  dropped.
- the Node wrong-manager guard walks past a workspace MEMBER's leaf
  package.json to the workspace root (root `workspaces` field or
  pnpm-workspace.yaml), so a member install is checked against the root's
  manager. Standalone fresh projects still stop at their own leaf.
@juangaitanv juangaitanv force-pushed the install-gate-phase-3-uv branch from c39ab0f to d9af832 Compare June 12, 2026 14:51
@juangaitanv juangaitanv force-pushed the install-gate-phase-2 branch from dd4b575 to c86aa2d Compare June 12, 2026 16:42
juangaitanv added a commit that referenced this pull request Jun 12, 2026
… guard

Addresses Cursor review on #113.

- uv commands are now classified after skipping leading global flags, so
  `uv --project ./app sync` / `uv --quiet add x` are gated instead of
  falling through to ungated passthrough.
- the custom-index warning (from Phase 1) now fires for uv install/add/sync
  too, listing uv's index flags (--index, --default-index, --find-links, …).
- the pip↔uv wrong-manager guard is applied consistently: it stays on
  `uv add` (project management, writes pyproject) but NOT `uv pip install` /
  `uv pip sync` — those are uv's pip-compatible interface, correct to use in
  a requirements project, and already fully gated by the tree pass. (Partial
  decline of the review's ask, with the reasoning above.)
- parse_uv_lock now verdicts ONLY registry-sourced packages: git/url direct
  artifacts are skipped (their name@version is not a PyPI identity), and a
  registry package missing a version fails closed instead of being silently
  dropped.
- the Node wrong-manager guard walks past a workspace MEMBER's leaf
  package.json to the workspace root (root `workspaces` field or
  pnpm-workspace.yaml), so a member install is checked against the root's
  manager. Standalone fresh projects still stop at their own leaf.
@juangaitanv juangaitanv force-pushed the install-gate-phase-3-uv branch from d9af832 to 36350f3 Compare June 12, 2026 16:42
Harvested from the install-vuln-gate spike (dfac68e); still public-mode
only, no --json.

- corgea uv: `uv pip install` / `uv add` / `uv pip sync` gate through
  `uv pip compile` (--only-binary :all:, temp .in file) so the full
  resolved set is verdicted; `uv sync` is gated from the
  nearest-ancestor uv.lock (local/editable stanzas skipped, unparsable
  lock refuses, --force escape); `uv lock` and everything else passes
  through; top-level `uv install` gets a did-you-mean
- corgea yarn|pnpm: named targets verified (with the loud named-only
  warning — no safe dry-run); bare installs exec unchecked behind an
  honest stderr note; bare `yarn` routes through `yarn install`
- wrong-package-manager guard: npm/yarn/pnpm cross-checked against
  lockfiles + the packageManager field (ambiguous indicators stand
  down, fresh projects don't inherit ancestor lockfiles); pip↔uv
  cross-checked against uv.lock / requirements files; all suggestions
  name the corgea-wrapped command; --force bypasses
- SKILL.md updated for the new managers and limitations
… guard

Addresses Cursor review on #113.

- uv commands are now classified after skipping leading global flags, so
  `uv --project ./app sync` / `uv --quiet add x` are gated instead of
  falling through to ungated passthrough.
- the custom-index warning (from Phase 1) now fires for uv install/add/sync
  too, listing uv's index flags (--index, --default-index, --find-links, …).
- the pip↔uv wrong-manager guard is applied consistently: it stays on
  `uv add` (project management, writes pyproject) but NOT `uv pip install` /
  `uv pip sync` — those are uv's pip-compatible interface, correct to use in
  a requirements project, and already fully gated by the tree pass. (Partial
  decline of the review's ask, with the reasoning above.)
- parse_uv_lock now verdicts ONLY registry-sourced packages: git/url direct
  artifacts are skipped (their name@version is not a PyPI identity), and a
  registry package missing a version fails closed instead of being silently
  dropped.
- the Node wrong-manager guard walks past a workspace MEMBER's leaf
  package.json to the workspace root (root `workspaces` field or
  pnpm-workspace.yaml), so a member install is checked against the root's
  manager. Standalone fresh projects still stop at their own leaf.
…flag-skip, ungated disclosures

- SECURITY: valued global flags missing from takes_value made their VALUE
  classify as the subcommand → silent ungated passthrough. Added uv's
  --color/--config-file/--cache-dir/--allow-insecure-host and yarn's
  --cwd ('corgea uv --color always add x' and 'corgea yarn --cwd dir add
  x' installed unchecked). Unit + e2e regression tests with valued flags.
- classify_uv_command skips flags between 'pip' and its verb, so
  'uv pip --quiet install x' gates instead of passing through.
- uv add's --optional/--bounds/--script values no longer parse as specs.
- 'uv run' / 'uv tool install|run|upgrade' print an ungated-install note
  (and SKILL.md lists them as limitations) instead of passing silently;
  same for 'yarn global add'.
- Workspace-member walk now checks dir membership against the declared
  globs (package.json workspaces / pnpm-workspace.yaml packages), so a
  standalone project nested under an unrelated monorepo keeps its leaf
  boundary instead of being wrong-manager-refused.
- uv.lock parsing discloses skipped non-registry pin counts and warns on
  non-default registry sources; run_uv_sync echoes the command correctly
  behind global flags.
@juangaitanv juangaitanv force-pushed the install-gate-phase-2 branch from c86aa2d to 33da96b Compare June 12, 2026 18:28
@juangaitanv juangaitanv force-pushed the install-gate-phase-3-uv branch from 36350f3 to f8426b6 Compare June 12, 2026 18:28
Comment thread src/precheck/uv.rs
{
set.non_default_registries.insert(registry.to_string());
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add a continue here? non default registries might still have versions (e.g internal package) and stil be added to set.packages. then it fails when vulnerability api tries to validate it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants