Skip to content

bug(vim): resolveVimRuntime never matches Windows path separators #1458

Description

@dnieblesdev

Before submitting

  • I searched open and closed issues and did not find a report of this problem.
  • I reviewed this report and removed credentials, tokens, private paths, hostnames, and other sensitive data.

Problem

On Windows, resolveVimRuntime() in extensions/gentle-shell.ts can never identify the Pi runtime, because its candidate tests compare a native Windows path against POSIX-style suffixes:

  • extensions/gentle-shell.ts:47 — if (cli.endsWith("/dist/bundle/cli.js"))
  • extensions/gentle-shell.ts:68 — if (cli.endsWith("/dist/bundle/cli.js")) candidates.push(resolve(dirname(cli), "../.."))
  • extensions/gentle-shell.ts:73 — if (localIndex.endsWith("/dist/index.js")) candidates.push(resolve(dirname(localIndex), ".."))

On Windows those paths are backslash-separated (...\node_modules\@earendil-works\pi-coding-agent\dist\index.js), so every check is false, candidates stays empty, and the function returns undefined. The verified runtime path is therefore unreachable on Windows: vimAdapter() falls back to this.deps.tuiVersion?.() ?? "unknown" with the locally imported Editor and an undefined verifiedVersion, and the identity guard in lib/vim-editor-adapter.ts (value instanceof editorClass) can then reject the host editor, which disables Vim through the existing "Gentle Vim unsupported by this Pi editor layout/version" path.

This is production code, and it is separate from #1430: #1430 reports two Editor constructors under a fresh npm install on Linux (fixtures). Here resolution never reaches the constructor comparison at all, because the separators never match.

Suggested fix: make all three sites separator-agnostic, for example endsWith(join("dist", "bundle", "cli.js")) or by comparing against resolve(root, "dist", "index.js") instead of a suffix.

Steps to reproduce

  1. On Windows, check out 54568116 (gentle-pi 3.7.0) and install dependencies with pnpm install (Node 24, pnpm 11.1.1).
  2. Run node --experimental-strip-types --test tests/vim-editor-adapter.test.ts. Three tests fail, all of them on resolveVimRuntime() returning undefined instead of the installed pair.
  3. The separator mismatch alone reproduces it, without the test suite:
import { fileURLToPath } from "node:url";
console.log(fileURLToPath(import.meta.resolve("@earendil-works/pi-coding-agent")));
// <checkout>\node_modules\@earendil-works\pi-coding-agent\dist\index.js
console.log(fileURLToPath(import.meta.resolve("@earendil-works/pi-coding-agent")).endsWith("/dist/index.js"));
// false — so no candidate root is ever pushed on Windows

Expected and actual behavior

Expected: resolveVimRuntime() resolves the installed Pi pair on Windows exactly as it does on macOS/Linux, reporting { version: "0.87.1", editorClass: <host editor class> }.

Actual: it returns undefined on Windows, in both the CLI-entry candidate branch and the local-index candidate branch, so the runtime identity is never verified there.

gentle-pi version

3.7.0 (54568116)

Pi version

0.87.1

Operating system

Windows

Relevant logs or error output (optional)

failing tests (tests/vim-editor-adapter.test.ts):
- PATH bundled virtual host is admitted only through its exact bundled class and version
- runtime identity resolves only the matching installed coding-agent/TUI pair
- resolveVimRuntime's default entry resolves the declared local 0.87.1 install without any PATH Pi

✖ resolveVimRuntime's default entry resolves the declared local 0.87.1 install without any PATH Pi
  AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
  + actual - expected
  + undefined
  - { editorClass: [class Editor], version: '0.87.1' }

# separator probe on the same checkout
import.meta.resolve(agent): <checkout>\node_modules\@earendil-works\pi-coding-agent\dist\index.js
endsWith("/dist/index.js"): false
candidate roots: []
resolveVimRuntime("/nonexistent/cli.js"): undefined

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions