Skip to content

Commit b001ed2

Browse files
tznthouclaude
andcommitted
docs: update README/tutorial/architecture for 0.3.0 trust split (#21 P1)
User-facing surface for the session_journal split was missing — only CHANGELOG and version bump landed in the prior P1 commits. End users would not have learned `ccmem promote` exists; contributors would not have found the rationale for splitting trust off the persistence gate. - README (EN/ZH): replace v0.2.6 caveat with v0.3.0 trust split notice; Features adds "Trust two-tier" row; new CLI Commands section covers ccmem promote / reject; API table adds /journal/pending|promote|reject; Project Structure adds src/cli/journal.ts; test count 475/32 → 562/37 - tutorial (EN/ZH): Hooks section explains journal trust; Verifying-fires section now counts session_journal; Scenario 4 walks through promote and reject with rationale link to issue #21 - architecture (EN/ZH): Engine 2 documents sweepJournal; Engine 3 documents new harvest target; new "Promote and reject paths" plus "Trust grade vs persistence gate" sections explain the 0.3.0 redesign; Trade-offs adds two new rows; Where to Look adds 4 file pointers 562 tests still passing; no source changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a399abe commit b001ed2

6 files changed

Lines changed: 260 additions & 40 deletions

File tree

README.md

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ A local memory service for Claude Code — indexes your conversation history, re
1111

1212
---
1313

14-
> ⚠️ **v0.2.6English coverage caveat**
14+
> 📐 **v0.3.0Trust split (breaking change for harvest write path)**
1515
>
16-
> The harvester's knowledge-bearing scorer (introduced in v0.2.6) was corpus-validated against Mandarin Chinese sessions only. Each of the 5 signal categories ships with 1–3 anchor patterns per language as plan-time scaffolding. **English-language sessions may see a higher skip rate than expected** — the harvester will write fewer new memories until pattern coverage expands.
16+
> The SessionEnd hook now writes to a low-trust `session_journal` table instead of `memories`. Journal entries are scored, surfaced via `/health` (`journalPendingCount`), and **do not appear in `recall_query` / `recall_context` results** until you run `ccmem promote <id>`. Manual `recall_save` is unchanged — it still writes directly to high-trust `memories`.
1717
>
18-
> If you observe English outcome sessions failing to harvest, please contribute a redacted excerpt at [issue #23](https://github.com/tznthou/ccRecall/issues/23) — that's the corpus we need to expand coverage deliberately rather than by guesswork.
18+
> The rule scorer is no longer on the persistence gate; it informs trust grade and promotion priority instead. Background reasoning at [issue #21](https://github.com/tznthou/ccRecall/issues/21).
1919
>
20-
> Memories accumulated pre-v0.2.6 are preserved; a separate cleanup release will purge legacy noise after a 7-day observation window.
20+
> Pre-0.3.0 memories stay queryable as-is. The v22 schema migration runs automatically on first daemon startup; existing rows are not touched. New harvest goes to journal from now on.
2121
2222
---
2323

@@ -43,6 +43,7 @@ ccRecall is the "memory" counterpart to [ccRewind](https://github.com/tznthou/cc
4343
| **Incremental indexing** | Only re-indexes sessions that changed (mtime diffing), handles resumed sessions via UUID dedup |
4444
| **Metacognition** | `knowledge_map` aggregates topic mentions from sessions + memories. Depth derived from mention count (shallow / medium / deep). Exposed via `/metacognition/check` and MCP `recall_context` |
4545
| **Forgetting curve** | Memories compress over time: raw → summary → one-liner → deleted. Confidence decays on unused memories. Background maintenance tick runs every 5 min |
46+
| **Trust two-tier** (v0.3.0) | Hooks write to a low-trust `session_journal` (reviewable, never recalled directly); manual `recall_save` writes high-trust `memories`. Promote candidates with `ccmem promote <id>`; rejected entries auto-clear after 7 days |
4647
| **Watch mode** | chokidar-based JSONL watcher picks up new sessions within 2 s; periodic 10 min full-resync covers missed filesystem events |
4748
| **Rescue reindex** | `/session/end` retries a reindex on cache miss — no fresh-session race between the hook and the daemon |
4849
| **Auto-start (macOS)** | `ccmem install-daemon` registers a LaunchAgent so the service stays up across reboots |
@@ -88,7 +89,7 @@ flowchart TB
8889
| FTS5 | Full-text search | Built into SQLite, trigram tokenizer with LIKE fallback for short CJK / mixed-script queries |
8990
| Native `http` | HTTP server | No Express — minimal surface, localhost only |
9091
| chokidar | Filesystem watcher | Cross-platform JSONL change detection with 2 s debounce + single-flight |
91-
| vitest | Testing | 475 tests across 32 files, integration-style |
92+
| vitest | Testing | 562 tests across 37 files, integration-style |
9293
| `@modelcontextprotocol/sdk` | MCP server | stdio transport, shared SQLite via WAL |
9394

9495
---
@@ -132,10 +133,13 @@ curl "http://127.0.0.1:7749/memory/query?q=authentication&limit=5"
132133

133134
| Endpoint | Method | Description | Status |
134135
|----------|--------|-------------|--------|
135-
| `/health` | GET | Service health + DB stats + integrity check status | Live |
136-
| `/memory/query?q=...&limit=...&project=...` | GET | FTS5 search across memories with optional project filter | Live |
136+
| `/health` | GET | Service health + DB stats + integrity check status + `journalPendingCount` (since v0.3.0) | Live |
137+
| `/memory/query?q=...&limit=...&project=...` | GET | FTS5 search across memories with optional project filter (journal entries excluded by design) | Live |
137138
| `/memory/save` | POST | Save a memory entry (origin-checked) | Live |
138-
| `/session/end` | POST | Harvest a finished session's summary into a memory (idempotent) | Live |
139+
| `/session/end` | POST | Harvest a finished session into `session_journal` (idempotent; was `memories` pre-0.3.0) | Live |
140+
| `/journal/pending` | GET | List journal entries awaiting promotion review | Live (v0.3.0) |
141+
| `/journal/promote` | POST | Atomically promote a journal entry into `memories` | Live (v0.3.0) |
142+
| `/journal/reject` | POST | Soft-delete a journal entry (cleared after 7-day TTL by decay sweep) | Live (v0.3.0) |
139143
| `/memory/context?session_id=...` | GET | Session context lookup | Stub |
140144
| `/metacognition/check?projectId=...[&topic=...]` | GET | Knowledge map: summary (top/recent/stale topics + counts) or topic detail (memories + related topics) | Live |
141145
| `/session/checkpoint` | POST | Mid-session snapshot into dedicated `session_checkpoints` table (not harvested as memory) | Live |
@@ -175,6 +179,40 @@ See [hooks/README.md](hooks/README.md) for SessionStart / SessionEnd hook instal
175179

176180
---
177181

182+
## CLI Commands
183+
184+
`@tznthou/ccrecall` ships two binaries:
185+
186+
- **`ccmem`** — daemon launcher + admin commands
187+
- **`ccmem-mcp`** — MCP server (registered with Claude Code via `claude mcp add`)
188+
189+
Daemon and hook lifecycle (macOS):
190+
191+
| Command | Purpose |
192+
|---------|---------|
193+
| `ccmem` | Run the daemon in foreground |
194+
| `ccmem install-daemon` | Register a LaunchAgent (auto-start at login) |
195+
| `ccmem uninstall-daemon` | Stop and remove the LaunchAgent |
196+
| `ccmem install-hooks` | Merge SessionStart / SessionEnd entries into `~/.claude/settings.json` |
197+
| `ccmem uninstall-hooks` | Remove ccRecall's hook entries (other hooks untouched) |
198+
199+
Journal review (since v0.3.0):
200+
201+
| Command | Purpose |
202+
|---------|---------|
203+
| `ccmem promote <id>` | Promote a journal entry into `memories`. Optional `--type` (default `discovery`) and `--confidence` (default `0.7`) |
204+
| `ccmem reject <id>` | Soft-delete a journal entry; cleaned up after the 7-day TTL by the decay sweep |
205+
206+
Surface pending candidates:
207+
208+
```bash
209+
curl http://127.0.0.1:7749/journal/pending
210+
# or just check the count
211+
curl http://127.0.0.1:7749/health | jq .journalPendingCount
212+
```
213+
214+
---
215+
178216
## ccRecall vs auto memory
179217

180218
ccRecall lives alongside Claude Code's built-in auto memory (`~/.claude/projects/*/memory/`). They're complementary — use them for different things.
@@ -192,6 +230,8 @@ ccRecall lives alongside Claude Code's built-in auto memory (`~/.claude/projects
192230

193231
ccRecall's value is the long tail that auto memory can't cover (nobody hand-curates 500 sessions of notes). If Claude defaults to both, auto memory wins because it's already loaded and curated. ccRecall earns its keep when the curated index misses.
194232

233+
**Within ccRecall there's now a second trust split** (since v0.3.0). The SessionEnd hook writes to a low-trust `session_journal` table that `recall_query` does **not** read. Promote a candidate to high-trust `memories` with `ccmem promote <id>` to make it queryable. Manual `recall_save` skips the journal entirely — it writes straight to memories. The point is to let the harvester record broadly while keeping recall results clean.
234+
195235
---
196236

197237
## Running as a service (macOS)
@@ -274,7 +314,7 @@ ccRecall/
274314
│ │ ├── memory-service.ts # Memory lifecycle (touch / delete / update)
275315
│ │ ├── compression.ts # L0→L1→L2→delete state machine
276316
│ │ ├── lint.ts # Orphan / stale memory detection
277-
│ │ ├── maintenance-coordinator.ts # Background compression tick
317+
│ │ ├── maintenance-coordinator.ts # Background compression tick + journal decay sweep
278318
│ │ ├── watcher.ts # chokidar JSONL watcher (Phase 4e)
279319
│ │ └── log-safe.ts # scrubErrorMessage — log-injection defence
280320
│ ├── api/
@@ -284,7 +324,8 @@ ccRecall/
284324
│ │ ├── server.ts # MCP stdio server entry (shebang bin)
285325
│ │ └── tools.ts # recall_query + recall_context + recall_save
286326
│ ├── cli/
287-
│ │ └── daemon.ts # install-daemon / uninstall-daemon (macOS)
327+
│ │ ├── daemon.ts # install-daemon / uninstall-daemon (macOS)
328+
│ │ └── journal.ts # ccmem promote / reject (since v0.3.0)
288329
│ └── index.ts # HTTP entry point + subcommand dispatch
289330
├── hooks/
290331
│ ├── session-start.mjs # Inject memories on SessionStart (stdout)
@@ -294,10 +335,11 @@ ccRecall/
294335
│ ├── tutorial.md # End-user walkthrough (install → MCP → usage)
295336
│ ├── architecture.md # Daemon design rationale (contributor-oriented)
296337
│ └── launchd.md # macOS LaunchAgent install/troubleshoot
297-
├── tests/ # 475 tests across 32 files (parser, scanner,
338+
├── tests/ # 562 tests across 37 files (parser, scanner,
298339
│ │ # summarizer, database, indexer, e2e, MCP,
299340
│ │ # memories, hooks, watcher, CLI, migrations,
300-
│ │ # FTS5 CJK edge cases, integrity monitor, ...)
341+
│ │ # FTS5 CJK edge cases, integrity monitor,
342+
│ │ # session_journal DAO, promote+reject, sweep, ...)
301343
│ └── fixtures/ # Sample JSONL + shared test helpers
302344
├── .mcp.json.example # MCP client config template
303345
└── NOTICE / SECURITY.md / CONTRIBUTING.md / CODE_OF_CONDUCT.md

README_ZH.md

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ Claude Code 的本地記憶服務——索引你的對話歷史,按需召回
1111

1212
---
1313

14-
> ⚠️ **v0.2.6英文覆蓋率說明**
14+
> 📐 **v0.3.0Trust 二層拆分(harvest 寫入路徑 breaking change)**
1515
>
16-
> v0.2.6 引入的 outcome scorer 採用「5 類訊號 × 每語言 1–3 個 anchor pattern」的規則式評分,但 corpus 實測只跑過繁中 session(維護者自己 dogfood 的 dataset)。**英文 session 的 skip rate 可能高於預期**——直到 pattern 覆蓋擴充之前,harvester 會寫進來的新記憶較少
16+
> SessionEnd hook 改寫到新建的 low-trust `session_journal` 表,不再寫 `memories`。Journal 條目會評分、透過 `/health``journalPendingCount` 露出,**`recall_query` / `recall_context` 不會直接召回 journal 條目**,需要先 `ccmem promote <id>` 升級。Manual `recall_save` 不變——仍直寫 high-trust `memories`
1717
>
18-
> 如果觀察到英文 session 該抓的 outcome 沒被抓到,請到 [issue #23](https://github.com/tznthou/ccRecall/issues/23) 留 redacted 對話片段——這是我們擴充 corpus 唯一需要的資訊,讓 pattern 依證據成長而不是靠猜
18+
> Rule scorer 不再卡在 persistence gate;改成提供 trust grade 與 promote 優先序。完整 rationale 見 [issue #21](https://github.com/tznthou/ccRecall/issues/21)
1919
>
20-
> v0.2.6 之前累積的 memories 會保留;另一個 cleanup release 會在 7 天觀察期後清掉舊雜訊
20+
> 0.3.0 之前的 memories 仍可正常查詢。v22 schema migration 在 daemon 第一次啟動時自動跑,既有 row 不會被動。新 harvest 從現在起寫 journal
2121
2222
---
2323

@@ -43,6 +43,7 @@ ccRecall 是 [ccRewind](https://github.com/tznthou/ccRewind)(對話回放 GUI
4343
| **增量索引** | 只重新索引有變動的 session(mtime 比對),透過 UUID 去重處理接續 session |
4444
| **元認知** | `knowledge_map` 聚合 session + memory 的主題提及。由 mention count 衍生深度(shallow / medium / deep)。透過 `/metacognition/check` 與 MCP `recall_context` 暴露 |
4545
| **遺忘曲線** | 記憶隨時間壓縮:原始→摘要→一行結論→刪除。未使用的記憶信心衰減。背景維護 tick 每 5 分鐘跑一次 |
46+
| **Trust 二層**(v0.3.0) | Hook 寫入 low-trust `session_journal`(可審閱、不被 recall);manual `recall_save` 寫 high-trust `memories`。用 `ccmem promote <id>` 升級候選;reject 後 7 天 TTL 自動清 |
4647
| **Watch mode** | 基於 chokidar 的 JSONL watcher 在 2 秒內偵測新 session;每 10 分鐘 full-resync 補救 FS 事件漏接 |
4748
| **Rescue reindex** | `/session/end` 遇到 cache miss 時會重 index 再試一次——hook 和 daemon 間不會有 fresh-session race |
4849
| **macOS 自動啟動** | `ccmem install-daemon` 安裝 LaunchAgent,重開機自動復原服務 |
@@ -88,7 +89,7 @@ flowchart TB
8889
| FTS5 | 全文搜尋 | SQLite 內建、trigram tokenizer,短 token / 中英混合查詢透過 LIKE fallback 補齊 |
8990
| 原生 `http` | HTTP 伺服器 | 不用 Express——最小表面積、僅 localhost |
9091
| chokidar | 檔案系統 watcher | 跨平台 JSONL 變動偵測,2 秒 debounce + single-flight |
91-
| vitest | 測試 | 475 個測試(32 檔案)、整合式風格 |
92+
| vitest | 測試 | 562 個測試(37 檔案)、整合式風格 |
9293
| `@modelcontextprotocol/sdk` | MCP server | stdio transport,透過 WAL 共用 SQLite |
9394

9495
---
@@ -132,10 +133,13 @@ curl "http://127.0.0.1:7749/memory/query?q=authentication&limit=5"
132133

133134
| 端點 | 方法 | 說明 | 狀態 |
134135
|------|------|------|------|
135-
| `/health` | GET | 服務健康 + DB 統計 + integrity 檢查狀態 | 已上線 |
136-
| `/memory/query?q=...&limit=...&project=...` | GET | FTS5 跨 session 搜尋,可選 project 過濾 | 已上線 |
136+
| `/health` | GET | 服務健康 + DB 統計 + integrity 檢查狀態 + `journalPendingCount`(v0.3.0 新增) | 已上線 |
137+
| `/memory/query?q=...&limit=...&project=...` | GET | FTS5 跨 session 搜尋,可選 project 過濾(journal 條目 by design 不含) | 已上線 |
137138
| `/memory/save` | POST | 儲存記憶條目(Origin 驗證) | 已上線 |
138-
| `/session/end` | POST | 從結束的 session 萃取記憶(idempotent) | 已上線 |
139+
| `/session/end` | POST | 把結束的 session 寫入 `session_journal`(idempotent;0.3.0 前是寫 `memories`| 已上線 |
140+
| `/journal/pending` | GET | 列出待 promote 審閱的 journal 條目 | 已上線(v0.3.0) |
141+
| `/journal/promote` | POST | atomic 把 journal 條目升級到 `memories` | 已上線(v0.3.0) |
142+
| `/journal/reject` | POST | soft-delete journal 條目(7 天 TTL,由 decay sweep 清理) | 已上線(v0.3.0) |
139143
| `/memory/context?session_id=...` | GET | Session context 查詢 | Stub |
140144
| `/metacognition/check?projectId=...[&topic=...]` | GET | 知識地圖:summary(top/recent/stale topics + counts)或 topic detail(memories + related topics) | 已上線 |
141145
| `/session/checkpoint` | POST | 會話中途快照寫入獨立 `session_checkpoints` 表(不會被 harvest 成 memory) | 已上線 |
@@ -173,6 +177,40 @@ SessionStart / SessionEnd hook 安裝見 [hooks/README.md](hooks/README.md)。
173177

174178
---
175179

180+
## CLI 指令
181+
182+
`@tznthou/ccrecall` 提供兩個 binary:
183+
184+
- **`ccmem`** — daemon 啟動 + 管理指令
185+
- **`ccmem-mcp`** — MCP server(透過 `claude mcp add` 註冊到 Claude Code)
186+
187+
Daemon 與 hook 生命週期(macOS):
188+
189+
| 指令 | 用途 |
190+
|------|------|
191+
| `ccmem` | 前景跑 daemon |
192+
| `ccmem install-daemon` | 註冊 LaunchAgent(開機自動啟動) |
193+
| `ccmem uninstall-daemon` | 停掉並移除 LaunchAgent |
194+
| `ccmem install-hooks` | 把 SessionStart / SessionEnd 條目合併進 `~/.claude/settings.json` |
195+
| `ccmem uninstall-hooks` | 移除 ccRecall 自己的 hook 條目(其他 hook 不動) |
196+
197+
Journal 審閱(v0.3.0 新增):
198+
199+
| 指令 | 用途 |
200+
|------|------|
201+
| `ccmem promote <id>` | 把 journal 條目升級到 `memories`。可選 `--type`(預設 `discovery`)、`--confidence`(預設 `0.7`|
202+
| `ccmem reject <id>` | soft-delete journal 條目;7 天 TTL 後由 decay sweep 清掉 |
203+
204+
查待 promote 候選:
205+
206+
```bash
207+
curl http://127.0.0.1:7749/journal/pending
208+
# 或只看計數
209+
curl http://127.0.0.1:7749/health | jq .journalPendingCount
210+
```
211+
212+
---
213+
176214
## ccRecall 與 auto memory 的分工
177215

178216
ccRecall 和 Claude Code 內建的 auto memory(`~/.claude/projects/*/memory/`)是互補關係,各司其職,不要混用。
@@ -190,6 +228,8 @@ ccRecall 和 Claude Code 內建的 auto memory(`~/.claude/projects/*/memory/`
190228

191229
ccRecall 的價值在長尾——幾百個 session 不可能全手工整理。如果 Claude 兩邊都試,auto memory 永遠會贏(本來就在 context 裡而且已經被策展)。ccRecall 存在的意義是:策展索引漏掉時,長尾那堆還在資料庫裡可以撈出來。
192230

231+
**ccRecall 內部從 v0.3.0 起多了一層 trust 拆分。** SessionEnd hook 寫到 low-trust `session_journal` 表——`recall_query` 不會去讀那裡。要讓某筆候選進到查詢結果,跑 `ccmem promote <id>` 升級到 high-trust `memories`。Manual `recall_save` 完全不經 journal——直接寫 memories。設計目的:讓 harvester 廣捕,但 recall 結果保持乾淨。
232+
193233
---
194234

195235
## 作為服務運行(macOS)
@@ -267,7 +307,7 @@ ccRecall/
267307
│ │ ├── memory-service.ts # 記憶生命週期(touch / delete / update)
268308
│ │ ├── compression.ts # L0→L1→L2→delete 狀態機
269309
│ │ ├── lint.ts # Orphan / stale 記憶偵測
270-
│ │ ├── maintenance-coordinator.ts # 背景壓縮 tick
310+
│ │ ├── maintenance-coordinator.ts # 背景壓縮 tick + journal decay sweep
271311
│ │ ├── watcher.ts # chokidar JSONL watcher(Phase 4e)
272312
│ │ └── log-safe.ts # scrubErrorMessage — log-injection 防護
273313
│ ├── api/
@@ -277,7 +317,8 @@ ccRecall/
277317
│ │ ├── server.ts # MCP stdio server 入口(含 shebang)
278318
│ │ └── tools.ts # recall_query + recall_context + recall_save
279319
│ ├── cli/
280-
│ │ └── daemon.ts # install-daemon / uninstall-daemon(macOS)
320+
│ │ ├── daemon.ts # install-daemon / uninstall-daemon(macOS)
321+
│ │ └── journal.ts # ccmem promote / reject(v0.3.0 新增)
281322
│ └── index.ts # HTTP 入口 + 子指令分派
282323
├── hooks/
283324
│ ├── session-start.mjs # SessionStart 注入記憶(stdout)
@@ -287,10 +328,11 @@ ccRecall/
287328
│ ├── tutorial_zh.md # 使用者教學(安裝 → MCP → 日常使用)
288329
│ ├── architecture_zh.md # Daemon 設計取捨(給 contributor 看)
289330
│ └── launchd.md # macOS LaunchAgent 安裝/troubleshoot
290-
├── tests/ # 475 個測試橫跨 32 檔案(parser、scanner、
331+
├── tests/ # 562 個測試橫跨 37 檔案(parser、scanner、
291332
│ │ # summarizer、database、indexer、e2e、MCP、
292333
│ │ # memories、hooks、watcher、CLI、migrations、
293-
│ │ # FTS5 CJK edge cases、integrity monitor 等)
334+
│ │ # FTS5 CJK edge cases、integrity monitor、
335+
│ │ # session_journal DAO、promote+reject、sweep 等)
294336
│ └── fixtures/ # 測試用 JSONL + 共用 helpers
295337
├── .mcp.json.example # MCP client 設定範本
296338
└── NOTICE / SECURITY.md / CONTRIBUTING.md / CODE_OF_CONDUCT.md

0 commit comments

Comments
 (0)