1714 Commits

Author SHA1 Message Date
Alex Newman 1d7500604f chore: bump version to 12.1.2
Publish to npm / publish (push) Has been cancelled
v12.1.2
2026-04-15 01:00:38 -07:00
Ben Younes 05232ff091 fix: reap stuck generators in reapStaleSessions (fixes #1652) (#1698)
* fix: reap stuck generators in reapStaleSessions (fixes #1652)

Sessions whose SDK subprocess hung would stay in the active sessions
map forever because `reapStaleSessions()` unconditionally skipped any
session with a non-null `generatorPromise`.  The generator was blocked
on `for await (const msg of queryResult)` inside SDKAgent and could
never unblock itself — the idle-timeout only fires when the generator
is in `waitForMessage()`, and the orphan reaper skips processes whose
session is still in the map.

Add `MAX_GENERATOR_IDLE_MS` (5 min).  When `reapStaleSessions()` sees
a session whose `generatorPromise` is set but `lastGeneratorActivity`
has not advanced in over 5 minutes, it now:
1. SIGKILLs the tracked subprocess to unblock the stuck `for await`
2. Calls `session.abortController.abort()` so the generator loop exits
3. Calls `deleteSession()` which waits up to 30 s for the generator to
   finish, then cleans up supervisor-tracked children

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

* fix: freeze time in stale-generator test and import constants from production source

- Export MAX_GENERATOR_IDLE_MS, MAX_SESSION_IDLE_MS, StaleGeneratorCandidate,
  StaleGeneratorProcess, and detectStaleGenerator from SessionManager.ts so
  tests no longer duplicate production constants or detection logic.
- Use setSystemTime() from bun:test to freeze Date.now() in the
  "exactly at threshold" test, eliminating the flaky double-Date.now() race.

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

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 00:58:35 -07:00
Ben Younes b411d91885 fix: add circuit breaker to OpenClaw worker client (#1636) (#1697)
* fix: add circuit breaker to OpenClaw worker client (#1636)

When the claude-mem worker is unreachable, every plugin event (before_agent_start,
before_prompt_build, tool_result_persist, agent_end) triggered a new fetch that
failed and logged a warning, causing CPU-spinning and continuous log spam.

Add a CLOSED/OPEN/HALF_OPEN circuit breaker: after 3 consecutive network errors
the circuit opens, silently drops all worker calls for 30 s, then sends one probe.
Individual failures are only logged while the circuit is still CLOSED; once open
it logs once ("disabling requests for 30s") and goes quiet until recovery.

Generated by Claude Code
Vibe coded by Ousama Ben Younes

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

* fix: limit HALF_OPEN to single probe and move circuitOnSuccess after response.ok check

- Add _halfOpenProbeInFlight flag so only one probe is allowed in HALF_OPEN state;
  concurrent callers are silently dropped until the probe completes (success or failure)
- Move circuitOnSuccess() to after the response.ok check in workerPost, workerPostFireAndForget,
  and workerGetText so non-2xx HTTP responses no longer close the circuit
- Clear _halfOpenProbeInFlight in both circuitOnSuccess and circuitOnFailure, and in circuitReset
- Add regression test covering HALF_OPEN one-probe behavior: non-2xx keeps circuit open,
  2xx closes it

* chore: trigger CodeRabbit re-review

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 00:58:32 -07:00
Ben Younes 4538e686ad fix: resolve Setup hook broken reference and warn on macOS-only binary (#1547) (#1696)
* fix: resolve Setup hook broken reference and warn on macOS-only binary (#1547)

On Linux ARM64, the plugin silently failed because:
1. The Setup hook called setup.sh which was removed; the hook exited 127
   (file not found), causing the plugin to appear uninstalled.
2. The committed plugin/scripts/claude-mem binary is macOS arm64 only;
   no warning was shown when it could not execute on other platforms.

Fix the Setup hook to call smart-install.js (the current setup mechanism)
and add checkBinaryPlatformCompatibility() to smart-install.js, which reads
the Mach-O magic bytes from the bundled binary and warns users on non-macOS
platforms that the JS fallback (bun-runner.js + worker-service.cjs) is active.

Generated by Claude Code
Vibe coded by ousamabenyounes

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

* fix: close fd in finally block, strengthen smart-install tests to use production function

- Wrap openSync/readSync in checkBinaryPlatformCompatibility with a finally block so the file descriptor is always closed even if readSync throws
- Export checkBinaryPlatformCompatibility with an optional binaryPath param for testability
- Refactor Mach-O detection tests to call the production function directly, mocking process.platform and passing controlled binary paths, eliminating duplicated inline logic
- Strengthen plugin-distribution test to assert at least one command hook exists before checking for smart-install.js, preventing vacuous pass

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 00:58:29 -07:00
Ben Younes f97c50bfb9 fix: session lifecycle guards to prevent runaway API spend (#1590) (#1693)
* fix: add session lifecycle guards to prevent runaway API spend (#1590)

Three root causes allowed 30+ subprocess accumulation over 36 hours:
1. SIGTERM-killed processes (code 143) triggered crash recovery and
   immediately respawned — now detected and treated as intentional
   termination (aborts controller so wasAborted=true in .finally).
2. No wall-clock limit: sessions ran for 13+ hours continuously
   spending tokens — now refuses new generators after 4 hours and
   drains the pending queue to prevent further spawning.
3. Duplicate --resume processes for the same session UUID — now
   killed and unregistered before a new spawn is registered.

Generated by Claude Code
Vibe coded by ousamabenyounes

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

* fix: use normalized errorMsg in logger.error payload and annotate SIGTERM override

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

* fix: use persisted createdAt for wall-clock guard and bind abortController locally to prevent stale abort

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

* chore: re-trigger CodeRabbit review after rate limit reset

* fix: defer process unregistration until exit and align boundary test with strict > (#1693)

- ProcessRegistry: don't unregister PID immediately after SIGTERM — let the
  existing 'exit' handler clean up when the process actually exits, preventing
  tracking loss for still-live processes.
- Test: align wall-clock boundary test with production's strict `>` operator
  (exactly 4h is NOT terminated, only >4h is).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 00:58:23 -07:00
Ben Younes 983be42998 fix: resolve Gemini CLI 0.37.0 session capture failures (#1664) (#1692)
Three root causes prevented Gemini sessions from persisting prompts,
observations, and summaries:

1. BeforeAgent was mapped to user-message (display-only) instead of
   session-init (which initialises the session and starts the SDK agent).

2. The transcript parser expected Claude Code JSONL (type: "assistant")
   but Gemini CLI 0.37.0 writes a JSON document with a messages array
   where assistant entries carry type: "gemini". extractLastMessage now
   detects the format and routes to the correct parser, preserving
   full backward compatibility with Claude Code JSONL transcripts.

3. The summarize handler omitted platformSource from the
   /api/sessions/summarize request body, causing sessions to be recorded
   without the gemini-cli source tag.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 00:58:20 -07:00
UCHIDA Masayuki 544e9d39f5 fix: replace hardcoded nvm/homebrew PATH with universal login shell resolution (#1833)
* fix: replace hardcoded nvm/homebrew PATH with universal login shell resolution

Hook commands previously hardcoded PATH entries for nvm and homebrew,
causing `node: command not found` for users with other Node version
managers (mise, asdf, volta, fnm, Nix, etc.).

Replace with `$($SHELL -lc 'echo $PATH')` which inherits the user's
login shell PATH regardless of how Node was installed. Also adds the
missing PATH export to the PreToolUse hook (#1702).

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

* fix: add cache-path fallback to PreToolUse hook

Aligns PreToolUse _R resolution with all other hooks by adding the
cache directory lookup before falling back to the marketplace path.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 00:58:17 -07:00
Ethan 16a0737dfc fix: use parent project name for worktree observation writes (#1820)
* fix: use parent project name for worktree observation writes (#1819)

Observations and sessions from git worktrees were stored under
basename(cwd) instead of the parent repo name because write paths
called getProjectName() (not worktree-aware) instead of
getProjectContext() (worktree-aware). This is the same bug as
#1081, #1317, and #1500 — it regressed because the two functions
coexist and new code reached for the simpler one.

Fix: getProjectContext() now returns parentProjectName as primary
when in a worktree, and all four write-path call sites now use
getProjectContext().primary instead of getProjectName().

Includes regression test that creates a real worktree directory
structure and asserts primary === parentProjectName.

* fix: address review nitpicks — allProjects fallback, JSDoc, write-path test

- ContextBuilder: default projects to context.allProjects for legacy
  worktree-labeled record compatibility
- ProjectContext: clarify JSDoc that primary is canonical (parent repo
  in worktrees)
- Tests: add write-path regression test mirroring session-init/SessionRoutes
  pattern; refactor worktree fixture into beforeAll/afterAll

* refactor(project-name): rename local to cwdProjectName and dedupe allProjects

Addresses final CodeRabbit nitpick: disambiguates the local variable
from the returned `primary` field, and dedupes allProjects via Set
in case parent and cwd resolve to the same name.

---------

Co-authored-by: Ethan Hurst <ethan.hurst@outlook.com.au>
2026-04-15 00:58:14 -07:00
biswanath-cmd 3d92684e04 fix: filter empty string args before Bun spawn() to prevent CLI parsing errors (#1781)
Bun's child_process.spawn() silently drops empty string arguments from
argv, unlike Node which preserves them. When the Agent SDK defaults
settingSources to [] (empty array), [].join(",") produces "" which gets
pushed as ["--setting-sources", ""]. Bun drops the "", causing
--permission-mode to be consumed as the value for --setting-sources:

  Error processing --setting-sources: Invalid setting source: --permission-mode

This caused 100% observation failure (exit code 1 on every SDK subprocess
spawn), resulting in 0 observations stored across all sessions.

The fix filters empty string args before passing to spawn(), making the
behavior consistent between Node and Bun runtimes.

Fixes #1779
Related: #1660

Co-authored-by: bswnth48 <69203760+bswnth48@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 00:58:11 -07:00
enma998 471e1f62f9 Fix npx search and default Codex context to workspace-local AGENTS (#1780)
* Fix npx search query parameter mismatch

* Use workspace-local Codex AGENTS context by default

---------

Co-authored-by: bnb <bnb>
2026-04-15 00:58:08 -07:00
Aviral Arora f44605658d docs: add CLAUDE_MEM_MODE documentation for language and modes (fix #… (#1777)
* docs: add CLAUDE_MEM_MODE documentation for language and modes (fix #1767)

* docs: fix markdown formatting for CLAUDE_MEM_MODE section

* docs: fix markdown code block formatting properly

* docs: fix markdown issues in modes section

* docs: fix markdown spacing and table note formatting

* Update README.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* docs: fix markdown

* docs: fix markdown issues in modes

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-15 00:58:05 -07:00
suyua9 eeb6841033 fix: coerce corpus route filters (#1776)
* fix: coerce corpus route filters

* test: cover unsupported corpus type filters
2026-04-15 00:58:01 -07:00
Tran Quang 2a2008bac2 fix(file-context): preserve targeted reads + invalidate on mtime (#1719) (#1729)
* fix(file-context): preserve targeted reads + invalidate on mtime (#1719)

The PreToolUse:Read hook unconditionally rewrote tool input to
{file_path, limit:1}, which interacted with two failure modes:

1. Subagent edits a file → parent's next Read still gets truncated
   because the observation snapshot predates the change.
2. Claude requests a different section with offset/limit → the hook
   strips them, so the Claude Code harness's read-dedup cache returns
   "File unchanged" against the prior 1-line read. The file becomes
   unreadable for the rest of the conversation, even though the hook's
   own recovery hint says "Read again with offset/limit for the
   section you need."

Two complementary fixes:

- **mtime invalidation**: stat the file (we already stat for the size
  gate) and compare mtimeMs to the newest observation's created_at_epoch.
  If the file is newer, pass the read through unchanged so fresh content
  reaches Claude.

- **Targeted-read pass-through**: when toolInput already specifies
  offset and/or limit, preserve them in updatedInput instead of
  collapsing to {limit:1}. The harness's dedup cache then sees a
  distinct input and lets the read proceed.

The unconstrained-read path (no offset, no limit) is unchanged: still
truncated to 1 line plus the observation timeline, so token economics
are preserved for the common case.

Tests cover all three branches: existing truncation, targeted-read
pass-through (offset+limit, limit-only), and mtime-driven bypass.

Fixes #1719

* refactor(file-context): address review findings on #1719 fix

- Add offset-only test case for full targeted-read branch coverage
- Use >= for mtime comparison to handle same-millisecond edge case
- Add Number.isFinite() + bounds guards on offset/limit pass-through
- Trim over-verbose comments to concise single-line summaries
- Remove redundant `as number` casts after typeof narrowing
- Add comment explaining fileMtimeMs=0 sentinel invariant
2026-04-15 00:57:57 -07:00
Suryansh Rohil d64c252f4d Update: Updated readme for opencode installation (#1765) 2026-04-15 00:57:54 -07:00
Jochen Meyer 59ce0fc553 fix: exclude primary key index from unique constraint check in migration 7 (#1771)
* fix: exclude primary key index from unique constraint check in migration 7

PRAGMA index_list returns all indexes including those backing PRIMARY KEY
columns (origin='pk'), which always have unique=1. The check was therefore
always true, causing migration 7 to run the full DROP/CREATE/RENAME table
sequence on every worker startup instead of short-circuiting once the
UNIQUE constraint had already been removed.

Fix: filter to non-PK indexes by requiring idx.origin !== 'pk'. The
origin field is already present on the existing IndexInfo interface.

Fixes #1749

* fix: apply pk-origin guard to all three migration code paths

CodeRabbit correctly identified that the origin !== 'pk' fix was only
applied to MigrationRunner.ts but not to the two other active code paths
that run the same removeSessionSummariesUniqueConstraint logic:

- SessionStore.ts:220 — used by DatabaseManager and worker-service
- plugin/scripts/context-generator.cjs — bundled artifact (minified)

All three paths now consistently exclude primary-key indexes when
detecting unique constraints on session_summaries.
2026-04-15 00:57:51 -07:00
Jochen Meyer 31ee1024c5 fix: restrict ~/.claude-mem/.env permissions to owner-only (0600) (#1770)
* fix: restrict .env file permissions to owner-only (0600)

API keys stored in ~/.claude-mem/.env were created without explicit
permissions, defaulting to umask-dependent mode. On systems with a
permissive umask (e.g. 0022), the file would be world-readable.

- Set directory permissions to 0700 on creation
- Set file permissions to 0600 via writeFileSync mode option
- Call chmodSync after write to fix permissions on pre-existing files

Signed-off-by: Jochen Meyer

* fix: also restrict pre-existing directory permissions to 0700

The initial fix only set directory mode on creation. Pre-existing
~/.claude-mem/ directories from earlier installs remained world-readable.
Add chmodSync for the directory alongside the existing file chmod,
and document the Windows limitation (ACLs, not POSIX permissions).

---------

Signed-off-by: Jochen Meyer
2026-04-15 00:57:48 -07:00
Alex Newman 7d5d4c5036 docs: update CHANGELOG.md for v12.1.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:16:36 -07:00
Alex Newman 06b997e3d0 chore: bump version to 12.1.1
Publish to npm / publish (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v12.1.1
2026-04-14 19:14:03 -07:00
Alex Newman a390a537c9 fix: broadcast uses summaryForStore to support salvaged summaries (#1718)
syncAndBroadcastSummary was using the raw ParsedSummary (null when salvaged)
instead of summaryForStore for the SSE broadcast, causing a crash when the
LLM returns <observation> without <summary> tags. Also removes misplaced
tree-sitter docs from mem-search/SKILL.md (belongs in smart-explore).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:11:48 -07:00
Alex Newman 2357835942 Merge pull request #1686 from ousamabenyounes/fix/issue-1633
fix: expose summaryStored in session status to detect silent summary loss (#1633)
2026-04-14 18:41:58 -07:00
Alex Newman 77a22d30b2 Merge pull request #1555 from ousamabenyounes/fix/issue-1384-mcp-inputschema
fix: declare inputSchema properties for search and timeline MCP tools (#1384 #1413)
2026-04-14 18:41:54 -07:00
Alex Newman 40a25e0225 Merge pull request #1676 from ousamabenyounes/fix/issue-1625
fix: filter ghost observations with no content fields (#1625)
2026-04-14 18:41:51 -07:00
Alex Newman 4c2ab98d90 Merge pull request #1679 from ousamabenyounes/fix/issue-1297
fix: set cwd to homedir when spawning chroma-mcp to prevent pydantic .env.local crash (#1297)
2026-04-14 18:41:48 -07:00
Alex Newman 7bcfd73985 Merge pull request #1677 from ousamabenyounes/fix/issue-1503
fix: avoid DEP0190 deprecation on Windows by using single-string spawnSync for where bun (#1503)
2026-04-14 18:41:34 -07:00
Alex Newman 7dd321f869 Merge pull request #1678 from ousamabenyounes/fix/issue-1342
fix: add .gitattributes to enforce LF endings on plugin scripts (#1342)
2026-04-14 18:41:31 -07:00
Alex Newman 153ddb814b Merge pull request #1670 from ousamabenyounes/fix/issue-1651
docs: add Language Support section to smart-explore/SKILL.md (#1651)
2026-04-14 18:41:28 -07:00
Alex Newman 216d17879d Merge pull request #1680 from ousamabenyounes/fix/issue-1447
fix: suppress false ERROR when duplicate daemon loses port bind race (#1447)
2026-04-14 18:41:25 -07:00
Alex Newman fa73dd483c Merge pull request #1666 from ousamabenyounes/fix/issue-1299
fix: remove leaky mock.module() for project-name that polluted parallel workers (#1299)
2026-04-14 18:41:22 -07:00
Alex Newman 9dd0ae10a3 Merge pull request #1658 from octo-patch/fix/issue-1648-mcp-server-use-bun-command
fix: use bun to run mcp-server.cjs instead of node shebang
2026-04-14 18:41:17 -07:00
Alex Newman 9a91a1be2b Merge pull request #1701 from ck0park/fix/list-corpora-mcp-result-shape
fix: list_corpora MCP tool — wrap response in CallToolResult shape (fixes #1700)
2026-04-14 18:41:13 -07:00
Alex Newman a5b2c26592 Merge pull request #1718 from aaronwong1989/fix/1312-summary-salvage-from-observations
fix(ResponseProcessor): salvage synthetic summary when AI returns <observation> instead of <summary> (Issue #1312)
2026-04-14 18:41:10 -07:00
Alex Newman fc9331fc39 Merge pull request #1724 from kbroughton/fix/upgrade-glob-v11-to-v13
fix(deps): upgrade glob ^11.0.3 → ^13.0.0 (fixes #1717)
2026-04-14 18:41:07 -07:00
Alex Newman ff17609a81 Merge pull request #1725 from joao-oliveira-softtor/fix/sessionstart-hook-worker-race-soft-fail
fix(hooks): soft-fail SessionStart health check on cold start
2026-04-14 18:41:04 -07:00
joaovictorolvr fe8737420d fix(hooks): soft-fail SessionStart health check on cold start
The three SessionStart hooks poll http://localhost:37777/health with an
8-second retry budget and then exit 1 silently (via `curl -sf || exit 1`)
when the worker has not stabilized in time. Claude Code surfaces this as
two `SessionStart:startup hook error - Failed with non-blocking status
code: No stderr output` messages on every first session of the day.

This happens because of a race between the MCP server auto-starting the
worker and the hook's own `worker-service.cjs start` path, which on Linux
respects a live PID file written by an earlier session and waits for the
existing worker to become healthy. 8s is not always enough.

Mitigate in the hook layer without touching worker-service.cjs:

- bump the inner retry loop from 8 to 20 attempts (up to ~20s)
- replace `|| exit 1` with `|| true` so the hook emits its continue JSON
  regardless (Claude Code no longer logs a phantom error)
- guard the context-injection hook with a health check - only run
  `worker-service.cjs hook claude-code context` if the worker is actually
  responding, otherwise skip silently

Trade-off: on cold starts where the worker takes longer than ~20s to
come up, the recent-context preamble is skipped for that first session
instead of surfacing an error. Subsequent sessions in the same day work
normally because the worker is already healthy.

Refs #1447
2026-04-11 16:20:03 -03:00
kbroughton 8275b3da3b fix(deps): upgrade glob from ^11.0.3 to ^13.0.0 (fixes #1717)
glob@11.x is deprecated by its maintainer and flagged as containing
widely-publicised security vulnerabilities (including ReDoS risks).
The latest stable version is glob@13.0.6.

Compatibility verified: the codebase uses only `globSync` with
`{ nodir, absolute }` options in two files:
- src/services/transcripts/watcher.ts
- scripts/analyze-transformations-smart.js

The `globSync` function signature and these options are identical
in glob@13. No call-site changes are required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 11:00:37 -05:00
Sisyphus 🏔️ b7c23ca232 fix(ResponseProcessor): salvage synthetic summary when AI returns <observation> instead of <summary>
Fixes Issue #1312: AI sometimes returns <observation> XML tags instead of
<summary> tags during the summarize phase, despite clear instructions in
buildSummaryPrompt() requiring <summary> ONLY output.

When this occurs, parseSummary() returns null and the entire session summary
is lost. This fix detects the condition (summary missing + observations
present) and synthesizes a summary from the observation data, ensuring
session summaries are not completely lost.

The salvage mapping:
- request: observation title
- investigated: observation narrative or facts
- learned: observation facts joined
- completed: title if type is feature/bugfix
- notes: indicates this is a synthetic salvage summary

Observations are stored normally regardless of this fallback.

Co-authored-by: Sisyphus <sisyphus@openclaw>
2026-04-11 20:29:35 +08:00
Ousama Ben Younes edc8535ac1 fix: skip queueLength===0 completion branch when session returns 404 2026-04-11 08:16:35 +00:00
ck0park ad127bec40 fix: wrap list_corpora response in MCP CallToolResult shape (fixes #1700)
GET /api/corpus returned a bare array, which the MCP server wrapper
(callWorkerAPI) forwards directly. MCP's tools/call validation rejects
non-object results with "expected object, received array", so the
list_corpora MCP tool was completely unusable.

Every other corpus endpoint is a POST that already returns the
{content:[...]} shape, so this is a targeted one-file fix.
2026-04-11 09:57:01 +09:00
Ousama Ben Younes 2f19eab9c2 fix: expose summaryStored in session status to detect silent summary loss (#1633)
Stop hook polled queueLength===0 as a proxy for summary success, but the queue
empties regardless of whether the LLM produced valid <summary> tags. Added
lastSummaryStored tracking on ActiveSession, surfaced via the /api/sessions/status
endpoint, and emit a logger.warn in the Stop hook when summaryStored===false.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 15:06:18 +00:00
Ousama Ben Younes e7bf2ac65a docs: add custom grammar and markdown special support sections to smart-explore/SKILL.md
- Add Custom Grammars (.claude-mem.json) section explaining how to register
  additional tree-sitter parsers for unsupported file extensions
- Add Markdown Special Support section documenting heading-based outline,
  code-fence search, section unfold, and frontmatter extraction behaviors
- Expand bundled language test to cover all 10 documented languages plus
  the plain-text fallback sentence to prevent partial doc regressions

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 10:52:31 +00:00
Ousama Ben Younes 5ac54239d8 fix: add context-generator.cjs to SHEBANG_SCRIPTS and assert file existence
- Add missing context-generator.cjs to the SHEBANG_SCRIPTS list so CRLF
  regressions in that script are caught by the test suite
- Replace silent early-returns with expect(existsSync(filePath)).toBe(true)
  so the suite fails loudly when expected build artifacts are absent

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 10:51:34 +00:00
Ousama Ben Younes 08cf2ba3bd fix: suppress false ERROR when duplicate daemon loses port bind race (#1447)
When the MCP server and SessionStart hook both spawn a worker daemon
concurrently, one loses the bind race (EADDRINUSE / Bun's port-in-use
error). The loser now checks if the winner is healthy; if so, it logs
INFO and exits cleanly instead of logging a misleading ERROR on every
first session start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:01:08 +00:00
Ousama Ben Younes c7c4fd54d6 fix: set cwd to homedir when spawning chroma-mcp to prevent pydantic .env.local crash (#1297)
chroma-mcp uses pydantic-settings which auto-reads .env/.env.local from
the CWD. When the project directory contains non-chroma variables (e.g.
CELERY_TASK_ALWAYS_EAGER), pydantic rejects them with "Extra inputs are
not permitted", crashing the subprocess and triggering a permanent
backoff loop. Passing cwd: os.homedir() to StdioClientTransport ensures
pydantic never reads project env files.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:55:02 +00:00
Ousama Ben Younes f61eb2d162 fix: add .gitattributes to enforce LF endings on plugin scripts (#1342)
Without .gitattributes, building on Windows produces plugin scripts with
CRLF line endings. The CRLF on the shebang line causes
"env: node\r: No such file or directory" on macOS/Linux, breaking the
MCP server and all hook scripts. Add text=auto eol=lf as the global
default plus explicit eol=lf rules for plugin/scripts/*.cjs and *.js.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:51:22 +00:00
Ousama Ben Younes e9a234308a fix: avoid DEP0190 deprecation on Windows by using single-string spawnSync for where bun (#1503)
Node 22+ emits DEP0190 when spawnSync is called with a separate args
array and shell:true, because the args are only concatenated (not
escaped). Split the findBun() PATH check into platform-specific calls:
Windows uses spawnSync('where bun', { shell: true }) as a single string,
Unix uses spawnSync('which', ['bun']) with no shell option.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:49:23 +00:00
Ousama Ben Younes e398212983 fix: filter ghost observations with no content fields (#1625)
When the LLM is overwhelmed by large context it can emit bare
<observation/> blocks (or ones containing only <type>). These are
stored as rows where title, narrative, facts and concepts are all
null/empty, appearing as meaningless "Untitled" entries in the context
window. Add a guard in parseObservations() that skips any observation
where every content field is null/empty before pushing it to the
result array.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:40:40 +00:00
Ousama Ben Younes 36a03f75b2 docs: add Language Support section to smart-explore/SKILL.md (#1651)
tree-sitter language docs belonged in smart-explore but were absent;
this adds the Bundled Languages table (10 languages) with correct placement.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-09 23:24:14 +00:00
Ousama Ben Younes 5676cab83f fix: remove leaky mock.module() for project-name that polluted parallel workers (#1299)
Top-level mock.module() in context-reinjection-guard.test.ts permanently stubbed
getProjectName() to 'test-project' for the entire Bun worker process, causing
tests in other files to receive the wrong value. Removed the unnecessary mock
(session-init tests don't assert on project name), added bunfig.toml smol=true
for worker isolation, and added a regression test.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-09 22:55:54 +00:00
octo-patch 126129fbac fix: use bun to run mcp-server.cjs instead of node shebang (fixes #1648)
The mcp-server.cjs script requires bun:sqlite, a Bun-specific built-in
that is unavailable in Node.js. When Claude Code spawns the script using
the shebang (#!/usr/bin/env node), the import fails with:
  Error: Cannot find module 'bun:sqlite'

Fix: explicitly invoke bun as the command and pass the script as an arg,
so the correct runtime is used regardless of the shebang line.
2026-04-09 09:29:23 +08:00
Alex Newman cde4faae2f docs: update CHANGELOG.md for v12.1.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 17:37:57 -07:00