* fix(plugins): load newest managed generation when a prior install lingers
An upgrade writes a plugin's new version into a distinct managed project
directory (an `__openclaw-generation__` dir) without removing the previous one.
The persisted install record keeps pointing at the older, still-present
directory, so `mergeRecoveredManagedNpmRecord` falls through to returning the
persisted record and the runtime imports the stale version even though the newer
generation is installed. `isUnavailableManagedNpmInstallRecord` only self-heals
when the persisted path is gone, so an upgrading install (both directories
present) is not covered — `plugins inspect <id> --runtime` reports the old
version and `install`/`update` appear to silently no-op.
- Recovery now selects the highest-version record per plugin id across the
legacy flat dir and any generation dirs, instead of whichever project root
sorts last (generation-dir suffixes are hashes, so on-disk order is unrelated
to version).
- When the recovered managed install is a strictly newer version at a different
path, repoint to it, reusing the metadata merge the unavailable-path branch
uses. The repoint is gated to persisted records that live inside the managed
npm root, so intentional custom/outside npm installs are left untouched.
This is a recovery-layer self-heal, so it also repairs installs that already
diverged from an earlier upgrade.
Refs #107228
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(plugins): honor active managed generations
Recover ambiguous managed installs by package recency only when no usable active ledger path exists, and let doctor retire non-authoritative generations safely.
Co-authored-by: Peter Lindsey <peter@lindsey.jp>
* test(plugins): use shared temp cleanup
* fix(plugins): compare active paths per platform
* fix(plugins): use managed install timestamps
* test(plugins): timestamp managed project roots
* test(plugins): exclude retired legacy recovery
* refactor(plugins): keep recovery candidate private
---------
Co-authored-by: Peter Lindsey <peter@lindsey.jp>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>