Fix: Windows Terminal tab accumulation and Windows 11 compatibility (#625) (#628)

* docs: add folder index generator plan

RFC for auto-generating folder-level CLAUDE.md files with observation
timelines. Includes IDE symlink support and root CLAUDE.md integration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: implement folder index generator (Phase 1)

Add automatic CLAUDE.md generation for folders containing observed files.
This enables IDE context providers to access relevant memory observations.

Core modules:
- FolderDiscovery: Extract folders from observation file paths
- FolderTimelineCompiler: Compile chronological timeline per folder
- ClaudeMdGenerator: Write CLAUDE.md with tag-based content replacement
- FolderIndexOrchestrator: Coordinate regeneration on observation save

Integration:
- Event-driven regeneration after observation save in ResponseProcessor
- HTTP endpoints for folder discovery, timeline, and manual generation
- Settings for enabling/configuring folder index behavior

The <claude-mem-context> tag wrapping ensures:
- Manual CLAUDE.md content is preserved
- Auto-generated content won't be recursively observed
- Clean separation between user and system content

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add updateFolderClaudeMd function to CursorHooksInstaller

Adds function to update CLAUDE.md files for folders touched by observations.
Uses existing /api/search/by-file endpoint, preserves content outside
<claude-mem-context> tags, and writes atomically via temp file + rename.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: hook updateFolderClaudeMd into ResponseProcessor

Calls updateFolderClaudeMd after observation save to update folder-level
CLAUDE.md files. Uses fire-and-forget pattern with error logging.
Extracts file paths from saved observations and workspace path from registry.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add timeline formatting for folder CLAUDE.md files

Implements formatTimelineForClaudeMd function that transforms API response
into compact markdown table format. Converts emojis to text labels,
handles ditto marks for timestamps, and groups under "Recent" header.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: remove old folder-index implementation

Deletes redundant folder-index services that were replaced by the simpler
updateFolderClaudeMd approach in CursorHooksInstaller.ts.

Removed:
- src/services/folder-index/ directory (5 files)
- FolderIndexRoutes.ts
- folder-index settings from SettingsDefaultsManager
- folder-index route registration from worker-service

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add worktree-aware project filtering for unified timelines

Detect git worktrees and show both parent repo and worktree observations
in the session start timeline. When running in a worktree, the context
now includes observations from both projects, interleaved chronologically.

- Add detectWorktree() utility to identify worktree directories
- Add getProjectContext() to return parent + worktree projects
- Update context hook to pass multi-project queries
- Add queryObservationsMulti() and querySummariesMulti() for IN clauses
- Maintain backward compatibility with single-project queries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* fix: restructure logging to prove session correctness and reduce noise

Add critical logging at each stage of the session lifecycle to prove the session ID chain (contentSessionId → sessionDbId → memorySessionId) stays aligned. New logs include CREATED, ENQUEUED, CLAIMED, MEMORY_ID_CAPTURED, STORING, and STORED. Move intermediate migration and backfill progress logs to DEBUG level to reduce noise, keeping only essential initialization and completion logs at INFO level.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* refactor: extract folder CLAUDE.md utils to shared location

Moves folder CLAUDE.md utilities from CursorHooksInstaller to a new
shared utils file. Removes Cursor registry dependency - file paths
from observations are already absolute, no workspace lookup needed.

New file: src/utils/claude-md-utils.ts
- replaceTaggedContent() - preserves user content outside tags
- writeClaudeMdToFolder() - atomic writes with tag preservation
- formatTimelineForClaudeMd() - API response to compact markdown
- updateFolderClaudeMdFiles() - orchestrates folder updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: trigger folder CLAUDE.md updates when observations are saved

The folder CLAUDE.md update was previously only triggered in
syncAndBroadcastSummary, but summaries run with observationCount=0
(observations are saved separately). Moved the update logic to
syncAndBroadcastObservations where file paths are available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* all the claudes

* test: add unit tests for claude-md-utils pure functions

Add 11 tests covering replaceTaggedContent and formatTimelineForClaudeMd:
- replaceTaggedContent: empty content, tag replacement, appending, partial tags
- formatTimelineForClaudeMd: empty input, parsing, ditto marks, session IDs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: add integration tests for file operation functions

Add 9 tests for writeClaudeMdToFolder and updateFolderClaudeMdFiles:
- writeClaudeMdToFolder: folder creation, content preservation, nested dirs, atomic writes
- updateFolderClaudeMdFiles: empty skip, fetch/write, deduplication, error handling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: add unit tests for timeline-formatting utilities

Add 14 tests for extractFirstFile and groupByDate functions:
- extractFirstFile: relative paths, fallback to files_read, null handling, invalid JSON
- groupByDate: empty arrays, date grouping, chronological sorting, item preservation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: rebuild plugin scripts with merged features

* docs: add project-specific CLAUDE.md with architecture and development notes

* fix: exclude project root from auto-generated CLAUDE.md updates

Skip folders containing .git directory when auto-updating subfolder
CLAUDE.md files. This ensures:

1. Root CLAUDE.md remains user-managed and untouched by the system
2. SessionStart context injection stays pristine throughout the session
3. Subfolder CLAUDE.md files continue to receive live context updates
4. Cleaner separation between user-authored root docs and auto-generated folder indexes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: prevent crash from resuming stale SDK sessions on worker restart

When the worker restarts, it was incorrectly passing the `resume` parameter
to INIT prompts (lastPromptNumber=1) when a memorySessionId existed from a
previous SDK session. This caused "Claude Code process exited with code 1"
crashes because the SDK tried to resume into a session that no longer exists.

Root cause: The resume condition only checked `hasRealMemorySessionId` but
did not verify that this was a CONTINUATION prompt (lastPromptNumber > 1).

Fix: Add `session.lastPromptNumber > 1` check to the resume condition:
- Before: `...(hasRealMemorySessionId && { resume: session.memorySessionId })`
- After: `...(hasRealMemorySessionId && session.lastPromptNumber > 1 && { resume: ... })`

Also added:
- Enhanced debug logging that warns when skipping resume for INIT prompts
- Unit tests in tests/sdk-agent-resume.test.ts (9 test cases)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: properly handle Chroma MCP connection errors

Previously, ensureCollection() caught ALL errors from chroma_get_collection_info
and assumed they meant "collection doesn't exist", triggering unnecessary
collection creation attempts. Connection errors like "Not connected" or
"MCP error -32000: Connection closed" would cascade into failed creation attempts.

Similarly, queryChroma() would silently return empty results when the MCP call
failed, masking the underlying connection problem.

Changes:
- ensureCollection(): Detect connection errors and re-throw immediately instead
  of attempting collection creation
- queryChroma(): Wrap MCP call in try-catch and throw connection errors instead
  of returning empty results
- Both methods reset connection state (connected=false, client=null) on
  connection errors so subsequent operations can attempt to reconnect

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* pushed

* fix: scope regenerate-claude-md.ts to current working directory

Critical bug fix: The script was querying ALL observations from the database
across ALL projects ever recorded (1396+ folders), then attempting to write
CLAUDE.md files everywhere including other projects, non-existent paths, and
ignored directories.

Changes:
- Use git ls-files to discover folders (respects .gitignore automatically)
- Filter database query to current project only (by folder name)
- Use relative paths for database queries (matches storage format)
- Add --clean flag to remove auto-generated CLAUDE.md files
- Add fallback directory walker for non-git repos

Now correctly scopes to 26 folders with observations instead of 1396+.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs and adjustments

* fix: cleanup mode strips tags instead of deleting files blindly

The cleanup mode was incorrectly deleting entire files that contained
<claude-mem-context> tags. The correct behavior (per original design):

1. Strip the <claude-mem-context>...</claude-mem-context> section
2. If empty after stripping → delete the file
3. If has remaining content → save the stripped version

Now properly preserves user content in CLAUDE.md files while removing
only the auto-generated sections.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* deleted some files

* chore: regenerate folder CLAUDE.md files with fixed script

Regenerated 23 folder CLAUDE.md files using the corrected script that:
- Scopes to current working directory only
- Uses git ls-files to respect .gitignore
- Filters by project name

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Update CLAUDE.md files for January 5, 2026

- Regenerated and staged 23 CLAUDE.md files with a mix of new and modified content.
- Fixed cleanup mode to properly strip tags instead of deleting files blindly.
- Cleaned up empty CLAUDE.md files from various directories, including ~/.claude and ~/Scripts.
- Conducted dry-run cleanup that identified a significant reduction in auto-generated CLAUDE.md files.
- Removed the isAutoGeneratedClaudeMd function due to incorrect file deletion behavior.

* feat: use settings for observation limit in batch regeneration script

Replace hard-coded limit of 10 with configurable CLAUDE_MEM_CONTEXT_OBSERVATIONS
setting (default: 50). This allows users to control how many observations appear
in folder CLAUDE.md files.

Changes:
- Import SettingsDefaultsManager and load settings at script startup
- Use OBSERVATION_LIMIT constant derived from settings at both call sites
- Remove stale default parameter from findObservationsByFolder function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: use settings for observation limit in event-driven updates

Replace hard-coded limit of 10 in updateFolderClaudeMdFiles with
configurable CLAUDE_MEM_CONTEXT_OBSERVATIONS setting (default: 50).

Changes:
- Import SettingsDefaultsManager and os module
- Load settings at function start (once, not in loop)
- Use limit from settings in API call

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Implement configurable observation limits and enhance search functionality

- Added configurable observation limits to batch regeneration scripts.
- Enhanced SearchManager to handle folder queries and normalize parameters.
- Introduced methods to check for direct child files in observations and sessions.
- Updated SearchOptions interface to include isFolder flag for filtering.
- Improved code quality with comprehensive reviews and anti-pattern checks.
- Cleaned up auto-generated CLAUDE.md files across various directories.
- Documented recent changes and improvements in CLAUDE.md files.

* build asset

* Project Context from Claude-Mem auto-added (can be auto removed at any time)

* CLAUDE.md updates

* fix: resolve CLAUDE.md files to correct directory in worktree setups

When using git worktrees, CLAUDE.md files were being written relative to
the worker's process.cwd() instead of the actual project directory. This
fix threads the project's cwd from message processing through to the file
writing utilities, ensuring CLAUDE.md files are created in the correct
project directory regardless of where the worker was started.

Changes:
- Add projectRoot parameter to updateFolderClaudeMdFiles for path resolution
- Thread projectRoot through ResponseProcessor call chain
- Track lastCwd from messages in SDKAgent, GeminiAgent, OpenRouterAgent
- Add tests for relative/absolute path handling with projectRoot

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* more project context updates

* context updates

* planning context

* feat: add CLI infrastructure for unified hook architecture (Phase 1)

- Add src/cli/types.ts with NormalizedHookInput, HookResult, PlatformAdapter, EventHandler interfaces
- Add src/cli/stdin-reader.ts with readJsonFromStdin() extracted from save-hook.ts pattern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add platform adapters for unified hook CLI (Phase 2)

- Add claude-code adapter mapping session_id, tool_name, etc.
- Add cursor adapter mapping conversation_id, workspace_roots, result_json
- Add raw adapter for testing/passthrough
- Add getPlatformAdapter() factory function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add event handlers for unified hook CLI (Phase 3)

- Add context handler (GET /api/context/inject)
- Add session-init handler (POST /api/sessions/init)
- Add observation handler (POST /api/sessions/observations)
- Add summarize handler (POST /api/sessions/summarize)
- Add user-message handler (stderr output, exit code 3)
- Add file-edit handler for Cursor afterFileEdit events
- Add getEventHandler() factory function

All handlers copy exact HTTP calls from original hooks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add hook command dispatcher (Phase 4)

- Add src/cli/hook-command.ts dispatching stdin to adapters and handlers
- Add 'hook' case to worker-service.ts CLI switch
- Usage: bun worker-service.cjs hook <platform> <event>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: update hooks.json to use unified CLI (Phase 5)

- Change context-hook.js to: hook claude-code context
- Change new-hook.js to: hook claude-code session-init
- Change save-hook.js to: hook claude-code observation
- Change summary-hook.js to: hook claude-code summarize
- Change user-message-hook.js to: hook claude-code user-message

All hooks now route through unified CLI: bun worker-service.cjs hook <platform> <event>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: update Cursor integration to use unified CLI (Phase 6)

- Update CursorHooksInstaller to generate unified CLI commands
- Use node instead of shell scripts for Cursor hooks
- Add platform field to NormalizedHookInput for handler decisions
- Skip SDK agent init for Cursor platform (not supported)
- Fix file-edit handler to use 'write_file' tool name

Cursor event mapping:
- beforeSubmitPrompt → session-init, context
- afterMCPExecution/afterShellExecution → observation
- afterFileEdit → file-edit
- stop → summarize

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: remove old hook files, complete unified CLI migration (Phase 7)

Deleted files:
- src/hooks/context-hook.ts, new-hook.ts, save-hook.ts, summary-hook.ts, user-message-hook.ts
- cursor-hooks/*.sh and *.ps1 shell scripts
- plugin/scripts/*-hook.js built files

Modified:
- scripts/build-hooks.js: removed hook build loop

Build now produces only: worker-service.cjs, mcp-server.cjs, context-generator.cjs
All hooks route through: bun worker-service.cjs hook <platform> <event>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: handle undefined stdin in platform adapters for SessionStart hooks

SessionStart hooks don't receive stdin data from Claude Code, causing the
adapters to crash when trying to access properties on undefined. Added
null coalescing to handle empty input gracefully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* context update

* fix: replace deprecated WMIC with PowerShell for Windows 11 compatibility

Fixes #625

Changes:
- Replace WMIC process queries with PowerShell Get-Process and Get-CimInstance
- WMIC is deprecated in Windows 11 and causes terminal tab accumulation
- PowerShell provides simpler output format (just PIDs, not "ProcessId=1234")
- Update tests to match new PowerShell output parsing logic

Benefits:
- Windows 11 compatibility (WMIC removal planned)
- Fixes terminal window accumulation issue on Windows
- Cleaner, more maintainable parsing logic
- Same security validation (PID > 0, integer checks)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: graceful exit strategy to prevent Windows Terminal tab accumulation (#625)

Problem:
Windows Terminal keeps tabs open when processes exit with code 1, leading
to tab accumulation during worker lifecycle operations (start, stop, restart,
version mismatches, port conflicts). This created a poor user experience with
dozens of orphaned terminal tabs.

Solution:
Implemented graceful exit strategy using exit code 0 for all expected failure
scenarios. The wrapper and plugin handle restart logic, so child processes
don't need to signal failure with non-zero exit codes.

Key Changes:
- worker-service.ts: Changed all process.exit(1) to process.exit(0) in:
  - Port conflict scenarios
  - Version mismatch recovery
  - Daemon spawn failures
  - Health check timeouts
  - Restart failures
  - Worker startup errors
- mcp-server.ts: Changed fatal error exit from 1 to 0
- ProcessManager.ts: Changed signal handler error exit from 1 to 0
- hook-command.ts: Changed hook error exit code from 1 to 2 (BLOCKING_ERROR)
  to ensure users see error messages (per Claude Code docs, exit 1 only shows
  in verbose mode)

All exits include explanatory comments documenting the graceful exit strategy.

Fixes #625

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* docs: update CLAUDE.md activity logs

Auto-generated context updates from work on issue #625:
- Windows 11 WMIC migration
- PowerShell process enumeration
- Graceful exit strategy implementation
- PR creation for Windows Terminal tab fix

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* docs: update activity logs in CLAUDE.md files across multiple directories

* chore: update CLAUDE.md files with recent activity and documentation improvements

- Adjusted dates and entries in CLAUDE.md for various components including reports and services.
- Added detailed activity logs for worker services, CLI commands, and server interactions.
- Documented exit code strategy in CLAUDE.md to clarify graceful exit philosophy.
- Extracted PowerShell timeout constant and updated related documentation and tests.
- Enhanced log level audit strategy and clarified logging patterns across services.

* polish: extract PowerShell timeout constant and document exit code strategy

- Extract magic number 60000ms to HOOK_TIMEOUTS.POWERSHELL_COMMAND (10000ms)
- Reduce PowerShell timeout from 60s to 10s per review feedback
- Document exit code strategy in CLAUDE.md
- Add test coverage for new constant

Addresses review feedback from PR #628

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* build assets

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2026-01-09 23:13:31 -05:00
committed by GitHub
parent 817c4348b1
commit 601596f5cb
67 changed files with 1621 additions and 2665 deletions
+50 -25
View File
@@ -3,36 +3,61 @@
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
### Jan 5, 2026
### Dec 10, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #37989 | 8:39 PM | 🔵 | Worker Service CLI Commands | ~370 |
| #37988 | " | 🔵 | Worker Service Hook Command Integration | ~356 |
| #37943 | 8:09 PM | 🔵 | Worker service provides hook command interface | ~372 |
| #37936 | 8:08 PM | 🔵 | Worker service module located in budapest architecture | ~173 |
| #37837 | 6:55 PM | 🔵 | Worker Service CLI Structure and Extension Pattern | ~536 |
| #37836 | 6:54 PM | 🔵 | Worker Service HTTP API Architecture and Hook Integration Pattern | ~639 |
| #37830 | 6:50 PM | ⚖️ | Architectural Refactoring Plan: Unified CLI Hook System | ~631 |
| #37812 | 6:43 PM | 🔵 | WorkerService Architecture and CLI Entry Points | ~447 |
| #37738 | 6:17 PM | 🔵 | ActiveSession and PendingMessage Structures Analyzed for Phase 3 | ~327 |
| #37701 | 6:01 PM | 🔵 | Complete cwd data flow traced from hooks through observation processing | ~447 |
| #37691 | 5:55 PM | 🔵 | ActiveSession interface contains project name but no project root path | ~346 |
| #37418 | 1:04 AM | 🔴 | Fixed CLAUDE.md duplicate content by filtering to direct children only | ~469 |
| #37391 | 12:48 AM | ✅ | Staged 23 CLAUDE.md files with mix of new and modified content | ~400 |
| #37390 | 12:47 AM | ✅ | Regenerated 23 CLAUDE.md files in budapest workspace | ~365 |
| #23832 | 11:15 PM | 🔵 | Current worker-service.ts Lacks Admin Endpoints | ~393 |
### Jan 7, 2026
### Dec 14, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #38467 | 10:29 PM | ⚖️ | Log Level Audit Strategy: Tighten ERROR Messages for Runtime Issue Discovery | ~464 |
| #38446 | 10:26 PM | 🔵 | Worker Service Logs Startup Recovery Failures at WARN Level | ~419 |
| #38444 | 10:25 PM | 🔵 | Worker service auto-recovery error handling pattern | ~393 |
| #38431 | 10:24 PM | 🔵 | ERROR-Level Logging Used Across 21 Source Files | ~480 |
| #38404 | 10:06 PM | ⚖️ | Log Level Audit Analysis - WARN to ERROR Promotion Criteria Established | ~769 |
| #38354 | 9:10 PM | 🔵 | Provider Selection Architecture and Default Settings Location | ~478 |
| #38352 | 9:09 PM | 🔵 | Worker Service Environment Inheritance and Process Spawning Mechanisms | ~469 |
| #38269 | 7:53 PM | 🔵 | Worker Types Shared Type Definitions | ~847 |
| #38256 | 7:49 PM | 🔵 | Worker Service Orchestration Architecture | ~1166 |
| #26740 | 11:26 PM | 🔵 | Worker Service Refactored to Orchestrator with Background Initialization | ~421 |
| #26739 | 11:25 PM | 🔵 | Worker Service Architecture Uses Domain Services and Background Initialization | ~438 |
| #26255 | 8:31 PM | 🔵 | Context Generator Timeline Rendering Logic Details File Grouping Implementation | ~397 |
| #26251 | 8:30 PM | 🔵 | Worker Service Orchestrates Domain Services and Route Handlers | ~292 |
| #26246 | 8:29 PM | 🔵 | Context Generator Implements Rich Date-Grouped Timeline Format | ~468 |
### Dec 17, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #28548 | 4:49 PM | 🔵 | Worker service cleanup method uses Unix-specific process management | ~323 |
| #28446 | 4:23 PM | 🔵 | Worker Service Refactored to Orchestrator Pattern | ~529 |
### Dec 18, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #29340 | 3:11 PM | ✅ | Constructor Initialization Comment Updated | ~267 |
| #29339 | " | ✅ | Class Member Comment Updated in WorkerService | ~267 |
| #29338 | " | ✅ | Service Import Comment Updated | ~222 |
| #29337 | 3:10 PM | ✅ | Terminology Update in Worker Service Documentation | ~268 |
| #29239 | 12:11 AM | 🔵 | Worker Service Refactored as Domain-Driven Orchestrator | ~477 |
### Dec 20, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #30808 | 6:05 PM | 🔴 | Fixed worker readiness check to fail on initialization errors | ~315 |
| #30800 | 6:03 PM | 🔵 | Dual Error Logging in Background Initialization | ~367 |
| #30799 | " | 🔵 | Background Initialization Invocation Pattern | ~365 |
| #30797 | " | 🔵 | Background Initialization Sequence and Error Handler Confirmed | ~450 |
| #30795 | 6:02 PM | 🔵 | Readiness Endpoint Returns 503 During Initialization | ~397 |
| #30793 | " | 🔵 | Dual Initialization State Tracking Pattern | ~388 |
| #30791 | " | 🔵 | Worker Service Constructor Defers SearchRoutes Initialization | ~387 |
| #30790 | " | 🔵 | Initialization Promise Resolver Pattern Located | ~321 |
| #30788 | " | 🔵 | Worker Service Initialization Resolves Promise Despite Errors | ~388 |
### Jan 1, 2026
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #35654 | 11:29 PM | ✅ | Added APPROVED OVERRIDE annotation for instruction loading HTTP route error handler | ~339 |
| #35651 | 11:28 PM | ✅ | Added APPROVED OVERRIDE annotation for shutdown error handler with process.exit | ~354 |
| #35649 | " | ✅ | Added APPROVED OVERRIDE annotation for readiness check retry loop error handling | ~374 |
| #35647 | " | ✅ | Added APPROVED OVERRIDE annotation for port availability probe error handling | ~327 |
| #35646 | " | ✅ | Added APPROVED OVERRIDE annotation for Cursor context file update error handling | ~342 |
| #35643 | 11:27 PM | ✅ | Added APPROVED OVERRIDE annotation for PID file cleanup error handling | ~320 |
</claude-mem-context>
+6 -1
View File
@@ -3,5 +3,10 @@
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
*No recent activity*
### Jan 4, 2026
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #36864 | 1:52 AM | 🔵 | ProcessManager Module Imports Reviewed | ~245 |
| #36860 | 1:50 AM | 🔵 | ProcessManager Source Code Reviewed for WMIC Implementation | ~608 |
</claude-mem-context>
+27 -22
View File
@@ -14,6 +14,7 @@ import { existsSync, writeFileSync, readFileSync, unlinkSync, mkdirSync } from '
import { exec, execSync, spawn } from 'child_process';
import { promisify } from 'util';
import { logger } from '../../utils/logger.js';
import { HOOK_TIMEOUTS } from '../../shared/hook-constants.js';
const execAsync = promisify(exec);
@@ -88,16 +89,16 @@ export async function getChildProcesses(parentPid: number): Promise<number[]> {
}
try {
const cmd = `wmic process where "parentprocessid=${parentPid}" get processid /format:list`;
const { stdout } = await execAsync(cmd, { timeout: 60000 });
// PowerShell Get-Process instead of WMIC (deprecated in Windows 11)
const cmd = `powershell -NoProfile -NonInteractive -Command "Get-Process | Where-Object { \\$_.ParentProcessId -eq ${parentPid} } | Select-Object -ExpandProperty Id"`;
const { stdout } = await execAsync(cmd, { timeout: HOOK_TIMEOUTS.POWERSHELL_COMMAND });
// PowerShell outputs just numbers (one per line), simpler than WMIC's "ProcessId=1234" format
return stdout
.trim()
.split('\n')
.map(line => {
const match = line.match(/ProcessId=(\d+)/i);
return match ? parseInt(match[1], 10) : NaN;
})
.filter(n => !isNaN(n) && Number.isInteger(n) && n > 0);
.map(line => line.trim())
.filter(line => line.length > 0 && /^\d+$/.test(line))
.map(line => parseInt(line, 10))
.filter(pid => pid > 0);
} catch (error) {
// Shutdown cleanup - failure is non-critical, continue without child process cleanup
logger.error('SYSTEM', 'Failed to enumerate child processes', { parentPid }, error as Error);
@@ -120,7 +121,7 @@ export async function forceKillProcess(pid: number): Promise<void> {
try {
if (process.platform === 'win32') {
// /T kills entire process tree, /F forces termination
await execAsync(`taskkill /PID ${pid} /T /F`, { timeout: 60000 });
await execAsync(`taskkill /PID ${pid} /T /F`, { timeout: HOOK_TIMEOUTS.POWERSHELL_COMMAND });
} else {
process.kill(pid, 'SIGKILL');
}
@@ -170,24 +171,26 @@ export async function cleanupOrphanedProcesses(): Promise<void> {
try {
if (isWindows) {
// Windows: Use WMIC to find chroma-mcp processes (avoids PowerShell $_ issues in Git Bash/WSL)
const cmd = `wmic process where "name like '%python%' and commandline like '%chroma-mcp%'" get processid /format:list`;
const { stdout } = await execAsync(cmd, { timeout: 60000 });
// Windows: Use PowerShell Get-CimInstance instead of WMIC (deprecated in Windows 11)
const cmd = `powershell -NoProfile -NonInteractive -Command "Get-CimInstance Win32_Process | Where-Object { \\$_.Name -like '*python*' -and \\$_.CommandLine -like '*chroma-mcp*' } | Select-Object -ExpandProperty ProcessId"`;
const { stdout } = await execAsync(cmd, { timeout: HOOK_TIMEOUTS.POWERSHELL_COMMAND });
if (!stdout.trim()) {
logger.debug('SYSTEM', 'No orphaned chroma-mcp processes found (Windows)');
return;
}
const lines = stdout.trim().split('\n');
// PowerShell outputs just numbers (one per line), simpler than WMIC's "ProcessId=1234" format
const lines = stdout
.split('\n')
.map(line => line.trim())
.filter(line => line.length > 0 && /^\d+$/.test(line));
for (const line of lines) {
const match = line.match(/ProcessId=(\d+)/i);
if (match) {
const pid = parseInt(match[1], 10);
// SECURITY: Validate PID is positive integer before adding to list
if (!isNaN(pid) && Number.isInteger(pid) && pid > 0) {
pids.push(pid);
}
const pid = parseInt(line, 10);
// SECURITY: Validate PID is positive integer before adding to list
if (!isNaN(pid) && Number.isInteger(pid) && pid > 0) {
pids.push(pid);
}
}
} else {
@@ -236,7 +239,7 @@ export async function cleanupOrphanedProcesses(): Promise<void> {
continue;
}
try {
execSync(`taskkill /PID ${pid} /T /F`, { timeout: 60000, stdio: 'ignore' });
execSync(`taskkill /PID ${pid} /T /F`, { timeout: HOOK_TIMEOUTS.POWERSHELL_COMMAND, stdio: 'ignore' });
} catch (error) {
// [ANTI-PATTERN IGNORED]: Cleanup loop - process may have exited, continue to next PID
logger.debug('SYSTEM', 'Failed to kill process, may have already exited', { pid }, error as Error);
@@ -306,7 +309,9 @@ export function createSignalHandler(
} catch (error) {
// Top-level signal handler - log any shutdown error and exit
logger.error('SYSTEM', 'Error during shutdown', {}, error as Error);
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// Even on shutdown errors, exit cleanly to prevent tab accumulation
process.exit(0);
}
};
}
@@ -171,6 +171,28 @@ export function findMcpServerPath(): string | null {
return null;
}
/**
* Find worker-service.cjs path for unified CLI
* Searches in order: marketplace install, source repo
*/
export function findWorkerServicePath(): string | null {
const possiblePaths = [
// Marketplace install location
path.join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack', 'plugin', 'scripts', 'worker-service.cjs'),
// Development/source location (relative to built worker-service.cjs in plugin/scripts/)
path.join(path.dirname(__filename), 'worker-service.cjs'),
// Alternative dev location
path.join(process.cwd(), 'plugin', 'scripts', 'worker-service.cjs'),
];
for (const p of possiblePaths) {
if (existsSync(p)) {
return p;
}
}
return null;
}
/**
* Get the target directory for Cursor hooks based on install target
*/
@@ -261,13 +283,11 @@ export function configureCursorMcp(target: CursorInstallTarget): number {
// ============================================================================
/**
* Install Cursor hooks
* Install Cursor hooks using unified CLI
* No longer copies shell scripts - uses node CLI directly
*/
export async function installCursorHooks(sourceDir: string, target: CursorInstallTarget): Promise<number> {
const platform = detectPlatform();
const scriptExt = getScriptExtension();
console.log(`\nInstalling Claude-Mem Cursor hooks (${target} level, ${platform})...\n`);
export async function installCursorHooks(_sourceDir: string, target: CursorInstallTarget): Promise<number> {
console.log(`\nInstalling Claude-Mem Cursor hooks (${target} level)...\n`);
const targetDir = getTargetDir(target);
if (!targetDir) {
@@ -275,52 +295,30 @@ export async function installCursorHooks(sourceDir: string, target: CursorInstal
return 1;
}
const hooksDir = path.join(targetDir, 'hooks');
// Find the worker-service.cjs path
const workerServicePath = findWorkerServicePath();
if (!workerServicePath) {
console.error('Could not find worker-service.cjs');
console.error(' Expected at: ~/.claude/plugins/marketplaces/thedotmack/plugin/scripts/worker-service.cjs');
return 1;
}
const workspaceRoot = process.cwd();
try {
// Create directories
mkdirSync(hooksDir, { recursive: true });
// Create target directory
mkdirSync(targetDir, { recursive: true });
// Determine which scripts to copy based on platform
const commonScript = platform === 'windows' ? 'common.ps1' : 'common.sh';
const hookScripts = [
`session-init${scriptExt}`,
`context-inject${scriptExt}`,
`save-observation${scriptExt}`,
`save-file-edit${scriptExt}`,
`session-summary${scriptExt}`
];
const scripts = [commonScript, ...hookScripts];
for (const script of scripts) {
const srcPath = path.join(sourceDir, script);
const dstPath = path.join(hooksDir, script);
if (existsSync(srcPath)) {
const content = readFileSync(srcPath, 'utf-8');
// Unix scripts need execute permission; Windows PowerShell doesn't need it
const mode = platform === 'windows' ? undefined : 0o755;
writeFileSync(dstPath, content, mode ? { mode } : undefined);
console.log(` Copied ${script}`);
} else {
console.warn(` ${script} not found in source`);
}
}
// Generate hooks.json with correct paths and platform-appropriate commands
// Generate hooks.json with unified CLI commands
const hooksJsonPath = path.join(targetDir, 'hooks.json');
const hookPrefix = target === 'project' ? './.cursor/hooks/' : `${hooksDir}/`;
// For PowerShell, we need to invoke via powershell.exe
const makeHookCommand = (scriptName: string) => {
const scriptPath = `${hookPrefix}${scriptName}${scriptExt}`;
if (platform === 'windows') {
// PowerShell execution: use -ExecutionPolicy Bypass to ensure scripts run
return `powershell.exe -ExecutionPolicy Bypass -File "${scriptPath}"`;
}
return scriptPath;
// Use the absolute path to worker-service.cjs
// Escape backslashes for JSON on Windows
const escapedWorkerPath = workerServicePath.replace(/\\/g, '\\\\');
// Helper to create hook command using unified CLI
const makeHookCommand = (command: string) => {
return `node "${escapedWorkerPath}" hook cursor ${command}`;
};
const hooksJson: CursorHooksJson = {
@@ -328,25 +326,26 @@ export async function installCursorHooks(sourceDir: string, target: CursorInstal
hooks: {
beforeSubmitPrompt: [
{ command: makeHookCommand('session-init') },
{ command: makeHookCommand('context-inject') }
{ command: makeHookCommand('context') }
],
afterMCPExecution: [
{ command: makeHookCommand('save-observation') }
{ command: makeHookCommand('observation') }
],
afterShellExecution: [
{ command: makeHookCommand('save-observation') }
{ command: makeHookCommand('observation') }
],
afterFileEdit: [
{ command: makeHookCommand('save-file-edit') }
{ command: makeHookCommand('file-edit') }
],
stop: [
{ command: makeHookCommand('session-summary') }
{ command: makeHookCommand('summarize') }
]
}
};
writeFileSync(hooksJsonPath, JSON.stringify(hooksJson, null, 2));
console.log(` Created hooks.json (${platform} mode)`);
console.log(` Created hooks.json (unified CLI mode)`);
console.log(` Worker service: ${workerServicePath}`);
// For project-level: create initial context file
if (target === 'project') {
@@ -357,7 +356,7 @@ export async function installCursorHooks(sourceDir: string, target: CursorInstal
Installation complete!
Hooks installed to: ${targetDir}/hooks.json
Scripts installed to: ${hooksDir}
Using unified CLI: node worker-service.cjs hook cursor <command>
Next steps:
1. Start claude-mem worker: claude-mem start
@@ -453,7 +452,7 @@ export function uninstallCursorHooks(target: CursorInstallTarget): number {
const hooksDir = path.join(targetDir, 'hooks');
const hooksJsonPath = path.join(targetDir, 'hooks.json');
// Remove hook scripts for both platforms (in case user switches platforms)
// Remove legacy shell scripts if they exist (from old installations)
const bashScripts = ['common.sh', 'session-init.sh', 'context-inject.sh',
'save-observation.sh', 'save-file-edit.sh', 'session-summary.sh'];
const psScripts = ['common.ps1', 'session-init.ps1', 'context-inject.ps1',
@@ -465,7 +464,7 @@ export function uninstallCursorHooks(target: CursorInstallTarget): number {
const scriptPath = path.join(hooksDir, script);
if (existsSync(scriptPath)) {
unlinkSync(scriptPath);
console.log(` Removed ${script}`);
console.log(` Removed legacy script: ${script}`);
}
}
@@ -527,32 +526,36 @@ export function checkCursorHooksStatus(): number {
console.log(`${loc.name}: Installed`);
console.log(` Config: ${hooksJson}`);
// Detect which platform's scripts are installed
const bashScripts = ['session-init.sh', 'context-inject.sh', 'save-observation.sh'];
const psScripts = ['session-init.ps1', 'context-inject.ps1', 'save-observation.ps1'];
// Check if using unified CLI mode or legacy shell scripts
try {
const hooksContent = JSON.parse(readFileSync(hooksJson, 'utf-8'));
const firstCommand = hooksContent?.hooks?.beforeSubmitPrompt?.[0]?.command || '';
const hasBash = bashScripts.some(s => existsSync(path.join(hooksDir, s)));
const hasPs = psScripts.some(s => existsSync(path.join(hooksDir, s)));
if (firstCommand.includes('worker-service.cjs') && firstCommand.includes('hook cursor')) {
console.log(` Mode: Unified CLI (node worker-service.cjs)`);
} else {
// Detect legacy shell scripts
const bashScripts = ['session-init.sh', 'context-inject.sh', 'save-observation.sh'];
const psScripts = ['session-init.ps1', 'context-inject.ps1', 'save-observation.ps1'];
if (hasBash && hasPs) {
console.log(` Platform: Both (bash + PowerShell)`);
} else if (hasBash) {
console.log(` Platform: Unix (bash)`);
} else if (hasPs) {
console.log(` Platform: Windows (PowerShell)`);
} else {
console.log(` No hook scripts found`);
}
const hasBash = bashScripts.some(s => existsSync(path.join(hooksDir, s)));
const hasPs = psScripts.some(s => existsSync(path.join(hooksDir, s)));
// Check for appropriate scripts based on current platform
const platform = detectPlatform();
const scripts = platform === 'windows' ? psScripts : bashScripts;
const missing = scripts.filter(s => !existsSync(path.join(hooksDir, s)));
if (missing.length > 0) {
console.log(` Missing ${platform} scripts: ${missing.join(', ')}`);
} else {
console.log(` Scripts: All present for ${platform}`);
if (hasBash || hasPs) {
console.log(` Mode: Legacy shell scripts (consider reinstalling for unified CLI)`);
if (hasBash && hasPs) {
console.log(` Platform: Both (bash + PowerShell)`);
} else if (hasBash) {
console.log(` Platform: Unix (bash)`);
} else if (hasPs) {
console.log(` Platform: Windows (PowerShell)`);
}
} else {
console.log(` Mode: Unknown configuration`);
}
}
} catch {
console.log(` Mode: Unable to parse hooks.json`);
}
// Check for context file (project only)
+38 -8
View File
@@ -636,7 +636,9 @@ async function main() {
const freed = await waitForPortFree(port, getPlatformTimeout(15000));
if (!freed) {
logger.error('SYSTEM', 'Port did not free up after shutdown for version mismatch restart', { port });
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
removePidFile();
} else {
@@ -654,14 +656,18 @@ async function main() {
process.exit(0);
}
logger.error('SYSTEM', 'Port in use but worker not responding to health checks');
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
logger.info('SYSTEM', 'Starting worker daemon');
const pid = spawnDaemon(__filename, port);
if (pid === undefined) {
logger.error('SYSTEM', 'Failed to spawn worker daemon');
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
writePidFile({ pid, port, startedAt: new Date().toISOString() });
@@ -670,7 +676,9 @@ async function main() {
if (!healthy) {
removePidFile();
logger.error('SYSTEM', 'Worker failed to start (health check timeout)');
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
logger.info('SYSTEM', 'Worker started successfully');
@@ -694,14 +702,18 @@ async function main() {
const freed = await waitForPortFree(port, getPlatformTimeout(15000));
if (!freed) {
logger.error('SYSTEM', 'Port did not free up after shutdown, aborting restart', { port });
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
removePidFile();
const pid = spawnDaemon(__filename, port);
if (pid === undefined) {
logger.error('SYSTEM', 'Failed to spawn worker daemon during restart');
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
writePidFile({ pid, port, startedAt: new Date().toISOString() });
@@ -710,7 +722,9 @@ async function main() {
if (!healthy) {
removePidFile();
logger.error('SYSTEM', 'Worker failed to restart');
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
}
logger.info('SYSTEM', 'Worker restarted successfully');
@@ -737,13 +751,29 @@ async function main() {
process.exit(cursorResult);
}
case 'hook': {
const platform = process.argv[3];
const event = process.argv[4];
if (!platform || !event) {
console.error('Usage: claude-mem hook <platform> <event>');
console.error('Platforms: claude-code, cursor, raw');
console.error('Events: context, session-init, observation, summarize, user-message');
process.exit(1);
}
const { hookCommand } = await import('../cli/hook-command.js');
await hookCommand(platform, event);
break;
}
case '--daemon':
default: {
const worker = new WorkerService();
worker.start().catch((error) => {
logger.failure('SYSTEM', 'Worker failed to start', {}, error as Error);
removePidFile();
process.exit(1);
// Exit gracefully: Windows Terminal won't keep tab open on exit 0
// The wrapper/plugin will handle restart logic if needed
process.exit(0);
});
}
}
+112 -36
View File
@@ -3,47 +3,123 @@
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
### Jan 5, 2026
### Dec 10, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #37751 | 6:21 PM | 🔴 | OpenRouterAgent Fully Updated with projectRoot Threading | ~307 |
| #37748 | " | | OpenRouterAgent Observation Handler Updated with lastCwd | ~276 |
| #37746 | 6:20 PM | | GeminiAgent Summary Handler Updated with lastCwd | ~278 |
| #37745 | " | | OpenRouterAgent Init Prompt Call Updated with undefined projectRoot | ~299 |
| #37744 | " | | GeminiAgent First processAgentResponse Updated with lastCwd | ~274 |
| #37743 | " | | Added lastCwd Tracking to OpenRouterAgent | ~265 |
| #37742 | 6:19 PM | | Phase 3 Started: Added lastCwd Tracking to GeminiAgent | ~291 |
| #37741 | " | 🔵 | OpenRouterAgent Structure Analyzed for Phase 3 Implementation | ~367 |
| #37740 | " | 🔵 | SDKAgent Structure Analyzed for Phase 3 Implementation | ~430 |
| #37739 | 6:18 PM | 🔵 | GeminiAgent Structure Analyzed for Phase 3 Implementation | ~381 |
| #37737 | 6:16 PM | 🔵 | Identified processAgentResponse Callers for Phase 3 | ~275 |
| #37701 | 6:01 PM | 🔵 | Complete cwd data flow traced from hooks through observation processing | ~447 |
| #37421 | 1:06 AM | 🔵 | Identified by-file API endpoint usage across codebase | ~406 |
| #37416 | 1:02 AM | 🔴 | Fixed find_by_file Parameter Handling for Comma-Separated Values | ~375 |
| #37415 | " | 🟣 | SearchManager Parameter Normalization Enhanced for Folder Queries | ~406 |
| #37414 | 1:01 AM | 🔵 | SearchManager findByFile Uses filePath Parameter for File Search | ~429 |
| #37413 | " | 🔵 | Hybrid Search Strategy: Metadata-First with Semantic Ranking | ~475 |
| #37391 | 12:48 AM | ✅ | Staged 23 CLAUDE.md files with mix of new and modified content | ~400 |
| #37390 | 12:47 AM | ✅ | Regenerated 23 CLAUDE.md files in budapest workspace | ~365 |
| #23673 | 8:36 PM | | Add Project Filter Parameter to Session and Prompt Hydration in Search | ~306 |
| #23596 | 5:54 PM | ⚖️ | Import/Export Bug Fix Priority and Scope | ~415 |
| #23595 | 5:53 PM | 🔴 | SearchManager Returns Wrong Format for Empty Results | ~320 |
| #23594 | " | 🔵 | SearchManager Search Method Control Flow | ~313 |
| #23591 | 5:51 PM | 🔵 | SearchManager JSON Response Structure | ~231 |
| #23590 | " | 🔵 | Import/Export Feature Status Review | ~490 |
| #23583 | 5:50 PM | 🔵 | SearchManager Hybrid Search Architecture | ~495 |
### Jan 7, 2026
### Dec 13, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #38467 | 10:29 PM | ⚖️ | Log Level Audit Strategy: Tighten ERROR Messages for Runtime Issue Discovery | ~464 |
| #38437 | 10:24 PM | 🔵 | Claude-mem core functionality and logging patterns identified | ~710 |
| #38433 | " | 🔵 | SessionManager Uses ERROR Logging for Database Persistence Failures | ~503 |
| #38431 | " | 🔵 | ERROR-Level Logging Used Across 21 Source Files | ~480 |
| #38425 | " | ⚖️ | Log Level Architecture: Fail-Critical Over Fail-Fast for Chroma | ~467 |
| #38418 | 10:22 PM | 🔵 | ChromaDB Operates as Optional Subsystem with Graceful Degradation | ~586 |
| #38416 | " | 🔵 | ChromaDB Is Critical Not Optional - Log Audit Findings Challenged | ~405 |
| #38405 | 10:07 PM | ⚖️ | DEBUG Log Level Analysis - One Message Requires WARN Promotion | ~819 |
| #38404 | 10:06 PM | ⚖️ | Log Level Audit Analysis - WARN to ERROR Promotion Criteria Established | ~769 |
| #38372 | 9:43 PM | 🔵 | Logging Anti-Pattern Found: Critical Errors Logged as DEBUG Instead of ERROR | ~464 |
| #38354 | 9:10 PM | 🔵 | Provider Selection Architecture and Default Settings Location | ~478 |
| #38353 | " | 🔵 | Session ID Architecture and Message Yielding for SDK Interaction | ~536 |
| #38253 | 7:47 PM | 🔵 | SDK Agent Implementation with Resume Logic | ~1036 |
| #38250 | 7:46 PM | 🔵 | Session Manager Event-Driven Architecture | ~865 |
| #38248 | 7:45 PM | 🔵 | OpenRouter Agent Implementation | ~851 |
| #25191 | 8:04 PM | 🔵 | ChromaSync Instantiated in DatabaseManager Constructor | ~315 |
### Dec 14, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #26263 | 8:32 PM | 🔵 | SearchManager Timeline Methods Use Rich Formatting, Search Method Uses Flat Tables | ~464 |
| #26243 | 8:29 PM | 🔵 | FormattingService Provides Basic Table Format Without Dates or File Grouping | ~390 |
| #26240 | " | 🔵 | SearchManager Formats Results as Tables, Timeline Uses Rich Date-Grouped Format | ~416 |
| #26108 | 7:43 PM | | changes() Method Format Logic Removed | ~401 |
| #26107 | " | | changes() Method Format Parameter Removed | ~317 |
| #26106 | 7:42 PM | | decisions() Method Format Logic Removed | ~405 |
| #26105 | " | | decisions() Method Format Parameter Removed | ~310 |
| #26104 | " | | Main search() Method Format Handling Removed | ~430 |
| #26103 | 7:41 PM | | FormattingService.ts Rewritten to Table Format | ~457 |
| #26102 | " | 🔵 | SearchManager.ts Format Parameter Removal Status | ~478 |
### Dec 15, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #27043 | 6:04 PM | 🔵 | Subagent confirms no version switcher UI exists, only orphaned backend infrastructure | ~539 |
| #27041 | 6:03 PM | 🔵 | Branch switching code isolated to two backend files, no frontend UI components | ~473 |
| #27037 | 6:02 PM | 🔵 | Branch switching functionality exists in SettingsRoutes with UI switcher removal intent | ~463 |
### Dec 16, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #27727 | 5:45 PM | 🔵 | SearchManager returns raw data arrays when format=json is specified | ~349 |
### Dec 17, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #28473 | 4:25 PM | 🔵 | PaginationHelper LIMIT+1 Trick and Project Path Sanitization | ~499 |
| #28458 | 4:24 PM | 🔵 | SDK Agent Observer-Only Event-Driven Query Loop | ~513 |
| #28455 | " | 🔵 | Event-Driven Session Manager with Zero-Latency Queuing | ~566 |
### Dec 18, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #29240 | 12:12 AM | 🔵 | SDK Agent Event-Driven Query Loop with Tool Restrictions | ~507 |
### Dec 20, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #31100 | 8:01 PM | 🔵 | Summary and Memory Message Generation in SDK Agent | ~324 |
### Dec 25, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #32616 | 8:43 PM | 🔵 | Comprehensive analysis of "enable billing" setting and its impact on rate limiting | ~533 |
| #32599 | 8:40 PM | 🔄 | Added validation and explicit default for Gemini model configuration | ~393 |
| #32598 | " | 🔵 | Gemini configuration loaded from settings or environment variables | ~363 |
| #32591 | 8:38 PM | 🔴 | Removed Unsupported Gemini Model from Agent | ~282 |
| #32583 | " | 🔵 | Gemini Agent Implementation Details | ~434 |
| #32543 | 7:29 PM | 🔄 | Rate limiting applied conditionally based on billing status | ~164 |
| #32542 | " | 🔄 | Query Gemini now accepts billing status | ~163 |
| #32541 | " | 🔄 | Gemini config now includes billing status | ~182 |
| #32540 | " | 🔄 | Rate limiting logic refactored for Gemini billing | ~164 |
### Dec 26, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #32949 | 10:55 PM | 🔵 | Complete settings persistence flow for Xiaomi MIMO v2 Flash model | ~320 |
| #32948 | 10:53 PM | 🔵 | OpenRouterAgent uses CLAUDE_MEM_OPENROUTER_MODEL setting with Xiaomi as default | ~183 |
### Dec 27, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #33215 | 9:06 PM | 🔵 | SessionManager Implements Event-Driven Lifecycle with Database-First Persistence and Auto-Initialization | ~853 |
| #33214 | " | 🔵 | SDKAgent Implements Event-Driven Query Loop with Init/Continuation Prompt Selection | ~769 |
### Dec 28, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #33551 | 11:00 PM | 🔵 | GeminiAgent Does Not Implement Resume Functionality | ~307 |
| #33550 | " | 🔵 | OpenRouterAgent Does Not Implement Resume Functionality | ~294 |
| #33549 | 10:59 PM | 🔴 | SDKAgent Now Checks memorySessionId Differs From contentSessionId Before Resume | ~419 |
| #33547 | " | 🔵 | All Agents Call storeObservation with contentSessionId Instead of memorySessionId | ~407 |
| #33543 | 10:56 PM | 🔵 | SDKAgent Already Implements Memory Session ID Capture and Resume Logic | ~467 |
| #33542 | " | 🔵 | SessionManager Already Uses Renamed Session ID Fields | ~390 |
### Dec 30, 2025
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #34504 | 2:31 PM | 🔵 | SDKAgent V2 Message Handling and Processing Flow Detailed | ~583 |
| #34459 | 2:23 PM | 🔵 | Complete SDKAgent V2 Architecture with Comprehensive Message Processing | ~619 |
| #34453 | 2:21 PM | 🔵 | Memory Agent Configured as Observer-Only | ~379 |
### Jan 4, 2026
| ID | Time | T | Title | Read |
|----|------|---|-------|------|
| #36853 | 1:49 AM | 🔵 | GeminiAgent Implementation Reviewed for Model Support | ~555 |
</claude-mem-context>