Skip to content

Two @unbrained/pm-cli versions can resolve in one project and pm health reports ok, though which copy loads decides the gate verdict #1003

Closed

Description

@unbraind

Found by installing a published extension next to a pinned CLI in a clean project, not by reading code.

Two different @unbrained/pm-cli versions can coexist in one project's node_modules, and nothing in pm health says so. In this ecosystem that is not a cosmetic duplicate: consecutive CLI versions have disagreed about whether the same bytes on disk are fatal, a warning, or invisible (see #998), so which copy loads decides whether a workspace passes its own gates.

Reproduction

mkdir skew && cd skew && npm init -y
npm install @unbrained/pm-cli@2026.8.3 pm-beads
find node_modules -type d -path "*@unbrained/pm-cli" -exec sh -c \
  'printf "%s -> " "$1"; node -p "require(\"$1/package.json\").version"' _ {} \;

Observed:

node_modules/@unbrained/pm-cli            -> 2026.8.3
node_modules/pm-beads/node_modules/@unbrained/pm-cli -> 2026.8.13

Then:

./node_modules/.bin/pm init hz
./node_modules/.bin/pm health --json

ok: true, warnings: [], and the extensions check reports status: "ok" with no
mention of the second copy.

Why the host is the only component that can catch this

The immediate cause is an extension author declaring @unbrained/pm-cli in
dependencies while also declaring it as a peerDependency — the peer range
(>=2026.8.3) and the dependency range (^2026.8.6) are both satisfiable, but not by the
same version, so npm nests a second copy. That misdeclaration is the extension's bug and
we are fixing it in ours.

The reason this is worth a host-side check anyway:

  1. The project author cannot see it. They pinned one CLI version deliberately. Nothing
    in the install output, pm --version, or pm health tells them a second one is present.
  2. It is invisible precisely when it matters. npm dedupes whenever the ranges happen to
    overlap, so the duplicate appears only for some host pins — the tree is clean on the
    maintainer's machine and skewed on a consumer's.
  3. Every extension author can make this mistake independently, and each one produces a
    silently different runtime for a different subset of consumers.
  4. pm --version reports the host copy (2026.8.3 above), so the obvious way to check
    confirms the wrong thing.

Suggested shape

A pm health finding when more than one resolvable @unbrained/pm-cli exists in the
project's dependency tree, naming each path and version. It is cheap to compute — the
paths above came from one find — and it fails in the direction that matters: a workspace
whose gate verdict depends on which copy loaded should not report a clean bill of health.

A narrower variant, if a full tree walk is unwanted: warn when an installed extension
resolves @unbrained/pm-cli to a different version than the running host.

Related: #998 (same-bytes/different-verdict across versions is what makes skew consequential),
#681 (peer-range resolution surprises), #469 (pm --version reporting a copy other than the
one in effect).

Activity

  1. coderabbitai commented on Aug 13, 2026

    @coderabbitai
    🔗 Related PRs

    #302 - Optimize npm package SDK installs [merged]
    #414 - Clear CLI complexity suppressions across PM SDK and CLI [merged]
    #428 - Harden SDK extension runtime packaging [merged]
    #884 - SDK extension inventories, scoped activation, and stable agent context [merged]
    #935 - feat(sdk): govern runtime context, write safety, and verification gates [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. unbraind commented on Aug 13, 2026

    @unbraind
    OwnerAuthor

    Tracked by pm-643e0k. This item owns host/extension CLI-copy skew detection and temporary-project coverage.

  3. unbraind commented on Aug 15, 2026

    @unbraind
    OwnerAuthor

    Resolved by merged PR #1016. Canonical tracker evidence: pm-643e0k. Extension-host pm-cli copies are inventoried across dependency layouts with gate-visible skew and distinct privacy-safe external identities.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions