Skip to content

doctor misclassifies junction-backed source checkout as non-git install #82215

Description

@igormf

Summary

openclaw doctor can misclassify a source checkout as "not a git checkout" when the CLI is launched through a global npm/pnpm shim whose node_modules/openclaw entry is a Windows junction/symlink to the real repo checkout.

The install is actually source-backed, and openclaw update --dry-run --json correctly reports git mode, but doctor's pre-update offer uses a raw string comparison and shows package-manager guidance instead of offering the git update flow.

Repro shape

  1. Have a real OpenClaw git checkout.
  2. Expose it through a global npm/pnpm command shim where the package root is a junction/symlink to that checkout.
  3. Run openclaw doctor interactively.

Observed doctor output includes:

This install is not a git checkout.
Run `openclaw update` to update via your package manager (npm/pnpm), then rerun doctor.

But the same environment resolves as a git install through the update command:

{
  "installKind": "git",
  "mode": "git",
  "updateInstallKind": "git",
  "actions": [
    "Run git update flow on channel dev (fetch/rebase/build/doctor)"
  ]
}

Root cause

src/commands/doctor-update.ts detects a git checkout with:

return res.stdout.trim() === root ? "git" : "not-git";

On Windows junction/symlink installs, git -C <linked package root> rev-parse --show-toplevel returns the real checkout path, while root can still be the linked global package path. These refer to the same location but are not equal as raw strings.

src/infra/update-runner.ts already handles this class of problem with realpath-style comparison for the update flow, which is why openclaw update --dry-run --json reports git mode correctly.

Expected behavior

Doctor should canonicalize both paths before comparing them. If the install root and git rev-parse --show-toplevel refer to the same filesystem location, doctor should offer:

Update OpenClaw from git before running doctor?

Local proof

A focused local patch that compares canonicalized real paths makes doctor-update detection recognize the junction-backed checkout while preserving the real non-git package-manager guidance.

Validation run:

node scripts/run-vitest.mjs src/commands/doctor-update.test.ts
# Test Files  1 passed (1)
# Tests       2 passed (2)

pnpm oxlint src/commands/doctor-update.ts src/commands/doctor-update.test.ts
# Found 0 warnings and 0 errors.

openclaw update --dry-run --json
# installKind: git
# mode: git
# action: Run git update flow on channel dev (fetch/rebase/build/doctor)

Affected surface

  • src/commands/doctor-update.ts
  • Windows/global npm or pnpm source installs that use a junction/symlink into a git checkout

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions