Commit Graph

1172 Commits

Author SHA1 Message Date
Alex Newman 0622ebf534 MAESTRO: Close PR #830 requesting scope reduction and rebase after merge conflicts with #769/#884
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:18:27 -05:00
Alex Newman 63b0105d05 MAESTRO: Mark PR #884 task complete in PR-Triage-09 with detailed merge notes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:15:59 -05:00
Alex Newman 3ad53733e8 MAESTRO: Merge PR #884 adding Zscaler SSL certificate support for ChromaDB vector search
Adds automatic detection and handling of Zscaler enterprise security certificates
on macOS. Combines standard certifi CA certificates with Zscaler certificates into
a single bundle, passed via SSL_CERT_FILE/REQUESTS_CA_BUNDLE/CURL_CA_BUNDLE env vars
to the chroma-mcp subprocess. Certificate bundle is cached for 24 hours. Falls back
gracefully when Zscaler is not present, with no impact on non-Zscaler environments.

Co-Authored-By: RClark4958 <rickdclark48@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:15:19 -05:00
Alex Newman 403913a0fc MAESTRO: Merge PR #769 fixing chroma-mcp zombie processes, rebuild compiled output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:11:32 -05:00
Jenha Poyarkov 9f2a237aaf fix: close transport on connection error to prevent chroma-mcp zombie processes
Fixes #761

