# https://github.com/pbmagnet4/nlm-memory 项目说明书

生成时间：2026-06-22 17:38:49 UTC

## 目录

- [Overview & System Architecture](#page-1)
- [Runtime Adapters & Session Ingest](#page-2)
- [Recall, MCP Tools & REST API](#page-3)
- [Storage Backends, Schema & Migrations](#page-4)
- [Hooks, Hook Modes & Runtime Integration](#page-5)
- [Agent Self-Improvement Signals & Code Exemplars](#page-6)
- [CLI, Configuration, Setup & Security](#page-7)
- [UI Pages, Daily Digest & Telemetry](#page-8)

<a id='page-1'></a>

## Overview & System Architecture

### 相关页面

相关主题：[Runtime Adapters & Session Ingest](#page-2), [Recall, MCP Tools & REST API](#page-3), [Storage Backends, Schema & Migrations](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [src/core/recall/rewrite-prompt.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/rewrite-prompt.ts)
- [src/core/recall/related-facts.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/related-facts.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/hook/citation-detect.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts)
- [src/core/storage/sqlite-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts)
- [src/core/storage/pg-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/pg-code-exemplar-store.ts)
- [src/core/providers/provider-models.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/providers/provider-models.ts)
- [src/ui/lib/registries.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts)
- [src/ui/components/README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/README.md)
- [src/ui/components/Skeleton.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/Skeleton.tsx)
- [src/ui/pages/Pulse.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx)
- [src/ui/pages/Recall.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Recall.tsx)
- [src/ui/pages/Thread.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Thread.tsx)
</details>

# Overview & System Architecture

## 目的与定位

`nlm-memory` 是一个面向 AI 算力使用者的"本地优先（local-first）非线性记忆操作系统"。从 `package.json` 的描述与关键字集合可以确认：它被定位为 AI / MCP / Claude-Code / Codex / Hermes / 本地优先 / 召回 / 会话记忆 等交叉领域的基础设施，遵循 Apache-2.0 协议，并以 `nlm` CLI 作为唯一对外入口（`"bin": { "nlm": "dist/cli/nlm.js" }`）。整个系统以"会话 → 事实 → 代码范例"为主线，提供可被 Agent 即时调用的记忆通道 [package.json:2-3]()。

## 总体架构

系统由四层组成：CLI 组合根、HTTP/MCP 传输层、领域核心（Hexagonal Ports & Adapters）、以及基于 Vite + React 的 UI 单页应用。所有具体实现都从属于 `core/` 内的端口（Port），CLI 文件是唯一同时知晓 `SqliteStorage`、`PgStorage`、`OllamaClient`、`Hono`、`McpServer` 的"组合根"，替换后端时只需要修改该文件 [src/cli/nlm.ts:1-45]()。

```mermaid
flowchart LR
  A[AI Agent / Claude Code / Codex] -->|MCP stdio| B(CLI: src/cli/nlm.ts)
  A -->|HTTP| C[Hono: src/http/app.ts]
  B --> C
  C --> D[Recall Service]
  C --> E[Fact Recall Service]
  C --> F[Scheduler + Classifier]
  D --> G[Rewrite Prompt]
  E --> H[Related Facts]
  D --> I[Pointer Block]
  F --> J[Citation Detect]
  C --> K[(Sqlite / PgStorage)]
  C --> L[Provider Registry]
  M[UI: Vite + React] --> C
```

资料来源：[src/cli/nlm.ts:14-23]()、[src/core/recall/rewrite-prompt.ts:1-15]()、[src/core/hook/pointer-block.ts:1-30]()

## 核心模块组成

### 组合根与 CLI

`nlm` CLI 同时承担 `start`、`migrate`、`recall`、`mcp`、`setup`、`install`、`uninstall`、`hook install/uninstall`、`connect/disconnect`、`digest` 等十余个子命令 [src/cli/nlm.ts:30-46]()。它内嵌 Hono 的 `serve` 与 MCP `StdioServerTransport`，因此"用同一个 Node 进程既可以服务本地 Web UI，又可以以 stdio 形式接入 Claude-Code / Codex 客户端"，无需拆分多个二进制。

### 召回与改写

`rewrite-prompt.ts` 把模糊自然语言查询拆分为 `keywordQuery`（喂给 FTS5 BM25）与 `semanticQuery`（喂给向量嵌入）两个版本；改写失败时解析器会抛错，调用方"失败开放"地退回原始查询，避免把错误改写结果污染后续评分 [src/core/recall/rewrite-prompt.ts:1-25]()。`related-facts.ts` 在召回命中之上再选 3–5 条高置信度事实（按确认次数排序），阈值可由 `NLM_HOOK_FACT_LIMIT` 等环境变量调优；任一步骤异常都会返回空数组，让指针块优雅降级到"仅会话"模式 [src/core/recall/related-facts.ts:1-45]()。

### Hook 与指针块

`pointer-block.ts` 渲染 Hook 注入到对话上下文的"指针块"——只包含 ID + 标签，不复制会话正文；这是"教学 Tool 清单"的唯一跨运行时分发面，新装用户不需要手动改 prompt 即可了解 `recall_sessions` / `recall_facts` / `recall_code` / `get_fact_history` 四个工具 [src/core/hook/pointer-block.ts:1-32]()。`citation-detect.ts` 通过 `tool_use` 与 `prose` 两条信号通道判定 Agent 是否真正引用了被召回的 ID，是未来学习式重排模型的训练样本来源 [src/core/hook/citation-detect.ts:1-20]()。

### 存储与提供者抽象

`src/core/storage/` 同时提供 `SqliteCodeExemplarStore` 与 `PgCodeExemplarStore` 两种适配器：主键统一由 `sha256(installScope|repo|codeHash|outcome)[:16]` 派生，保证"同段代码在同一作用域内只占一行" [src/core/storage/sqlite-code-exemplar-store.ts:1-35]()；PG 适配器使用 `pgvector` 索引并把 `retired_at` 字段纳入 schema（修复记录见 v0.14.1）。`provider-models.ts` 把 LLM 提供方按"发现方式"区分：Ollama 调 `/api/tags`、OpenAI 系调 `/models`、DeepSeek/Anthropic 因无稳定列表端点而采用硬编码 [src/core/providers/provider-models.ts:1-45]()。`registries.ts` 暴露的 `SourceKind` 与 `ProviderKind` 联合类型就是 UI 表单的合法取值集合 [src/ui/lib/registries.ts:1-30]()。

### Web UI

UI 使用 Vite + React SPA 形态（`"build:ui": "vite build --config src/ui/vite.config.ts"`），并通过 React 端口的 `<Drawer>`、`<Pagination>`、`<Skeleton>` 等基础组件对外提供一致的交互 [src/ui/components/README.md:1-30]()。`Pulse` 页展示运行时分组的会话与主题热度 [src/ui/pages/Pulse.tsx:1-30]()；`Recall` 页把"会话召回 / 事实召回"的命中率、按来源、热门查询、热门主体并列展示，用于区分"采用度问题"与"语料覆盖度问题" [src/ui/pages/Recall.tsx:1-30]()；`Thread` 页提供实体筛选与分页浏览 [src/ui/pages/Thread.tsx:1-25]()。`StubPage` 用于标记尚未从旧 Astro UI 移植完成的页面，集中跟踪于 NocoDB #95 [src/ui/pages/Stub.tsx:1-5]()。

## 近期演进与社区焦点

v0.20.0 起，调度器在摄入阶段自动把超大会话切片（PR #341）；v0.19.0 / v0.18.0 为分类器补齐了 JSON 重试 + 分块容错以及分级分类与超大恢复；v0.16.0 / v0.15.0 引入了被动式 `recall_code` 与基于已提交会话的"代码范例自动捕获"两阶段闭环；v0.14.x 进一步把范例存储落到 Postgres 后端并在 HTTP `/mcp` 通道补线；v0.13.0 则增加了 `doctor` / `verify` / `codex-repair` 安装自检与每日备份。这意味着当前主线能力已从"会话检索"扩展为"事实 + 代码范例 + 安装自愈"的复合记忆体。资料来源：[社区发布说明](https://github.com/pbmagnet4/nlm-memory/releases)

## See Also

- [Recall Service & Query Pipeline](#) — 召回与改写内部细节
- [Storage Adapters (SQLite / Postgres)](#) — 两种后端的差异与迁移
- [CLI & Install Lifecycle](#) — `setup` / `install` / `doctor` / `verify` 流程
- [Pointer Block & Hook Protocol](#) — Hook 注入与 Citation 检测

---

<a id='page-2'></a>

## Runtime Adapters & Session Ingest

### 相关页面

相关主题：[Overview & System Architecture](#page-1), [Storage Backends, Schema & Migrations](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [src/ui/lib/registries.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts)
- [src/ui/pages/Pulse.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx)
- [src/core/recall/recall-service.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/recall-service.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/hook/citation-detect.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts)
- [src/core/storage/sqlite-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts)
- [src/core/storage/pg-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/pg-code-exemplar-store.ts)
- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
</details>

# Runtime Adapters & Session Ingest

## 概览

Runtime Adapters 是 nlm-memory 把不同 AI 编程代理（Claude Code、Codex、Hermes、Pi 等）的会话转录接入本地记忆库的适配层；Session Ingest 负责把适配器解析出的原始转录归一化为内部 `Session` 模型，并执行分类、嵌入、超限切分与代码示例抽取等下游处理。整个模块是事实写入路径的起点，其稳定性直接决定后续 Recall、Fact Recall 以及代码示例召回的质量。本项目版本 `0.20.0`（package.json）正是在该管道上增加了调度层面的自动切分能力。

资料来源：[src/cli/nlm.ts:1-30](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts#L1-L30) | [package.json:1-15](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json#L1-L15)

## 适配器种类（Source Kinds）

`SourceKind` 联合类型集中声明系统所支持的运行时后端；UI 注册表与 daemon 契约复用同一份定义，避免类型漂移。

| SourceKind | 接入方式 | 说明 |
| --- | --- | --- |
| `claude-code` | MCP stdio | Anthropic Claude Code CLI |
| `codex` | Codex 插件市场 | OpenAI Codex CLI |
| `hermes` | 独立插件 | Hermes Agent 配套 |
| `pi` | JSONL 解析 | Pi 编程代理 |
| `jsonl-generic` | 文件 watcher | 通用 JSONL 转录 |
| `webhook` | HTTP POST | 远程代理主动推送 |

每条 Source 记录携带 `runtimeLabel`、`parseConfig`、`enabled` 三个核心字段；`parseConfig` 决定具体解析器从何种结构中抽取对话轮次和时间戳。HTTP 列表接口仅返回 `hasToken: boolean`，明文 `token` 仅在 `insert / regenerate` 时一次性回显，避免长期泄露。

资料来源：[src/ui/lib/registries.ts:1-40](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts#L1-L40) | [src/ui/lib/registries.ts:50-80](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts#L50-L80)

## CLI 与安装路径

CLI 是 Runtime Adapter 的唯一组合根（composition root），所有具体后端的接线与排错命令均集中于 `src/cli/nlm.ts`：

- `nlm connect claude-code` — 在 `~/.mcp.json` 写入 MCP server block；
- `nlm connect codex` — 安装 Codex 插件市场包；
- `nlm disconnect claude-code` / `nlm disconnect codex` — 卸载对应接线；
- `nlm doctor` — 同时探测 Claude Code 与 Codex 的 MCP 接线状态，并扫描 `@nlm-memory-ts` 残留的过期 trust 条目；
- `nlm mcp` — 以 stdio 方式运行 MCP server，供宿主代理通过 MCP 协议调用 Recall / Fact Recall 工具；
- `nlm hook install` — 安装 Claude Code 的 recall 钩子（shadow 模式）。

doctor 报告一并返回 daemon 可达性、`~/.nlm/.env` 是否存在以及是否设置 `NLM_MCP_TOKEN`，便于安装失败时定位根因。

资料来源：[src/cli/nlm.ts:30-80](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts#L30-L80) | [src/cli/nlm.ts:80-120](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts#L80-L120)

## Session Ingest 管道

Session Ingest 是写入侧的主管道，其关键节点与发布节奏紧密相关：

```mermaid
flowchart LR
  A[Runtime 转录文件] --> B[Adapter 解析]
  B --> C[归一化 Session]
  C --> D{是否超限?}
  D -- 否 --> E[Classifier 分类]
  D -- 是 --> F[Auto-chunk 切分]
  F --> E
  E --> G[Embedder + Storage]
  G --> H[(SQLite / Postgres)]
```

- **解析**：Adapter 依据 `parseConfig` 把 JSONL 转录切分为 `user / assistant / tool_use` 块；
- **切分**：`v0.20.0` 起 scheduler 在 ingest 入口自动对超大会话做 chunk 处理，避免后续 LLM 分类与嵌入触发 token 上限；
- **分类**：`v0.18.0` 引入的分层分类器处理超长会话，并具备 JSON 弹性（`v0.19.0`：重试 + per-chunk 容错）；
- **代码示例抽取**：`v0.15.0` 起，落地会话自动触发 Phase 1 代码示例捕获，`v0.16.0` 增加被动召回（Phase 2）；
- **持久化**：分类与嵌入结果通过 `SqliteStorage` 或 `PgStorage` 持久化，并衍生 `code_exemplar` 行。

会话落地后还参与召回闭环：`RecallService` 在召回时合并 `PointerBlock` 中的"已知事实"（Spec G.2）与代码示例，被 `citation-detect` 标记为"已被代理引用"，构成训练数据回流。

资料来源：[src/core/recall/recall-service.ts:1-40](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/recall-service.ts#L1-L40) | [src/core/storage/sqlite-code-exemplar-store.ts:1-40](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts#L1-L40) | [src/core/storage/pg-code-exemplar-store.ts:1-30](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/pg-code-exemplar-store.ts#L1-L30) | [src/core/hook/pointer-block.ts:1-50](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts#L1-L50) | [src/core/hook/citation-detect.ts:1-40](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts#L1-L40)

## 运行态可见性（Pulse）

UI 的 Pulse 页按 Runtime 维度聚合 ingest 后的会话指标：本周新增、上周新增、累计会话数、最近会话时间，以及该 runtime 下最常出现的实体主题（Topics，cap 20）。运维者可凭此一眼识别某运行时是否在持续接入、是否退化。

资料来源：[src/ui/pages/Pulse.tsx:1-50](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx#L1-L50)

## 失败模式与常见问题

- **MCP 接线缺失**：`nlm doctor` 会同时报告 `claude-code.mcpConfigured` 与 `codex.mcpConfigured`；任一项为 false 即意味着 ingest 不会自动发生，需先执行 `nlm connect ...`。
- **过期 trust 条目**：Codex 注册表中若残留 `@nlm-memory-ts` 字符串，doctor 会标记为 `staleNlmMemoryTs`，防止旧 plugin 接管新版本。
- **超限会话**：`v0.18.0` 之前，分类器在长会话上可能静默失败；`v0.20.0` 后由 scheduler 在 ingest 阶段提前切分，无需手工干预。
- **来源 Token 泄露**：HTTP 列表接口只返回 `hasToken: boolean`；调用 `insert / regenerate` 才会一次性返回明文 token，避免长期泄露。
- **Storage 后端差异**：`SqliteStorage` 与 `PgStorage` 在 `code_exemplar` 表结构上完全一致，但 PG 端需要在迁移中显式声明 `retired_at` 列（`v0.14.1` 修复）。

资料来源：[src/cli/nlm.ts:50-90](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts#L50-L90) | [src/ui/lib/registries.ts:30-60](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts#L30-L60)

## See Also

- Recall Service 与 Citation 检测：[src/core/recall/recall-service.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/recall-service.ts)
- PointerBlock 与召回注入：[src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- Pulse 页 UI：[src/ui/pages/Pulse.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx)
- v0.20.0 Release Notes（auto-chunk oversized sessions on ingest）：https://github.com/pbmagnet4/nlm-memory/releases/tag/v0.20.0
- v0.18.0 Release Notes（hierarchical classification + oversized-session recovery）：https://github.com/pbmagnet4/nlm-memory/releases/tag/v0.18.0

---

<a id='page-3'></a>

## Recall, MCP Tools & REST API

### 相关页面

相关主题：[Overview & System Architecture](#page-1), [Storage Backends, Schema & Migrations](#page-4), [Hooks, Hook Modes & Runtime Integration](#page-5)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/recall/recall-service.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/recall-service.ts)
- [src/core/recall/related-facts.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/related-facts.ts)
- [src/core/recall/rewrite-prompt.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/rewrite-prompt.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/hook/citation-detect.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts)
- [src/core/hook/gate.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/gate.ts)
- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [src/ui/pages/Recall.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Recall.tsx)
- [nlm/README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/nlm/README.md)
</details>

# Recall, MCP Tools & REST API

## 架构总览

`nlm-memory` 通过 `RecallService` 把本地存储、FTS5 关键词检索、向量语义、改写器、相关事实/示例选择器统一为一个无副作用的 use case，对外同时为 MCP 工具、HTTP REST API 与 hook 注入提供召回能力。`RecallService` 显式声明只依赖端口（`SessionStore`、`LLMClient`、`FactStore`、`CodeExemplarStore`、`CodeEmbedder`），不引入框架或数据库，因此测试可以用 fake 适配器替换实现 资料来源：[src/core/recall/recall-service.ts:1-15]()。

整体数据流如下：

```mermaid
flowchart LR
  U[User prompt] --> H[classifyPrompt]
  H -->|evaluate| A[POST /api/recall]
  H -->|generative| X[skip]
  A --> R[RecallService.search]
  R --> RW[rewrite-prompt]
  R --> KW[Keyword match]
  R --> SM[Semantic embed]
  R --> RF[pickRelatedFacts]
  R --> RX[pickRelatedExemplars]
  R --> CIT[detectCitations]
  R --> PB[formatPointerBlock]
  PB --> T[LLM Context]
  T --> MCP[MCP tools]
```

## RecallService 与召回路径

`RecallService.search` 接收 `RecallQuery`，依次执行：模式选择（`keyword` / `semantic` / `hybrid`）、limit 截断、可选实体/类型过滤、查询改写、关键词打分、向量召回、reranker 合并与元数据 tiebreak 资料来源：[src/core/recall/recall-service.ts:48-89]()。

**查询改写**：`rewrite-prompt.ts` 把模糊自然语言查询（"那个 pgvector 的事情"）改写成 keyword + semantic 两种形式；解析失败或形状异常抛 `LLMUnreachableError`，由 `search()` 失败开放到原始 query，避免污染下游打分 资料来源：[src/core/recall/rewrite-prompt.ts:1-50]()。

**相关事实/示例**：当 `withRelatedFacts` 启用时，`pickRelatedFacts` 收集 top-N 命中涉及的实体，从 `FactStore` 抓取非废弃事实并要求至少 2 个 session 共同佐证，排序后取 3–5 条注入 pointer block；环境变量 `NLM_HOOK_FACT_LIMIT`、`NLM_HOOK_FACT_MIN_CORROBORATION`、`NLM_HOOK_FACT_MIN_CONFIDENCE` 可覆盖默认 5/2/0.7 资料来源：[src/core/recall/related-facts.ts:1-30]()。代码示例召回（v0.16.0 Phase 2）走 `pickRelatedExemplars`，需 `exemplarStore` + `codeEmbedder` + `installScope` 三件套同时就位 资料来源：[src/core/recall/recall-service.ts:30-50]()。

**引用检测**：`detectCitations` 识别助手回合引用了哪些被召回的 session ID，作为未来学习 reranker 的训练数据；`tool_use` 通道是模型调用 `get_session`/`recall_facts`/`get_fact_history`/`recall_sessions` 等 MCP 工具时携带 ID 的强信号，`prose` 通道在响应文本中匹配 ID 子串 资料来源：[src/core/hook/citation-detect.ts:1-30]()。

## MCP 工具集与 REST API

`nlm connect` 系列命令把 `nlm-memory` 注册为 Claude Code、Codex、Pi 等运行时的 MCP server。`pointer-block.ts` 在每次召回注入的 prompt 末尾强制列出 NLM MCP 工具清单——这是新装机用户唯一不需要编辑配置就能学到的工具目录 资料来源：[src/core/hook/pointer-block.ts:1-30]()。

核心 MCP 工具：

- `get_session` — 取回完整 session 正文，模型需引用某次会话
- `recall_sessions` — 跨会话关键词/语义检索，通用回忆问题
- `recall_facts` — 结构化事实查询，例如"我对 X 偏好 Y 吗"
- `get_fact_history` — 事实演变轨迹，同一事实需溯源
- `recall_code` — 代码示例向量检索，编码任务前查参考实现

`recall_code` 命令与 `/mcp` transport 在 v0.14.0 / v0.13.1 先后接通，HTTP 路径与 stdio 路径在 `mcpDeps` 上保持完全一致的依赖注入 资料来源：[src/cli/nlm.ts:1-100]()。

CLI 启动 `nlm start` 后，`createApp` 在 `http://localhost:3940` 同时挂载 `POST /mcp`（token 守门）与 `POST /api/recall` 路径；`POST /api/recall` 接收 `mode` 查询参数（`keyword` / `semantic` / `hybrid`），由 `RecallService` 处理后回 JSON 资料来源：[src/cli/nlm.ts:1-100]()。Hook 侧 `classifyPrompt` 是保守的生成式排除器，仅识别 `write/draft/create/...` 等高确定性开头跳回 recall；否则一律评估查询 资料来源：[src/core/hook/gate.ts:1-30]()。Pi 运行时由 `nlm connect pi` 把扩展挂到 `~/.pi/agent/settings.json`，每次 prompt 先打 `localhost:3940/api/recall?mode=keyword` 资料来源：[nlm/README.md:1-30]()。

UI 端 `Recall.tsx` 把 `/api/recall-stats` 拉来的 hit-rate、按来源分布与 top queries 渲染为"采用率"面板，与"覆盖率"并列以区分是没人用还是查不到 资料来源：[src/ui/pages/Recall.tsx:1-30]()。

## 故障模式与限制

- **改写器不可达**：模型挂了或返回非 JSON → 抛 `LLMUnreachableError`，`search()` 失败开放到原始 query，不影响 recall 主路径 资料来源：[src/core/recall/rewrite-prompt.ts:1-50]()。
- **事实/示例选择器异常**：`pickRelatedFacts` / `pickRelatedExemplars` 任何错误一律返回空数组，pointer block 退化为仅 session 列表 资料来源：[src/core/recall/related-facts.ts:1-30]()。
- **Citation 误报**：`MIN_ID_LEN = 6` 防止短 ID 与 prose 误匹配；`tool_use` 通道几乎无假阳性 资料来源：[src/core/hook/citation-detect.ts:1-30]()。
- **Hook 误判 generative**：高确定性反例会错误跳过 recall，是 `gate.ts` 设计上要消除的最差失败模式 资料来源：[src/core/hook/gate.ts:1-30]()。

## See Also

- [Code Exemplars & Recall Lane](Code-Exemplars-and-Recall-Lane.md)
- [Session Ingest & Hooks](Session-Ingest-and-Hooks.md)
- [Local Daemon & Installation](Local-Daemon-and-Installation.md)

---

<a id='page-4'></a>

## Storage Backends, Schema & Migrations

### 相关页面

相关主题：[Runtime Adapters & Session Ingest](#page-2), [Recall, MCP Tools & REST API](#page-3), [CLI, Configuration, Setup & Security](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
- [src/core/storage/sqlite-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts)
- [src/core/storage/pg-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/pg-code-exemplar-store.ts)
- [src/ui/lib/registries.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/recall/related-facts.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/related-facts.ts)

</details>

# 存储后端、Schema 与迁移

## 概述

`nlm-memory` 是一个本地优先（local-first）的非线性记忆操作系统（v0.20.0），其存储层采用**端口-适配器（Ports & Adapters）**模式，将具体数据库实现与上层业务逻辑解耦。整个栈的唯一组合根（composition root）是 `src/cli/nlm.ts`，它负责把 `SqliteSessionStore`、`OllamaClient`、`Hono`、`McpServer` 等具体实现装配起来；其他模块只依赖端口（ports）接口。资料来源：[src/cli/nlm.ts:1-19]()

存储层提供两个可互换后端：

| 后端 | 引擎 | 适用场景 | 关键依赖 |
|------|------|----------|----------|
| SQLite（默认规范库） | `better-sqlite3` + `sqlite-vec` | 本地单机、嵌入式安装 | `better-sqlite3@^12.10.0`, `sqlite-vec@^0.1.6` |
| PostgreSQL | `pg` + `pgvector` | 团队共享、需要 pgvector 扩展 | `pg@^8.21.0`, `pgvector@^0.3.0` |

资料来源：[package.json:1-90]()

发布产物 `files` 数组中包含 `dist`、`migrations`、`plugin`、`nlm`、`assets` 与许可文件，表明迁移脚本与 CLI 同包发布。资料来源：[package.json:30-40]()

## 存储后端架构

`nlm-memory` 的双后端设计源于其本地优先定位，同时保留向集中式部署升级的路径。`src/cli/nlm.ts` 中 `doctor` 子命令会根据运行时类型分发修复逻辑：

```ts
if (storage instanceof PgStorage) { /* PG 路径 */ } else { /* SQLite 路径 */ }
```

资料来源：[src/cli/nlm.ts:1-90]()

CLI 还显式导入并调用以下存储子系统，分别承担不同职责：

- `SqliteStorage` / `PgStorage` — 协议实现（位于 `src/core/storage/`，未在本文检索范围内）
- `applyPendingRestore` 与 `stageRestore`（来自 `src/core/storage/db-restore.ts`）— 数据库恢复管线
- `listBackupDates`、`resolveBackup`、`runRollingBackup`（来自 `src/core/storage/backup-rotation.ts`）— 滚动备份与轮转

资料来源：[src/cli/nlm.ts:30-45]()

下图展示了请求从 CLI 经过应用层到具体后端实现的典型路径：

```mermaid
flowchart LR
  CLI[nlm CLI] --> App[Hono HTTP / MCP]
  App -->|端口| Storage[Storage Port]
  Storage --> SQLite[(SQLite + sqlite-vec)]
  Storage --> PG[(PostgreSQL + pgvector)]
  SQLite --> Backup[db-restore + backup-rotation]
  PG --> Backup
  Backup --> Migrations[migrations/ 目录]
```

## Schema 与领域存储

存储后端承载多类领域对象，每一类都对应独立存储端口与具体实现。已知的领域存储包括：

### 会话存储（SessionStore）

由 `SqliteSessionStore`（推断自 `src/cli/nlm.ts:32` 的 `SqliteSessionStore` 注释）与对应 PG 实现承载，记录 AI 运行时的完整会话。

### 事实存储（FactStore）

用于结构化事实（subject/predicate/value），供 agent 在任务中途拉取。v0.14.1 的 `fix(pg): add facts.retired_at to the PG schema` 显示事实表具有退役时间字段，PG 与 SQLite 模式需同步演进。资料来源：[社区发布说明 v0.14.1]()

### 信号存储（SignalStore）

支撑主题（topic）与运行时（runtime）信号聚合，支撑 `Pulse` 页面上的「This week / Last week / Total sessions / Last session」指标。资料来源：[src/ui/pages/Pulse.tsx:1-40]()

### 代码样本存储（CodeExemplarStore）

存储从已提交会话中自动捕获的代码样本。SQLite 与 PG 两侧均使用确定性主键：

```ts
id = sha256(installScope|repo|codeHash|outcome).slice(0, 16)
```

保证同一 (scope, repo, 代码内容, outcome) 组合只产生一行。资料来源：[src/core/storage/sqlite-code-exemplar-store.ts:1-50]()

PG 端使用相同 ID 生成策略，但通过位置化参数（`$1, $2, ...`）绑定字段，行类型 `ExemplarRow` 与 SQLite 端的列名命名风格（`snake_case`）保持一致，以便上层共用类型映射。资料来源：[src/core/storage/pg-code-exemplar-store.ts:1-60]()

### 数据源注册表

`src/ui/lib/registries.ts` 暴露的 `SourceKind` 包含六类摄取来源：`claude-code`、`codex`、`hermes`、`pi`、`jsonl-generic`、`webhook`。v0.14.0 的「runtime-test the webhook ingestSession PG branch」表明 `webhook` 通道已在 PG 后端得到运行时测试覆盖。资料来源：[src/ui/lib/registries.ts:1-50]()、[社区发布说明 v0.14.0]()

## 迁移、备份与恢复

CLI 通过 `nlm migrate` 子命令对规范 SQLite 库运行待执行的迁移脚本；`migrations/` 目录与编译产物同包发布，便于在新机器上一次性应用。资料来源：[package.json:30-40]()

日常运维通过 `db-restore` 与 `backup-rotation` 模块完成：

- `applyPendingRestore` / `stageRestore` — 在 CLI 启动时检测挂起的恢复操作并原子地应用
- `listBackupDates` — 列出可选的备份日期
- `resolveBackup` — 按标识符解析具体备份
- `runRollingBackup` — 执行滚动备份

资料来源：[src/cli/nlm.ts:30-45]()

社区版本中以下变更涉及存储层演进路径：

| 版本 | 变更 | 影响 |
|------|------|------|
| v0.20.0 | `feat(scheduler): auto-chunk oversized sessions on ingest` | 摄取阶段对超大会话自动分块，缓解单行膨胀 |
| v0.14.1 | `fix(pg): add facts.retired_at to the PG schema` | PG 模式补齐事实退役时间字段 |
| v0.14.0 | `feat(exemplars): Postgres backend` | 代码样本存储新增 PG 后端 |
| v0.13.0 | `feat(pg): clear app.ts of all rawDb/cast escape hatches` | 应用层清空直接 DB 访问，统一走注册表与 action |

## 常见故障模式

1. **迁移缺失** — 直接运行 `nlm start` 前未执行 `nlm migrate` 会导致 `facts.retired_at` 等列不存在；先运行迁移子命令可解决。资料来源：[package.json:30-40]()
2. **PG/SQLite 模式漂移** — 历史上 PG 与 SQLite 字段演进不同步（如 v0.14.1 的 `retired_at` 修复），升级前需确认两库均已应用最新迁移。
3. **存储类型误用** — `app.ts` 历史上曾出现 `rawDb/cast` 逃生通道（v0.13.0 已清理），新增代码应继续走端口契约，避免再次出现方言泄漏。
4. **超大会话** — 升级到 v0.20.0 之前可能因单行内容过大触发摄取失败；调度器的自动分块是推荐的规避手段。

## 参见

- 召回管线（Query Rewriting 与相关事实选择）
- MCP 与 HTTP 传输
- 备份与灾难恢复流程

---

<a id='page-5'></a>

## Hooks, Hook Modes & Runtime Integration

### 相关页面

相关主题：[Recall, MCP Tools & REST API](#page-3), [CLI, Configuration, Setup & Security](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/hook/transcript.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/transcript.ts)
- [src/core/hook/citation-detect.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts)
- [src/ui/components/README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/README.md)
- [src/ui/pages/Pulse.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx)
- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
</details>

# Hooks, Hook Modes & Runtime Integration

## 概览

`nlm-memory` 是一个本地优先（local-first）的非线性记忆操作系统，专为 AI 算子设计 [package.json:1-10](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)。其 **Hook（钩子）系统** 是连接外部 AI 运行时（Claude Code、Codex、Hermes、Cursor、Windsurf、OpenCode、Pi 等）与本地记忆服务（HTTP/MCP 守护进程）的桥梁。Hook 在外部 agent 触发特定事件（如 Stop、UserPromptSubmit、PreToolUse）时自动调用 `nlm` 守护进程，把会话上下文转化为可被 recall 的指针、事实和代码样本 [src/cli/nlm.ts:18-44](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)。

Hook 子系统遵循"组合根（composition root）"模式——`src/cli/nlm.ts` 是唯一知道所有具体实现（`SqliteSessionStore`、`OllamaClient`、`Hono`、`McpServer`）的文件，core/ 中其他模块只依赖端口（ports）[src/cli/nlm.ts:46-58](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)。这意味着新增运行时只需修改 CLI 入口，而不动核心逻辑。

## Hook 模式

Hook 系统支持两种工作模式，由 `nlm hook install` 命令启用时确定：

| 模式 | 行为 | 用途 |
|------|------|------|
| **Shadow（影子）** | 只记录、不注入 | 评估 recall 准确率、收集训练数据 |
| **Live（实时）** | 把指针块注入上下文 | 生产使用，让 agent 主动调用 NLM 工具 |

Shadow 模式让用户在不改写 prompt 的情况下观察 recall 表现；Live 模式则将 `formatPointerBlock` 渲染的指针块直接拼到用户消息中。指针块是**纯指针**的：只包含 id + label + 摘要，不暴露会话正文，这是"新鲜安装用户从不编辑 prompt 或 settings 文件"约束下的核心分发面 [src/core/hook/pointer-block.ts:7-21](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)。

```mermaid
flowchart LR
    A[AI Runtime<br/>Stop Hook] -->|transcript_path| B[nlm hook handler]
    B --> C[Recall Service]
    C --> D[Pointer Block]
    D -->|Shadow| E[Log Only]
    D -->|Live| F[Inject into Context]
    F --> G[Agent 主动调用<br/>get_session / recall_facts]
    G --> H[Citation Detect]
    H --> I[Cite Memo<br/>训练数据]
```

指针块底部会列出全部四个 NLM MCP 工具名（`get_session`、`recall_facts`、`get_fact_history`、`recall_sessions`），并可选附加事实（Spec G.2）和代码样本（Phase 2 引入）[src/core/hook/pointer-block.ts:25-46](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)。

## 运行时集成

CLI 提供了统一的安装/卸载/连接/断开接口，覆盖多类 agent 运行时 [src/cli/nlm.ts:36-44](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)：

- `nlm connect claude-code` — 写入 `~/.mcp.json`
- `nlm connect codex` — 安装 Codex marketplace 插件
- `nlm connect hermes` / `hermes-agent` — Hermes 集成（agent 插件目录）
- `nlm connect cursor` / `windsurf` / `opencode` / `pi` — 编辑器侧集成
- `nlm disconnect <runtime>` — 对称移除（含 `--dry-run` 预演）

Doctor 命令会探测每个运行时的连接状态：当检测到 `~/.codex/config.toml` 中残留 `@nlm-memory-ts`（Codex 自身的注册项）时报告为 `staleNlmMemoryTs: true`，避免误判 [src/cli/nlm.ts:95-114](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)。

UI 层（Vite + React SPA）通过 `src/ui/pages/Pulse.tsx` 展示每个 runtime 的活跃度、话题和会话数，支持分页和抽屉详情。Skeleton 组件只用于形状已知且首屏延迟明显的场景，缓存刷新时不会再次展示骨架屏 [src/ui/components/README.md:11-22](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/README.md)，[src/ui/pages/Pulse.tsx:8-30](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx)。

## 关键组件

### Transcript Reader

`src/core/hook/transcript.ts` 从 Claude Code 的 JSONL transcript 中解析所有 assistant turn。Stop-hook 的引用检测需要**整个**会话的 tool_use 序列，而非仅最后一轮——模型通常先调工具、读结果、再写总结。读取失败时必须 fail-quiet，不能因 transcript I/O 错误中断 hook 链路 [src/core/hook/transcript.ts:7-22](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/transcript.ts)。

### Citation Detector

`detectCitations` 实现了两个有序通道：**tool_use**（强信号，模型实际调用了引用 ID 的工具）和 **prose**（弱信号，ID 出现在响应正文中）。最小 ID 长度过滤避免短 token 误命中。该模块的输出是未来学习型重排器（learned reranker）的训练数据基底 [src/core/hook/citation-detect.ts:7-32](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts)。

### 版本与变更追踪

最新稳定版 v0.20.0 引入了调度器对超大会话的自动分块（auto-chunk oversized sessions on ingest，PR #341）[package.json:2-2](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)。v0.13.1 修复了代码样本通道接入 HTTP `/mcp` 传输的接线问题；v0.14.0 进一步把代码样本后端迁到 Postgres 并保证 `recall_code` MCP 工具可用。运维侧硬化（`nlm doctor --fix`、`nlm verify`、`nlm codex-repair`）以及每日滚动备份在 v0.13.0 一起落地，详见社区变更日志。

## 常见失败模式

1. **Hook 未触发** — `nlm doctor` 会报告 `claudeCode.mcpConfigured`、`codex.mcpConfigured` 状态，可据此判断 wiring 是否生效 [src/cli/nlm.ts:98-114](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)。
2. **指针块为空** — `formatPointerBlock` 在 hits/facts/exemplars 全为空时返回 `""`；这意味着 recall 未命中，需要检查嵌入模型与回填状态。
3. **断开不彻底** — Codex 插件与 marketplace 卸载可能部分失败，CLI 采用"best-effort 移除 + 单独报错"的策略，调用方可重复运行直到完全清理 [src/cli/nlm.ts:62-78](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)。

## See Also

- [README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/README.md) — 项目总览与快速上手
- [CHANGELOG](https://github.com/pbmagnet4/nlm-memory/releases) — 完整版本变更记录
- `src/core/recall/` — Recall 服务、查询改写（rewrite-prompt）实现
- `src/install/` — 多运行时安装、规则文件、Ollama 健康检查
- `src/ui/components/README.md` — UI 组件库规范（Drawer、Pagination、Skeleton 等）

---

<a id='page-6'></a>

## Agent Self-Improvement Signals & Code Exemplars

### 相关页面

相关主题：[Recall, MCP Tools & REST API](#page-3), [Storage Backends, Schema & Migrations](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/storage/sqlite-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts)
- [src/core/storage/pg-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/pg-code-exemplar-store.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/hook/citation-detect.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/citation-detect.ts)
- [src/core/hook/strip-injected-context.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/strip-injected-context.ts)
- [src/core/recall/related-facts.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/related-facts.ts)
- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
</details>

# Agent Self-Improvement Signals & Code Exemplars

## 概述与定位

`nlm-memory` 是一个面向 AI 代理的"本地优先非线记忆操作系统"，其核心目标之一是让代理在多次会话之间形成可积累的"自我改进"能力，而不只是把上下文塞满一次性的提示窗口。围绕这一目标，系统引入了**信号（Signals）**与**代码示例（Code Exemplars）**两条数据线：前者记录代理在推理过程中产生的可观察事件，后者把"被实际采用并存活下来"的代码片段沉淀为可复用资产，二者共同构成代理随时间自我打磨的反馈基底 [资料来源：[src/cli/nlm.ts:1-30]()][资料来源：[package.json:1-15]()]。

代码示例子系统从 v0.14.0 起获得 Postgres 后端与 `recall_code` MCP 工具保证 [v0.14.0]，v0.15.0 引入"自动捕获已提交会话中的代码示例"（Phase 1）[v0.15.0]，v0.16.0 进一步提供"被动代码示例召回"（Phase 2）[v0.16.0]，v0.13.1 修复了 HTTP `/mcp` 传输未挂接该通道的问题 [v0.13.1]。

## 数据模型与存储

代码示例的类型契约 `CodeExemplar` 在 SQLite 与 Postgres 两套实现间保持一致，字段包括 `installScope`、`signalId`、`sessionId`、`repo`、`model`、`lang`、`taskContext`、`code`、`codeHash`、`outcome`、`gitSha`、`survived`、`ts`、`createdAt`、`retiredAt`、`labelSource` 等 [资料来源：[src/core/storage/sqlite-code-exemplar-store.ts:1-40]()][资料来源：[src/core/storage/pg-code-exemplar-store.ts:1-40]()]。主键使用确定性哈希：

```ts
sha256(installScope|repo|codeHash|outcome).slice(0, 16)
```

其语义保证"同一安装范围、同一仓库、同一段代码、同一结果"仅产生一条记录，便于跨会话去重与版本对比 [资料来源：[src/core/storage/sqlite-code-exemplar-store.ts:30-50]()]。

两个后端共享 `exemplarId()` 计算逻辑，差异主要在 SQL 绑定方式：SQLite 使用 `better-sqlite3` 的预编译 `insertStmt()`，Postgres 使用参数化 `INSERT INTO code_exemplars (...)` 数组绑定，二者写入失败均以 `{ id, skipped }` 形式返回，调用方可据此区分"新写入"与"命中已存在" [资料来源：[src/core/storage/sqlite-code-exemplar-store.ts:50-80]()][资料来源：[src/core/storage/pg-code-exemplar-store.ts:40-70]()]。

## 上下文注入与指针块

被动召回的关键载体是"指针块"（Pointer Block）。它是纯文本块，由 `formatPointerBlock()` 渲染，不携带会话正文，只包含 ID、标签、`startedAt` 与可选 `summary`，目的是让代理在最小上下文成本下决定"是否值得拉取" [资料来源：[src/core/hook/pointer-block.ts:1-30]()]。指针块同时承载会话、事实与示例三段内容：

```ts
formatPointerBlock(hits, facts = [], exemplars = [])
```

当 `exemplars` 非空时，块内会追加代码示例条目，结构由 `PointerExemplar` 接口约束：`{ outcome, lang, repo, taskContext }` [资料来源：[src/core/hook/pointer-block.ts:25-45]()]。这样设计的好处是指针块成为跨运行时（Claude Code、Codex、Hermes 等）唯一稳定分发面，新装用户无需修改任何 prompt 或 settings 文件即可感知到示例通道 [资料来源：[src/core/hook/pointer-block.ts:1-15]()]。

为了避免代理"看到自己之前的注入内容又被回灌"，`stripInjectedContext()` 在会话落库前清除块头与脚标：块头包括 `## Possibly-relevant prior sessions (nlm-memory)` 与 `## Known facts about top entities`，脚标为 `NLM tools:` 开头行；清除时还会把因此产生的 3+ 连续空行折叠为单行 [资料来源：[src/core/hook/strip-injected-context.ts:1-30]()][资料来源：[src/core/hook/strip-injected-context.ts:30-50]()]。这一机制确保示例注入对下游 LLM 是"无痕"的，避免污染后续分类与摘要任务。

## 引用检测与信号回流

被注入只是第一步，系统还需要判断代理**是否真的引用了**给到的示例，这由 `detectCitations()` 完成。识别按信号强度分两层：

| 通道 | 判定方式 | 误报率 |
|------|----------|--------|
| `tool_use` | 代理调用 `get_session` / `recall_facts` / `get_fact_history` / `recall_sessions` 等 MCP 工具且参数含被注入 ID | 极低 |
| `prose` | ID 字符串直接出现在响应文本中 | 模型极少回显，触发罕见 |

`MIN_ID_LEN = 6` 阈值用于过滤短通配串带来的误命中 [资料来源：[src/core/hook/citation-detect.ts:1-30]()]。返回值 `DetectedCitation[]` 同时携带 ID 与通道类型，可作为未来学习式重排模型的训练数据 [资料来源：[src/core/hook/citation-detect.ts:30-50]()]。

与示例并行的另一条信号线是"已知事实"。`pickRelatedFacts()` 在被召回的 Top-5 命中涉及的实体集合上，挑选置信度 ≥ 0.7 且至少被 2 个不同会话佐证过的事实，注入到指针块的 `## Known facts` 区段；该函数内部对超集与置信度阈值的失败采用"快速失败为空数组"策略，绝不阻塞主召回路径 [资料来源：[src/core/recall/related-facts.ts:1-30]()]。

## 失败模式与边界

常见问题与对应边界条件：

- **示例未生效**：检查会话是否被标记为 `committed`，只有 committed 会话才会进入 Phase 1 自动捕获管线 [v0.15.0]；
- **`recall_code` 不可达**：v0.13.1 修复了 HTTP `/mcp` 通道未挂接示例通道的问题，升级后即可 [v0.13.1]；
- **Postgres 端 `facts.retired_at` 列缺失**：v0.14.1 显式补齐该列，部署时需确认迁移已应用 [v0.14.1]；
- **指针块回灌**：若 `stripInjectedContext()` 漏掉新块头，需同步更新 `BLOCK_HEADERS` 数组 [资料来源：[src/core/hook/strip-injected-context.ts:5-15]()]。

## See Also

- nlm-memory 主项目首页：<https://github.com/pbmagnet4/nlm-memory>
- Release 索引：<https://github.com/pbmagnet4/nlm-memory/releases>
- 召回架构与查询改写：参见 `src/core/recall/rewrite-prompt.ts`
- 安装与连接流程：参见 `src/cli/nlm.ts` 中 `connect` / `disconnect` 子命令

---

<a id='page-7'></a>

## CLI, Configuration, Setup & Security

### 相关页面

相关主题：[Overview & System Architecture](#page-1), [Hooks, Hook Modes & Runtime Integration](#page-5), [UI Pages, Daily Digest & Telemetry](#page-8)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
- [src/core/recall/rewrite-prompt.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/rewrite-prompt.ts)
- [src/core/storage/sqlite-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts)
- [src/ui/lib/registries.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/lib/registries.ts)
- [src/ui/components/README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/README.md)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
</details>

# CLI, Configuration, Setup & Security

nlm-memory 的 CLI (`nlm`) 是整个栈的"组合根",在 `src/cli/nlm.ts` 中集中装配后端实现、HTTP 服务、MCP 传输和外部编辑器连接。本页聚焦于该 CLI 的命令结构、配置机制、首次安装流程以及与安全相关的设计。

## CLI 入口与子命令

`nlm` 命令是 Node 22+ 的 ESM 可执行文件,通过 `package.json` 中 `"bin": { "nlm": "dist/cli/nlm.js" }` 暴露 [资料来源：[package.json]()]。文件顶部的注释明确指出:`nlm.ts` 是唯一知道所有具体实现的文件,其他模块都通过端口 (port) 依赖注入,后端替换仅需编辑此文件 [资料来源：[src/cli/nlm.ts:25-26]()]。

CLI 主要子命令包括:

| 子命令 | 作用 |
| --- | --- |
| `start` | 启动 HTTP 服务(默认端口 `$NLM_PORT`, 默认 3940) |
| `migrate` | 对 SQLite 规范库执行待处理迁移 |
| `recall` | 一次性从 shell 发起 recall 查询(调试用) |
| `mcp` | 以 MCP stdio 服务运行,用于 `~/.mcp.json` 接入 |
| `setup` | 交互式首次安装向导(推荐入口) |
| `install` / `uninstall` | 注册/移除 macOS LaunchAgent(开机自启) |
| `hook install` / `hook uninstall` | 给 Claude Code 注入/移除 recall hook |
| `connect <runtime>` / `disconnect <runtime>` | 接入/移除 Claude Code、Codex、Hermes、Cursor、Pi、Windsurf、Opencode 等编辑器的 MCP 配置块 |
| `doctor` | 校验数据库完整性,可选 `--fix` 安全修复自环边 (I1)、孤立 superseded 会话 (I2) |
| `backfill-facts` | 对历史会话跑分类器并填充 FactStore (Phase B.5) |

资料来源:[src/cli/nlm.ts:13-23](),[src/cli/nlm.ts:71-94]()

`doctor` 子命令报告四个维度的健康状况:daemon 连通性与版本、`~/.nlm/.env` 状态、Claude Code `~/.mcp.json` 是否包含 MCP 块、Codex `config.toml` 与 marketplace 插件情况——同时还检测 `nlm-memory-ts` 这种陈旧条目以避免误判 [资料来源：[src/cli/nlm.ts:38-56]()]。

## 配置与分类器选择

CLI 通过环境变量驱动后端选择。`buildClassifier()` 在 `nlm.ts` 中实现,默认走 Ollama(`NLM_CLASSIFIER` 未设置时),生产模型为 `qwen3.5:4b`;若切换至 DeepSeek,则使用 `deepseek-v4-flash` [资料来源：[src/cli/nlm.ts:138-148]()]。Ollama 端点来自 `OLLAMA_URL` 环境变量,默认 `http://localhost:11434`,以保持"本地优先、无密钥"的姿态 [资料来源：[src/cli/nlm.ts:134-137]()]。

`buildAdapters()` 表明:数据源表 `sources` 是注册真相,每个启用行通过 `adapterFromSource()` 映射到对应 adapter;`NLM_ADAPTERS` 仍作为基于名字的子集过滤器用于开发期强制筛选 [资料来源：[src/cli/nlm.ts:151-160]()]。`backfill-facts` 提供 `--limit`、`--from <session-id>`、状态文件 resume、`--dry-run`、`--reprocess`、`--no-embed` 等丰富开关,适合长任务分批恢复 [资料来源：[src/cli/nlm.ts:189-201]()]。Recall 侧的查询改写在 `src/core/recall/rewrite-prompt.ts` 中以严格 JSON 输出 `keywordQuery` / `semanticQuery`,失败时 fail-open 回到原始查询,避免对下游打分造成静默污染 [资料来源：[src/core/recall/rewrite-prompt.ts:1-21]()]。

## 首次安装与安全硬化

`runSetup` 通过 `@clack/prompts` 实现交互式向导(作为依赖声明在 `package.json` 中 [资料来源：[package.json]()]）。`nlm install` 注册 macOS LaunchAgent 实现登录自启;`connect` 家族命令会读取 `~/.codex/config.toml` 检测 `[mcp_servers.nlm-memory]` 块,但不会误把 Codex 自身的 `[projects."…/nlm-memory-ts"]` 信任条目当作 nlm 残留 [资料来源：[src/cli/nlm.ts:39-49]()]。`disconnect codex` 阶段以"尽力而为"语义执行 plugin 与 marketplace 卸载,即使部分清理已先发生,也不会中断流程 [资料来源：[src/cli/nlm.ts:99-114]()]。v0.13.0 引入的 install hardening 包含 `doctor` / `verify` / `codex-repair` 与每日备份,直接服务于"可恢复、可审计"的运维姿态 [资料来源：v0.13.0 release]()。

## 安全:Token、目录权限与响应脱敏

Token 安全方面,`ensureMcpToken` 在安装阶段生成 `NLM_MCP_TOKEN`,`~/.nlm/.env` 路径由 `join(homedir(), ".nlm", ".env")` 拼出,`hardenNlmDirPermissions` 负责收紧 `~/.nlm` 目录权限。`doctor` 输出明确报告 `hasMcpToken: Boolean(process.env["NLM_MCP_TOKEN"])`,便于环境审计 [资料来源：[src/cli/nlm.ts:46-58]()]。UI 侧在 `src/ui/lib/registries.ts` 中明确:HTTP 响应中的 `SourceRow` / `ProviderRow` 永远不返回 `api_key` 与 `source token`,仅在插入或重新生成时一次性"揭示 (reveal)" 原始值 [资料来源：[src/ui/lib/registries.ts:1-9]()]。

Pointer 注入层面,`formatPointerBlock` 仅向 agent 暴露 id 与 label,不泄露会话正文,符合"指针不外带内容"原则 [资料来源：[src/core/hook/pointer-block.ts:1-15]()]。代码示例入库采用确定性主键 `sha256(installScope|repo|codeHash|outcome)[:16]`,保证同一 (scope, repo, 精确代码, 后果) 去重 [资料来源：[src/core/storage/sqlite-code-exemplar-store.ts:18-30]()]。`retired_at` 字段在 v0.14.1 补齐到 PG schema,实现软删除与可追溯的"召回体面退役"。

## 常见失败模式

1. **Codex 残留配置**:`disconnect codex` 未一并清理 marketplace 时,`doctor` 报告 `mcpConfigured=false` 但运行时仍能命中旧插件;以 `--withHooks` 同步剥离 `~/.codex/hooks.json`。
2. **分类器超时**:qwen3.5:4b 在超时预算(180s)下需 `think:false`,由 `ClassifierBox` 通过 `classifierNeedsThinkDisabled` 统一处理;若误用带思考的 prompt 模板,recall 评分会整体下移。
3. **查询改写崩解析**:`REWRITE_SYSTEM_PROMPT` 输出非 JSON 时 `RewriteResult` 解析抛错,已通过"返回原文"路径安全降级 [资料来源：[src/core/recall/rewrite-prompt.ts:30-50]()]。
4. **本地 Ollama 缺失**:`embeddingModelPresent` / `ollamaModelPresent` 引导用户拉取模型,`embedding` 缺位时 `backfill-facts --no-embed` 可绕过以保进度。

## See Also

- [Code Exemplars & Recall](./code-exemplars-recall.md)
- [Postgres & SQLite Storage](./storage.md)
- [MCP Integration & Hooks](./mcp-integration.md)

---

<a id='page-8'></a>

## UI Pages, Daily Digest & Telemetry

### 相关页面

相关主题：[Overview & System Architecture](#page-1), [Recall, MCP Tools & REST API](#page-3), [CLI, Configuration, Setup & Security](#page-7)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/ui/pages/Pulse.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx)
- [src/ui/pages/Recall.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Recall.tsx)
- [src/ui/pages/Thread.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Thread.tsx)
- [src/ui/pages/Stub.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Stub.tsx)
- [src/ui/components/Pagination.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/Pagination.tsx)
- [src/ui/components/Skeleton.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/Skeleton.tsx)
- [src/ui/components/README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/README.md)
- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts)
- [src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts)
- [src/core/hook/strip-injected-context.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/strip-injected-context.ts)
- [src/core/recall/rewrite-prompt.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/rewrite-prompt.ts)
- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json)
</details>

# UI 页面、每日摘要与遥测

nlm-memory v0.20.0 是一个本地优先的 AI 算子非线性记忆操作系统，其前端目前正从 Astro 迁移到 Vite + React SPA（参见 [src/ui/pages/Stub.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Stub.tsx)）。本页覆盖三大主题：用户界面的核心页面（Pulse / Recall / Thread）、`nlm digest` 每日活动摘要命令，以及 Recall 调用遥测的实现位置与口径。

## UI 页面概览

### Pulse 页 — 运行时与主题活跃度

[src/ui/pages/Pulse.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Pulse.tsx) 展示每个运行时的 `this_week`、`last_week`、`sessions_total`、`last_session_at` 等 KPI，并按主题一致性（coherence）分为三档：`active`（3+ 会话且 30 天内被触及）、`sparse`（仅 1–2 会话但最近被触及）、`stale`（30 天以上未触及）。`COHERENCE_HINT` 字典为用户提供从一档迁移到另一档时的判断依据。该页通过 `Pagination` 组件在 `footer` 槽中分页会话列表，并以 `runtime-topics` 渲染前 20 个主题芯片，超出时折叠显示。

### Recall 页 — 采用率与覆盖率遥测

[src/ui/pages/Recall.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Recall.tsx) 区分两类受众：**Session recall**（编排器回答历史问题时拉取，运维者面）与 **Fact recall**（代理在任务中途拉取结构化事实，代理面）。两条曲线互补——命中率回答"recall 是否返回了东西"，"by source" 回答"是否有任何东西调用它"，合起来区分采用率问题与语料覆盖问题。`EMPTY_SESSION` / `EMPTY_FACT` 默认值用于首屏无数据时稳定渲染。

### Thread 页 — 实体挑选器

[src/ui/pages/Thread.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Thread.tsx) 的 `EntityPicker` 通过 `entityRuntimeMap` 把每个实体映射到出现过的运行时集合，按 `most-active / least-active / a-z / z-a` 排序，`ENTITY_PAGE_SIZE_OPTIONS` 默认 `[24, 48, 96]`。该模式在 Stub.tsx 注释中明确指出尚未从 Astro UI 完全移植。

### Stub 页 — 迁移占位

[src/ui/pages/Stub.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Stub.tsx) 返回 `.stub-shell`，明确指向 NocoDB #95（Vite + React SPA 移植任务）作为追踪来源。

## 通用组件规范

[src/ui/components/README.md](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/README.md) 规定：

- **Drawer**：所有右侧滑入面板统一通过 `<Drawer>`，由其接管 backdrop 点击、Escape、焦点容器、`.drawer-head / .drawer-body` 结构。`blockEsc={mergeSource !== null}` 用于合并操作嵌套转义。
- **Pagination**：[src/ui/components/Pagination.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/Pagination.tsx) 是唯一分页器，`total === 0` 时返回 `null`。`DEFAULT_SIZES = [10, 25, 50]`，页码从 0 开始。
- **Skeleton**：[src/ui/components/Skeleton.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/components/Skeleton.tsx) 仅在形状已知且数据获取足够慢以致页面从 "Loading…" 跳变到填充内容显得突兀时使用；缓存的重新获取复用旧数据，永不显示骨架。
- **Format**：`fmt.plural`、`fmt.percent`、`fmt.shortDate`、`fmt.daysBetween`、`relativeAge` 取代内联的 `toLocaleString()` 与 `n === 1 ? "" : "s"` 模式。

## 每日活动摘要（Daily Digest）

`nlm digest` 由 [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts) 的文件头注释声明，用于打印每日活动摘要，或通过 `--telegram` 标志发送到 Telegram。该命令运行在 CLI 组合根，所有具体后端（SqliteSessionStore、OllamaClient、Hono、McpServer）仅在此文件中出现。其他模块通过端口依赖，替换后端只需编辑这一个文件——这种"composition root"模式让 digest 子命令与 HTTP 服务器、MCP stdio 服务器、LaunchAgent 安装器共用同一套构建管线。

## Recall 遥测与 Hook 注入

[src/core/hook/pointer-block.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/pointer-block.ts) 渲染 live 模式下由 recall hook 注入的指针块——纯展示，仅包含 `id` 与 `label`，不携带会话内容。底部固定列出全部 NLM MCP 工具名，因为指针块是跨运行时教学工具清单的唯一分发面；新装用户从不编辑提示词或设置文件，所有工具信息必须随此块一同发布。`PointerFact` 字段 `<subject> <predicate>: <value> [N sessions]` 为代理提供与指针并行的结构化上下文。

[src/core/hook/strip-injected-context.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/hook/strip-injected-context.ts) 的反向操作：`FOOTER_PREFIX = "NLM tools:"`，与 `BLOCK_HEADERS` 中的两段标题配对，从代理输出中剥离已注入上下文，避免重复渲染。`collapseBlankRuns` 把 3+ 连续空行折成一行。

[src/core/recall/rewrite-prompt.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/recall/rewrite-prompt.ts) 中的查询改写是 Recall 遥测的上游闸口——改写错则所有下游打分静默污染，故输出严格 JSON；解析失败抛出 `LLMUnreachableError` 让调用方回退到原始查询而非嵌入垃圾。

```mermaid
flowchart LR
  A[Claude/Codex prompt] --> B[Recall Hook]
  B --> C{rewrite-prompt}
  C -->|JSON ok| D[Keyword + Semantic query]
  C -->|parse fail| E[Fallback: raw query]
  D --> F[pointer-block.ts]
  F --> G[Pointer block + NLM tools footer]
  G --> A
  H[nlm digest] --> I[Telegram / stdout]
  J[Recall.tsx] --> K[session + fact hit rate]
```

## 失败模式与版本说明

- **Astro → SPA 移植**：未移植路由通过 [src/ui/pages/Stub.tsx](https://github.com/pbmagnet4/nlm-memory/blob/main/src/ui/pages/Stub.tsx) 占位，避免空白页与 404 混淆。
- **空集合渲染**：`Pagination` 在 `total === 0` 时返回 `null`，Recall 页用 `EMPTY_SESSION` / `EMPTY_FACT` 常量稳定首屏，避免组件树随 undefined 抖动。
- **JSON 韧性**：[package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json) 当前版本 0.20.0 在 v0.19.0 引入"JSON-resilience — retry + per-chunk tolerance"，与 rewrite-prompt 的"失败开放回退"策略互补：前者重试直到成功，后者立即回退防止污染。
- **Postgres 与 SQLite 后端并存**：v0.14.0 引入 Postgres 代码示例后端（[src/core/storage/pg-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/pg-code-exemplar-store.ts)），并与 [src/core/storage/sqlite-code-exemplar-store.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/core/storage/sqlite-code-exemplar-store.ts) 共享 `ExemplarRow` 字段语义；Telemetry 指标在两个后端上口径一致。

## 参见

- [package.json](https://github.com/pbmagnet4/nlm-memory/blob/main/package.json) — 项目元数据与脚本入口
- [src/cli/nlm.ts](https://github.com/pbmagnet4/nlm-memory/blob/main/src/cli/nlm.ts) — CLI 组合根与 `digest` 子命令
- 每日 digest 通过 `--telegram` 标志外发，与 `nlm doctor` 安装健康检查共用同一状态机

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：pbmagnet4/nlm-memory

摘要：发现 7 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。

## 1. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 证据：capability.host_targets | https://github.com/pbmagnet4/nlm-memory | host_targets=claude_code, claude, cursor, mcp_host, chatgpt

## 2. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/pbmagnet4/nlm-memory | README/documentation is current enough for a first validation pass.

## 3. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/pbmagnet4/nlm-memory | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/pbmagnet4/nlm-memory | no_demo; severity=medium

## 5. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/pbmagnet4/nlm-memory | no_demo; severity=medium

## 6. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/pbmagnet4/nlm-memory | issue_or_pr_quality=unknown

## 7. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/pbmagnet4/nlm-memory | release_recency=unknown

<!-- canonical_name: pbmagnet4/nlm-memory; human_manual_source: deepwiki_human_wiki -->
