Remove outdated documentation files related to Claude-Mem hooks cleanup, PR #335 review summary, and Windows worker struggles. These files contained obsolete information and action items that are no longer relevant to the current project state.
This commit is contained in:
@@ -1,561 +0,0 @@
|
||||
# Claude-Mem Smart Install & Plugin Hooks - Comprehensive Analysis
|
||||
|
||||
**Generated:** 2025-12-09
|
||||
**Scope:** Smart install system, all plugin hooks, cross-platform compatibility, error handling, edge cases
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This report provides a comprehensive analysis of claude-mem's smart install system and plugin hook infrastructure. The analysis focuses on cross-platform compatibility, error handling patterns, artificial blockers, and edge case handling.
|
||||
|
||||
**Key Findings:**
|
||||
- ✅ Overall architecture is well-designed with clear separation of concerns
|
||||
- ⚠️ Multiple cross-platform compatibility issues identified
|
||||
- ⚠️ Several silent failure patterns that hinder debugging
|
||||
- ⚠️ Artificial blockers that could prevent legitimate use cases
|
||||
- ⚠️ Inconsistent timeout values across different components
|
||||
- ✅ No nested try-catch anti-patterns found
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Smart Install System Flow
|
||||
|
||||
```
|
||||
User Invokes Hook
|
||||
↓
|
||||
ensureWorkerRunning() [worker-utils.ts]
|
||||
↓
|
||||
isWorkerHealthy() → fetch /health endpoint
|
||||
↓
|
||||
├─ [HEALTHY] → Continue
|
||||
└─ [UNHEALTHY] → startWorker()
|
||||
↓
|
||||
├─ [Windows] → PowerShell Start-Process (hidden window)
|
||||
└─ [Unix] → Bun start ecosystem.config.cjs
|
||||
↓
|
||||
Wait for health check (15 retries × 1000ms)
|
||||
↓
|
||||
├─ [SUCCESS] → Continue
|
||||
└─ [FAILURE] → Throw error with manual recovery instructions
|
||||
```
|
||||
|
||||
### Plugin Hook Lifecycle
|
||||
|
||||
1. **SessionStart** (context-hook.ts + user-message-hook.ts)
|
||||
- context-hook: Fetches context via HTTP/curl
|
||||
- user-message-hook: Displays context to user via stderr
|
||||
|
||||
2. **UserPromptSubmit** (new-hook.ts)
|
||||
- Creates/retrieves SDK session
|
||||
- Strips privacy tags from prompt
|
||||
- Initializes session via HTTP
|
||||
|
||||
3. **PostToolUse** (save-hook.ts)
|
||||
- Filters skipped tools
|
||||
- Sends observation to worker via HTTP
|
||||
|
||||
4. **Stop** (summary-hook.ts)
|
||||
- Parses transcript JSONL
|
||||
- Extracts last user/assistant messages
|
||||
- Requests summary generation via HTTP
|
||||
|
||||
5. **SessionEnd** (cleanup-hook.ts)
|
||||
- Marks session complete
|
||||
- Fire-and-forget HTTP request
|
||||
|
||||
---
|
||||
|
||||
## Cross-Platform Compatibility Issues
|
||||
|
||||
### 🔴 CRITICAL: curl Dependency (context-hook.ts)
|
||||
|
||||
**Location:** `src/hooks/context-hook.ts:32`
|
||||
|
||||
```typescript
|
||||
const result = execSync(`curl -s "${url}"`, { encoding: "utf-8", timeout: 5000 });
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
1. **Windows Compatibility:** curl is not guaranteed to be available on Windows systems (though included in Windows 10 1803+, it may be missing on older systems or custom installations)
|
||||
2. **Error Handling:** No try-catch around execSync - will throw unhandled exception if curl fails
|
||||
3. **Redundancy:** Uses curl when JavaScript's native `fetch` is already used everywhere else in the codebase
|
||||
|
||||
**Impact:** High - SessionStart hook will crash if curl is unavailable or returns non-zero exit code
|
||||
|
||||
**Edge Cases:**
|
||||
- Corporate proxies blocking curl
|
||||
- Systems without curl in PATH
|
||||
- curl returning non-zero exit with valid output (warnings, etc.)
|
||||
|
||||
**Recommendation:**
|
||||
```typescript
|
||||
// Replace curl with fetch (already used in user-message-hook.ts)
|
||||
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
|
||||
const result = await response.text();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🟡 MEDIUM: Platform-Specific Process Spawning (worker-utils.ts)
|
||||
|
||||
**Location:** `src/shared/worker-utils.ts:55-93`
|
||||
|
||||
**Windows Implementation:**
|
||||
```typescript
|
||||
spawnSync('powershell.exe', [
|
||||
'-NoProfile',
|
||||
'-NonInteractive',
|
||||
'-Command',
|
||||
`Start-Process -FilePath 'node' -ArgumentList '${workerScript}' -WorkingDirectory '${MARKETPLACE_ROOT}' -WindowStyle Hidden`
|
||||
])
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
1. **PowerShell Dependency:** Assumes PowerShell is available and in PATH
|
||||
2. **Command Injection Risk:** Worker script path inserted directly into command string without escaping
|
||||
3. **Process Monitoring:** Windows approach launches detached process with no Bun monitoring - harder to debug/restart
|
||||
4. **Health Check Timeout:** Comment says "Windows needs longer timeouts" but timeout is same for all platforms (500ms)
|
||||
|
||||
**Edge Cases:**
|
||||
- Windows systems with PowerShell execution policy restrictions
|
||||
- Paths containing single quotes or special characters
|
||||
- Windows subsystem for Linux (WSL) environments
|
||||
- Wine/Proton compatibility layers
|
||||
|
||||
**Unix Implementation:**
|
||||
```typescript
|
||||
const localBunBase = path.join(MARKETPLACE_ROOT, 'node_modules', '.bin', 'bun');
|
||||
const bunCommand = existsSync(localBunBase) ? localBunBase : 'bun';
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
1. **Bun Dependency:** Falls back to global bun if local not found, but doesn't verify it exists
|
||||
2. **Silent Failure:** If Bun not installed globally, spawnSync will fail with cryptic ENOENT error
|
||||
|
||||
**Recommendation:**
|
||||
- Add bun existence check before spawn
|
||||
- Implement consistent process monitoring across platforms
|
||||
- Add path escaping for Windows command construction
|
||||
- Actually implement longer timeout for Windows if needed
|
||||
|
||||
---
|
||||
|
||||
### 🟡 MEDIUM: Git Dependency (paths.ts)
|
||||
|
||||
**Location:** `src/shared/paths.ts:89-97`
|
||||
|
||||
```typescript
|
||||
export function getCurrentProjectName(): string {
|
||||
try {
|
||||
const gitRoot = execSync('git rev-parse --show-toplevel', {
|
||||
cwd: process.cwd(),
|
||||
encoding: 'utf8',
|
||||
stdio: ['pipe', 'pipe', 'ignore']
|
||||
}).trim();
|
||||
return basename(gitRoot);
|
||||
} catch {
|
||||
return basename(process.cwd());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
1. **Git Assumption:** Assumes git is installed and available in PATH
|
||||
2. **Non-Git Projects:** Silently falls back to cwd basename, but this behavior is undocumented
|
||||
|
||||
**Edge Cases:**
|
||||
- Projects not using git
|
||||
- Monorepos where cwd !== git root is desired
|
||||
- Systems without git installed
|
||||
|
||||
**Status:** ✅ Already handled with fallback, but could benefit from debug logging
|
||||
|
||||
---
|
||||
|
||||
## Error Handling Analysis
|
||||
|
||||
### 🔴 CRITICAL: Silent Failures Without Logging
|
||||
|
||||
#### 1. Settings File Loading (early-settings.ts:20-28)
|
||||
|
||||
```typescript
|
||||
try {
|
||||
if (existsSync(SETTINGS_PATH)) {
|
||||
const data = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
|
||||
const fileValue = data.env?.[key];
|
||||
if (fileValue !== undefined) return fileValue;
|
||||
}
|
||||
} catch {
|
||||
// Fail silently - fall through to env var
|
||||
}
|
||||
```
|
||||
|
||||
**Problem:**
|
||||
- Invalid JSON in settings file fails silently
|
||||
- File read permission errors fail silently
|
||||
- Users have no way to know their settings file is being ignored
|
||||
|
||||
**Impact:** High - Users may think settings are applied when they're actually using defaults
|
||||
|
||||
**Recommendation:**
|
||||
```typescript
|
||||
} catch (error) {
|
||||
logger.warn('SETTINGS', 'Failed to load settings file', { path: SETTINGS_PATH }, error);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. Worker Startup Failure (worker-utils.ts:104-107)
|
||||
|
||||
```typescript
|
||||
try {
|
||||
// ... worker startup logic ...
|
||||
} catch (error) {
|
||||
// Failed to start worker
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
**Problem:**
|
||||
- Catches ALL errors during worker startup
|
||||
- Returns boolean with no information about what failed
|
||||
- User only gets generic error after all retries exhausted
|
||||
|
||||
**Impact:** High - Makes debugging worker startup issues extremely difficult
|
||||
|
||||
**Recommendation:**
|
||||
```typescript
|
||||
} catch (error) {
|
||||
logger.error('WORKER', 'Failed to start worker', {}, error as Error);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 3. Worker Health Check (worker-utils.ts:30-40)
|
||||
|
||||
```typescript
|
||||
async function isWorkerHealthy(): Promise<boolean> {
|
||||
try {
|
||||
const port = getWorkerPort();
|
||||
const response = await fetch(`http://127.0.0.1:${port}/health`, {
|
||||
signal: AbortSignal.timeout(HEALTH_CHECK_TIMEOUT_MS)
|
||||
});
|
||||
return response.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Problem:**
|
||||
- Network errors, timeouts, and non-200 responses all indistinguishable
|
||||
- No logging at all - completely silent
|
||||
|
||||
**Impact:** Medium - Hard to debug why health checks fail
|
||||
|
||||
**Recommendation:**
|
||||
```typescript
|
||||
} catch (error) {
|
||||
logger.debug('WORKER', 'Health check failed', { port }, error);
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 4. Tool Formatting (logger.ts:122-124)
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const input = typeof toolInput === 'string' ? JSON.parse(toolInput) : toolInput;
|
||||
// ...
|
||||
} catch {
|
||||
return toolName;
|
||||
}
|
||||
```
|
||||
|
||||
**Problem:**
|
||||
- Invalid JSON in tool input fails silently
|
||||
- Could mask data corruption issues
|
||||
|
||||
**Impact:** Low - Only affects log formatting
|
||||
|
||||
**Status:** ✅ Acceptable for log formatting, but could log at DEBUG level
|
||||
|
||||
---
|
||||
|
||||
### 🟢 GOOD: No Nested Try-Catch Anti-Patterns
|
||||
|
||||
Analysis confirmed zero instances of nested try-catch blocks. Error handling is consistently at single level per function.
|
||||
|
||||
---
|
||||
|
||||
## Artificial Blockers & Unnecessary Checks
|
||||
|
||||
### 🔴 CRITICAL: First-Run Detection (user-message-hook.ts:14-40)
|
||||
|
||||
```typescript
|
||||
const nodeModulesPath = join(pluginDir, 'node_modules');
|
||||
|
||||
if (!existsSync(nodeModulesPath)) {
|
||||
// Show first-time setup message
|
||||
console.error(`...`);
|
||||
process.exit(3);
|
||||
}
|
||||
```
|
||||
|
||||
**Problems:**
|
||||
1. **False Positive:** Will trigger if user manually deletes node_modules (e.g., for troubleshooting)
|
||||
2. **Installation Race:** Could fail if installation is still in progress
|
||||
3. **Hook-Level Check:** Runs on EVERY SessionStart, not just actual first run
|
||||
|
||||
**Impact:** High - Prevents usage until node_modules exists, even if dependencies are installed elsewhere
|
||||
|
||||
**Edge Cases:**
|
||||
- User runs `rm -rf node_modules` for troubleshooting
|
||||
- Package manager installation interrupted
|
||||
- Symlinked node_modules (some package managers)
|
||||
|
||||
**Recommendation:**
|
||||
- Use a `.first-run-complete` marker file instead
|
||||
- Move check to npm postinstall script
|
||||
- Make check more robust (check for specific required modules)
|
||||
|
||||
---
|
||||
|
||||
### 🟡 MEDIUM: Overly Specific Validation (paths.ts:117-119)
|
||||
|
||||
```typescript
|
||||
if (!existsSync(join(commandsDir, 'save.md'))) {
|
||||
throw new Error('Package commands directory missing required files');
|
||||
}
|
||||
```
|
||||
|
||||
**Problem:**
|
||||
- Checks for ONE specific file to validate entire directory
|
||||
- Hardcoded filename could break if files reorganized
|
||||
- Error message doesn't specify what's missing
|
||||
|
||||
**Impact:** Medium - Could prevent package from working after internal refactoring
|
||||
|
||||
**Recommendation:**
|
||||
- Remove check entirely (let actual command invocation fail with better error)
|
||||
- Or check all required files if validation is critical
|
||||
|
||||
---
|
||||
|
||||
### 🟡 MEDIUM: Duplicate Health Endpoints
|
||||
|
||||
**Locations:**
|
||||
- `src/services/worker-service.ts:107` - `/api/health`
|
||||
- `src/services/worker/http/routes/ViewerRoutes.ts:27` - `/health`
|
||||
|
||||
**Usage:**
|
||||
- `worker-utils.ts` uses `/health`
|
||||
- `mcp-server.ts` uses `/api/health`
|
||||
|
||||
**Problem:**
|
||||
- Redundant endpoints doing the same thing
|
||||
- Inconsistent usage across codebase
|
||||
- Maintenance burden
|
||||
|
||||
**Impact:** Low - Both work, but creates confusion
|
||||
|
||||
**Recommendation:**
|
||||
- Standardize on `/api/health` (follows REST convention)
|
||||
- Remove `/health` endpoint
|
||||
- Update worker-utils.ts to use `/api/health`
|
||||
|
||||
---
|
||||
|
||||
## Timeout Configuration Issues
|
||||
|
||||
### Inconsistent Timeouts Across Components
|
||||
|
||||
| Component | Timeout | Location | Purpose |
|
||||
|-----------|---------|----------|---------|
|
||||
| Health check | 500ms | worker-utils.ts:13 | Check if worker alive |
|
||||
| Worker startup wait | 1000ms | worker-utils.ts:14 | Wait between health checks |
|
||||
| Worker startup retries | 15x | worker-utils.ts:15 | Max retries (15s total) |
|
||||
| Hook HTTP requests | 2000ms | cleanup-hook.ts:61, save-hook.ts:70, summary-hook.ts:164 | Send data to worker |
|
||||
| New hook session init | 5000ms | new-hook.ts:129 | Initialize session |
|
||||
| Context hook fetch | 5000ms | context-hook.ts:32 | Fetch context via curl |
|
||||
| User message hook | 5000ms | user-message-hook.ts:52 | Fetch context display |
|
||||
|
||||
**Problems:**
|
||||
1. **Health Check Too Aggressive:** 500ms may be too short for loaded systems or slow network
|
||||
2. **No Platform Adjustment:** Comment says "Windows needs longer timeouts" but values are same
|
||||
3. **Hook Timeout Variation:** Some hooks use 2s, others use 5s with no clear reasoning
|
||||
|
||||
**Recommendations:**
|
||||
- Increase health check timeout to 1000ms minimum
|
||||
- Actually implement longer timeouts for Windows
|
||||
- Standardize hook timeouts to 5000ms across the board
|
||||
- Make timeouts configurable via settings
|
||||
|
||||
---
|
||||
|
||||
## Edge Case Analysis
|
||||
|
||||
### Handled Well ✅
|
||||
|
||||
1. **JSONL Parsing:** summary-hook.ts continues on malformed lines (60-64, 117-121)
|
||||
2. **Git Not Available:** paths.ts falls back to cwd basename (89-97)
|
||||
3. **Settings File Missing:** early-settings.ts falls back to env vars and defaults (20-28)
|
||||
4. **Privacy Tags:** new-hook.ts handles fully-private prompts (99-109)
|
||||
5. **Tool Skipping:** save-hook.ts filters low-value tools (24-30)
|
||||
|
||||
### Missing Edge Case Handling ⚠️
|
||||
|
||||
1. **curl Failure:** context-hook.ts has no error handling for curl failures
|
||||
2. **Bun Not Installed:** worker-utils.ts assumes bun exists globally
|
||||
3. **PowerShell Restrictions:** worker-utils.ts doesn't check execution policy
|
||||
4. **Concurrent Worker Starts:** No locking to prevent multiple hooks from starting worker simultaneously
|
||||
5. **Port Already In Use:** No detection or recovery if worker port is taken
|
||||
6. **Zombie Processes:** Windows approach doesn't track PIDs, can't detect/kill zombies
|
||||
|
||||
---
|
||||
|
||||
## Recommendations Summary
|
||||
|
||||
### High Priority 🔴
|
||||
|
||||
1. **Replace curl with fetch** in context-hook.ts
|
||||
- Eliminates external dependency
|
||||
- Consistent with rest of codebase
|
||||
- Better error handling
|
||||
|
||||
2. **Add logging to silent failures**
|
||||
- early-settings.ts: Log when settings file fails to load
|
||||
- worker-utils.ts: Log startup failures with details
|
||||
- worker-utils.ts: Log health check failures at debug level
|
||||
|
||||
3. **Fix first-run detection**
|
||||
- Use marker file instead of node_modules check
|
||||
- More reliable and intentional
|
||||
|
||||
### Medium Priority 🟡
|
||||
|
||||
4. **Verify Bun availability** before attempting to use it
|
||||
- Check existence before spawn
|
||||
- Provide clear error message if missing
|
||||
|
||||
5. **Implement platform-specific timeouts**
|
||||
- Actually use longer timeouts on Windows as comment suggests
|
||||
- Make timeouts configurable
|
||||
|
||||
6. **Standardize health endpoints**
|
||||
- Remove duplicate `/health` endpoint
|
||||
- Use `/api/health` everywhere
|
||||
|
||||
7. **Add path escaping** for Windows PowerShell commands
|
||||
- Prevent injection issues
|
||||
- Handle paths with special characters
|
||||
|
||||
### Low Priority 🟢
|
||||
|
||||
8. **Standardize HTTP timeouts** across all hooks
|
||||
9. **Add concurrent startup protection** (locking mechanism)
|
||||
10. **Improve error messages** with actionable recovery steps
|
||||
|
||||
---
|
||||
|
||||
## Testing Recommendations
|
||||
|
||||
### Cross-Platform Testing Needed
|
||||
|
||||
1. **Windows Environments:**
|
||||
- Windows 10 (various versions)
|
||||
- Windows 11
|
||||
- Windows Server
|
||||
- WSL/WSL2
|
||||
- PowerShell execution policies (Restricted, RemoteSigned, Unrestricted)
|
||||
|
||||
2. **Unix Environments:**
|
||||
- macOS (Intel + Apple Silicon)
|
||||
- Linux (Ubuntu, Fedora, Arch)
|
||||
- FreeBSD
|
||||
|
||||
3. **Edge Environments:**
|
||||
- Docker containers
|
||||
- CI/CD environments
|
||||
- Systems without git installed
|
||||
- Systems without curl (or with restricted curl)
|
||||
- Corporate networks with proxies
|
||||
- Low-spec systems (slow startup)
|
||||
|
||||
### Test Scenarios
|
||||
|
||||
1. **Cold Start:** First run with no existing data
|
||||
2. **Corrupt Settings:** Invalid JSON in settings.json
|
||||
3. **Missing Dependencies:** No Bun, no git, no curl
|
||||
4. **Port Conflicts:** Worker port already in use
|
||||
5. **Rapid Hook Invocations:** Multiple hooks trying to start worker simultaneously
|
||||
6. **Permission Issues:** Read-only filesystem, restricted execution
|
||||
7. **Network Issues:** Localhost blocked, slow network
|
||||
|
||||
---
|
||||
|
||||
## Code Quality Assessment
|
||||
|
||||
### Strengths ✅
|
||||
|
||||
- Clean separation of concerns (hooks → worker → database)
|
||||
- No nested try-catch anti-patterns
|
||||
- Consistent use of modern async/await
|
||||
- Good use of TypeScript for type safety
|
||||
- Idempotent database operations
|
||||
- Clear documentation in critical sections
|
||||
|
||||
### Weaknesses ⚠️
|
||||
|
||||
- Silent failures hinder debugging
|
||||
- Inconsistent error handling patterns
|
||||
- Platform-specific code not fully tested/documented
|
||||
- Timeout configuration hardcoded and inconsistent
|
||||
- Some artificial blockers prevent legitimate use cases
|
||||
|
||||
### Technical Debt
|
||||
|
||||
- Duplicate health endpoints
|
||||
- curl dependency when fetch available
|
||||
- Bun dependency on Unix but not Windows (inconsistent monitoring)
|
||||
- First-run detection using node_modules existence
|
||||
- Hardcoded timeout values
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The claude-mem smart install and plugin hook system is architecturally sound with a well-designed separation of concerns. However, several cross-platform compatibility issues and silent failure patterns could cause problems in production, particularly on Windows systems or in edge case scenarios.
|
||||
|
||||
The highest priority improvements are:
|
||||
1. Removing the curl dependency
|
||||
2. Adding proper logging to silent failures
|
||||
3. Fixing the fragile first-run detection
|
||||
4. Verifying external dependencies before use
|
||||
|
||||
These changes would significantly improve debuggability and cross-platform reliability without requiring major architectural changes.
|
||||
|
||||
---
|
||||
|
||||
**Analysis Methodology:**
|
||||
- Systematic review of all TypeScript source files
|
||||
- Static analysis of error handling patterns
|
||||
- Cross-platform compatibility assessment
|
||||
- Edge case identification through code path analysis
|
||||
- Comparison against best practices and KISS principles
|
||||
|
||||
**Files Analyzed:**
|
||||
- src/hooks/*.ts (6 files)
|
||||
- src/services/worker-service.ts
|
||||
- src/services/worker/*.ts (10+ files)
|
||||
- src/servers/mcp-server.ts
|
||||
- src/shared/*.ts (worker-utils, early-settings, paths)
|
||||
- src/utils/*.ts (logger, silent-debug, tag-stripping)
|
||||
@@ -1,386 +0,0 @@
|
||||
# Test Suite Audit Report
|
||||
**Date:** 2025-12-13
|
||||
**Auditor:** Code Quality Assurance Manager
|
||||
**Focus:** Recent bugfixes and regression prevention
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The test suite has **critical gaps** in error handling coverage. While happy path tests exist, **zero tests verify that recent bugfixes actually prevent regressions**. The fish shell PATH bug (Issue #264), silent hook failures (observation 25389), and ChromaSync error standardization (observation 25458) are all unprotected by tests.
|
||||
|
||||
**Risk Level:** HIGH - Recent bugfixes can silently regress without detection.
|
||||
|
||||
---
|
||||
|
||||
## Coverage Analysis
|
||||
|
||||
### What We Have ✅
|
||||
|
||||
1. **Happy Path Tests** (`tests/happy-paths/`) - 6 files
|
||||
- Basic success scenarios work
|
||||
- Tool capture, search, session init/cleanup
|
||||
- Good foundation but insufficient
|
||||
|
||||
2. **Unit Tests**
|
||||
- `bun-path.test.ts` - Tests PATH resolution logic
|
||||
- `parser.test.ts` - SDK parser validation
|
||||
- `strip-memory-tags.test.ts` - Privacy tag handling
|
||||
|
||||
3. **Integration Test** (`full-lifecycle.test.ts`)
|
||||
- ONE error recovery test (too shallow)
|
||||
- Mostly happy paths
|
||||
- All tests mock `fetch()` - never test real failures
|
||||
|
||||
### What's Missing ❌
|
||||
|
||||
## 1. Silent Hook Failures (CRITICAL GAP)
|
||||
|
||||
**Issue:** Multiple hooks had no error logging until recently fixed
|
||||
|
||||
**Fixed In:**
|
||||
- `save-hook.ts` (observation 25389) - Added `handleFetchError`/`handleWorkerError`
|
||||
- `new-hook.ts` - Added error handlers
|
||||
- `context-hook.ts` - Added error handlers
|
||||
|
||||
**Test Gap:** ZERO tests verify hooks actually log errors when they fail
|
||||
|
||||
**Created:** `/Users/alexnewman/Scripts/claude-mem/tests/error-handling/hook-error-logging.test.ts`
|
||||
|
||||
**Tests:**
|
||||
- `handleFetchError()` logs with full context (status, hook, operation, tool, port)
|
||||
- `handleFetchError()` throws user-facing error with restart instructions
|
||||
- `handleWorkerError()` handles timeout/connection errors
|
||||
- Real hook scenarios (save-hook, new-hook, context-hook failures)
|
||||
- Error message quality (actionable, includes next steps)
|
||||
|
||||
**Why This Matters:**
|
||||
If someone refactors hooks and removes error handlers, the system will silently fail again. These tests catch that regression immediately.
|
||||
|
||||
---
|
||||
|
||||
## 2. ChromaSync Client Initialization (MEDIUM GAP)
|
||||
|
||||
**Issue:** Standardized error messages across all client checks (observation 25458)
|
||||
|
||||
**Code Locations:** ChromaSync.ts lines 140-145, 324-329, 504-509, 761-766
|
||||
|
||||
**Test Gap:** NO tests verify error messages are consistent or fire correctly
|
||||
|
||||
**Created:** `/Users/alexnewman/Scripts/claude-mem/tests/services/chroma-sync-errors.test.ts`
|
||||
|
||||
**Tests:**
|
||||
- Calling methods before `ensureConnection()` throws correct message
|
||||
- All error messages include project name
|
||||
- Error messages are consistent across all 4 locations
|
||||
- Fail-fast behavior (no silent retries)
|
||||
- Error context preservation
|
||||
|
||||
**Why This Matters:**
|
||||
Prevents "works on my machine" bugs where Chroma isn't properly initialized. Ensures all 4 error checks stay in sync during refactoring.
|
||||
|
||||
---
|
||||
|
||||
## 3. Fish Shell PATH Issues (PARTIAL COVERAGE)
|
||||
|
||||
**Issue:** Issue #264 - Hooks fail with fish shell because bun not in /bin/sh PATH
|
||||
|
||||
**Current Test:** `bun-path.test.ts` tests the utility function
|
||||
|
||||
**Gap:** Doesn't test the ACTUAL bug - hooks failing when bun not in PATH
|
||||
|
||||
**Created:** `/Users/alexnewman/Scripts/claude-mem/tests/integration/hook-execution-environments.test.ts`
|
||||
|
||||
**Tests:**
|
||||
- Running hook when `bun` only in `~/.bun/bin/bun` (not in PATH)
|
||||
- Hook finds bun from common install locations
|
||||
- Cross-platform bun resolution (macOS, Linux, Windows)
|
||||
- Fish shell with custom PATH
|
||||
- Zsh with homebrew in non-standard location
|
||||
- Error messages include PATH diagnostic info
|
||||
|
||||
**Why This Matters:**
|
||||
Fish shell users (and anyone with non-standard PATH) will get "command not found" errors if this regresses. Test ensures hooks work regardless of shell.
|
||||
|
||||
---
|
||||
|
||||
## 4. General Error Handling Patterns (CRITICAL GAP)
|
||||
|
||||
**Issue:** "264 silent failure locations" - widespread lack of error handling
|
||||
|
||||
**Current State:** Recent fixes added standardized error handlers
|
||||
|
||||
**Test Gap:** No systematic tests for error handling patterns
|
||||
|
||||
**Covered By:** `/Users/alexnewman/Scripts/claude-mem/tests/error-handling/hook-error-logging.test.ts`
|
||||
|
||||
**Why This Matters:**
|
||||
If new hooks are added without using `handleFetchError`/`handleWorkerError`, they'll fail silently. Tests enforce the pattern.
|
||||
|
||||
---
|
||||
|
||||
## 5. Integration Test Weaknesses
|
||||
|
||||
**Current Test:** `full-lifecycle.test.ts` has ONE error recovery test (lines 292-352)
|
||||
|
||||
**Issues:**
|
||||
- Too shallow - just checks second request succeeds after first fails
|
||||
- Doesn't verify error logging
|
||||
- Never tests real worker failures (all mocked)
|
||||
|
||||
**Needs:**
|
||||
```
|
||||
/tests/integration/hook-failures.test.ts
|
||||
```
|
||||
|
||||
Should test:
|
||||
- Worker crashes mid-session - hooks fail gracefully
|
||||
- Worker returns 500 error - hook logs and throws
|
||||
- Worker times out - hook aborts with timeout message
|
||||
- Worker returns malformed JSON - hook handles parse error
|
||||
|
||||
---
|
||||
|
||||
## YAGNI Violations (Unnecessary Test Complexity)
|
||||
|
||||
### Problem: `/Users/alexnewman/Scripts/claude-mem/tests/happy-paths/search.test.ts`
|
||||
|
||||
**Lines 80-196:** Tests for features that DON'T EXIST:
|
||||
|
||||
1. **Line 80-107:** "supports filtering by observation type"
|
||||
- Endpoint: `/api/search/by-type` - DOES NOT EXIST
|
||||
|
||||
2. **Line 109-136:** "supports filtering by concept tags"
|
||||
- Endpoint: `/api/search/by-concept` - DOES NOT EXIST
|
||||
|
||||
3. **Line 138-168:** "supports pagination for large result sets"
|
||||
- Includes `page`, `limit`, `offset` params - NOT IMPLEMENTED
|
||||
|
||||
4. **Line 170-196:** "supports date range filtering"
|
||||
- `dateStart`, `dateEnd` params - NOT IMPLEMENTED
|
||||
|
||||
5. **Line 227-271:** "supports semantic search ranking"
|
||||
- `orderBy=relevance` with relevance scores - NOT IMPLEMENTED
|
||||
|
||||
**Impact:** These tests are ALL PASSING because they mock `fetch()`. They create false confidence - making it look like features exist when they don't.
|
||||
|
||||
**Fix:** DELETE these tests until features actually exist. Write tests AFTER implementing features, not before.
|
||||
|
||||
**Philosophy Violation:** "Write the dumb, obvious thing first" - these tests violate YAGNI by testing features we don't need yet.
|
||||
|
||||
---
|
||||
|
||||
## KISS Violations (Overcomplicated Tests)
|
||||
|
||||
### Problem: Excessive Mocking
|
||||
|
||||
**Pattern Found:** 49 instances of `global.fetch = vi.fn()` across 8 test files
|
||||
|
||||
**Issue:** Every test mocks the worker, so tests never verify real integration
|
||||
|
||||
**Example:** `/Users/alexnewman/Scripts/claude-mem/tests/integration/full-lifecycle.test.ts`
|
||||
- Called "integration test" but mocks everything
|
||||
- Never actually tests hooks talking to worker
|
||||
- Can't catch real integration bugs
|
||||
|
||||
**Fix:** Add TRUE integration tests that:
|
||||
1. Start real worker process
|
||||
2. Run real hooks
|
||||
3. Verify real database writes
|
||||
4. Tear down cleanly
|
||||
|
||||
**Philosophy Violation:** "Simple First" - mocking everything is more complex than just testing the real thing.
|
||||
|
||||
---
|
||||
|
||||
## DRY Violations (Test Code Duplication)
|
||||
|
||||
### Problem: Repeated Mock Setup
|
||||
|
||||
**Pattern:** Every test file has identical beforeEach blocks:
|
||||
|
||||
```typescript
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
```
|
||||
|
||||
**Pattern:** Every test manually mocks fetch with same structure:
|
||||
|
||||
```typescript
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => ({ ... })
|
||||
});
|
||||
```
|
||||
|
||||
**Solution:** Extract to test helpers:
|
||||
|
||||
```typescript
|
||||
// tests/helpers/mock-worker.ts
|
||||
export function mockWorkerSuccess(responseData: any) {
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => responseData
|
||||
});
|
||||
}
|
||||
|
||||
export function mockWorkerError(status: number, message: string) {
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: false,
|
||||
status,
|
||||
text: async () => message
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Impact:** Reduces 49 instances to ~10 helper calls. Makes test intent clearer.
|
||||
|
||||
---
|
||||
|
||||
## Actionable Recommendations
|
||||
|
||||
### Priority 1: Critical Regressions (Implement Now) ✅ DONE
|
||||
|
||||
1. **Hook Error Logging Tests** ✅ Created
|
||||
- File: `/Users/alexnewman/Scripts/claude-mem/tests/error-handling/hook-error-logging.test.ts`
|
||||
- Prevents silent failure regressions
|
||||
- Verifies error messages are actionable
|
||||
|
||||
2. **ChromaSync Error Tests** ✅ Created
|
||||
- File: `/Users/alexnewman/Scripts/claude-mem/tests/services/chroma-sync-errors.test.ts`
|
||||
- Ensures consistent error messages
|
||||
- Catches initialization bugs
|
||||
|
||||
3. **Hook Environment Tests** ✅ Created
|
||||
- File: `/Users/alexnewman/Scripts/claude-mem/tests/integration/hook-execution-environments.test.ts`
|
||||
- Prevents fish shell PATH regression
|
||||
- Cross-platform coverage
|
||||
|
||||
### Priority 2: Remove False Positives (Do Next)
|
||||
|
||||
1. **DELETE Unimplemented Feature Tests**
|
||||
- `/Users/alexnewman/Scripts/claude-mem/tests/happy-paths/search.test.ts` lines 80-271
|
||||
- These create false confidence
|
||||
- Re-add when features actually exist
|
||||
|
||||
### Priority 3: Reduce Test Complexity
|
||||
|
||||
1. **Extract Mock Helpers**
|
||||
- Create `/Users/alexnewman/Scripts/claude-mem/tests/helpers/mock-worker.ts`
|
||||
- Replace 49 instances of manual mocking
|
||||
- See DRY section above for example
|
||||
|
||||
2. **Add TRUE Integration Tests**
|
||||
- Create `/Users/alexnewman/Scripts/claude-mem/tests/integration/real-worker.test.ts`
|
||||
- Start real worker, run real hooks
|
||||
- Currently ALL integration tests are mocked
|
||||
|
||||
### Priority 4: Systematic Error Testing
|
||||
|
||||
1. **Worker Failure Scenarios**
|
||||
- Create `/Users/alexnewman/Scripts/claude-mem/tests/integration/hook-failures.test.ts`
|
||||
- Test crash, timeout, malformed response scenarios
|
||||
|
||||
2. **Spinner Timeout Tests**
|
||||
- Create `/Users/alexnewman/Scripts/claude-mem/tests/utils/spinner-timeout.test.ts`
|
||||
- Verify hardened spinner cleanup works
|
||||
|
||||
---
|
||||
|
||||
## Test Quality Checklist
|
||||
|
||||
For EVERY new test, verify:
|
||||
|
||||
- [ ] Tests actual bug, not mocked behavior
|
||||
- [ ] Will FAIL if bug reappears
|
||||
- [ ] Error messages are checked (not just success paths)
|
||||
- [ ] No YAGNI - tests code that exists NOW
|
||||
- [ ] DRY - uses test helpers, not duplicated setup
|
||||
- [ ] KISS - simple, obvious test structure
|
||||
- [ ] Fail fast - no silent fallbacks tested
|
||||
|
||||
---
|
||||
|
||||
## Coverage Metrics
|
||||
|
||||
**Before Audit:**
|
||||
- Error handling: 0% (no tests for error paths)
|
||||
- Silent failures: Undetected
|
||||
- Recent bugfixes: Unprotected
|
||||
|
||||
**After Audit:**
|
||||
- Error handling: ~40% (3 new test files)
|
||||
- Silent failures: Detected by hook-error-logging.test.ts
|
||||
- Recent bugfixes: Protected
|
||||
|
||||
**Remaining Gaps:**
|
||||
- True integration tests (worker + hooks + database)
|
||||
- Spinner error handling
|
||||
- Worker crash scenarios
|
||||
- Malformed response handling
|
||||
|
||||
---
|
||||
|
||||
## Files Created
|
||||
|
||||
1. `/Users/alexnewman/Scripts/claude-mem/tests/error-handling/hook-error-logging.test.ts`
|
||||
- 200+ lines
|
||||
- Tests handleFetchError, handleWorkerError
|
||||
- Real hook error scenarios
|
||||
- Error message quality checks
|
||||
|
||||
2. `/Users/alexnewman/Scripts/claude-mem/tests/services/chroma-sync-errors.test.ts`
|
||||
- 300+ lines
|
||||
- Client initialization errors
|
||||
- Error message consistency
|
||||
- Fail-fast behavior
|
||||
|
||||
3. `/Users/alexnewman/Scripts/claude-mem/tests/integration/hook-execution-environments.test.ts`
|
||||
- 250+ lines
|
||||
- Fish shell PATH resolution
|
||||
- Cross-platform bun finding
|
||||
- Real-world shell scenarios
|
||||
|
||||
**Total:** ~750 lines of new regression-preventing tests
|
||||
|
||||
---
|
||||
|
||||
## Philosophy Alignment
|
||||
|
||||
These tests follow the project's coding standards:
|
||||
|
||||
✅ **YAGNI** - Only test code that exists (removed future-feature tests)
|
||||
✅ **DRY** - Identified duplication, recommended helpers
|
||||
✅ **Fail Fast** - All tests verify explicit errors, not silent failures
|
||||
✅ **Simple First** - Recommended real integration over complex mocks
|
||||
✅ **Delete Aggressively** - Flagged unimplemented feature tests for deletion
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Run new tests:** `npm test tests/error-handling/ tests/services/ tests/integration/hook-execution-environments.test.ts`
|
||||
|
||||
2. **Delete false positives:** Remove search.test.ts lines 80-271 (unimplemented features)
|
||||
|
||||
3. **Extract helpers:** Create `tests/helpers/mock-worker.ts` to reduce duplication
|
||||
|
||||
4. **Add true integration:** Create real worker + hook integration test
|
||||
|
||||
5. **Continuous:** Apply "Test Quality Checklist" to all future tests
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The test suite now has **regression protection for recent bugfixes**. The three new test files will catch if:
|
||||
- Hooks start failing silently again
|
||||
- ChromaSync error messages become inconsistent
|
||||
- Fish shell PATH issues return
|
||||
|
||||
However, we still need **true integration tests** that don't mock everything. The current integration tests are really "mocked end-to-end tests" - they test the shape of the API, not the actual behavior.
|
||||
|
||||
**Risk reduced from HIGH → MEDIUM**. Remaining risk: real integration failures not caught by mocked tests.
|
||||
@@ -1,152 +0,0 @@
|
||||
# Research Report: The Genesis of Biomimetic Architecture in Claude-Mem
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The concept of **"biomimetic architecture"** in claude-mem emerged organically during a concentrated development period in mid-November 2025, crystallizing around three foundational observations created on November 17, 2025. What began as a practical solution to AI context window exhaustion evolved into a comprehensive philosophy of mirroring human memory systems while augmenting them with computational advantages. This report traces the intellectual journey from problem identification through architectural breakthrough to public messaging.
|
||||
|
||||
---
|
||||
|
||||
## The Foundational Philosophy (November 17, 2025, Early Morning)
|
||||
|
||||
The biomimetic architecture concept was formally articulated in three seminal observations created within a four-minute window between **1:31 AM and 1:35 AM** on November 17, 2025:
|
||||
|
||||
### Observation #10140 (Nov 17, 2025 at 1:31 AM)
|
||||
**"Memory System Design Philosophy: Selective Retention with Total Recall Capability"**
|
||||
|
||||
This observation established the core philosophical foundation: humans observe selectively and retain only portions that seem relevant, never creating complete transcripts of all experiences. The innovation was recognizing this selective retention as fundamental to human cognition, then creating a hybrid approach—normal operation uses human-like selective observation-based memory, but leverages computational advantages by maintaining capability for complete recall through optional transcript archival when needed.
|
||||
|
||||
> **Key insight:** "Selective retention is fundamental to human cognition. The designed system replicates this behavior by observing and recording key observations, decisions, and discoveries rather than archiving everything."
|
||||
|
||||
### Observation #10142 (Nov 17, 2025 at 1:35 AM)
|
||||
**"Biological Memory Principles in Endless Mode Architecture"**
|
||||
|
||||
Created just four minutes later, this observation made the problem-solution connection explicit: Claude's context window was exploding from endless raw data accumulation—exactly the same problem biological brains evolved to solve through compression. The architecture directly implements the brain's solution: compressing experiences into abstract observations rather than retaining verbose raw transcripts.
|
||||
|
||||
> **Critical innovation articulated:** "Unlike human memory which permanently loses raw data once compressed, Endless Mode maintains an archive of the original data. This creates a hybrid approach: the working memory operates on compressed abstractions for efficiency, while the full data remains available for later retrieval."
|
||||
|
||||
The observation concluded: *"This design naturally feels correct because it implements proven biological principles at the AI level—the brain's solution to memory management, now augmented with perfect archival recall."*
|
||||
|
||||
---
|
||||
|
||||
## The Breakthrough: 95.1% Token Reduction (November 21, 2025)
|
||||
|
||||
### Observation #13556 (Nov 21, 2025 at 10:25 PM)
|
||||
**"Endless Mode breakthrough: 95.1% token reduction through biomimetic memory compression"**
|
||||
|
||||
Four days after the philosophical foundation was laid, the team validated the approach with empirical data. Real dataset analysis of 48 observations showed **95.1% token reduction** (16.5M → 801K tokens) with **20.6x efficiency gains**. The breakthrough document revealed the critical insight: observations are not lossy data compression but rather **memoized synthesis results**—caching the computational output Claude would generate from reading raw data.
|
||||
|
||||
This transformed the recursive synthesis problem from **O(N²) quadratic complexity to O(N) linear complexity**. Each tool use previously forced Claude to re-read and re-synthesize ALL previous tool outputs. With Endless Mode, Claude reads pre-computed observations instead, turning each synthesis into a one-time cost with cached results.
|
||||
|
||||
The observation explicitly framed this as: *"Two-tier memory system mimicking human working memory (compressed observations) but with digital advantages (perfect archival recall)."*
|
||||
|
||||
---
|
||||
|
||||
## Hybrid Architecture Recognition (November 21, 2025)
|
||||
|
||||
### Observation #13169 (Nov 21, 2025 at 1:32 AM)
|
||||
**"Claude-mem Identified as Hybrid Architecture Mirroring Human Memory Systems"**
|
||||
|
||||
This observation synthesized the complete architectural understanding, identifying claude-mem as combining three components that directly parallel human memory systems:
|
||||
|
||||
1. **Episodic Memory** - Temporal timelines storing autobiographical, action-based experiences
|
||||
*("On Nov 20, I fixed auth bug in session X")*
|
||||
|
||||
2. **Semantic Memory** - RAG-like vector similarity search for retrieving relevant past episodes
|
||||
*("Find all times I worked on authentication")*
|
||||
|
||||
3. **Working Memory Compression** - Endless Mode preventing exponential context growth during active sessions
|
||||
*(forget details, keep insights)*
|
||||
|
||||
**The full lifecycle:** During sessions, Endless Mode compresses in real-time; between sessions, observations are stored in episodic memory; new sessions start with RAG-like retrieval plus temporal timeline injection.
|
||||
|
||||
### Observation #13177 (Nov 21, 2025 at 1:35 AM)
|
||||
**"Final Synthesis: General-Purpose AI Context Management Solution for Entire Industry"**
|
||||
|
||||
This observation expanded the vision beyond coding assistants, identifying seven application domains (healthcare, therapy, education, research, personal assistants, gaming, journalism) with the universal pattern: anywhere AI accumulates context over time benefits from ~80% compression.
|
||||
|
||||
> **Critical distinction clarified:** "RAG accesses external static knowledge while claude-mem accesses the AI's own episodic memories. The system combines episodic memory, RAG-like retrieval, and real-time compression, making it more sophisticated than pure RAG with temporal, autobiographical, and compression features."
|
||||
|
||||
---
|
||||
|
||||
## Translation to Public Messaging (November 26, 2025)
|
||||
|
||||
### Observation #15781 (Nov 26, 2025 at 5:15 PM)
|
||||
**"Memory search reveals 19 results on biomimetic design philosophy origins"**
|
||||
|
||||
Five days later, during landing page development, the team executed a memory search for "biomimetic human memory design philosophy" which returned 19 matches. This search surfaced the November 17th foundational observations, providing the backstory needed for public-facing content development.
|
||||
|
||||
### Observation #15757 (Nov 26, 2025 at 4:30 PM)
|
||||
**"BiomimeticDesign Component Created with Human Memory Philosophy Narrative"**
|
||||
|
||||
The team created a landing page component explaining the philosophy to users. The narrative established that LLMs "simply DO" with no retention between sessions, then explained human memory as reconstructive—built from scattered fragments rather than photographic playback—framed as *"genius compression, not a bug."*
|
||||
|
||||
**The three-pillar architecture** directly mapped human cognitive systems to technical implementation:
|
||||
|
||||
- **Episodic Memory** → Timeline Observations
|
||||
- **Semantic Memory** → RAG Vector Search
|
||||
- **Working Memory** → Endless Mode (95% compression)
|
||||
|
||||
### Observation #15818 (Nov 26, 2025 at 5:27 PM)
|
||||
**"Timeline Search as Causal Navigation Pattern Over Efficiency Metrics"**
|
||||
|
||||
This observation refined the public messaging, identifying that the actual innovation wasn't compression percentages but **timeline-based search** returning contextual windows (7 before, 7 after) to expose causal relationships, combined with semantically rich titles functioning as retrieval cues.
|
||||
|
||||
> **Key insight:** "The proof of effectiveness is behavioral: Claude knows exactly where to go without searching, using only index tables. The upfront cost of creating detailed observations eliminates ongoing re-synthesis cost—the understanding was already built, and the index preserves access to that synthesis."
|
||||
|
||||
### Observation #15805 (Nov 26, 2025 at 5:24 PM)
|
||||
**"Reframed landing page copy from abstract to concrete Claude experience"**
|
||||
|
||||
User feedback about "low context malarkey" prompted a pivot from theoretical human memory metaphors to concrete Claude behavior descriptions. The messaging shifted to specific examples:
|
||||
|
||||
- **Pain point:** Claude re-reading, re-discovering, re-researching
|
||||
- **Solution:** Timeline feature showing 7 observations before/after
|
||||
- **Proof:** "It barely ever searches. It just knows where to go."
|
||||
|
||||
---
|
||||
|
||||
## The Terminology Debate (December 2, 2025)
|
||||
|
||||
### Observation #19374 (Dec 2, 2025 at 7:37 PM)
|
||||
**"User Questioning Biomimetic Design Terminology"**
|
||||
|
||||
The user raised questions about whether "biomimetic design" terminology should be changed to alternative phrasing, indicating potential reconsideration of naming conventions.
|
||||
|
||||
### Observation #19377 (Dec 2, 2025 at 7:38 PM)
|
||||
**"Renamed BiomimeticDesign component to HowYouRemember"**
|
||||
|
||||
The component was renamed from "BiomimeticDesign" to "HowYouRemember" for user-friendliness, though the underlying architecture and philosophy remained unchanged. The renaming improved semantic clarity by aligning the component name with its actual content—explaining how users can remember and query information.
|
||||
|
||||
---
|
||||
|
||||
## Key Timeline
|
||||
|
||||
| Date | Time | Event |
|
||||
|------|------|-------|
|
||||
| **Nov 17, 2025** | 1:31-1:35 AM | Core biomimetic philosophy articulated in observations #10140 and #10142 |
|
||||
| **Nov 17, 2025** | 3:28 PM | Observation #10364 documents comprehensive development narrative |
|
||||
| **Nov 21, 2025** | 1:32 AM | Hybrid architecture recognition in observation #13169 |
|
||||
| **Nov 21, 2025** | 10:25 PM | Breakthrough validation with 95.1% token reduction in observation #13556 |
|
||||
| **Nov 26, 2025** | 4:30-5:27 PM | Public-facing BiomimeticDesign component created and messaging refined |
|
||||
| **Dec 2, 2025** | 7:37 PM | Terminology questioned and component renamed to HowYouRemember |
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The biomimetic architecture concept emerged from a deep first-principles analysis of the AI context management problem. Rather than treating memory as a pure engineering challenge, the team recognized the parallel to biological systems that evolved to solve identical problems.
|
||||
|
||||
The innovation wasn't merely copying human memory limitations, but rather **understanding the why behind selective retention and compression**, then augmenting those principles with computational advantages (perfect archival recall).
|
||||
|
||||
The concept evolved through distinct phases:
|
||||
1. **Internal architectural philosophy** (Nov 17)
|
||||
2. **Empirical validation** (Nov 21)
|
||||
3. **Public messaging** (Nov 26)
|
||||
4. **User-friendly terminology** (Dec 2)
|
||||
|
||||
...while preserving the core biomimetic principles that make the system work.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
**Observations:** #10140, #10142, #10363, #10364, #13169, #13177, #13556, #15757, #15781, #15784, #15785, #15805, #15818, #15824, #19374, #19377
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #10140
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #10142
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #10363
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #10364
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #13169
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #13177
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #13556
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15757
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15781
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15784
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15785
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15805
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15818
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #15824
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #19374
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Observation #19377
|
||||
|
||||
**Created**:
|
||||
**Type**:
|
||||
**Session**:
|
||||
**Project**:
|
||||
|
||||
## Title
|
||||
|
||||
|
||||
## Subtitle
|
||||
|
||||
|
||||
## Narrative
|
||||
|
||||
|
||||
## Facts
|
||||
|
||||
## Concepts
|
||||
|
||||
|
||||
## Discovery Tokens
|
||||
|
||||
@@ -1,360 +0,0 @@
|
||||
# Dual-Tag System Architecture
|
||||
|
||||
**Date**: 2025-11-30
|
||||
**Branch**: `feature/meta-observation-control`
|
||||
**Status**: Implemented
|
||||
**Based on**: PR #105 dual-tag system
|
||||
|
||||
## Overview
|
||||
|
||||
The dual-tag system provides fine-grained control over what content gets persisted in claude-mem's observation database. It uses an edge processing pattern to filter tagged content at the hook layer before it reaches the worker service.
|
||||
|
||||
## The Two Tags
|
||||
|
||||
### Tag 1: `<private>`
|
||||
**Purpose**: User-controlled privacy
|
||||
**Status**: User-facing feature (documented)
|
||||
**Use case**: Users wrap content they don't want persisted
|
||||
|
||||
```xml
|
||||
<private>
|
||||
This content won't be stored in observations
|
||||
</private>
|
||||
```
|
||||
|
||||
**Examples**:
|
||||
- Sensitive information (API keys, credentials, internal URLs)
|
||||
- Temporary context (deadlines, personal notes)
|
||||
- Debug output (logs, stack traces)
|
||||
- Exploratory prompts (brainstorming, hypotheticals)
|
||||
|
||||
### Tag 2: `<claude-mem-context>`
|
||||
**Purpose**: System-level meta-observation control
|
||||
**Status**: Infrastructure-ready (not user-facing yet)
|
||||
**Use case**: Prevents recursive storage when real-time context injection is active
|
||||
|
||||
```xml
|
||||
<claude-mem-context>
|
||||
# Relevant Context from Past Sessions
|
||||
|
||||
[Auto-injected past observations...]
|
||||
</claude-mem-context>
|
||||
```
|
||||
|
||||
**Context**: This tag is used by the real-time context injection feature (not yet shipped). When past observations are injected into new prompts, they're wrapped in this tag to prevent them from being re-stored as new observations (recursive storage problem).
|
||||
|
||||
## Architecture Pattern: Edge Processing
|
||||
|
||||
**Principle**: "Process at edge, send clean data to server"
|
||||
|
||||
The dual-tag system follows the edge processing pattern from hooks-in-composition:
|
||||
|
||||
```text
|
||||
UserPrompt → [Hook Layer] → Worker → Database
|
||||
↑
|
||||
Filter here
|
||||
(strip tags at edge)
|
||||
```
|
||||
|
||||
### Data Flow
|
||||
|
||||
**Without Filtering** (broken):
|
||||
```
|
||||
UserPrompt with <private> → PostToolUse hook → Worker → Memory Agent → Database
|
||||
↓
|
||||
Private content stored
|
||||
```
|
||||
|
||||
**With Edge Processing** (correct):
|
||||
```
|
||||
UserPrompt with <private> → PostToolUse hook → stripMemoryTags() → Worker → Memory Agent → Database
|
||||
↑ ↓
|
||||
Filter at edge Only clean data stored
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### File: `src/hooks/save-hook.ts`
|
||||
|
||||
**Function Added** (lines 31-53):
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Strip memory tags to prevent recursive storage and enable privacy control
|
||||
*/
|
||||
function stripMemoryTags(content: string): string {
|
||||
if (typeof content !== 'string') {
|
||||
silentDebug('[save-hook] stripMemoryTags received non-string:', { type: typeof content });
|
||||
return '{}'; // Safe default for JSON context
|
||||
}
|
||||
|
||||
return content
|
||||
.replace(/<claude-mem-context>[\s\S]*?<\/claude-mem-context>/g, '')
|
||||
.replace(/<private>[\s\S]*?<\/private>/g, '')
|
||||
.trim();
|
||||
}
|
||||
```
|
||||
|
||||
**Application** (lines 95-100):
|
||||
|
||||
```typescript
|
||||
tool_input: tool_input !== undefined
|
||||
? stripMemoryTags(JSON.stringify(tool_input))
|
||||
: '{}',
|
||||
tool_response: tool_response !== undefined
|
||||
? stripMemoryTags(JSON.stringify(tool_response))
|
||||
: '{}',
|
||||
```
|
||||
|
||||
### File: `tests/strip-memory-tags.test.ts`
|
||||
|
||||
**Test Coverage**: 19 tests across 4 categories:
|
||||
|
||||
1. **Basic Functionality** (7 tests)
|
||||
- Strip `<claude-mem-context>` tags
|
||||
- Strip `<private>` tags
|
||||
- Strip both tag types
|
||||
- Handle nested tags
|
||||
- Multiline content
|
||||
- Multiple tags
|
||||
- Empty results
|
||||
|
||||
2. **Edge Cases** (5 tests)
|
||||
- Malformed tags (unclosed)
|
||||
- Tag-like strings (not actual tags)
|
||||
- Very large content (10k+ chars)
|
||||
- Whitespace trimming
|
||||
- Strings without tags
|
||||
|
||||
3. **Type Safety** (5 tests)
|
||||
- Non-string inputs (number, null, undefined, object, array)
|
||||
- All return safe default '{}'
|
||||
|
||||
4. **Real-World Scenarios** (2 tests)
|
||||
- JSON.stringify output
|
||||
- Efficient large content handling
|
||||
|
||||
**All tests passing** ✅ (19/19)
|
||||
|
||||
## Design Decisions
|
||||
|
||||
### 1. Always Active (No Configuration)
|
||||
|
||||
**Decision**: Tag stripping is always on, no environment variable needed
|
||||
**Rationale**: Privacy and anti-recursion protection should be default, not opt-in
|
||||
|
||||
### 2. Edge Processing (Not Worker-Level)
|
||||
|
||||
**Decision**: Filter at hook layer before sending to worker
|
||||
**Rationale**:
|
||||
- Keeps worker service simple
|
||||
- Follows one-way data stream
|
||||
- No worker changes needed
|
||||
- Hook becomes a filter/gateway
|
||||
|
||||
### 3. Defensive Coding with Silent Debug
|
||||
|
||||
**Decision**: Handle non-string inputs with silentDebug, return safe default
|
||||
**Rationale**:
|
||||
- Never block the agent (hooks-in-composition principle)
|
||||
- Log issues for observability
|
||||
- Safe fallback maintains system stability
|
||||
|
||||
### 4. Both Tags Now (Progressive Enhancement)
|
||||
|
||||
**Decision**: Implement both tags even though only `<private>` is user-facing
|
||||
**Rationale**:
|
||||
- Infrastructure ready for real-time context feature
|
||||
- No rework needed when context injection ships
|
||||
- Same code path for both tags (simple)
|
||||
- Progressive enhancement approach
|
||||
|
||||
### 5. Regex-Based Stripping
|
||||
|
||||
**Decision**: Use regex `/<tag>[\s\S]*?<\/tag>/g` instead of XML parser
|
||||
**Rationale**:
|
||||
- No dependencies needed
|
||||
- Handles multiline content (`[\s\S]*?`)
|
||||
- Non-greedy (`*?`) prevents over-matching
|
||||
- Global flag (`g`) handles multiple tags
|
||||
- Good enough for this use case
|
||||
|
||||
## Edge Cases Handled
|
||||
|
||||
| Case | Input | Output | Why |
|
||||
|------|-------|--------|-----|
|
||||
| Nested tags | `<private>a <private>b</private> a</private>` | `` | Outer tag matches all |
|
||||
| Malformed | `<private>unclosed` | `<private>unclosed` | Regex requires closing tag |
|
||||
| Multiple | `<private>a</private> b <private>c</private>` | `b` | Global flag removes all |
|
||||
| Empty | `<private></private>` | `` | Matches and removes |
|
||||
| Tag-like | `<tag>not private</tag>` | `<tag>not private</tag>` | Different tag name |
|
||||
| Large content | 10MB+ string | (stripped) | O(n) regex handles it |
|
||||
| Non-string | `123`, `null`, `{}` | `'{}'` | Defensive default |
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### 1. Real-Time Context Injection
|
||||
|
||||
**Status**: Deferred (not in this PR)
|
||||
**When ready**: The `<claude-mem-context>` tag infrastructure is already in place
|
||||
|
||||
The missing piece is in `src/hooks/new-hook.ts`:
|
||||
- Select relevant observations from timeline
|
||||
- Wrap in `<claude-mem-context>` tags
|
||||
- Return via `hookSpecificOutput`
|
||||
- Tag stripping already handles the rest
|
||||
|
||||
### 2. System-Level Meta-Observation Tagging
|
||||
|
||||
**Concept**: Auto-tag observations about observations
|
||||
**Examples**:
|
||||
- Search skill results: `<claude-mem-context>[search results]</claude-mem-context>`
|
||||
- Memory lookups: Fetched observations wrapped in tag
|
||||
- Observation summaries: Meta-level analysis wrapped
|
||||
|
||||
**Implementation**: Tools/skills that produce meta-observations can wrap output in `<claude-mem-context>` tags to prevent recursive storage.
|
||||
|
||||
### 3. Additional Tag Types
|
||||
|
||||
**Potential tags**:
|
||||
- `<ephemeral>`: Content that should be seen but not stored (alias for `<private>`)
|
||||
- `<debug>`: Debug output that should be logged but not persisted
|
||||
- `<scratch>`: Thinking/planning content not meant for observations
|
||||
|
||||
**Note**: Current implementation handles any tag you add to the regex. Adding new tags requires one line change in `stripMemoryTags()`.
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
```bash
|
||||
node --test tests/strip-memory-tags.test.ts
|
||||
```
|
||||
**Expected**: 19/19 passing ✅
|
||||
|
||||
### Integration Tests
|
||||
|
||||
**Test 1: Basic Privacy**
|
||||
```bash
|
||||
# Submit prompt with <private> tag
|
||||
# Query database: should not contain private content
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT COUNT(*) FROM observations WHERE narrative LIKE '%<private>%';"
|
||||
# Expected: 0
|
||||
```
|
||||
|
||||
**Test 2: Dual Tags**
|
||||
```bash
|
||||
# Submit prompt with both tags
|
||||
# Verify neither tag appears in database
|
||||
sqlite3 ~/.claude-mem/claude-mem.db "SELECT COUNT(*) FROM observations WHERE narrative LIKE '%<private>%' OR narrative LIKE '%<claude-mem-context>%';"
|
||||
# Expected: 0
|
||||
```
|
||||
|
||||
**Test 3: Function Exists**
|
||||
```bash
|
||||
# Verify stripMemoryTags in built file
|
||||
grep -c "claude-mem-context.*private.*trim" ~/.claude/plugins/marketplaces/thedotmack/plugin/scripts/save-hook.js
|
||||
# Expected: 1
|
||||
```
|
||||
|
||||
### Regression Tests
|
||||
|
||||
**Ensure**:
|
||||
- Normal observations still work (no tags broken)
|
||||
- Worker service receives clean data
|
||||
- No errors in `~/.claude-mem/silent.log`
|
||||
- Tool executions still captured correctly
|
||||
|
||||
## Known Limitations
|
||||
|
||||
### 1. Tag Format is Fixed
|
||||
|
||||
Tags must use exact XML-style format: `<tag>content</tag>`
|
||||
|
||||
**Won't work**:
|
||||
- `[private]content[/private]` (wrong syntax)
|
||||
- `<!-- private -->content<!-- /private -->` (comment syntax)
|
||||
- `{{private}}content{{/private}}` (curly braces)
|
||||
|
||||
**Future**: Could add support for alternative formats if needed.
|
||||
|
||||
### 2. Partial Tag Matching
|
||||
|
||||
If user writes about tags without intending to use them:
|
||||
```
|
||||
I want to add a <private> tag feature to my app
|
||||
```
|
||||
|
||||
This won't be stripped (no closing tag). But if they accidentally write:
|
||||
```
|
||||
I want to add a <private>tag</private> feature
|
||||
```
|
||||
|
||||
"tag" gets stripped.
|
||||
|
||||
**Mitigation**: Documentation educates users on proper usage.
|
||||
|
||||
### 3. Performance with Very Large Content
|
||||
|
||||
Regex performance is O(n) where n = content length.
|
||||
|
||||
**Tested**: Works fine with 10,000 character strings
|
||||
**Unknown**: Performance with multi-megabyte tool responses
|
||||
|
||||
**Mitigation**: Most tool I/O is small. If issues arise, could optimize with:
|
||||
- Early exit if no '<' character found
|
||||
- Streaming regex for very large content
|
||||
- Size limits on stripMemoryTags input
|
||||
|
||||
## Documentation
|
||||
|
||||
### User-Facing
|
||||
|
||||
**Location**: `docs/public/usage/private-tags.mdx`
|
||||
**Content**:
|
||||
- How to use `<private>` tags
|
||||
- Use cases and examples
|
||||
- Best practices
|
||||
- Troubleshooting
|
||||
|
||||
**Available in**: Mintlify docs site, navigation under "Get Started"
|
||||
|
||||
### Technical/Internal
|
||||
|
||||
**Location**: `docs/context/dual-tag-system-architecture.md` (this file)
|
||||
**Content**:
|
||||
- Complete dual-tag system architecture
|
||||
- Implementation details
|
||||
- Design decisions
|
||||
- Future enhancements
|
||||
|
||||
**Audience**: Contributors, maintainers, future developers
|
||||
|
||||
## References
|
||||
|
||||
### Original Work
|
||||
- **PR #105**: Real-time context injection with dual-tag system
|
||||
- **Branch**: `feature/real-time-context` (merged to main)
|
||||
- **Investigator**: @basher83
|
||||
|
||||
### Documentation
|
||||
- **Investigation**: `docs/context/real-time-context-recursive-memory-investigation.md`
|
||||
- **User Guide**: `docs/public/usage/private-tags.mdx`
|
||||
- **This Document**: `docs/context/dual-tag-system-architecture.md`
|
||||
|
||||
### Patterns Applied
|
||||
- **Edge Processing**: From hooks-in-composition pattern
|
||||
- **Never Block the Agent**: Defensive coding, safe defaults
|
||||
- **One-Way Data Stream**: Hook → Worker → Database
|
||||
|
||||
## Summary
|
||||
|
||||
The dual-tag system is a complete, production-ready implementation that:
|
||||
- ✅ Gives users privacy control via `<private>` tags
|
||||
- ✅ Prepares infrastructure for real-time context injection
|
||||
- ✅ Uses edge processing pattern for clean architecture
|
||||
- ✅ Has comprehensive test coverage (19 tests, all passing)
|
||||
- ✅ Includes user documentation and technical reference
|
||||
- ✅ Requires no configuration (always active)
|
||||
- ✅ Handles edge cases defensively
|
||||
|
||||
**Status**: Ready to ship 🚀
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,83 +0,0 @@
|
||||
# Claude-Mem Hooks Cleanup Todo
|
||||
|
||||
## ✅ Phase 1: Delete Dead Code (Modified)
|
||||
|
||||
**hook-response.ts**
|
||||
|
||||
- [ ] Remove `| string` from HookType union to restore type safety
|
||||
- [ ] Delete PreCompact branch (lines 23-36, 14 lines)
|
||||
- [x] ~~Delete pointless branches~~ — SKIP (intentional)
|
||||
- [x] ~~Simplify wrapper function~~ — SKIP (intentional)
|
||||
|
||||
**new-hook.ts**
|
||||
|
||||
- [ ] Delete 34-line architecture comment block (lines 1-34)
|
||||
- [ ] Replace 18 lines of debug logging with single 4-line log call (lines 64-81)
|
||||
|
||||
**cleanup-hook.ts**
|
||||
|
||||
- [ ] Remove `cwd`, `transcript_path`, `hook_event_name` from SessionEndInput interface
|
||||
- [ ] Replace 12-line manual mode help with simple error throw
|
||||
|
||||
**user-message-hook.ts**
|
||||
|
||||
- [ ] Delete all 40 lines of expired announcement code (lines 31-70)
|
||||
- [ ] Add comment explaining exit code 3: `// exit code 3 = show user message that Claude does NOT receive as context`
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 2: Extract Shared Utilities
|
||||
|
||||
- [ ] Create `src/shared/hook-error-handler.ts` with `handleWorkerError()`
|
||||
- [ ] Update all 4 hooks to use shared error handler (context-hook, new-hook, save-hook, summary-hook)
|
||||
- [ ] Create `src/shared/transcript-parser.ts` — merge `extractLastUserMessage` + `extractLastAssistantMessage` into single parameterized function
|
||||
- [ ] Create `src/shared/hook-constants.ts` for exit codes, timeouts
|
||||
|
||||
---
|
||||
|
||||
## ❌ Phase 3: SKIPPED
|
||||
|
||||
_(Entry points stay as-is, hook-response.ts wrapper stays as-is)_
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 4: Restore Type Safety
|
||||
|
||||
**context-hook.ts**
|
||||
|
||||
- [ ] Make `session_id`, `cwd`, `transcript_path` required in SessionStartInput
|
||||
- [ ] Remove `[key: string]: any`
|
||||
- [ ] Remove unused `source` field
|
||||
- [ ] Keep using `happy_path_error__with_fallback` for defaults (hooks use exit codes, logging tool is appropriate)
|
||||
|
||||
**All 4 hook interfaces**
|
||||
|
||||
- [ ] Remove `[key: string]: any` from all interfaces
|
||||
|
||||
**save-hook.ts**
|
||||
|
||||
- [ ] Keep `happy_path_error__with_fallback` usage (it's appropriate for hook context)
|
||||
|
||||
**summary-hook.ts**
|
||||
|
||||
- [ ] Add timeout (2s) and error logging to spinner stop request
|
||||
|
||||
---
|
||||
|
||||
## ✅ Phase 5: Relocate Business Logic (Modified)
|
||||
|
||||
- [ ] Move `SKIP_TOOLS` from save-hook.ts to worker service
|
||||
- [ ] Make `SKIP_TOOLS` configurable via settings.json
|
||||
- [x] ~~Move announcements to database~~ — SKIP
|
||||
- [x] ~~Merge context-hook + user-message-hook~~ — SKIP (intentionally separate)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Action | Count |
|
||||
| ----------------- | ----- |
|
||||
| Lines to delete | ~150 |
|
||||
| New shared files | 3 |
|
||||
| Interfaces to fix | 4 |
|
||||
| Items skipped | 5 |
|
||||
@@ -1,125 +0,0 @@
|
||||
⏺ PR #335 Review Summary: Queue Monitoring UI + Windows Fixes
|
||||
|
||||
What PR #335 Does
|
||||
|
||||
Additions: 3,724 lines
|
||||
Author: ToxMox
|
||||
Main Changes:
|
||||
1. Switch worker runtime from Bun → Node.js (all platforms)
|
||||
2. Add persistent message queue in SQLite (pending_messages table)
|
||||
3. Add queue monitoring UI with drawer interface
|
||||
4. Add watchdog service for auto-recovery (30s polling)
|
||||
5. Fix Windows console popups using PowerShell Start-Process -WindowStyle Hidden
|
||||
|
||||
Initial Concerns (My Review)
|
||||
|
||||
Raised red flags about:
|
||||
- Lack of evidence for "zombie socket" issue (no GitHub issue, only ToxMox reported)
|
||||
- Over-engineering: Full persistent queue + watchdog + retry logic + UI for unproven problems
|
||||
- Mixing multiple concerns in one PR (should be 3-4 separate PRs)
|
||||
- No automated tests for complex state machine logic
|
||||
- Global runtime change (Bun→Node) affects all platforms for Windows-specific issue
|
||||
- Command injection vulnerability in PowerShell string (ProcessManager.ts:67)
|
||||
|
||||
What We Discovered
|
||||
|
||||
1. Problems ARE Real & Documented
|
||||
|
||||
- Found detailed analysis in PR #315 comments by ToxMox
|
||||
- Zombie socket issue has upstream Bun GitHub issues linked:
|
||||
- oven-sh/bun#12127, #5774, #8786
|
||||
- windowsHide: true doesn't work with detached: true (Node.js bug #21825)
|
||||
- SDK subprocess hangs documented with testing details
|
||||
|
||||
2. Queue UI Has Real Value
|
||||
|
||||
- You saw video demo and said it's "gorgeous and helpful"
|
||||
- Provides visibility into worker activity
|
||||
- Recovery controls prevent user frustration
|
||||
- Real-time updates via existing SSE infrastructure
|
||||
|
||||
3. Architecture Makes Sense
|
||||
|
||||
Why persistent worker is needed:
|
||||
- Real-time UI at http://localhost:37777 requires persistent process
|
||||
- SSE (Server-Sent Events) for live updates
|
||||
- Can't do on-demand worker if UI needs to be always available
|
||||
|
||||
Why queue in database is justified:
|
||||
- Transactional consistency (save observation + enqueue atomically)
|
||||
- Relational queries (JOIN with sessions/projects)
|
||||
- Foreign key cascades (session deleted → queue entries auto-cleaned)
|
||||
- Already have SQLite infrastructure
|
||||
|
||||
4. Storage Optimization Strategy
|
||||
|
||||
Smart cleanup approach (your insight):
|
||||
- Keep full data while pending/processing (needed for retry)
|
||||
- Clear payloads immediately on completion: Set tool_input, tool_response, last_user_message, last_assistant_message to NULL
|
||||
- Keep lightweight metadata for "Recently Processed" UI
|
||||
- Eventually delete old completed records (after 1hr or >100 count)
|
||||
- Result: 100x storage reduction while keeping UI history
|
||||
|
||||
Rejected approach: Linking to transcript files (overly complex, YAGNI)
|
||||
|
||||
Critical Insight: Bun → Node Switch Likely Unnecessary
|
||||
|
||||
Your final assessment:
|
||||
"honestly thats more an llm hallucinating an overengineered solution based on incorrect data that probably could be solved by just killing the process correctly"
|
||||
|
||||
The real issue is probably:
|
||||
- Missing cleanup handlers (server.close() before exit)
|
||||
- Process killed too fast (SIGKILL before cleanup finishes)
|
||||
- Not receiving SIGTERM properly
|
||||
- No registered signal handlers for graceful shutdown
|
||||
|
||||
Simple fix to try FIRST:
|
||||
const server = app.listen(port);
|
||||
|
||||
async function cleanup() {
|
||||
server.close(); // Close server
|
||||
sessionManager.abortAll(); // Stop active work
|
||||
db.close(); // Close DB
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.on('SIGTERM', cleanup);
|
||||
process.on('SIGINT', cleanup);
|
||||
|
||||
Final Assessment
|
||||
|
||||
PR #335 is mostly solid with real benefits, BUT:
|
||||
|
||||
✅ What's Good:
|
||||
|
||||
- Queue UI provides real value
|
||||
- Persistent queue in DB is architecturally justified
|
||||
- Auto-recovery prevents stuck sessions
|
||||
- Problems are real and documented
|
||||
- Comprehensive solution to multiple pain points
|
||||
|
||||
⚠️ What Needs Validation:
|
||||
|
||||
1. Bun zombie socket issue - Only ToxMox reported, not validated by you
|
||||
2. Proper cleanup handlers - Try fixing process termination before switching runtimes
|
||||
3. Platform-specific runtime - If Bun issue is real, use Node only on Windows, keep Bun on Mac/Linux
|
||||
|
||||
🔧 What Needs Fixing:
|
||||
|
||||
1. Add tests - Zero automated tests for complex state machine
|
||||
2. Fix command injection - ProcessManager.ts:67 PowerShell string interpolation
|
||||
3. Implement payload cleanup - Clear heavy data immediately on completion
|
||||
4. Try simple fix first - Proper signal handlers before runtime switch
|
||||
|
||||
Action Items for Next Session
|
||||
|
||||
1. Ask ToxMox: Did you try proper cleanup handlers before switching runtimes?
|
||||
2. Suggest: Platform-specific runtime (Bun on Unix, Node on Windows only if needed)
|
||||
3. Request: Reproduction steps for zombie socket issue
|
||||
4. Require: Basic tests before merge
|
||||
5. Fix: Command injection vulnerability
|
||||
6. Consider: Splitting into separate PRs (optional, not required)
|
||||
|
||||
Key Takeaway
|
||||
|
||||
The PR solves real problems with solid architecture, but the Bun→Node switch is likely over-engineered. Try proper process cleanup first.
|
||||
@@ -1,332 +0,0 @@
|
||||
# Windows, Bun, and Worker Service Struggles
|
||||
|
||||
A comprehensive chronicle of platform-specific issues, attempted fixes, and architectural decisions.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The claude-mem project has faced persistent Windows-specific issues centered around three core problems:
|
||||
|
||||
1. **Console Window Popups**: Blank terminal windows appearing when spawning worker and SDK subprocess
|
||||
2. **Zombie Socket Issues**: Bun leaving TCP sockets in LISTEN state after termination on Windows
|
||||
3. **Process Management Complexity**: Platform-specific spawning logic and reliability issues
|
||||
|
||||
These issues have driven multiple PRs, architectural pivots, and significant debate about runtime switching (Bun → Node.js).
|
||||
|
||||
---
|
||||
|
||||
## Timeline of Issues
|
||||
|
||||
### Issue #209: Windows Worker Startup Failures (Dec 12-13, 2025)
|
||||
|
||||
**Problem**: Worker service failed to start on Windows using PowerShell Start-Process approach.
|
||||
|
||||
**Symptoms**:
|
||||
- Worker startup attempted via `powershell.exe -NoProfile -NonInteractive -Command Start-Process`
|
||||
- Health check retries exhausted (15 attempts over 15 seconds)
|
||||
- Users left unable to start worker manually
|
||||
|
||||
**Root Causes**:
|
||||
- Platform-conditional process spawning (PowerShell for Windows, PM2 for Unix)
|
||||
- PowerShell spawning without `-PassThru` to capture PID
|
||||
- Inconsistent process management across platforms
|
||||
|
||||
**Resolution**: Issue was marked as closed, suggesting it was resolved in v7.1.0 through architectural unification with Bun-based ProcessManager using PID file tracking consistently across all platforms.
|
||||
|
||||
**Status**: ✅ Resolved (pre-PR #335)
|
||||
|
||||
---
|
||||
|
||||
### Issue #309 & PR #315: Console Window Popups (Dec 14-15, 2025)
|
||||
|
||||
**Problem**: Blank terminal windows appear when spawning worker processes and SDK subprocesses on Windows.
|
||||
|
||||
**First Attempted Fix (PR #315)**: Add `windowsHide: true` to spawn options
|
||||
|
||||
**Why It Failed**: Node.js bug #21825 - `windowsHide: true` is **ignored** when `detached: true` is also set. Both flags are required:
|
||||
- `detached: true` - Needed for background process
|
||||
- `windowsHide: true` - Needed to hide window (but doesn't work when detached)
|
||||
|
||||
**Testing Results** (by ToxMox):
|
||||
- Tested PR #315 on Windows 11
|
||||
- Confirmed blank terminal windows still appear for both worker and SDK subprocess spawns
|
||||
- Affects both `ProcessManager.ts` (worker) and `SDKAgent.ts` (SDK subprocess)
|
||||
|
||||
**Working Solution**: Use PowerShell's `Start-Process` with `-WindowStyle Hidden` flag instead of standard spawn.
|
||||
|
||||
**Status**: ❌ PR #315 closed in favor of more comprehensive solution
|
||||
|
||||
---
|
||||
|
||||
### Bun Zombie Socket Issue (Dec 15, 2025)
|
||||
|
||||
**Problem**: Bun leaves TCP sockets in zombie LISTEN state on Windows after worker termination.
|
||||
|
||||
**Symptoms**:
|
||||
- Port remains bound even though no process owns it
|
||||
- `OwningProcess` shows 0 or dead PID
|
||||
- New worker instances cannot start due to `EADDRINUSE` errors
|
||||
- Happens regardless of termination method (process.exit(), external kill, Ctrl+C)
|
||||
- **Only system reboot clears zombie ports**
|
||||
|
||||
**Upstream Tracking**:
|
||||
- Bun issue #12127
|
||||
- Bun issue #5774
|
||||
- Bun issue #8786
|
||||
|
||||
**Impact**: Windows users may need to reboot their systems when worker crashes or is restarted.
|
||||
|
||||
**Proposed Solution**: Switch worker runtime from Bun to Node.js on Windows (or globally).
|
||||
|
||||
**Status**: 🟡 Unresolved - Platform-specific bug in Bun's Windows socket cleanup
|
||||
|
||||
---
|
||||
|
||||
### SDK Subprocess Hang Issue (Dec 15, 2025)
|
||||
|
||||
**Problem**: SDK subprocesses can hang indefinitely, blocking observation processing.
|
||||
|
||||
**Root Cause**: `AbortController.abort()` does not actually terminate child processes.
|
||||
|
||||
**Symptoms**:
|
||||
- For-await loop blocks forever waiting for output from hung subprocess
|
||||
- Observation processing halts
|
||||
- No recovery mechanism
|
||||
|
||||
**Solution**: Implement watchdog timer that explicitly kills child processes using platform-specific commands:
|
||||
- **Windows**: `wmic process where ParentProcessId=<pid> delete`
|
||||
- **Unix**: `pkill -P <pid>`
|
||||
|
||||
**Timeout**: `SDK_QUERY_TIMEOUT_MS` set to 2 minutes
|
||||
|
||||
**Status**: ✅ Fixed in PR #335 (watchdog implementation)
|
||||
|
||||
---
|
||||
|
||||
## PR #335: Comprehensive Windows Fix (Dec 15, 2025)
|
||||
|
||||
### What It Attempted
|
||||
|
||||
ToxMox developed a comprehensive PR addressing all Windows issues simultaneously:
|
||||
|
||||
1. **PowerShell-based spawning** to fix popup windows
|
||||
2. **Runtime switch** from Bun to Node.js (globally) to fix zombie sockets
|
||||
3. **Queue monitoring system** with persistent message queue
|
||||
4. **Watchdog service** for stuck message recovery
|
||||
5. **SQLite compatibility layer** for Node.js support
|
||||
|
||||
### Architecture Decisions
|
||||
|
||||
**ProcessManager Changes**:
|
||||
- Switched from `startWithBun()` to `startWithNode()`
|
||||
- Windows: Uses PowerShell `Start-Process -WindowStyle Hidden -PassThru`
|
||||
- Unix: Uses standard `spawn()` with `detached: true`
|
||||
- Captures PID via PowerShell `Select-Object -ExpandProperty Id`
|
||||
- Comment states: "Use Node on all platforms (Bun has zombie socket issues on Windows)"
|
||||
|
||||
**SQLite Compatibility Layer**:
|
||||
- Created `sqlite-compat.ts` adapter pattern
|
||||
- Provides `bun:sqlite` API compatibility via `better-sqlite3`
|
||||
- Allows code to work with both Bun and Node.js runtimes
|
||||
|
||||
### Critical Issues Identified
|
||||
|
||||
#### 1. **Global vs Platform-Conditional Runtime**
|
||||
|
||||
**The Inconsistency**: Code comment explicitly states zombie sockets occur "on Windows", yet solution applies Node.js universally across all platforms.
|
||||
|
||||
**Questions Raised**:
|
||||
- Why sacrifice Bun's performance on macOS/Linux where no issues documented?
|
||||
- Platform-specific spawning already implemented - why not platform-specific runtime?
|
||||
- No documented Bun reliability issues on non-Windows platforms
|
||||
|
||||
#### 2. **Performance Regressions**
|
||||
|
||||
**better-sqlite3 Blocking**:
|
||||
- Synchronous-only API blocks Node.js event loop during all DB operations
|
||||
- Contrasts with Bun's async SQLite support
|
||||
- Affects: enqueue, markProcessing, markProcessed, watchdog checks
|
||||
|
||||
**Watchdog Polling Overhead**:
|
||||
- Full table scans every 30 seconds even when idle
|
||||
- Constant database I/O overhead
|
||||
- No max queue size limits = unbounded growth
|
||||
|
||||
**Startup Latency**:
|
||||
- Node.js initialization (slower than Bun)
|
||||
- Native module loading (better-sqlite3)
|
||||
- Database migrations
|
||||
- Stuck message scan
|
||||
- Watchdog initialization
|
||||
- HTTP server startup
|
||||
|
||||
#### 3. **Build Dependencies**
|
||||
|
||||
**better-sqlite3 Requirements**:
|
||||
- node-gyp
|
||||
- Python
|
||||
- C++ compiler toolchains
|
||||
- Visual Studio Build Tools (Windows)
|
||||
|
||||
**Impact**:
|
||||
- Local development machines without build tools fail
|
||||
- CI/CD pipelines need updated Docker images
|
||||
- Restricted environments where compilers not permitted
|
||||
- ARM/M1 Mac compatibility issues
|
||||
|
||||
#### 4. **Migration Risks**
|
||||
|
||||
**Breaking Changes**:
|
||||
- Automatic database migration adds `pending_messages` table
|
||||
- Runtime switch not documented in PR
|
||||
- Node.js becomes undocumented hard requirement
|
||||
- No migration guide or rollback procedure
|
||||
|
||||
**Unanswered Questions**:
|
||||
- What happens to in-flight messages during upgrade?
|
||||
- Can users safely downgrade?
|
||||
- Is migration idempotent?
|
||||
|
||||
#### 5. **Code Quality Issues**
|
||||
|
||||
**Command Injection Risk** (ProcessManager.ts:67):
|
||||
- PowerShell commands use template literal concatenation
|
||||
- Vulnerable if `MARKETPLACE_ROOT` or script paths attacker-controlled
|
||||
- Should use array-based argument passing
|
||||
|
||||
**Missing Error Handling** (WatchdogService.ts:61):
|
||||
- `setInterval` callback lacks error handling
|
||||
- Timer continues running if `check()` throws
|
||||
- Creates zombie watchdog scenario
|
||||
|
||||
**No Queue Size Limits**:
|
||||
- Unbounded database growth if messages accumulate
|
||||
- Failed messages (exceeding `maxRetries`) accumulate indefinitely
|
||||
- Only 24-hour retention for processed messages
|
||||
|
||||
---
|
||||
|
||||
## Assessment and Recommendations
|
||||
|
||||
### What Was Validated
|
||||
|
||||
**Legitimate Windows Issues**:
|
||||
- ✅ Console window popups are real (Node.js bug #21825)
|
||||
- ✅ PowerShell `Start-Process` solution works
|
||||
- ✅ Bun zombie socket issue is real and Windows-specific
|
||||
- ✅ SDK subprocess hang issue is real
|
||||
|
||||
### What Remains Questionable
|
||||
|
||||
**Global Runtime Switch**:
|
||||
- ❌ No evidence Bun problematic on macOS/Linux
|
||||
- ❌ Platform-conditional runtime not considered
|
||||
- ❌ Performance trade-offs not documented
|
||||
- ❌ "Windows-only" issue applied globally
|
||||
|
||||
**Zombie Socket Root Cause**:
|
||||
- 🟡 May be fixable with proper cleanup handlers:
|
||||
- Missing `server.close()` calls before exit
|
||||
- Processes killed with `SIGKILL` before cleanup finishes
|
||||
- Missing `SIGTERM` signal handlers for graceful shutdown
|
||||
- 🟡 Runtime switch may be unnecessary over-engineering
|
||||
|
||||
### Salvageable Components
|
||||
|
||||
**If Extracted into Separate PRs**:
|
||||
|
||||
1. **PowerShell Spawning for Windows Worker**
|
||||
- Focused PR: "Windows: Use Node.js instead of Bun for worker process"
|
||||
- Platform-conditional logic (Node.js on Windows, Bun elsewhere)
|
||||
- Independent justification required
|
||||
|
||||
2. **SQLite Compatibility Layer**
|
||||
- Well-designed adapter pattern
|
||||
- Requires independent justification for Node.js runtime need
|
||||
- Should not be bundled with other changes
|
||||
|
||||
3. **Queue Monitoring UI Concept**
|
||||
- Valuable visibility into worker state
|
||||
- Should build on in-memory state first
|
||||
- Remove database persistence requirement initially
|
||||
|
||||
4. **Watchdog Improvements**
|
||||
- SDK subprocess timeout handling
|
||||
- Evidence of superiority over current approach needed
|
||||
|
||||
---
|
||||
|
||||
## Current Status
|
||||
|
||||
### Resolved
|
||||
- ✅ Issue #209: Windows worker startup (v7.1.0)
|
||||
- ✅ SDK subprocess hang issue (watchdog implementation)
|
||||
|
||||
### In Progress
|
||||
- 🔄 PR #339: Windows console popup fix (extracted from PR #335)
|
||||
- 🔄 PR #338: Queue monitoring system (extracted from PR #335)
|
||||
|
||||
### Open Questions
|
||||
- ❓ Should runtime switch be global or Windows-only?
|
||||
- ❓ Can zombie socket issue be fixed without runtime switch?
|
||||
- ❓ Is better-sqlite3's synchronous blocking acceptable?
|
||||
- ❓ Should queue persistence be in-memory first?
|
||||
|
||||
---
|
||||
|
||||
## Lessons Learned
|
||||
|
||||
### Architectural Principles Violated
|
||||
|
||||
**YAGNI**: Queue persistence, watchdog service, and comprehensive monitoring added without proven need.
|
||||
|
||||
**Happy Path**: Should have started with simplest Windows fix (PowerShell spawning), validated, then added complexity if needed.
|
||||
|
||||
**Incremental Validation**: Bundling multiple architectural changes prevents isolating what actually solves the problem.
|
||||
|
||||
### What Should Have Happened
|
||||
|
||||
1. **Phase 1**: PowerShell spawning fix for Windows console popups (targeted, testable)
|
||||
2. **Phase 2**: Investigate zombie socket root cause (cleanup handlers vs runtime switch)
|
||||
3. **Phase 3**: If runtime switch justified, implement as Windows-conditional first
|
||||
4. **Phase 4**: Add queue monitoring as optional feature with in-memory state
|
||||
5. **Phase 5**: Add persistence only if in-memory insufficient
|
||||
|
||||
### Key Takeaways
|
||||
|
||||
- **Windows-specific issues don't justify global architectural changes** without clear evidence
|
||||
- **Platform-conditional logic is acceptable** when solving platform-specific problems
|
||||
- **Native module dependencies are heavy** - avoid unless necessary
|
||||
- **Performance regressions need explicit justification** - synchronous blocking, startup latency, polling overhead all impact UX
|
||||
- **Bundle size matters** - build tools, compilers, Python are significant requirements
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
**GitHub Issues**:
|
||||
- #209: Windows worker startup failures
|
||||
- #309: Console window popups
|
||||
- #315: windowsHide approach (closed)
|
||||
|
||||
**PRs**:
|
||||
- #335: Comprehensive Windows fix (under review)
|
||||
- #338: Queue monitoring system (extracted)
|
||||
- #339: Windows console popup fix (extracted)
|
||||
|
||||
**Upstream Bugs**:
|
||||
- Node.js #21825: windowsHide ignored with detached
|
||||
- Bun #12127, #5774, #8786: Windows zombie sockets
|
||||
|
||||
**Related Observations**:
|
||||
- #27302: PR #315 windowsHide failure analysis
|
||||
- #27233: Bun zombie socket discovery
|
||||
- #27232: Windows background window root cause
|
||||
- #27286: Runtime switch assessment
|
||||
- #27283: PowerShell process spawn fix
|
||||
- #27190: ProcessManager Node.js implementation
|
||||
- #24532: Issue #209 resolution
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-12-16
|
||||
**Document Status**: Comprehensive review based on memory search through #S3485
|
||||
Reference in New Issue
Block a user