Root cause: When connection errors occur (MCP error -32000, Connection closed),
the code was resetting \`connected\` and \`client\` but NOT calling
\`transport.close()\`, leaving the chroma-mcp subprocess alive. Each
reconnection attempt spawned a NEW process while old ones accumulated.

Changes:
- Close transport before resetting state in ensureCollection() error handler
- Close transport before resetting state in queryChroma() error handler
- Set transport = null after closing to match close() method behavior
- Add regression tests for Issue #761 with source code verification

Tested on macOS - no more zombie processes after the fix.
2026-02-06 02:10:18 -05:00
Alex Newman b967772897 MAESTRO: Mark PR #887 task complete in PR-Triage-09
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:07:41 -05:00
Alex Newman e19617a065 build: rebuild compiled output after PR #887 merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:07:22 -05:00
Abdelkarim Mateos Sanchez 9bd56c993c fix: align IDs with metadatas in ChromaSearchStrategy
ChromaSync.queryChroma() returns deduplicated sqlite_ids but the
metadatas array contains multiple entries per observation (narrative +
facts). The filterByRecency() method was iterating over metadatas and
using the index to access ids, causing array out-of-bounds access.

The fix builds a Map from sqlite_id to metadata, then iterates over
the deduplicated ids array to ensure proper alignment.

Symptoms before fix:
- Semantic search returning incorrect/empty results
- Search only working with near-exact queries
- Recent items (same day) not being found

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 02:07:03 -05:00
Alex Newman f62b5d248c MAESTRO: Mark PR #615 task complete in PR-Triage-08
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:04:53 -05:00
Alex Newman 711f5455df fix: generate synthetic memorySessionId for stateless providers (PR #615)
Gemini and OpenRouter are stateless APIs that never return session IDs.
Without synthetic IDs, PR #693's defensive memorySessionId checks throw
errors on every observation processing call for these providers.

Generates provider-prefixed IDs (gemini-/openrouter-{contentSessionId}-
{timestamp}) before the first API call, persisted to the database via
updateMemorySessionId(). Applied from PR #615 (closed due to staleness).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:04:49 -05:00
Alex Newman e36efff00d MAESTRO: Close PR #910 in PR-Triage-08 — stale branch with regressions
PR #910 reverts 5 recently merged fixes (PRs #693, #937, #913, Issue #733,
createIterator API) and bundles unrelated features (observation dedup,
summary soft-delete, CLAUDE.md deletions). Requested re-submission as
focused PRs for the valuable synthetic memorySessionId feature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 02:02:00 -05:00
Alex Newman 486bae633b MAESTRO: Mark PR #741 task complete in PR-Triage-08
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:58:59 -05:00
Alex Newman 228a006953 build: rebuild compiled output after PR #741 merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:58:08 -05:00
Alex Newman 2d40afe7ef fix: provider-aware recovery and stale session cleanup (PR #741)
Applies PR #741 by @licutis onto main, resolving conflicts with
recently merged PRs #693, #937, and #627. Adds getActiveAgent() to
WorkerService so startup-recovery uses the correct provider instead
of hardcoding SDKAgent. Also cleans up sessions stuck 'active' for
6+ hours and their pending messages before processing orphaned queues.

Co-Authored-By: licutis <43884712+licutis@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:58:00 -05:00
Alex Newman ff55b6e4e0 MAESTRO: Mark PR #627 task complete in PR-Triage-08
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:54:28 -05:00
Alex Newman e2de295c41 build: rebuild compiled output after PR #627 merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:53:44 -05:00
TranslateMe ea38601564 fix: Reset AbortController before starting generator to prevent infinite abort loop
When a generator exits with wasAborted=true, the AbortController remains in
aborted state but generatorPromise is set to null. When a new observation
arrives, ensureGeneratorRunning() sees generatorPromise=null and tries to
start a new generator, but the new generator immediately sees
signal.aborted=true and exits, causing an infinite "Generator aborted" loop.

This fix resets the AbortController if it's already aborted before starting
a new generator, allowing the session to recover from the stuck state.

Bug reproduction:
1. Session receives observations
2. Something causes the generator to be aborted
3. generatorPromise = null, but abortController.signal.aborted = true
4. New observation arrives → starts generator → immediately aborted → loop

Fix: Check if abortController.signal.aborted before starting generator,
and create a new AbortController if needed.
2026-02-06 01:53:17 -05:00
Alex Newman 9fd32ad44b MAESTRO: Close PR #899 - too broad, overlaps with merged PRs #693, #937, #940
Reviewed PR #899 (multi-session message processing fix). Identified significant
overlap with 3 recently merged PRs causing merge conflicts in 3 files. Closed
with detailed feedback requesting focused re-submission of the genuinely valuable
parts: AbortController stale-check, FK constraint protection, and queueDepth fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:51:52 -05:00
Alex Newman dd753184db MAESTRO: Mark PR #937 task complete in PR-Triage-08
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:48:50 -05:00
Alex Newman e8097caed7 build: rebuild compiled output after PR #937 merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:48:04 -05:00
Alex Newman eb7e37dcf1 MAESTRO: Merge PR #937 - gracefully process orphaned pending messages after session termination 2026-02-06 01:47:55 -05:00
jayvenn21 f24bba21e9 fix(worker): gracefully process orphaned pending messages after session termination 2026-02-06 01:47:43 -05:00
Alex Newman 1a1297c12a MAESTRO: Merge PR #940 - backfill project field on SDK session creation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:45:35 -05:00
Michael Lipscombe af308ea5c8 fix: Backfill project field on SDK session creation to prevent race condition
PostToolUse hook can create the session before UserPromptSubmit's
session-init sets the project, leaving it empty. Add an UPDATE after
INSERT OR IGNORE to backfill the project when a later hook provides it.

Closes #939

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 01:44:42 -05:00
Alex Newman 6382d6f9c7 MAESTRO: Merge PR #693 - prevent infinite restart loop that causes runaway API costs
Add restart limit (max 3 consecutive restarts) with exponential backoff
to prevent infinite generator restart loops. Also add defensive
memorySessionId checks in GeminiAgent and OpenRouterAgent before
expensive LLM calls to fail fast when session ID hasn't been captured.

Based on PR #693 by @ajbmachon (applied to current main).

Co-Authored-By: Andre Machon <ajbmachon2@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:43:12 -05:00
Alex Newman 1ae6c5708c MAESTRO: Merge PR #934 - terminate session on prompt-too-long instead of retrying indefinitely
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:40:20 -05:00
jayvenn21 93bad99d79 fix: terminate session on prompt-too-long instead of retrying indefinitely 2026-02-06 01:39:55 -05:00
Alex Newman 9c68a3ba3d MAESTRO: Merge PR #913 - respect CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED setting
Folder CLAUDE.md generation is now gated behind the CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED
setting (default: false). The setting is exposed via the settings API and handles both
string and boolean JSON values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:38:01 -05:00
Alex Newman 117710d449 Merge PR #913: respect CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED setting 2026-02-06 01:36:58 -05:00
Michel Tomas b07130acc6 fix: handle both boolean and string types for settings
JSON.parse preserves native types, so boolean true/false stay as
booleans rather than strings. The previous check only handled string
'true', meaning users who set `"ENABLED": true` (boolean) wouldn't
have the feature work.

Now both `getBool()` helper and ResponseProcessor check handle:
- String 'true' → enabled
- Boolean true → enabled
- Any other value → disabled

Tested: Confirmed feature stays disabled with string "false" and
no new CLAUDE.md files are created when accessing directories.
2026-02-06 01:36:45 -05:00
Michel Tomas bb96092d74 fix: add FOLDER_CLAUDEMD_ENABLED to settingKeys for API/UI access 2026-02-06 01:36:45 -05:00
Michel Tomas 9907df1db8 fix: respect CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED setting
The CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED setting was documented but never
actually checked in code. The folder CLAUDE.md generation ran
unconditionally whenever files were touched.

Changes:
- Add CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED to SettingsDefaults interface
- Add default value 'false' to DEFAULTS object
- Check setting in ResponseProcessor before calling updateFolderClaudeMdFiles

Fixes the issue identified in issue-600-documentation-audit-features-not-implemented.md:
"The setting CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED is never read."
2026-02-06 01:36:45 -05:00
Alex Newman ab3d4ca865 MAESTRO: Prevent CLAUDE.md generation in unsafe directories (PR #929 concept)
Add exclusion list for directories where CLAUDE.md generation breaks
toolchains: res/ (Android aapt2), .git/, build/, node_modules/,
__pycache__/. Closes issue #912. Credit to @jayvenn21.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:35:31 -05:00
Alex Newman e424d85a93 MAESTRO: Close PR #834 - isInsideGitRepo would disable folder CLAUDE.md feature for all git projects
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 01:32:50 -05:00
Alex Newman e5a133b3da MAESTRO: Prevent nested duplicate directory creation in CLAUDE.md paths (PR #836 concept)
Add hasConsecutiveDuplicateSegments() check to isValidPathForClaudeMd() to reject paths
like frontend/frontend/ or src/src/ that occur when cwd already includes the directory name.
3 new tests added (46 total for claude-md-utils). Fixes #814. Credit to @Glucksberg.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 00:03:03 -05:00
Alex Newman 15e9473533 MAESTRO: Fix CLAUDE.md race condition from PR #974 - skip folders with active CLAUDE.md edits
Prevents "file modified since read" errors when Claude Code is actively editing
a CLAUDE.md file by detecting CLAUDE.md paths in observation file lists and
skipping those folders during updates. Closes #859. Credit: @cheapsteak.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:57:32 -05:00
Alex Newman 20333e6214 MAESTRO: Merge PR #932 - prevent duplicate generator spawns in handleSessionInit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:49:23 -05:00
jayvenn21 5d1ee20076 fix: prevent duplicate generator spawns in handleSessionInit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-05 23:48:56 -05:00
Alex Newman 576d407c00 MAESTRO: Fix image-only prompts skipping session init (PR #928 concept)
Image-only prompts have empty text content, causing session-init handler
to skip session creation entirely. Use '[media prompt]' placeholder so
sessions still get created and tracked in memory.

Closes PR #928 (applied directly due to merge conflicts with outdated base).
Credit: @iammike for identifying the issue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 23:47:12 -05:00
Alex Newman 3eb0154d58 MAESTRO: Close PR #829 as redundant - empty prompt fix already merged via PR #828
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 22:39:20 -05:00
Alex Newman 80663fff97 MAESTRO: Merge PR #828 - server-side DB readiness wait for session-init endpoint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 22:37:47 -05:00
Rajiv Sinclair 27aa98c269 fix: wait for database initialization before processing session-init requests
Fixes a race condition where the UserPromptSubmit hook could call
/api/sessions/init before the database is fully initialized, resulting
in a 500 error with "Database not initialized".

Root cause:
- Worker starts HTTP server immediately for fast startup
- Health endpoint (/api/health) returns OK when server is listening
- session-init hook waits for health check, then calls /api/sessions/init
- Database initialization happens in background, creating a race window

Solution:
- Add early handler for /api/sessions/init that waits for initialization
- Uses same pattern as existing /api/context/inject handler
- Returns 503 with retry message if initialization times out

The fix ensures hooks receive proper responses even during the brief
startup window when the server is listening but DB isn't ready yet.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-02-05 22:23:52 -05:00
Rajiv Sinclair 9789a1969c fix: gracefully handle empty prompts in session-init hook
When a user submits an empty or whitespace-only prompt to Claude Code,
the UserPromptSubmit hook would throw "sessionInitHandler requires prompt"
and block the operation.

This change returns early with `{ continue: true }` instead of throwing,
allowing the session to continue gracefully.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 22:23:52 -05:00
Alex Newman d333c7dc08 MAESTRO: Expand startup orphan cleanup to target mcp-server and worker-service processes
The startup cleanupOrphanedProcesses() only targeted chroma-mcp, leaving
orphaned mcp-server.cjs and worker-service.cjs processes undetected after
daemon crashes. Expanded to target all claude-mem process types with
30-minute age filtering and current PID exclusion. Closes PR #687 (which
had a spawnDaemon regression removing Windows WMIC support).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 22:06:46 -05:00
Alex Newman edfc1a403f MAESTRO: Close PR #713 - subprocess accumulation fix already covered by ProcessRegistry and idle timeout
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 20:19:43 -05:00
Alex Newman ad37629f0a MAESTRO: Close PR #738 - parallel subprocess tracking system duplicates ProcessRegistry
PR #738's QueryWrapper/QueryWrapperManager introduces a separate process tracking
system alongside the existing ProcessRegistry. Its orphan cleanup duplicates
killSystemOrphans() and killIdleDaemonChildren() already in main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 20:13:26 -05:00
Alex Newman 7be19b20cd MAESTRO: Close PR #847 - observer session isolation already shipped via PRs #845, #733
All changes from the comprehensive PR were merged incrementally:
- PR #845 (v9.0.12): cwd isolation replacing CLAUDE_CONFIG_DIR
- PR #733: EnvManager.ts with buildIsolatedEnv() for credential isolation
- CLAUDE_MEM_CLAUDE_AUTH_METHOD setting already in SettingsDefaultsManager

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 20:09:52 -05:00
Alex Newman 5b2eb9f599 MAESTRO: Merge PR #879 - daemon children cleanup fills orphan reaper gap
PR #879 adds killIdleDaemonChildren() to ProcessRegistry, targeting idle
Claude SDK processes that are children of the worker-service daemon but
weren't caught by the existing registry-based or ppid=1 cleanup paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 20:04:59 -05:00
Alex Newman ede75b1c5b Merge PR #879: fix: add daemon children cleanup to orphan reaper 2026-02-05 20:03:15 -05:00
david718 cdb0e823aa fix: add daemon children cleanup to orphan reaper
Add killIdleDaemonChildren() to clean up SDK-spawned claude processes
that don't terminate after completing their work.

Problem:
- Worker-service daemon spawns Claude SDK processes
- These processes remain alive after work completes
- They accumulate over time, consuming significant memory
- Existing killSystemOrphans() only handles PPID=1 orphans

Solution:
- Add killIdleDaemonChildren() that finds claude processes where:
  - Parent PID = daemon's PID (children of worker-service)
  - CPU = 0% (idle, not actively working)
  - Running > 2 minutes (completed their work)
- Call it from reapOrphanedProcesses() (runs every 5 minutes)

Testing:
- Verified locally: 15+ zombie processes cleaned up
- Memory saved: ~2GB
- Normal processes (MCP server, Chroma) unaffected

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-05 19:50:46 -05:00