Skip to content

fix(cli): classify a pnpm dlx runtime as ephemeral - #12

Draft
andromarces wants to merge 2 commits into
rjx18:mainfrom
andromarces:fix/pnpm-dlx-ephemeral-runtime
Draft

fix(cli): classify a pnpm dlx runtime as ephemeral#12
andromarces wants to merge 2 commits into
rjx18:mainfrom
andromarces:fix/pnpm-dlx-ephemeral-runtime

Conversation

@andromarces

Copy link
Copy Markdown
Contributor

Problem

pnpm dlx @richhardry/codor install completes and registers a service whose entrypoint lives inside pnpm's dlx cache (<cacheDir>/dlx/<hash>/<timestamp>/...). The service works until that cache is pruned or expires, then fails to start with no configuration change on the user's part and no diagnostic pointing at the cause.

isEphemeralRuntime (packages/cli/src/runtime-install.ts) recognized two shapes only: npm's _npx cache and the OS temp directory. Neither matches pnpm's dlx layout, so resolveInstallSource reported durable: true for a dlx-sourced install, installDurableRuntime short-circuited to action: 'in-place', and runSetup pointed the registered service at the transient cache instead of copying it into ~/.codor/runtime. The durable-runtime machinery that exists precisely to prevent this was bypassed by a predicate that didn't recognize the layout.

Fix

isEphemeralRuntime now also matches a ${sep}dlx${sep} path segment, alongside the existing _npx and temp-dir checks, so a pnpm dlx-cache runtime is classified ephemeral and gets copied into the durable location like an npx runtime already does.

Matching on the dlx segment rather than the cache's absolute location was deliberate: pnpm's dlx cache path is platform-specific and user-configurable via cacheDir, and pnpm does not publish the internal <cacheDir>/dlx/<hash>/<timestamp>/ shape as a contract — it documents cacheDir itself, not what's under it. This matcher is derived from an observed tree on Windows, not a documented guarantee. Widening the match is safe in the direction that matters: a false positive costs one extra tree copy into ~/.codor/runtime (still durable), while the previous false negative left a service pointed at a directory that can disappear with no diagnostic.

Testing

  • Added a pnpm dlx case to the existing isEphemeralRuntime test block.
  • Added an installDurableRuntime case asserting a dlx-shaped runtime produces action: 'installed' (not 'in-place') and a cliEntrypoint rooted at ~/.codor/runtime containing no dlx segment, mirroring the existing npx case's .not.toContain('_npx') check.
  • The new case asserts rootedness with .toContain(LOCATION) rather than .toBe(...) against a full literal path. The sibling npx-case assertion (runtime-install.spec.ts:129, pre-existing) fails on Windows for an unrelated, already-tracked reason: path.resolve() drive-qualifies the spec's POSIX-shaped fixture paths. Reusing that assertion style would have added a distinct-looking sixth failure to the suite that is actually the same known cause. .toContain proves the same fact (rooted at the durable location, not the dlx cache) without depending on that drive-letter behavior.

Commands run on Windows 11 / Node 26.2.0 / pnpm 10.9.0, branched from origin/main at bc47942 (no other pending fixes present on this branch):

pnpm install --frozen-lockfile   # passes
pnpm -r build                    # passes
cd packages/cli
pnpm exec vitest run             # not `pnpm test` — the wrapper can't spawn Vitest on this
                                  # Windows toolchain until a separate portability fix lands

Result: 176 passed, 18 skipped, 5 failed — the same 5 pre-existing failures unrelated to this change (Windows path-portability issues in test fixtures, tracked separately), no new failures introduced. pnpm -r test was also run to confirm scope: it aborts in packages/adapters/antigravity on an unrelated, pre-existing failure and never reaches packages/cli; this is untouched by this PR.

What was not verified

  • No real pnpm dlx install was exercised end-to-end (dlx install → cache removal/expiry → confirming the registered service survives). The fix is verified at the unit level (the predicate, and its effect through resolveInstallSource/installDurableRuntime); the end-to-end durability claim is a manual check that wasn't performed here.
  • The dlx cache's internal path shape was observed on Windows only. The macOS and Linux equivalents were not inspected. If pnpm's dlx layout differs there, the matcher may need adjustment — feedback from a reviewer on another platform welcome.
  • macOS and Linux service-generator paths are otherwise unaffected by this change (it's a runtime-install.ts predicate only, platform-independent), but were not exercised on those platforms.

Scope

Only packages/cli/src/runtime-install.ts and packages/cli/src/runtime-install.spec.ts are touched. No other behavior changes.

isEphemeralRuntime recognized npm's _npx cache and the OS temp
directory but not pnpm's dlx cache, so `pnpm dlx @richhardry/codor
install` reported the install as durable and skipped the copy into
~/.codor/runtime. The registered service was left pointing at the
dlx cache, which pnpm can prune or expire independently of the
service's lifetime, breaking it later with no configuration change
on the user's part.

Match on the `dlx` path segment, the same way the existing `_npx`
check works, so the durable-runtime copy (and everything gated on
it) engages for pnpm's dlx layout too.
…ring

Codex review on PR 6 caught that this comment still described ephemeral
installs as only npx cache / temp dir, missing the dlx case isEphemeralRuntime
now also matches.
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