v10.0.3

thedotmack/claude-memv10.0.3Feb 11, 2026by thedotmack

AI Summary

This is a critical bug fix release addressing a severe spawn storm issue where killing the worker daemon caused 641 chroma-mcp Python processes to spawn in ~5 minutes, consuming 75%+ CPU and ~64GB virtual memory. The fix implements a comprehensive 5-layer defense system to prevent concurrent race conditions and error-driven reconnection loops.

Key Highlights

  • Fixed critical spawn storm bug that caused 641 chroma-mcp processes to spawn in ~5 minutes
  • Implemented 5-layer defense: connection mutex via promise memoization, process count guard, hardened close() with try-finally and pkill fallback, count-based orphan reaper, and circuit breaker
  • Changed process guards to use etime-based sorting instead of PID ordering for reliable age determination
  • Added 16 new tests covering mutex, circuit breaker, close() hardening, and count guard (947 pass, 3 skip)
  • Resolved root cause: race condition in ChromaSync.ensureConnection() where concurrent syncObservation() calls bypassed check-then-act guard

New Features

  • Connection mutex via promise memoization to coalesce concurrent callers onto single spawn attempt
  • Pre-spawn process count guard using execFileSync('ps') to kill excess processes
  • Hardened close() with try-finally and Unix pkill -P fallback to guarantee state reset
  • Count-based orphan reaper in ProcessManager that kills by count (not age)
  • Circuit breaker with 3 failures triggering 60s cooldown to stop error-driven reconnection loops
  • etime-based process sorting for reliable age determination instead of PID ordering

Full Release Notes

## Fix: Prevent chroma-mcp spawn storm (PR #1065)

Fixes a critical bug where killing the worker daemon during active sessions caused **641 chroma-mcp Python processes** to spawn in ~5 minutes, consuming 75%+ CPU and ~64GB virtual memory.

### Root Cause

`ChromaSync.ensureConnection()` had no connection mutex. Concurrent fire-and-forget `syncObservation()` calls from multiple sessions raced through the check-then-act guard, each spawning a chroma-mcp subprocess via `StdioClientTransport`. Error-driven reconnection created a positive feedback loop.

### 5-Layer Defense

| Layer | Mechanism | Purpose |
|-------|-----------|---------|
| **0** | Connection mutex via promise memoization | Coalesces concurrent callers onto a single spawn attempt |
| **1** | Pre-spawn process count guard (`execFileSync('ps')`) | Kills excess chroma-mcp processes before spawning new ones |
| **2** | Hardened `close()` with try-finally + Unix `pkill -P` fallback | Guarantees state reset even on error, kills orphaned children |
| **3** | Count-based orphan reaper in `ProcessManager` | Kills by count (not age), catches spawn storms where all processes are young |
| **4** | Circuit breaker (3 failures → 60s cooldown) | Stops error-driven reconnection positive feedback loop |

### Additional Fix

- Process guards now use `etime`-based sorting instead of PID ordering for reliable age determination (PIDs wrap and don't guarantee ordering)

### Testing

- 16 new tests for mutex, circuit breaker, close() hardening, and count guard
- All tests pass (947 pass, 3 skip)

Closes #1063, closes #695. Relates to #1010, #707.

**Contributors:** @rodboev