Skip to content

fix(cli): resolve packages status the way a Build resolves - #361

Merged
rponeawa merged 1 commit into
mainfrom
fix/packages-status-asks-the-loader
Sep 26, 2026
Merged

rponeawa merged 1 commit into
mainfrom
fix/packages-status-asks-the-loader

Conversation

@rponeawa

Copy link
Copy Markdown
Member

What this changes

hypit packages status <name>@<version> reported on the machine package home only. The loader
finds an external package in two places — the node_modules chain above whoever requires it, and the
machine home addressed by the version that requirer declares — so a package installed where the
first half looks was reported not ready, and hypit doctor loaded the provider from it anyway.

The case that surfaced it: an agent container that installs @hypit/hypit and
@hyperframes/engine with npm i -g. Both land in the same global node_modules, the ancestor
walk from packages/provider-hyperframes-local finds the engine, Builds work — and packages status said Ready false and exited 1, so the agent concluded the dependency was missing and
went looking for other package names.

The fix

Status now locates the Distribution package that declares the specifier, then makes one
locateNodePackage call from there. That single call covers both places the loader looks, instead
of this command reimplementing one of them beside it — which is how the two came to disagree.

Version locking is unchanged in kind and checked twice: distributionPackageDeclaring matches the
declared range byte for byte, so a requirer is found only at the exact version asked for, and the
resolved manifest's version is compared to it afterwards.

install keeps its own path. With no Distribution on disk, reading the machine home is still the
answer, because then there is no requirer to resolve from.

Measured

Global install, empty machine home (the container's layout), before and after the change:

Ready exit
before false 1
after true 0

After, in full:

✓ Machine package status

  Package       @hyperframes/engine@0.7.101
  Ready         true
  Required by   .../lib/node_modules/@hypit/hypit/packages/provider-hyperframes-local
  Installation  .../lib/node_modules/@hyperframes/engine

@hyperframes/producer@0.7.101 behaves the same. A specifier nothing declares now names the
reason instead of a bare not-ready:

! Machine package status

  Package  @hyperframes/engine@0.7.999
  Ready    false
  Detail   no Distribution package declares @hyperframes/engine@0.7.999

left-pad@1.3.0 likewise, both exit 1.

The status payload gains declaredBy, installedVersion and detail as optional fields; the
format stays hypit.cli-package@1.

Checks

  • npm run check (tsc) clean.
  • npm run check:distribution -- hypit-hypit-0.2.13.tgz exit 0.
  • npm test: two failures, both present on unmodified main and unrelated —
    packages/video-cli/test/cli.test.ts "provider-free example plans from installed Source
    packages", and a sibling case asserting empty stderr that a Node 26
    module.register() DeprecationWarning breaks.

`packages status <name>@<version>` read the machine package home and nothing
else, while the loader finds an external package in two places: the
node_modules chain above whoever requires it, and the machine home addressed by
the version that requirer declares. A package installed where the first half
looks — a pnpm workspace's own node_modules, or the global node_modules a
`npm i -g @hypit/hypit` shares with a `npm i -g @hyperframes/engine` — was
reported `Ready false` and exited 1, and `hypit doctor` then loaded the provider
from it on the next line.

Measured on a global install with an empty machine home, before and after:

  @hyperframes/engine@0.7.101   Ready false, exit 1
  @hyperframes/engine@0.7.101   Ready true,  exit 0
                                Required by   .../packages/provider-hyperframes-local
                                Installation  .../lib/node_modules/@hyperframes/engine

Status now locates the Distribution package that declares the specifier and
asks `locateNodePackage` once, from there — one call covering both places
rather than a second opinion beside the loader, which is how the two came to
disagree. The version is still exact: `distributionPackageDeclaring` matches the
declared range byte for byte, so the requirer is found only at the version asked
for, and the resolved manifest's version is compared again afterwards.

A specifier no Distribution package declares now says so, rather than reporting
a bare `Ready false`, and `install` keeps its own path untouched.

Reading only the machine home remains the answer when there is no Distribution
on disk, because then there is no requirer to resolve from.
@rponeawa
rponeawa merged commit 32baae6 into main Sep 26, 2026
8 checks passed
@rponeawa
rponeawa deleted the fix/packages-status-asks-the-loader branch September 26, 2026 11:52
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.

1 participant