- skip CLIProxy auto-update checks on runtime bootstrap paths
- fail fast when local startup needs a missing binary instead of attempting installs
- add regression coverage for dashboard limited mode and startup test isolation
Claude Code's marketplace auto-update uses a three-step atomic rename:
clone to <name>.staging → rename old dir to <name>.bak → rename staging
to the final name. On Windows, EPERM errors can interrupt the rename-dance
and leave a <name>.staging directory permanently on disk.
CCS scanned physical directories to discover marketplaces, so a lingering
.staging directory was registered as a bare { installLocation } entry in
known_marketplaces.json. Claude Code's Zod schema requires each entry to
also have `source` and `lastUpdated` fields, so the corrupt entry caused
the /plugin command to throw a validation error.
Fix (two layers of defence):
- discoverMarketplaceEntries: skip any directory whose name starts with
'.' or ends with '.staging'. This filters all hidden dirs including
.staging and .bak left behind by interrupted rename operations.
- buildMarketplaceRegistryContent: invert the loop direction. Instead of
iterating discoveredEntries and adding to the registry (which could
introduce bare entries for disk-only directories with no registry
record), iterate the merged registry and only keep entries that also
exist on disk. Disk-only directories are now silently ignored.
Adds two regression tests: one for .staging pollution, one for orphan
registry entries whose physical directory has been removed.
- fall back to stale CLIProxy version caches instead of surfacing 500s
- remove duplicate dashboard update-check fetches and disable retry/focus refetch
- add backend and UI regressions for the degraded-path behavior
Direct function references in defaultDeps (checkRemoteProxy, fetchRemoteAuthStatus,
getAuthStatus, getProxyTarget, initializeAccounts) are captured at module load time.
Due to circular dependencies in the module graph, auth-handler.js may not have
finished initializing when this module is first evaluated, causing these references
to be captured as undefined.
Wrapping each reference in an arrow function defers evaluation to call time,
by which point all modules are fully initialized.
isCliproxyRunning was already wrapped correctly; this patch applies the same
pattern consistently to all deps.
Fixes#973