claude-mem-lite 4.0.3 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +0 -49
- package/README.zh-CN.md +0 -48
- package/adopt-content.mjs +0 -1
- package/cli/common.mjs +0 -17
- package/cli.mjs +19 -3
- package/commands/update.md +4 -11
- package/format-utils.mjs +0 -21
- package/hook-context.mjs +6 -1
- package/hook-handoff.mjs +9 -0
- package/hook-update.mjs +37 -12
- package/hook.mjs +5 -29
- package/hooks/hooks.json +0 -10
- package/install.mjs +24 -666
- package/lib/doctor-drift.mjs +0 -1
- package/lib/fast-summary.mjs +11 -0
- package/lib/frontmatter.mjs +1 -2
- package/lib/hook-prune.mjs +133 -0
- package/lib/hook-stdin.mjs +1 -1
- package/lib/hook-telemetry.mjs +1 -1
- package/lib/metrics.mjs +2 -2
- package/lib/shard-gc.mjs +11 -7
- package/mem-cli.mjs +2 -423
- package/nlp.mjs +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +3 -15
- package/schema.mjs +0 -1
- package/scripts/hook-launcher.mjs +2 -2
- package/scripts/prompt-search-utils.mjs +0 -30
- package/scripts/user-prompt-search.js +3 -125
- package/server.mjs +11 -449
- package/source-files.mjs +11 -28
- package/synonyms.mjs +2 -1
- package/tool-schemas.mjs +0 -80
- package/utils.mjs +5 -13
- package/commands/tools.md +0 -67
- package/install-metadata.mjs +0 -2193
- package/lib/registry-core.mjs +0 -264
- package/registry/preinstalled.json +0 -2419
- package/registry-enricher.mjs +0 -124
- package/registry-github.mjs +0 -86
- package/registry-importer.mjs +0 -569
- package/registry-recommend.mjs +0 -503
- package/registry-retriever.mjs +0 -611
- package/registry-scanner.mjs +0 -261
- package/registry.mjs +0 -665
- package/resource-discovery.mjs +0 -199
- package/scripts/pre-skill-bridge.js +0 -146
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "claude-mem-lite",
|
|
13
|
-
"version": "
|
|
13
|
+
"version": "5.0.0",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark)."
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "sdsrss"
|
package/README.md
CHANGED
|
@@ -105,7 +105,6 @@ How claude-mem-lite differs from the major neighbors in the LLM-memory space (ve
|
|
|
105
105
|
- **Atomic writes** -- All file writes (episodes, CLAUDE.md) use write-to-tmp + rename to prevent corruption on crash
|
|
106
106
|
- **Robust locking** -- PID-aware lock files with automatic stale/orphan cleanup (>30s timeout or dead PID)
|
|
107
107
|
- **Stale session cleanup** -- Sessions active for >24h are automatically marked as abandoned on next start
|
|
108
|
-
- **Resource registry** -- Indexes installed skills and agents with FTS5 search, composite scoring, and invocation tracking; searchable via `mem_registry` MCP tool
|
|
109
108
|
- **Unified resource discovery** -- Shared filesystem traversal layer (`resource-discovery.mjs`) used by both runtime scanner and offline indexer, supporting flat directories, plugin nesting, and loose `.md` files
|
|
110
109
|
- **Domain synonym expansion** -- Registry search queries expand to domain synonyms (e.g., "fix" → debug, bugfix, troubleshoot, diagnose, repair)
|
|
111
110
|
- **Multi-provider LLM mode** -- Provider priority `ANTHROPIC_API_KEY` (direct Anthropic API) → `OPENROUTER_API_KEY` (OpenRouter, OpenAI-compatible — point it at any model via `OPENROUTER_MODEL`) → `claude -p` CLI fallback when no key is set
|
|
@@ -121,7 +120,6 @@ How claude-mem-lite differs from the major neighbors in the LLM-memory space (ve
|
|
|
121
120
|
- **Configurable LLM model** -- Switch between Haiku (fast/cheap) and Sonnet (deeper analysis) via `CLAUDE_MEM_MODEL` env var
|
|
122
121
|
- **DB auto-recovery** -- Detects and cleans corrupted WAL/SHM files on startup; periodic WAL checkpoints prevent unbounded growth
|
|
123
122
|
- **Schema auto-migration** -- Idempotent `ALTER TABLE` migrations run on every startup, safely adding new columns and indexes without data loss
|
|
124
|
-
- **Exploration bonus** -- New resources in the registry get a fair chance in composite ranking; zombie resources (high recommend, zero adopt) are penalized in scoring
|
|
125
123
|
- **LLM concurrency control** -- File-based semaphore limits background workers to 2 concurrent LLM calls, preventing resource contention
|
|
126
124
|
- **stdin overflow protection** -- Hook input truncated at 256KB with regex-based action salvage for oversized tool outputs
|
|
127
125
|
- **Cross-session handoff** -- Captures session state (request, completed work, next steps, key files) on `/clear` or `/exit`, then injects context when the next session detects continuation intent via explicit keywords or FTS5 term overlap
|
|
@@ -224,7 +222,6 @@ rm -rf ~/claude-mem-lite/ # pre-v0.5 unhidden (if not auto-moved)
|
|
|
224
222
|
```
|
|
225
223
|
~/.claude-mem-lite/
|
|
226
224
|
claude-mem-lite.db # SQLite database — memory (WAL mode)
|
|
227
|
-
resource-registry.db # SQLite database — skill/agent registry
|
|
228
225
|
runtime/
|
|
229
226
|
session-<project> # Active session state
|
|
230
227
|
ep-<project>.json # Episode buffer
|
|
@@ -274,8 +271,6 @@ surface — reach them through the CLI column in the second table.
|
|
|
274
271
|
| `mem_export` | `claude-mem-lite export` | JSON / JSONL dump, filters by project, type, date. |
|
|
275
272
|
| `mem_fts_check` | `claude-mem-lite fts-check <check\|rebuild>` | FTS5 integrity + rebuild. |
|
|
276
273
|
| `mem_browse` | `claude-mem-lite browse` | Tier-grouped dashboard (working / active / archive). |
|
|
277
|
-
| `mem_registry` | `claude-mem-lite registry <action>` | List / search / import / remove skills + agents. |
|
|
278
|
-
| `mem_use` | _MCP only_ | Load a skill / agent from the registry by name. |
|
|
279
274
|
|
|
280
275
|
### Skill Commands (in Claude Code chat)
|
|
281
276
|
|
|
@@ -472,29 +467,6 @@ Stop
|
|
|
472
467
|
-> Spawn LLM summary worker (poll-based wait)
|
|
473
468
|
```
|
|
474
469
|
|
|
475
|
-
### Resource Registry
|
|
476
|
-
|
|
477
|
-
The resource registry (`registry.mjs`, `registry-retriever.mjs`) indexes installed skills and agents into a searchable FTS5 database. Unlike the previous proactive dispatch system, the registry is now on-demand — it's reachable via the `claude-mem-lite registry` CLI (primary path for Claude Code since v2.34.0 hides the `mem_registry` MCP tool from `tools/list`) or by direct `tools/call mem_registry` for MCP clients that know the name.
|
|
478
|
-
|
|
479
|
-
```
|
|
480
|
-
Registry pipeline:
|
|
481
|
-
-> registry-scanner.mjs discovers skills/agents on filesystem
|
|
482
|
-
-> resource-discovery.mjs handles flat dirs, plugin nesting, loose .md files
|
|
483
|
-
-> registry-indexer.mjs indexes content into FTS5 with metadata
|
|
484
|
-
-> registry-retriever.mjs provides BM25-ranked search with synonym expansion
|
|
485
|
-
-> mem_registry MCP tool exposes search/list/stats/import/remove/reindex actions
|
|
486
|
-
|
|
487
|
-
Smart invocation (three layers):
|
|
488
|
-
L1 auto-load: UserPromptSubmit matches managed skill name in prompt
|
|
489
|
-
-> Loads content with path="~/.claude-mem-lite/managed/.../SKILL.md"
|
|
490
|
-
-> Guides: Read("path") or mem_use(name="..."), never Skill()
|
|
491
|
-
L2 bridge: PreToolUse hook intercepts Skill("name") for managed resources
|
|
492
|
-
-> Outputs content, prevents native handler failure
|
|
493
|
-
L3 explicit: mem_use(name="...") loads full content with reload path
|
|
494
|
-
Search: managed resources → Read(path), native plugins → Skill("full:name")
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
Composite scoring for search results: BM25 relevance (40%) + repo stars (15%) + success rate (15%) + adoption rate (10%) + freshness (10%) + exploration bonus (10%). Domain filtering ensures platform-specific resources (iOS, Go, Rust) only surface for matching projects.
|
|
498
470
|
|
|
499
471
|
### Episode Encoding
|
|
500
472
|
|
|
@@ -656,12 +628,6 @@ claude-mem-lite/
|
|
|
656
628
|
format-utils.mjs # String formatting: truncate, typeIcon, date/time/week formatting
|
|
657
629
|
hash-utils.mjs # MinHash signatures, Jaccard similarity for dedup
|
|
658
630
|
bash-utils.mjs # Bash output significance detection: errors, tests, builds, deploys
|
|
659
|
-
# Resource registry
|
|
660
|
-
registry.mjs # Resource registry DB: schema, CRUD, FTS5, invocation tracking
|
|
661
|
-
registry-retriever.mjs # FTS5 retrieval with synonym expansion and composite scoring
|
|
662
|
-
registry-indexer.mjs # Resource indexing pipeline
|
|
663
|
-
registry-scanner.mjs # Filesystem scanner: reads content + hashes, delegates discovery
|
|
664
|
-
resource-discovery.mjs # Shared discovery layer: flat dirs, plugin nesting, loose .md files
|
|
665
631
|
haiku-client.mjs # Unified Haiku LLM wrapper: direct API or CLI fallback
|
|
666
632
|
# Install & config
|
|
667
633
|
install.mjs # CLI installer: setup, uninstall, status, doctor (npx/git clone mode)
|
|
@@ -809,18 +775,6 @@ claude-mem-lite.
|
|
|
809
775
|
| `CLAUDE_MEM_NO_TEMPLATE_REFRESH` | `1` stops SessionStart from refreshing the adopted `CLAUDE.md` managed block when the shipped template changes. | _(refreshes)_ |
|
|
810
776
|
| `MEM_QUIET_HOOKS` | See Core above — the broadest injection-volume switch. | _(disabled)_ |
|
|
811
777
|
|
|
812
|
-
### Registry import bounds
|
|
813
|
-
|
|
814
|
-
`registry import-url` pulls from a third-party repository, so it is bounded. Entries past a
|
|
815
|
-
bound are refused, not truncated, and the refusal is printed with the import result. Set any
|
|
816
|
-
of these to `0` for the pre-v3.98 unlimited behavior; an unparseable or negative value keeps
|
|
817
|
-
the default rather than removing the bound.
|
|
818
|
-
|
|
819
|
-
| Variable | Description | Default |
|
|
820
|
-
|----------|-------------|---------|
|
|
821
|
-
| `CLAUDE_MEM_IMPORT_MAX_ITEMS` | Max skills/agents imported from one repository. | `200` |
|
|
822
|
-
| `CLAUDE_MEM_IMPORT_MAX_FILE_BYTES` | Max size of a single `SKILL.md`/`AGENT.md`. Oversized entries are skipped; the rest still import. | `2097152` (2 MB) |
|
|
823
|
-
| `CLAUDE_MEM_IMPORT_MAX_TOTAL_BYTES` | Byte budget for one import run. Exhausting it stops the walk and books the remainder as refused. | `52428800` (50 MB) |
|
|
824
778
|
|
|
825
779
|
### Retrieval tuning
|
|
826
780
|
|
|
@@ -840,7 +794,6 @@ benchmark and A/B harness are calibrated against — changing them invalidates t
|
|
|
840
794
|
| `CLAUDE_MEM_ERROR_RECALL_BM25_MIN` | Relevance floor for the error-recall surface (memories injected after a failed Bash command). **Off by default.** Setting it to `10.5` (the calibrated value) makes the surface stay silent when its best-matching memory is not actually about the failure — the whole set is dropped, never trimmed row-by-row. **It is a real trade, not a free win:** measured on a live database at that threshold, injections fall ~37% and ~39% of firings go silent, concentrated in projects with few memories. Off by default because nothing shows the dropped rows were noise. Explore with `node benchmark/error-recall-suite.mjs --sweep`. | `0` (off) |
|
|
841
795
|
| `CLAUDE_MEM_ERROR_RECALL_RERANK` | `off` restores the flat keyword ordering of the error-recall surface. **On by default**, and unlike the floor above it removes nothing: memories that share only the failed command's vocabulary are demoted below memories that mention the failure itself, and when a project has none of the latter the result is unchanged. Measured on a live database over 52 real failing commands × 15 projects: the lead memory matched no error term in 42.3% of firings before, 21.5% after, with the injected row count identical. | _(on)_ |
|
|
842
796
|
| `CLAUDE_MEM_ERROR_RECALL_ON_FAILURE` | `off` stops the plugin from recalling memories when a Bash command **fails at the host level**. On by default. Claude Code delivers failed tool calls to a separate `PostToolUseFailure` hook event, so before this the surface only ever saw commands that exited `0` while printing error-ish text — a genuinely failing build recalled nothing. Denials from your own guardrails (sandbox, policy hooks, declined permission prompts) and commands you interrupted are never recalled for. | _(on)_ |
|
|
843
|
-
| `CLAUDE_MEM_REGISTRY_CONFINE` | `off` lets registry enrichment read a resource whose `local_path` lies outside the managed data directory. **On by default.** Enrichment reads the file at `resources.local_path` and sends it to an LLM; the confinement check used to guard one of the four code paths that do this (`mem_registry(action="enrich")`) and not the other three, so `enrich <name>`, `enrich --all` and `import --enrich` read any path the row happened to hold. All four are gated now. Turn it off only if you deliberately registered resources outside `CLAUDE_MEM_DIR` and want them enriched; only `off` disables it — case-insensitively and ignoring surrounding whitespace — so a typo leaves the guard on. | _(on)_ |
|
|
844
797
|
| `CLAUDE_MEM_UPS_IDENTIFIER_BYPASS` | `0` disables the bypass that lets an exact identifier match skip the score floors. | _(on)_ |
|
|
845
798
|
| `CLAUDE_MEM_UPS_PROMPT_FALLBACK_LIMIT` | How many past-prompt rows the fallback arm may return. | `1` |
|
|
846
799
|
| `MEM_COVERAGE_THRESHOLD` | Fraction of query terms a memory must cover to qualify (∈ [0,1]). | `0.4` |
|
|
@@ -885,7 +838,6 @@ what is already stored — only whether new work runs.
|
|
|
885
838
|
| `CLAUDE_MEM_SKIP_MARKER_GC` | Skip the runtime-marker sweep. | _(runs)_ |
|
|
886
839
|
| `CLAUDE_MEM_SKIP_UPDATE` | Skip the 24h auto-update check against GitHub Releases. | _(runs)_ |
|
|
887
840
|
| `CLAUDE_MEM_SKIP_SIG_VERIFY` | Skip Ed25519 signature verification of a downloaded update. **Escape hatch — leaves updates unauthenticated.** | _(verifies)_ |
|
|
888
|
-
| `CLAUDE_MEM_SKIP_REPOS` | Skip skill/agent registry seeding during install. | _(seeds)_ |
|
|
889
841
|
| `CLAUDE_MEM_NO_LESSON_RETRY` | `1` disables the one-shot retry that re-asks for a missing `lesson_learned`. | _(retries)_ |
|
|
890
842
|
| `CLAUDE_MEM_FLUSH_TIMEOUT` | Seconds the Stop hook waits for pending episode flushes. | `15` |
|
|
891
843
|
| `CLAUDE_MEM_BACKUP_BUDGET_MB` | Disk budget for backup snapshots; the next maintain/save evicts oldest snapshots past the 7-day undo grace. | `256` |
|
|
@@ -897,7 +849,6 @@ and names can change between releases.
|
|
|
897
849
|
|
|
898
850
|
| Variable | Description | Default |
|
|
899
851
|
|----------|-------------|---------|
|
|
900
|
-
| `CLAUDE_MEM_RECOMMEND_MODE` | Skill-recommendation engine: `shadow` (log would-be recommendations, inject nothing) or `off`. **`live` is parsed but not implemented** — live injection is Phase 2. Setting it runs shadow and prints one warning to stderr per process; `claude-mem-lite doctor` also reports it as an inert flag. | `shadow` |
|
|
901
852
|
| `CLAUDE_MEM_TASK_IMPERATIVE` | `on`/`1` injects the single most relevant lesson at prompt position under an imperative template. | _(off)_ |
|
|
902
853
|
| `CLAUDE_MEM_SUBAGENT_INJECT` | Dispatch-time memory injection for subagents. | _(off)_ |
|
|
903
854
|
| `CLAUDE_MEM_SALIENCE` | Selects a comprehension-bridge arm (`bridge`, `bind`); unset = current default behavior. | _(unset)_ |
|
package/README.zh-CN.md
CHANGED
|
@@ -81,8 +81,6 @@
|
|
|
81
81
|
- **原子写入** -- 所有文件写入(episode、CLAUDE.md)使用 write-to-tmp + rename 防止崩溃时损坏
|
|
82
82
|
- **健壮锁机制** -- PID 感知的锁文件,自动清理过期(>30s)或孤儿(PID 已死)锁
|
|
83
83
|
- **过期会话清理** -- 活跃超过 24 小时的会话在下次启动时自动标记为 abandoned
|
|
84
|
-
- **智能调用** -- 三层调用系统:L1 自动加载(UserPromptSubmit 匹配 skill 名注入内容 + `Read()` 路径),L2 Bridge(PreToolUse 拦截 `Skill()` 误调),L3 显式调用(`mem_use` MCP 工具)。managed 资源用 `Read("~/.claude-mem-lite/managed/.../SKILL.md")`,原生插件用 `Skill("full:name")`
|
|
85
|
-
- **资源注册表** -- 对已安装的 skill 和 agent 建立 FTS5 索引,支持复合评分和调用追踪。搜索结果区分 managed(Read 路径)vs native(Skill 全名)调用方式
|
|
86
84
|
- **统一资源发现** -- 共享文件系统遍历层(`resource-discovery.mjs`),运行时扫描器和离线索引器共用,支持扁平目录、插件嵌套和松散 `.md` 文件
|
|
87
85
|
- **领域同义词扩展** -- 注册表搜索查询自动扩展领域同义词(如 "修复" → fix, debug, bugfix, repair, error)
|
|
88
86
|
- **持久化冷却机制** -- 5 分钟跨会话冷却 + 同会话去重,避免重复推荐 skill 自动加载
|
|
@@ -188,7 +186,6 @@ rm -rf ~/claude-mem-lite/ # v0.5 前的非隐藏目录(如未自动迁移)
|
|
|
188
186
|
```
|
|
189
187
|
~/.claude-mem-lite/
|
|
190
188
|
claude-mem-lite.db # SQLite 数据库 — 记忆(WAL 模式)
|
|
191
|
-
resource-registry.db # SQLite 数据库 — skill/agent 注册表
|
|
192
189
|
runtime/
|
|
193
190
|
session-<project> # 活跃会话状态
|
|
194
191
|
ep-<project>.json # Episode 缓冲区
|
|
@@ -233,8 +230,6 @@ v2.34.0 起服务端注册 17 个工具,但 `tools/list` 只暴露 6 个 **核
|
|
|
233
230
|
| `mem_export` | `claude-mem-lite export` | JSON / JSONL 导出,支持项目/类型/日期过滤。 |
|
|
234
231
|
| `mem_fts_check` | `claude-mem-lite fts-check <check\|rebuild>` | FTS5 完整性检查与重建。 |
|
|
235
232
|
| `mem_browse` | `claude-mem-lite browse` | 分层仪表盘(working / active / archive)。 |
|
|
236
|
-
| `mem_registry` | `claude-mem-lite registry <action>` | 列 / 搜索 / 导入 / 移除 skill / agent。 |
|
|
237
|
-
| `mem_use` | _MCP only_ | 从 registry 按名载入 skill / agent。 |
|
|
238
233
|
|
|
239
234
|
### 技能命令(在 Claude Code 聊天中使用)
|
|
240
235
|
|
|
@@ -370,11 +365,6 @@ PostToolUse(每次工具执行)
|
|
|
370
365
|
-> 为有意义的 episode 启动 LLM episode worker
|
|
371
366
|
-> 错误触发回忆:搜索记忆中相关的历史修复
|
|
372
367
|
|
|
373
|
-
PreToolUse(工具执行前)
|
|
374
|
-
-> L2 Skill Bridge:拦截对 managed 资源的 Skill() 调用
|
|
375
|
-
-> 匹配 managed 路径 → 输出内容 + mem_use() 提示
|
|
376
|
-
-> 未匹配 → 静默放行到原生 handler
|
|
377
|
-
|
|
378
368
|
UserPromptSubmit(两个并行路径)
|
|
379
369
|
-> [user-prompt-search.js] 通过 FTS5 + 活跃文件上下文自动搜索记忆
|
|
380
370
|
-> [user-prompt-search.js] 注入相关历史观察(按时效和重要性加权)
|
|
@@ -393,36 +383,6 @@ Stop
|
|
|
393
383
|
-> 启动 LLM 摘要 worker(轮询等待)
|
|
394
384
|
```
|
|
395
385
|
|
|
396
|
-
### 智能调用系统
|
|
397
|
-
|
|
398
|
-
三层调用系统确保 managed 资源(`~/.claude-mem-lite/managed/` 中的 skill 和 agent)能被正确调用:
|
|
399
|
-
|
|
400
|
-
```
|
|
401
|
-
L1 自动加载(UserPromptSubmit,<50ms)
|
|
402
|
-
-> 匹配 prompt 中的 managed skill/agent 名称
|
|
403
|
-
-> 加载 SKILL.md / {name}.md 内容
|
|
404
|
-
-> 输出:Read("~/.claude-mem-lite/managed/.../path.md") 调用指引
|
|
405
|
-
-> 截断时提供 mem_use(name="...") 备选
|
|
406
|
-
|
|
407
|
-
L2 Bridge(PreToolUse Skill hook,<30ms)
|
|
408
|
-
-> 拦截 Skill("name") 调用,查询 managed 注册表
|
|
409
|
-
-> 匹配到 → 输出内容 + mem_use() 提示(防止原生 handler 报错)
|
|
410
|
-
-> 未匹配 → 放行到原生 Skill handler
|
|
411
|
-
|
|
412
|
-
L3 显式调用(mem_use MCP 工具)
|
|
413
|
-
-> 按名称精确匹配 + FTS5 模糊回退
|
|
414
|
-
-> 返回完整内容 + 便携路径供 Read() 重载
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
**调用方式区分:**
|
|
418
|
-
|
|
419
|
-
| 资源类型 | 位置 | 调用方式 |
|
|
420
|
-
|---------|------|---------|
|
|
421
|
-
| Managed skill | `~/.claude-mem-lite/managed/skills/` | `Read("~/.../SKILL.md")` 或 `mem_use(name="...")` |
|
|
422
|
-
| Managed agent | `~/.claude-mem-lite/managed/agents/` | `Read("~/.../{name}.md")` 或 `mem_use(name="...", type="agent")` |
|
|
423
|
-
| 原生插件 skill | `~/.claude/plugins/cache/` | `Skill("plugin:skill-name")` |
|
|
424
|
-
| 用户自建 skill | `~/.claude/skills/` | `Skill("name")` |
|
|
425
|
-
|
|
426
386
|
### Episode 编码
|
|
427
387
|
|
|
428
388
|
Episode 是一批相关操作(对同一组文件的编辑),由后台 LLM worker 处理:
|
|
@@ -548,13 +508,6 @@ claude-mem-lite/
|
|
|
548
508
|
format-utils.mjs # 字符串格式化:截断、类型图标、日期/时间格式化
|
|
549
509
|
hash-utils.mjs # MinHash 签名、Jaccard 相似度(去重用)
|
|
550
510
|
bash-utils.mjs # Bash 输出显著性检测:错误、测试、构建、部署
|
|
551
|
-
# 智能调度
|
|
552
|
-
dispatch.mjs # 三级调度编排:快速过滤、上下文信号、FTS5、Haiku
|
|
553
|
-
dispatch-inject.mjs # 注入模板渲染:skill/agent 推荐
|
|
554
|
-
registry.mjs # 资源注册表 DB:schema、CRUD、FTS5、调用追踪
|
|
555
|
-
registry-retriever.mjs # FTS5 检索:同义词扩展与复合评分
|
|
556
|
-
registry-scanner.mjs # 文件系统扫描器:读取内容 + 哈希,委托发现层
|
|
557
|
-
resource-discovery.mjs # 共享发现层:扁平目录、插件嵌套、松散 .md 文件
|
|
558
511
|
haiku-client.mjs # 统一 Haiku LLM 封装:直连 API 或 CLI 回退
|
|
559
512
|
# 安装与配置
|
|
560
513
|
install.mjs # CLI 安装器:设置、卸载、状态、诊断(npx/git clone 模式)
|
|
@@ -620,7 +573,6 @@ npm run benchmark:gate # CI 门控:指标回退超过 5% 容差时失败
|
|
|
620
573
|
| `MEM_QUIET_HOOKS` | 低噪声 hook。设为 `1` 时,SessionStart 注入去掉 `File Lessons` / `Key Context` 两节,`[mem] Related memories` 去掉 lesson 后缀,MCP server instructions 去掉 `WHEN TO USE` / `Decision rules` 两段。ID 与 `Recent` 表仍保留,`mem_get(ids=[…])` 可继续展开细节。适用于启用了 invited-memory adopt 流程或偏好最小化自动注入的用户。**v2.82.0 起此 env 不再阻挡 auto-adopt——如需关闭 auto-adopt 用 `MEM_NO_AUTO_ADOPT=1`。** | _(禁用)_ |
|
|
621
574
|
| `MEM_NO_AUTO_ADOPT` | auto-adopt 全局关闭开关(v2.82.0+)。设为 `1` 阻止每次 SessionStart 在**所有**项目自动写入 `CLAUDE.md` 托管块。项目级关闭走 `claude-mem-lite adopt --disable`(写 `<memdir>/.mem-no-auto-adopt` 哨兵,存活于 marker 删除)。 | _(禁用)_ |
|
|
622
575
|
| `MEM_NO_ADOPT_HINT` | 静音当前项目未 adopt 时 SessionStart 追加的那一行 "Invited-memory 未启用…" 提示。v2.82.1 起任何安装路径每次 SessionStart 都自动 adopt,所以该提示一般只在你显式 opt out(`MEM_NO_AUTO_ADOPT=1` 或 `claude-mem-lite adopt --disable`)的项目才会出现。 | _(禁用)_ |
|
|
623
|
-
| `CLAUDE_MEM_REGISTRY_CONFINE` | 设为 `off` 允许 registry enrich 读取 `local_path` 位于托管数据目录之外的资源。**默认开启。** enrich 会读取 `resources.local_path` 指向的文件并发给 LLM;此前这道路径限制只接在四条读取路径中的一条(`mem_registry(action="enrich")`)上,`enrich <name>`、`enrich --all` 和 `import --enrich` 三条都是裸读。现在四条同门。仅当你确实把资源注册在 `CLAUDE_MEM_DIR` 之外并希望对其 enrich 时才关闭;只有精确值 `off` 会关闭它,拼错则守卫保持开启。 | _(开启)_ |
|
|
624
576
|
|
|
625
577
|
## 许可证
|
|
626
578
|
|
package/adopt-content.mjs
CHANGED
|
@@ -151,7 +151,6 @@ PreToolUse hook 在你 Read / Edit / Write 文件前已自动 \`mem_recall\` 该
|
|
|
151
151
|
| 导出 JSON/JSONL | \`${CLI} export [--format jsonl]\` |
|
|
152
152
|
| 统计总量 / 健康 | \`${CLI} stats [--days 30]\` |
|
|
153
153
|
| 删除 / 更新某条 | \`${CLI} delete <id>[,<id>]\` · \`${CLI} update <id> [--title ...]\` |
|
|
154
|
-
| skill-agent registry | \`${CLI} registry <list\\|search\\|import>\` |
|
|
155
154
|
|
|
156
155
|
## CLI 速查(常用检索)
|
|
157
156
|
|
package/cli/common.mjs
CHANGED
|
@@ -209,27 +209,21 @@ export const KNOWN_CLI_FLAGS = new Set([
|
|
|
209
209
|
'age-days',
|
|
210
210
|
'all',
|
|
211
211
|
'anchor',
|
|
212
|
-
'batch',
|
|
213
212
|
'before',
|
|
214
213
|
'benchmark',
|
|
215
214
|
'body',
|
|
216
215
|
'branch',
|
|
217
|
-
'capability-summary',
|
|
218
|
-
'category',
|
|
219
216
|
'closes-deferred',
|
|
220
217
|
'concepts',
|
|
221
218
|
'confirm',
|
|
222
219
|
'days',
|
|
223
220
|
'deep',
|
|
224
221
|
'detail',
|
|
225
|
-
'domain-tags',
|
|
226
222
|
'dry-run',
|
|
227
|
-
'enrich',
|
|
228
223
|
'execute',
|
|
229
224
|
'fields',
|
|
230
225
|
'file',
|
|
231
226
|
'files',
|
|
232
|
-
'floors',
|
|
233
227
|
'force',
|
|
234
228
|
'format',
|
|
235
229
|
'from',
|
|
@@ -240,16 +234,11 @@ export const KNOWN_CLI_FLAGS = new Set([
|
|
|
240
234
|
'importance',
|
|
241
235
|
'include-compressed',
|
|
242
236
|
'include-noise',
|
|
243
|
-
'intent-tags',
|
|
244
|
-
'invocation-name',
|
|
245
237
|
'json',
|
|
246
238
|
'key',
|
|
247
|
-
'keywords',
|
|
248
239
|
'lesson',
|
|
249
240
|
'lesson-learned',
|
|
250
241
|
'limit',
|
|
251
|
-
'local-path',
|
|
252
|
-
'margins',
|
|
253
242
|
'max',
|
|
254
243
|
'memdir',
|
|
255
244
|
'merge-ids',
|
|
@@ -265,9 +254,7 @@ export const KNOWN_CLI_FLAGS = new Set([
|
|
|
265
254
|
'quality',
|
|
266
255
|
'query',
|
|
267
256
|
'reason',
|
|
268
|
-
'repo-url',
|
|
269
257
|
'rerank',
|
|
270
|
-
'resource-type',
|
|
271
258
|
'retain-days',
|
|
272
259
|
'retry',
|
|
273
260
|
'run',
|
|
@@ -279,16 +266,12 @@ export const KNOWN_CLI_FLAGS = new Set([
|
|
|
279
266
|
'sort',
|
|
280
267
|
'source',
|
|
281
268
|
'status',
|
|
282
|
-
'sweep',
|
|
283
269
|
'task',
|
|
284
|
-
'tech-stack',
|
|
285
270
|
'text',
|
|
286
271
|
'tier',
|
|
287
272
|
'title',
|
|
288
273
|
'to',
|
|
289
|
-
'trigger-patterns',
|
|
290
274
|
'type',
|
|
291
|
-
'use-cases',
|
|
292
275
|
'verbose',
|
|
293
276
|
// Catalogued 2026-08-13 when suggestUnknownFlags started reporting EVERY unknown
|
|
294
277
|
// flag: these are real, code-read flags that the old edit-distance gate happened to
|
package/cli.mjs
CHANGED
|
@@ -18,10 +18,7 @@ const CLI_COMMANDS = new Set([
|
|
|
18
18
|
'maintain',
|
|
19
19
|
'optimize',
|
|
20
20
|
'fts-check',
|
|
21
|
-
'registry',
|
|
22
|
-
'import',
|
|
23
21
|
'import-jsonl',
|
|
24
|
-
'enrich',
|
|
25
22
|
'activity',
|
|
26
23
|
'adopt',
|
|
27
24
|
'unadopt',
|
|
@@ -29,6 +26,10 @@ const CLI_COMMANDS = new Set([
|
|
|
29
26
|
'defer',
|
|
30
27
|
'help',
|
|
31
28
|
]);
|
|
29
|
+
// Removed with the skill/agent resource registry (docs/audits/20260906-145304.md).
|
|
30
|
+
// Kept as a named set so a stale script or muscle-memory invocation gets the reason rather
|
|
31
|
+
// than a bare "Unknown command" plus a misleading edit-distance suggestion.
|
|
32
|
+
const REMOVED_COMMANDS = new Set(['registry', 'import', 'enrich']);
|
|
32
33
|
const INSTALL_COMMANDS = new Set([
|
|
33
34
|
'install',
|
|
34
35
|
'uninstall',
|
|
@@ -95,6 +96,21 @@ if (cmd === '--version' || cmd === '-v' || cmd === '-V' || cmd === 'version') {
|
|
|
95
96
|
} else if (INSTALL_COMMANDS.has(cmd)) {
|
|
96
97
|
const { main } = await import('./install.mjs');
|
|
97
98
|
await main(process.argv.slice(2));
|
|
99
|
+
} else if (REMOVED_COMMANDS.has(cmd)) {
|
|
100
|
+
// Released-artifact discoverability signal for the skill-registry removal. Deliberately
|
|
101
|
+
// names NO version: this ships before the version is decided, and a hardcoded one is a
|
|
102
|
+
// guess in a third place (package.json and the CHANGELOG heading being the other two).
|
|
103
|
+
// The revert instruction is version-specific and correct, which is what a user needs.
|
|
104
|
+
// Deliberately NOT routed through the edit-distance suggester below: its nearest
|
|
105
|
+
// match for `import` is `import-jsonl`, a different feature that accepts a path
|
|
106
|
+
// argument, so a stale `import <github-url>` would be pointed at something that
|
|
107
|
+
// could plausibly run. Naming the removal is the only honest answer.
|
|
108
|
+
process.stderr.write(
|
|
109
|
+
`[mem] "${cmd}" was removed along with the skill/agent resource registry.\n` +
|
|
110
|
+
"[mem] Claude Code's own plugins/marketplace replace it. See CHANGELOG.md for the\n" +
|
|
111
|
+
'[mem] migration note; to revert, pin claude-mem-lite@4.0.4.\n',
|
|
112
|
+
);
|
|
113
|
+
process.exit(1);
|
|
98
114
|
} else {
|
|
99
115
|
process.stderr.write(`[mem] Unknown command: "${cmd}"\n`);
|
|
100
116
|
// Suggest closest command by edit distance
|
package/commands/update.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: update
|
|
3
|
-
description: "Use when: search results seem noisy
|
|
3
|
+
description: "Use when: search results seem noisy or for periodic memory maintenance"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Memory
|
|
6
|
+
# Memory Maintenance
|
|
7
7
|
|
|
8
|
-
Run intelligent maintenance on
|
|
8
|
+
Run intelligent maintenance on the memory database.
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
11
|
|
|
@@ -24,15 +24,8 @@ When the user invokes `/mem:update`, perform the following maintenance cycle:
|
|
|
24
24
|
5. Run `mem_compress(preview=false)` for old low-value observations
|
|
25
25
|
6. **If pending purge items > 0**: Report the count to the user and ask for confirmation. If confirmed, call `mem_maintain(action="execute", operations=["purge_stale"])`. User may optionally specify `retain_days` (default 30) to control how many days of data to keep. Do NOT purge without explicit user confirmation.
|
|
26
26
|
|
|
27
|
-
### Phase 2:
|
|
28
|
-
|
|
29
|
-
1. Call `mem_registry(action="stats")` to get registry overview
|
|
30
|
-
2. Call `mem_registry(action="reindex")` to rebuild FTS5 search index
|
|
31
|
-
3. Report updated stats
|
|
32
|
-
|
|
33
|
-
### Phase 3: Summary
|
|
27
|
+
### Phase 2: Summary
|
|
34
28
|
|
|
35
29
|
Summarize all maintenance actions taken in zh-CN:
|
|
36
30
|
- Memory: observations cleaned, decayed, boosted, deduplicated, compressed
|
|
37
|
-
- Registry: total resources, adoption rates, reindex status
|
|
38
31
|
- Overall health assessment
|
package/format-utils.mjs
CHANGED
|
@@ -125,27 +125,6 @@ export function neutralizeSkillDelimiters(s) {
|
|
|
125
125
|
return defangToFixpoint(s, SKILL_BLOCK_RE);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
// <skill-bridge> is the wrapper scripts/pre-skill-bridge.js puts around a managed
|
|
129
|
-
// skill body it injects as PreToolUse additionalContext. The body comes from a
|
|
130
|
-
// third-party repo (tools/adopt import) — an untrusted boundary — so a literal
|
|
131
|
-
// `</skill-bridge>` inside it would close the wrapper early and spill the rest of
|
|
132
|
-
// the payload (e.g. a forged <system-reminder>) as undelimited context (audit
|
|
133
|
-
// 2026-08-14 M-4). Not in CONTEXT_DELIMITER_RE for the same reason <skill-loaded>
|
|
134
|
-
// isn't: the bridge's OWN wrapper must stay live, so the defang is applied per
|
|
135
|
-
// call site to the untrusted body only.
|
|
136
|
-
const SKILL_BRIDGE_RE = /<\/?skill-bridge(?:\s[^>]*)?>/gi;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Defang a literal `<skill-bridge>` opener/closer in untrusted text that is about
|
|
140
|
-
* to be wrapped in a real skill-bridge block. Same fixpoint treatment as the
|
|
141
|
-
* classes above. Never apply to the wrapper itself.
|
|
142
|
-
* @param {string} s Input string (any type; coerced)
|
|
143
|
-
* @returns {string} Text with skill-bridge delimiters defanged
|
|
144
|
-
*/
|
|
145
|
-
export function neutralizeSkillBridgeDelimiters(s) {
|
|
146
|
-
return defangToFixpoint(s, SKILL_BRIDGE_RE);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
128
|
/**
|
|
150
129
|
* Render the PostToolUse error-recall hint block (hook.mjs::triggerErrorRecall).
|
|
151
130
|
* The single most-relevant hit (rows[0]) that carries a lesson_learned gets its
|
package/hook-context.mjs
CHANGED
|
@@ -60,11 +60,16 @@ function mdCell(s) {
|
|
|
60
60
|
|
|
61
61
|
export function computeAdaptiveWindows(db, project) {
|
|
62
62
|
const sevenDaysAgo = Date.now() - 7 * DAY_MS;
|
|
63
|
+
// liveObsFilterSql, not a hand-written half of it (A20260906-R8-§11.3). This COUNT is a
|
|
64
|
+
// POOL-SIZING input: the windows returned below are handed to the recall queries at :201 /
|
|
65
|
+
// :468 / :502, all three of which filter live rows. Counting a strictly larger population
|
|
66
|
+
// than the window is applied to inverts the documented intent — 80 superseded rows read as
|
|
67
|
+
// >10 obs/day and earned the TIGHTEST window (12h) for finding the few live rows left.
|
|
63
68
|
const row = db
|
|
64
69
|
.prepare(
|
|
65
70
|
`
|
|
66
71
|
SELECT COUNT(*) as c FROM observations
|
|
67
|
-
WHERE project = ? AND created_at_epoch > ? AND
|
|
72
|
+
WHERE project = ? AND created_at_epoch > ? AND ${liveObsFilterSql('')}
|
|
68
73
|
`,
|
|
69
74
|
)
|
|
70
75
|
.get(project, sevenDaysAgo);
|
package/hook-handoff.mjs
CHANGED
|
@@ -136,6 +136,15 @@ export function buildAndSaveHandoff(db, sessionId, project, type, episodeSnapsho
|
|
|
136
136
|
const obsWindowParams = ccWindowStart !== null ? [ccWindowStart] : [];
|
|
137
137
|
|
|
138
138
|
// 2. Completed — from observations (include narrative for richer handoff)
|
|
139
|
+
//
|
|
140
|
+
// `compressed_into` ONLY, deliberately — not a half-written liveObsFilterSql. Audit
|
|
141
|
+
// 2026-08-14 F4 ruled on exactly this line: `completed` is the session's own history, and a
|
|
142
|
+
// decision a later save overturned still happened, so erasing it here would misreport the
|
|
143
|
+
// session. Only key_decisions (:242) is re-presented to a LATER session as standing policy,
|
|
144
|
+
// and that one does filter superseded_at. The scope guard is the third case of "F4 — handoff
|
|
145
|
+
// key_decisions excludes a retracted decision" in tests/audit-silent-20260814.test.mjs.
|
|
146
|
+
// Audit R8 §11.3 proposed adding the filter here from a repo-wide regex sweep of the
|
|
147
|
+
// predicate shape; it was rejected on this reasoning, and the guard catches it.
|
|
139
148
|
const completed = db
|
|
140
149
|
.prepare(
|
|
141
150
|
`
|
package/hook-update.mjs
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
readFileSync,
|
|
8
8
|
writeFileSync,
|
|
9
9
|
copyFileSync,
|
|
10
|
-
cpSync,
|
|
11
10
|
readdirSync,
|
|
12
11
|
existsSync,
|
|
13
12
|
lstatSync,
|
|
@@ -404,11 +403,11 @@ export function getCurrentVersion() {
|
|
|
404
403
|
}
|
|
405
404
|
|
|
406
405
|
// SWITCHABLE_PATHS = everything in SOURCE_FILES plus the recursive dirs that
|
|
407
|
-
// install.mjs copies as whole subtrees (scripts,
|
|
406
|
+
// install.mjs copies as whole subtrees (scripts, node_modules). It's
|
|
408
407
|
// built per-call from the *tarball's* manifest, not the locally-imported one —
|
|
409
408
|
// see loadReleaseManifest comment for why.
|
|
410
409
|
function buildSwitchablePaths(sourceFiles) {
|
|
411
|
-
return [...sourceFiles, 'scripts', '
|
|
410
|
+
return [...sourceFiles, 'scripts', 'node_modules'];
|
|
412
411
|
}
|
|
413
412
|
|
|
414
413
|
// Load the SOURCE_FILES / HOOK_SCRIPT_FILES manifest from the *extracted
|
|
@@ -989,6 +988,41 @@ export async function installExtractedRelease(sourceDir, targetDir = INSTALL_DIR
|
|
|
989
988
|
rmSync(stagingDir, { recursive: true, force: true });
|
|
990
989
|
rmSync(backupDir, { recursive: true, force: true });
|
|
991
990
|
|
|
991
|
+
// Post-update migration: reconcile settings.json against the release we just
|
|
992
|
+
// swapped in. `configureHooks()` already strips stale mem entries — but its only
|
|
993
|
+
// caller is `install()`, and this path never runs it, while `buildSwitchablePaths`
|
|
994
|
+
// replaces `scripts/` wholesale. So an upgrade that REMOVES a hook script deletes
|
|
995
|
+
// the file and leaves settings.json pointing at it; the launcher then reports a
|
|
996
|
+
// broken install on every fire, for a file that is not coming back (R9 review P1-1,
|
|
997
|
+
// first hit by the `PreToolUse:Skill` removal). Plugin-channel installs are
|
|
998
|
+
// unaffected — hooks/hooks.json is replaced wholesale — so this is npm-channel only.
|
|
999
|
+
//
|
|
1000
|
+
// The reconciler lives in lib/hook-prune.mjs, not install.mjs: install.mjs already
|
|
1001
|
+
// imports THIS file, so importing it back would close a cycle the repo's import-graph
|
|
1002
|
+
// guard rejects. Failure is non-fatal — a stale entry is noisy, not broken, and must
|
|
1003
|
+
// never roll back an otherwise-good update.
|
|
1004
|
+
try {
|
|
1005
|
+
const settingsPath = join(homedir(), '.claude', 'settings.json');
|
|
1006
|
+
if (existsSync(settingsPath)) {
|
|
1007
|
+
const { pruneDanglingMemHooks } = await import('./lib/hook-prune.mjs');
|
|
1008
|
+
const before = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
1009
|
+
const { settings, removed } = pruneDanglingMemHooks(before, targetDir);
|
|
1010
|
+
if (removed.length > 0) {
|
|
1011
|
+
// Through the shared writer: settings.json is user-owned config and may be a
|
|
1012
|
+
// symlink into a dotfiles repo, which a bare temp+rename would sever (P0-5).
|
|
1013
|
+
const { atomicWriteFileSync } = await import('./lib/atomic-write.mjs');
|
|
1014
|
+
atomicWriteFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', { backup: true });
|
|
1015
|
+
debugLog(
|
|
1016
|
+
'INFO',
|
|
1017
|
+
'update',
|
|
1018
|
+
`pruned ${removed.length} dangling hook entr(ies): ${removed.join(', ')}`,
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
} catch (e) {
|
|
1023
|
+
debugCatch(e, 'pruneDanglingMemHooks');
|
|
1024
|
+
}
|
|
1025
|
+
|
|
992
1026
|
// Post-update migration: clean stale global MCPs if plugin handles it.
|
|
993
1027
|
// Both "mem" (legacy, pre-v2.78) and "mem-lite" (current) are purged so a
|
|
994
1028
|
// user who manually ran `claude mcp add` in either era doesn't end up with
|
|
@@ -1194,15 +1228,6 @@ function copyReleaseIntoStaging(
|
|
|
1194
1228
|
}
|
|
1195
1229
|
}
|
|
1196
1230
|
|
|
1197
|
-
// registry/ stays recursive — preinstalled.json is the only current entry
|
|
1198
|
-
// but the directory is consumed wholesale by the registry indexer and may
|
|
1199
|
-
// grow subtrees. Pre-v2.55 readdirSync+copyFileSync would EISDIR-throw on
|
|
1200
|
-
// any subdir and silently roll back the entire update.
|
|
1201
|
-
const sourceRegistry = join(sourceDir, 'registry');
|
|
1202
|
-
if (existsSync(sourceRegistry)) {
|
|
1203
|
-
cpSync(sourceRegistry, join(stagingDir, 'registry'), { recursive: true });
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
1231
|
const stagedScripts = join(stagingDir, 'scripts');
|
|
1207
1232
|
if (existsSync(stagedScripts)) {
|
|
1208
1233
|
for (const sf of readdirSync(stagedScripts).filter((n) => n.endsWith('.sh'))) {
|
package/hook.mjs
CHANGED
|
@@ -165,10 +165,10 @@ async function loadCacheGuard() {
|
|
|
165
165
|
// Audit 2026-09-02 P1-8. `hook.mjs` is ONE entry point for seven events, so every static
|
|
166
166
|
// import is paid by every event — PostToolUse, the highest-frequency one, was loading 85
|
|
167
167
|
// modules (1.37 MB) to use a handful. The six modules below are loaded inside the handler
|
|
168
|
-
// that needs them instead:
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
//
|
|
168
|
+
// that needs them instead: patha-exclude-meter, hook-update, hook-optimize, adopt-cli,
|
|
169
|
+
// upgrade-banner. Measured marginal cost of the largest, same process: hook-update
|
|
170
|
+
// 9.4 ms, hook-optimize 5.9, the rest 0.5-2.4 each. (registry-recommend, 5.1 ms, was a
|
|
171
|
+
// sixth entry until the skill-registry subsystem was removed — see docs/audits/20260906-145304.md.)
|
|
172
172
|
//
|
|
173
173
|
// A failing dynamic import lands in the dispatcher's tail catch -> recordHookError, the
|
|
174
174
|
// same place a failing static import would have landed the whole process; each site keeps
|
|
@@ -642,23 +642,6 @@ async function handlePostToolUse() {
|
|
|
642
642
|
if (SKIP_TOOLS.has(tool_name)) return;
|
|
643
643
|
if (SKIP_PREFIXES.some((p) => tool_name.startsWith(p))) return;
|
|
644
644
|
|
|
645
|
-
// Shadow skill-adoption telemetry. mem_use is pre-filtered above, so the Skill tool is
|
|
646
|
-
// the only visible adoption signal (v1). Placed before the resp-length gate because a
|
|
647
|
-
// skill load's response shape varies. Never throws.
|
|
648
|
-
if (tool_name === 'Skill') {
|
|
649
|
-
const ti = typeof tool_input === 'string' ? tryParseJson(tool_input) : tool_input || {};
|
|
650
|
-
// hookData.session_id (CC UUID) pairs this adoption to the would-be reco from the
|
|
651
|
-
// UserPromptSubmit hook earlier in the same session (matched precision, B1).
|
|
652
|
-
// Lazy: only a `Skill` tool call needs this module, which is a small fraction of
|
|
653
|
-
// PostToolUse fires.
|
|
654
|
-
try {
|
|
655
|
-
const { recordSkillAdoption } = await import('./registry-recommend.mjs');
|
|
656
|
-
recordSkillAdoption('Skill', ti, inferProject(), hookData.session_id);
|
|
657
|
-
} catch {
|
|
658
|
-
/* telemetry only — never blocks capture */
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
645
|
const resp = normalizeToolResponse(tool_response);
|
|
663
646
|
if (!resp || resp.length < 10) return;
|
|
664
647
|
|
|
@@ -2254,14 +2237,7 @@ async function handleSessionStart() {
|
|
|
2254
2237
|
} catch {
|
|
2255
2238
|
/* best-effort */
|
|
2256
2239
|
}
|
|
2257
|
-
// Bound the
|
|
2258
|
-
try {
|
|
2259
|
-
const { gcOldShadowShards } = await import('./registry-recommend.mjs');
|
|
2260
|
-
gcOldShadowShards();
|
|
2261
|
-
} catch {
|
|
2262
|
-
/* best-effort, never blocks SessionStart */
|
|
2263
|
-
}
|
|
2264
|
-
// Same for the opt-in metrics sink, which lives under DB_DIR. Runs even when
|
|
2240
|
+
// Bound the opt-in metrics sink, which lives under DB_DIR. Runs even when
|
|
2265
2241
|
// metrics are disabled, so shards left by a since-toggled-off run still get pruned.
|
|
2266
2242
|
try {
|
|
2267
2243
|
gcOldMetricShards(DB_DIR);
|
package/hooks/hooks.json
CHANGED
|
@@ -41,16 +41,6 @@
|
|
|
41
41
|
}
|
|
42
42
|
]
|
|
43
43
|
},
|
|
44
|
-
{
|
|
45
|
-
"matcher": "Skill",
|
|
46
|
-
"hooks": [
|
|
47
|
-
{
|
|
48
|
-
"type": "command",
|
|
49
|
-
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hook-launcher.mjs\" scripts/pre-skill-bridge.js",
|
|
50
|
-
"timeout": 3
|
|
51
|
-
}
|
|
52
|
-
]
|
|
53
|
-
},
|
|
54
44
|
{
|
|
55
45
|
"matcher": "Agent|Task",
|
|
56
46
|
"hooks": [
|