fix: plugin no longer vanishes after Claude Code updates

Root cause: plugin registered as directory source in known_marketplaces.json,
which gets wiped on CLI updates. Now registers in extraKnownMarketplaces
(settings.json) as a GitHub source — same mechanism caveman/context-mode use.

Binaries install to ~/.claude-mnemonic/bin/ instead of the Claude-managed
plugins directory. Thin wrapper scripts in the repo let the marketplace
clone find them. Nothing gets cleaned up when Claude refreshes its cache.

Also fixed along the way:
- ONNX Runtime 1.24.3 → 1.26.0 (API v25 mismatch broke all embedding tests)
- Vector client leaked on DB reinit, processQueue had a race on sessionManager
- reloadConfig called os.Exit(0) bypassing graceful shutdown
- Removed dead QueryRowWithTimeout that leaked contexts
- Added tests for graph/watcher/maintenance/update (all were at 0%)
This commit is contained in:
2026-05-24 01:15:23 +01:00
parent cfc95c9ce4
commit f07875ee82
32 changed files with 3217 additions and 127 deletions
+10 -4
View File
@@ -397,7 +397,15 @@ func KillProcessOnPort(port int) error {
// findWorkerBinary finds the worker binary path.
func findWorkerBinary() string {
// Check CLAUDE_PLUGIN_ROOT first (set by Claude Code when running hooks)
home := os.Getenv("HOME")
// Stable binary location (primary, survives Claude Code updates)
stablePath := filepath.Join(home, ".claude-mnemonic", "bin", "worker")
if _, err := os.Stat(stablePath); err == nil {
return stablePath
}
// Check CLAUDE_PLUGIN_ROOT (set by Claude Code when running hooks)
if pluginRoot := os.Getenv("CLAUDE_PLUGIN_ROOT"); pluginRoot != "" {
workerPath := filepath.Join(pluginRoot, "worker")
if _, err := os.Stat(workerPath); err == nil {
@@ -406,7 +414,6 @@ func findWorkerBinary() string {
}
// Check common locations
home := os.Getenv("HOME")
locations := []string{
"./worker",
"./bin/worker",
@@ -418,10 +425,9 @@ func findWorkerBinary() string {
}
}
// Try cache directory with any version (glob returns lexically sorted matches)
// Try cache directory with any version
matches, _ := filepath.Glob(filepath.Join(home, ".claude/plugins/cache/claude-mnemonic/claude-mnemonic/*/worker"))
if len(matches) > 0 {
// Use the last match (latest version due to lexical sorting)
return matches[len(matches)-1]
}