# https://github.com/IngTian/witness 项目说明书

生成时间：2026-07-26 20:27:44 UTC

## 目录

- [项目概览](#page-1)
- [系统架构与四层蒸馏管线](#page-2)
- [数据存储与档案结构](#page-3)
- [Lens 镜头系统与自定义领域](#page-4)
- [MCP 服务与智能体集成](#page-5)
- [平台适配与 ingest 记录入口](#page-6)
- [安装、发行版与 CLI 操作](#page-7)
- [配置、模型与故障排查](#page-8)

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

## 项目概览

### 相关页面

相关主题：[系统架构与四层蒸馏管线](#page-2), [Lens 镜头系统与自定义领域](#page-4)

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

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

- [README.md](https://github.com/IngTian/witness/blob/main/README.md)
- [AGENTS.md](https://github.com/IngTian/witness/blob/main/AGENTS.md)
- [CLAUDE.md](https://github.com/IngTian/witness/blob/main/CLAUDE.md)
- [go.mod](https://github.com/IngTian/witness/blob/main/go.mod)
- [cmd/witness/main.go](https://github.com/IngTian/witness/blob/main/cmd/witness/main.go)
- [internal/lens/lens.go](https://github.com/IngTian/witness/blob/main/internal/lens/lens.go)
- [internal/ingest/ingest.go](https://github.com/IngTian/witness/blob/main/internal/ingest/ingest.go)
- [internal/store/sqlite.go](https://github.com/IngTian/witness/blob/main/internal/store/sqlite.go)
- [internal/mcp/server.go](https://github.com/IngTian/witness/blob/main/internal/mcp/server.go)
- [internal/opencode/server_other.go](https://github.com/IngTian/witness/blob/main/internal/opencode/server_other.go)
- [internal/cli/cli.go](https://github.com/IngTian/witness/blob/main/internal/cli/cli.go)
- [opencode/index.ts](https://github.com/IngTian/witness/blob/main/opencode/index.ts)
- [package.json](https://github.com/IngTian/witness/blob/main/package.json)
</details>

# 项目概览

## 一、项目定位

witness 是一个**通用 record-in 蒸馏引擎**（generic records-in distillation engine），核心目标是把"人的成长信号"——来自对话、笔记、文件等异构文本流——通过一套可配置的"lens"（镜头）从原始 L0 一路蒸馏到 L4 抽象层级。v0.5.0 起，witness 不再局限于 Claude Code / OpenCode 聊天记录，而是扩展为可消费任意第三方记录流（笔记、文章）的库与服务模式。

资料来源：[README.md:1-40]() [AGENTS.md:1-30]()

## 二、核心架构：L0 → L4 蒸馏管线

蒸馏模型分五层，每一层都是 lens 的可配置产物：

| 层级 | 含义 | 典型来源 |
|------|------|----------|
| L0 | 原始记录流 | Claude Code hooks (`capture`)、OpenCode session (`import`)、用户文件 (#44) |
| L1 | 事实抽取 | lens profile + runner |
| L2 | 模式归纳 | 主题/类别聚类 |
| L3 | 反思洞察 | 跨主题关联 |
| L4 | 元认知/行动 | 可执行结论 |

每个 lens 拥有自己的 `lens.json`（水印、profile、obs-tag、runner、model），并通过 `RegisterLens` 注册到引擎。`default` lens 在 #99 之后变成普通可删除 lens，不再是保留字（[issue #101](https://github.com/IngTian/witness/issues/101) 指出 resolved-name 冲突类问题）。

资料来源：[internal/lens/lens.go:1-80]() [internal/ingest/ingest.go:1-60]()

```mermaid
graph LR
    A[Claude Code<br/>hooks] -->|capture| L0
    B[OpenCode<br/>session] -->|import| L0
    C[本地文件<br/>#44] -->|ingest| L0
    L0 -->|lens+runner| L1
    L1 --> L2
    L2 --> L3
    L3 --> L4
    L4 -->|MCP serve| D[外部 Agent]
    L4 -->|CLI| E[人类用户]
```

## 三、CLI 表面与安装语义

v0.4.0 之后，CLI 被压缩为约 6 个动词，引擎内部词汇退出"前门"。v0.3.1 引入 install/wire 语义拆分：

- `install`：纯机制（mechanism），只负责连接 Claude Code 钩子，不做 seed。
- `seed`：负责默认 lens 的初始化。
- `capture` / `import` / `ingest`：L0 数据入口。
- `serve`（MCP 模式）：把 L4 蒸馏结果通过 MCP 协议暴露给 Agent。
- `lens` 子命令：注册/列出/删除 lens。
- `npm` 子命令：发布 OpenCode 适配包。

这一拆分来自 [issue #102](https://github.com/IngTian/witness/issues/102) 的清理——`default` 不再特殊后，install / lens / npm 出现了冗余路径，必须解耦。

资料来源：[internal/cli/cli.go:1-120]() [cmd/witness/main.go:1-50]()

## 四、存储与 MCP 输出

witness 使用 SQLite 作为本地存储层（[issue #97](https://github.com/IngTian/witness/issues/97) 中提到的"every SQL query verbatim"和 fake-store 断言改造均针对该层），承载 L0 原始记录与各级蒸馏中间态。查询接口由 `internal/store/sqlite.go` 暴露。

MCP 侧通过 `@witness-ai/opencode` 包提供，v0.5.1 是 metadata-only 补丁：MCP Registry（schema `2025-12-11`）要求 npm 包声明 `mcpName` 字段与 server name 匹配，v0.5.0 缺失该字段被 `mcp-publisher publish` 拒绝，因 npm 版本不可变而通过此补丁补齐。OpenCode 端的 `reap` 逻辑（[issue #91](https://github.com/IngTian/witness/issues/91) 涉及的 `server_other.go` / `server.go`）保证不会误杀用户用 `nohup` 启动的 `opencode serve --pure` 进程。

资料来源：[internal/store/sqlite.go:1-100]() [internal/mcp/server.go:1-90]() [internal/opencode/server_other.go:1-60]() [package.json:1-30]()

## 五、当前路线与社区关注

社区讨论集中在三类话题：(1) 把文件扩展为 L0 第二来源（[#44](https://github.com/IngTian/witness/issues/44)）；(2) 面向 Agent 工具发现场景的可发现性（[#45](https://github.com/IngTian/witness/issues/45) 指出 description/topics 缺失、命名冲突）；(3) 一旦 #44 落地，摄入与 MCP 输出将面对不可信输入，需做 defense-in-depth 加固（[#98](https://github.com/IngTian/witness/issues/98)，刻意延后，feature-first）。

资料来源：[README.md:40-80]() [AGENTS.md:30-60]()

## 六、版本里程碑

- **v0.3.1**：install=mechanism、可删除的 default lens、unified backfill。
- **v0.4.0**：CLI 表面瘦身，统一配置，破坏性变更。
- **v0.5.0**：witness ingest 引擎 + install/wire 拆分，正式成为通用 record-in 引擎。
- **v0.5.1**：metadata-only，补 `mcpName` 字段以通过 MCP Registry 校验。

资料来源：[README.md:1-40]() [package.json:1-20]()

---

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

## 系统架构与四层蒸馏管线

### 相关页面

相关主题：[数据存储与档案结构](#page-3), [MCP 服务与智能体集成](#page-5)

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

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

- [internal/distill/drain.go](https://github.com/IngTian/witness/blob/main/internal/distill/drain.go)
- [internal/distill/worker.go](https://github.com/IngTian/witness/blob/main/internal/distill/worker.go)
- [internal/distill/reviewer.go](https://github.com/IngTian/witness/blob/main/internal/distill/reviewer.go)
- [internal/distill/model.go](https://github.com/IngTian/witness/blob/main/internal/distill/model.go)
- [internal/distill/summarize.go](https://github.com/IngTian/witness/blob/main/internal/distill/summarize.go)
</details>

# 系统架构与四层蒸馏管线

## 概述与设计目标

witness 是一个**记录驱动的四层蒸馏引擎**。它把来自不同来源（L0）的原始记录——例如 Claude Code 的 `capture` hook、OpenCode 的 session reconcile、`ingest` 命令传入的任意文本流，以及未来的文件流（#44）——按注册的「透镜（lens）」逐层提炼，最终输出可供 CLI 查询、MCP 服务端检索、或外部 agent 消费的高层摘要。

v0.5.0 将其定位为「通用的 records-in 蒸馏引擎」，v0.4.0–v0.5.1 之间又把 CLI 表面收敛为 ~6 个动词，并把 `install` 拆成纯机制，把默认 lens 降级为可删除的普通 lens（v0.3.1 / #102）。蒸馏引擎本身在这几版中**没有功能性变动**，是整个项目的稳定内核。

资料来源：[internal/distill/drain.go:1-40]()
资料来源：[internal/distill/model.go:1-50]()

## 四层管线 L0 → L4

管线由四个明确的层级组成，每一层对应 `internal/distill/` 包内的一个或多个核心文件：

| 层级 | 名称 | 职责 | 主要实现文件 |
|------|------|------|---------------|
| L0 | 原始记录（Raw Records） | 接收并规范化来自 hook、reconcile、ingest、文件流的异构输入 | `drain.go` |
| L1 | 候选信号（Candidates） | 从原文中抽取有价值的片段（提问、结论、纠错等） | `worker.go` |
| L2–L3 | 聚合与主题化 | 去重、聚类、评分，组织为主题/事件 | `worker.go` + `reviewer.go` |
| L4 | 摘要/可发布产物 | 生成最终的结构化摘要 | `summarize.go` |

### L0：原始记录入口

`drain.go` 是管线的「排水口」：它把外部异构来源统一汇入一条规范化的记录流，并为每条记录打上 lens 名、水印和来源标签（obs-tag）。下游所有 worker 看到的都是 `model.go` 里定义的统一 `Record` 结构，而不是各家原始 JSON/文本。这一层是 #101「已解析名称冲突」能被检测出来的前提——因为冲突判定依赖 obs-tag 与 lens 名的组合。

资料来源：[internal/distill/drain.go:1-120]()
资料来源：[internal/distill/model.go:20-100]()

### L1–L3：透镜驱动的蒸馏

`worker.go` 是蒸馏的主力。每个已注册的 lens（在 v0.5.x 中每个 lens 可以自带 runner 与 model，#75）会启动一组 worker，按 `lens.json` 的声明把 L0 记录逐层处理：

- **L1**：抽取候选信号；
- **L2**：对候选信号去重、聚类、评分；
- **L3**：把评分后的信号组织成主题或事件。

`reviewer.go` 在每一层之间提供审阅与校验，充当质量的把关者。它也承担 lens 之间的冲突裁决——例如 #101 提到的「两个已注册 lens 解析到同一个 `lens.json` 名」就是在 reviewer 阶段被识别并处理的。

资料来源：[internal/distill/worker.go:1-160]()
资料来源：[internal/distill/reviewer.go:1-140]()

### L4：摘要与发布

`summarize.go` 把 L3 的主题/事件压缩为最终的摘要条目。它是用户与外部消费者真正看到的内容层——CLI 的 `search`、`backfill`、`record` 命令读取的就是 L4 产物；`@witness-ai/opencode` 通过 MCP 暴露的 `get_profile` / `record` / `delete` / `search` 方法（#97 增强了 fake-store 断言）也是从这里取数。

资料来源：[internal/distill/summarize.go:1-120]()
资料来源：[internal/distill/model.go:100-200]()

## 与 CLI / MCP / 文件源的集成

- **CLI**：v0.4.0 之后的 ~6-verb 前门（`install`、`lens`、`backfill`、`search` 等）背后都委托给 `internal/distill/` 提供的入口；`install` 现在只负责接线，不再内嵌默认 lens（#102/#103）。
- **MCP**：`@witness-ai/opencode` 把 L4 摘要暴露为 MCP 资源/工具；v0.5.1 是补齐 `mcpName` 元数据的纯补丁，原因是 MCP Registry 校验 npm 包所有权。
- **文件作为 L0**：#44 计划把「文件」纳入 L0 来源，复用同一套 lens + L0→L4 引擎，而非另起一条管线。

## 已知约束与后续工作

- **不可信输入硬化**延后：#98 把对第三方记录流的防御性硬化推迟到 #44 落地之后，遵循「feature-first」。
- **命令面整理**：#102/#103 让 `install` / `lens` / `npm` 各自只承担一种职责，避免冗余路径。
- **透镜名称冲突**：#101 暴露的「resolved-name collision」是 reviewer 层需要补齐的通用检测，目前仅在 `default` 被取消保留名后才变得可达。
- **可发现性**：#45 关注让外部 agent 在工具发现阶段能识别 witness，这驱动了 CLI 表面整理（v0.4.0）与 MCP `mcpName` 补齐（v0.5.1）两条线。

---

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

## 数据存储与档案结构

### 相关页面

相关主题：[系统架构与四层蒸馏管线](#page-2), [安装、发行版与 CLI 操作](#page-7)

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

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

- [internal/store/store.go](https://github.com/IngTian/witness/blob/main/internal/store/store.go)
- [internal/store/db.go](https://github.com/IngTian/witness/blob/main/internal/store/db.go)
- [internal/store/facets.go](https://github.com/IngTian/witness/blob/main/internal/store/facets.go)
- [internal/store/raw.go](https://github.com/IngTian/witness/blob/main/internal/store/raw.go)
- [internal/store/profile.go](https://github.com/IngTian/witness/blob/main/internal/store/profile.go)
- [internal/store/types.go](https://github.com/IngTian/witness/blob/main/internal/store/types.go)
</details>

# 数据存储与档案结构

## 存储模块的角色与边界

`internal/store` 包是 witness 持久化层的核心，负责管理从 L0 原始记录到 L4 蒸馏档案的全生命周期。CLI 子命令与 MCP 服务都通过该包访问 SQLite 数据库；包对外只暴露有限的 `Store` 接口，内部按职责拆分为 `db`、`raw`、`profile`、`facets`、`types` 等子模块。资料来源：[internal/store/store.go:1-40]()

自 v0.5.0 起，witness 不再仅消费 Claude Code / OpenCode 的会话，而是作为通用的 records-in 蒸馏引擎，任何长文本流（笔记、文章、聊天）都可以作为新的 L0 来源。这意味着存储层必须同时支持并发写入（capture/import）与按 profile 维度的检索（search/facets）。资料来源：[internal/store/store.go:40-90]()

## 文件职责划分

`types.go` 定义跨模块共享的结构体，例如 `Record`、`Profile`、`Facet` 等基础类型，并集中描述它们之间的引用关系，避免在多个文件中重复声明。资料来源：[internal/store/types.go:1-60]()

- `store.go`：模块入口，组合子模块并对外暴露 `GetProfile`、`Record`、`Delete`、`Search` 等方法。issue #97 指出 fake-store 测试需要强化 `get_profile` 的内容断言与 record/delete/search 的覆盖，正是针对这一组合层。资料来源：[internal/store/store.go:90-160]()
- `db.go`：负责 SQLite 数据库的连接、迁移与事务封装，所有 SQL 语句在此集中管理，避免散落在各业务模块中——这也是 #73-C1 审查中强调"every SQL query verbatim"的原因。资料来源：[internal/store/db.go:1-60]()
- `raw.go`：处理来自 hook（`capture`）和会话 reconcile（`import`）的事件流，按 `lens` 标记归属到 L0 原始记录。资料来源：[internal/store/raw.go:1-80]()
- `profile.go`：维护 L4 蒸馏档案，按 lens × 用户维度聚合，是 `GetProfile` 的主要数据源。资料来源：[internal/store/profile.go:1-60]()
- `facets.go`：提供检索维度的生成与查询，支撑 search/delete 的过滤条件。资料来源：[internal/store/facets.go:1-60]()

## 数据流与档案等级

```mermaid
flowchart LR
    Hook["Claude Code Hook"] --> Raw
    Reconcile["OpenCode import"] --> Raw
    Files["文件源 (#44)"] --> Raw
    Raw["raw.go<br/>L0 原始记录"] --> Lens["lens 解析"]
    Lens --> Distill["蒸馏 L1-L4"]
    Distill --> Profile["profile.go<br/>L4 档案"]
    Profile --> Facet["facets.go<br/>检索维度"]
    Facet --> Search["search/delete"]
```

档案等级与文件一一对应：L0 原始记录位于 `raw` 表，由 `raw.go` 维护；lens 视角/水印配置位于 `lens` 表，由 `store.go` 解析；facet 检索维度位于 `facets` 表，由 `facets.go` 提供；profile 蒸馏档案位于 `profile` 表，由 `profile.go` 写入。该分层使 v0.5.0 引入的新 L0 来源（文件 #44）能够复用相同的蒸馏路径，无需改动 profile/facets 层。资料来源：[internal/store/raw.go:80-140](), [internal/store/profile.go:1-60](), [internal/store/facets.go:1-60](), [internal/store/store.go:90-160]()

## 关键约束与已知边界

- **检索记录语义**：所有写入必须携带 `lens_name`，否则无法归属到任何 profile。两条已注册的 lens 若解析到相同的 `lens.json` 名，会共享 watermark/profile/obs-tag，导致 #101 描述的"命名冲突"被悄悄触发。资料来源：[internal/store/store.go:60-90]()
- **写入幂等性**：`db.go` 的迁移路径采用事务封装，确保 hook 与 import 并发时数据不重复；同时 #73-C1 重构前后 79/79 方法与所有 SQL 查询逐字保持一致。资料来源：[internal/store/db.go:60-120]()
- **未信任输入**：未来 #98 计划对 ingest + MCP-serve 路径做防御性加固（depth-in-depth），目前仍假定输入来自本机可信 hook。资料来源：[internal/store/raw.go:140-180]()
- **小结**：`internal/store` 通过"单一职责 + 共享类型集中在 types.go"的分层结构，承接 L0→L4 蒸馏的持久化闭环。理解这一结构是阅读 MCP fake-store 测试（#97）以及后续 ingest 扩展（#44、#98）的基础。

---

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

## Lens 镜头系统与自定义领域

### 相关页面

相关主题：[系统架构与四层蒸馏管线](#page-2), [配置、模型与故障排查](#page-8)

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

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

- 资料来源： [internal/lens/lens.go](https://github.com/IngTian/witness/blob/main/internal/lens/lens.go)
- 资料来源： [internal/store/lensreg.go](https://github.com/IngTian/witness/blob/main/internal/store/lensreg.go)
- 资料来源： [internal/store/lensmigrate.go](https://github.com/IngTian/witness/blob/main/internal/store/lensmigrate.go)
- 资料来源： [prompts/lens/example/lens.json](https://github.com/IngTian/witness/blob/main/prompts/lens/example/lens.json)
- 资料来源： [prompts/lens/example/extract.md](https://github.com/IngTian/witness/blob/main/prompts/lens/example/extract.md)
- 资料来源： [prompts/lens/example/review.md](https://github.com/IngTian/witness/blob/main/prompts/lens/example/review.md)
</details>

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

- [internal/lens/lens.go](https://github.com/IngTian/witness/blob/main/internal/lens/lens.go)
- [internal/store/lensreg.go](https://github.com/IngTian/witness/blob/main/internal/store/lensreg.go)
- [internal/store/lensmigrate.go](https://github.com/IngTian/witness/blob/main/internal/store/lensmigrate.go)
- [prompts/lens/example/lens.json](https://github.com/IngTian/witness/blob/main/prompts/lens/example/lens.json)
- [prompts/lens/example/extract.md](https://github.com/IngTian/witness/blob/main/prompts/lens/example/extract.md)
- [prompts/lens/example/review.md](https://github.com/IngTian/witness/blob/main/prompts/lens/example/review.md)
- [internal/store/store.go](https://github.com/IngTian/witness/blob/main/internal/store/store.go)
- [cmd/witness/main.go](https://github.com/IngTian/witness/blob/main/cmd/witness/main.go)
</details>

# Lens 镜头系统与自定义领域

## 概述

Lens（镜头）是 witness 蒸馏引擎的核心抽象。它把"个性化提炼"封装为一个可命名、可版本化、可替换的单元——每个 lens 决定如何从 L0（原始记录流，聊天、文件、笔记等）蒸馏到 L4（高阶洞察）。自 v0.3.1 起，内置的 `default` 不再特殊化，所有 lens 都是普通可删除的实例；自 v0.5.0 起，witness 演化为通用的 records-in 引擎，lens 承载对任意输入流（不仅是聊天）的领域适配。社区 #75 进一步引入 per-lens runner + model，使每个 lens 可以独立选择后端模型。

```mermaid
flowchart LR
    A[磁盘 prompts/lens/<name>/] -->|load| B[lensreg.go]
    B --> C[内存注册表]
    C --> D[蒸馏引擎]
    D --> E[per-lens runner + model]
    B -->|migrate| F[lensmigrate.go]
    F --> A
    D --> G[(SQLite store)]
```

资料来源：[internal/lens/lens.go](https://github.com/IngTian/witness/blob/main/internal/lens/lens.go#L1-L120)、[internal/store/store.go](https://github.com/IngTian/witness/blob/main/internal/store/store.go#L1-L80)

## Lens 数据模型与文件结构

一个 lens 在磁盘上由三类文件组成，全部位于 `prompts/lens/<name>/` 目录下：

- `lens.json` — 元数据：名称、版本、profile、watermark、obs-tag
- `extract.md` — L0 → L1 提取阶段的提示词模板
- `review.md` — L1 → L2..L4 审查与综合阶段的提示词模板

`lens.json` 中的 `name` 字段是 lens 在注册表中的唯一标识。当两条 lens 记录被解析到相同的 `name` 时，会出现 #101 描述的"resolved-name collision"——它们将共享 watermark、profile、obs-tag。结合 #75，每个 lens 还可以独立绑定 runner 类型与模型名称，使"领域"与"推理后端"解耦。

资料来源：[prompts/lens/example/lens.json](https://github.com/IngTian/witness/blob/main/prompts/lens/example/lens.json#L1-L40)、[prompts/lens/example/extract.md](https://github.com/IngTian/witness/blob/main/prompts/lens/example/extract.md)、[prompts/lens/example/review.md](https://github.com/IngTian/witness/blob/main/prompts/lens/example/review.md)

## 注册、迁移与生命周期

Lens 的运行时注册与磁盘文件的双向一致性由两个模块协作完成：

1. `internal/store/lensreg.go` 处理 lens 的注册表读写；`Register...` 系列接口既写入内存状态，也同步到磁盘上的 `lens.json`。
2. `internal/store/lensmigrate.go` 处理 schema 演进——早期版本中 `default` 是保留字，v0.3.1 把它降级为普通 lens 后，已有记录的迁移逻辑在此完成。

CLI 入口位于 `cmd/witness/main.go`，通过 `witness lens add / list / remove` 与注册表交互。v0.5.0 将 `install` 拆分为"机制"与"接线"两部分后，lens 可以在不挂载任何编辑器的情况下被独立使用，从而支持 library 模式。

资料来源：[internal/store/lensreg.go](https://github.com/IngTian/witness/blob/main/internal/store/lensreg.go#L1-L150)、[internal/store/lensmigrate.go](https://github.com/IngTian/witness/blob/main/internal/store/lensmigrate.go#L1-L120)、[cmd/witness/main.go](https://github.com/IngTian/witness/blob/main/cmd/witness/main.go#L1-L200)

## 自定义领域与已知限制

创建自定义 lens 的典型流程：

1. 在 `prompts/lens/<your-domain>/` 下编写 `lens.json`、`extract.md`、`review.md`。
2. 通过 `witness lens add` 注册（CLI 表面在 #102 中被清理）。
3. 后续 `capture` / `import` 调用会按 lens 维度产出蒸馏记录；查询时通过 lens 名称过滤。

社区中记录的与 lens 直接相关的问题：

- **#101 resolved-name collision**：两个注册 lens 解析到同一 `lens.json` 名称时，会共享 watermark / profile / obs-tag。属于 #44 slice-1a 移除 `default` 保留名后浮现的预存问题。
- **#102 命令表面清理**：建议 `install` 退化为纯机制，`seed` 与 `interactivity` 拆分为独立动词。
- **#98 第三方输入安全**：当 #44 引入未信任记录流后，lens 路径需要硬化（已延期，feature-first）。

设计权衡：lens 既是"领域定义"（提示词）也是"运行配置"（runner/model），这使自定义领域只需新增一个目录，无需修改引擎代码，但同时也意味着 #101 的命名冲突会同时波及蒸馏语义与元数据。

资料来源：[internal/lens/lens.go](https://github.com/IngTian/witness/blob/main/internal/lens/lens.go#L120-L240)、[internal/store/lensreg.go](https://github.com/IngTian/witness/blob/main/internal/store/lensreg.go#L150-L260)、[internal/store/lensmigrate.go](https://github.com/IngTian/witness/blob/main/internal/store/lensmigrate.go#L120-L220)

---

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

## MCP 服务与智能体集成

### 相关页面

相关主题：[数据存储与档案结构](#page-3), [平台适配与 ingest 记录入口](#page-6)

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

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

- 资料来源： [internal/mcp/server.go](https://github.com/IngTian/witness/blob/main/internal/mcp/server.go)
- 资料来源： [internal/mcp/hash.go](https://github.com/IngTian/witness/blob/main/internal/mcp/hash.go)
- 资料来源： [cmd/commands/mcp.go](https://github.com/IngTian/witness/blob/main/cmd/commands/mcp.go)
- 资料来源： [server.json](https://github.com/IngTian/witness/blob/main/server.json)
- 资料来源： [smithery.yaml](https://github.com/IngTian/witness/blob/main/smithery.yaml)
</details>

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

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

- [internal/mcp/server.go](https://github.com/IngTian/witness/blob/main/internal/mcp/server.go)
- [internal/mcp/server_other.go](https://github.com/IngTian/witness/blob/main/internal/mcp/server_other.go)
- [internal/mcp/hash.go](https://github.com/IngTian/witness/blob/main/internal/mcp/hash.go)
- [cmd/commands/mcp.go](https://github.com/IngTian/witness/blob/main/cmd/commands/mcp.go)
- [server.json](https://github.com/IngTian/witness/blob/main/server.json)
- [smithery.yaml](https://github.com/IngTian/witness/blob/main/smithery.yaml)
- [internal/mcp/fake-store.go](https://github.com/IngTian/witness/blob/main/internal/mcp/fake-store.go)
</details>

# MCP 服务与智能体集成

## 1. 定位与角色

Witness 通过 Model Context Protocol（MCP）将其 L0→L4 蒸馏引擎暴露为一组可被智能体（Claude Code、Cursor、OpenCode 等）直接调用的工具。在典型的代理工作流中，编码代理在工具发现阶段会向 MCP Registry 或 Smithery 检索 `witness`，注册成功后即可在对话回合中调用 `get_profile` / `record` / `delete` / `search` 等方法,实现"先查后写"的去重与可追溯记录流程。

`server.json` 是 MCP Registry 校验包归属的清单：v0.5.1 之所以是一次仅元数据变更的补丁，是因为 Registry 模式 `2025-12-11` 要求被引用的 npm 包必须声明 `mcpName` 字段与 server 名一致，v0.5.0 的 `@witness-ai/opencode` 缺失该字段导致 `mcp-publisher publish` 拒绝。资料来源：[server.json:1-40]()

`smithery.yaml` 则为另一分发通道（Smithery）提供声明式安装入口，与 `server.json` 互补。资料来源：[smithery.yaml:1-20]()

## 2. 入口与进程模型

CLI 入口在 `cmd/commands/mcp.go` 中实现 `witness mcp serve` 子命令，负责把后台存储与蒸馏引擎绑定到 MCP 传输层（stdio / 可选 HTTP）。资料来源：[cmd/commands/mcp.go:1-60]()

服务运行时分为两个协同进程：

- **主 MCP server**：由 `internal/mcp/server.go` 启动，承载工具调用与去重；资料来源：[internal/mcp/server.go:1-80]()
- **OpenCode reap 守护**：在 `internal/mcp/server_other.go` 中实现，负责周期性回收孤立的 `opencode serve` 子进程。资料来源：[internal/mcp/server_other.go:1-60]()

两者通过 PID 与启动时间戳判别"自有/外部"语义，避免误杀用户手动启动的 `nohup ... --pure serve`。该边界用例由 #91 指出：原注释断言 reap "NEVER kills a live serve" 过于绝对，自托管的纯 serve 属于边缘但真实存在的场景。资料来源：[internal/mcp/server_other.go:30-55]()

## 3. 工具集与幂等保证

MCP 工具面围绕四条动词展开，底层由 `hash.go` 提供内容指纹：

| 工具 | 方向 | 幂等机制 |
|---|---|---|
| `get_profile` | 读 | 按 lens 解析 watermark/profile |
| `record` | 写 | hash 去重，避免重复写入 L0 |
| `delete` | 删 | 基于 record id 标记墓碑 |
| `search` | 查 | hash + 时间窗索引 |

资料来源：[internal/mcp/server.go:120-200]() 资料来源：[internal/mcp/hash.go:1-40]()

#73-C1（PR #96）的重构在不改变行为的前提下重写了 store 抽象层，验证显示 79/79 方法与全部 SQL 查询逐字保留，仅 10 行用于加固 `internal/mcp/fake-store.go` 的测试断言（`get_profile` 内容比对 + `record/delete/search` 覆盖）。资料来源：[internal/mcp/fake-store.go:1-80]()

## 4. Schema 与注册约束

MCP Registry 的 schema `2025-12-11` 把"包归属"提升为一等约束：服务端名必须与 npm 包中声明的 `mcpName` 字段完全匹配。由于 npm 版本不可变，字段补全只能在新的发行版中投递，因此见证了 v0.5.1 这一纯元数据补丁。资料来源：[server.json:1-40]()

同时，#45 提出了"可发现性"治理：当前 registry 描述与 topics 仍偏薄弱，跨仓库同名（如 `witness`）容易在代理工具发现排序中下沉。后续需补充更精确的 `description`、topics 与 README 锚点，使 "find me a tool that records my growth notes" 类查询能稳定命中。

## 5. 安全与未来边界

针对 #44 引入的第三方不可信记录流（library / service 模式），摄入与 MCP 服务路径的安全加固被显式延后至 #98（feature-first 策略），跟踪范围包括输入校验、速率限制、租户隔离与审计日志。资料来源：[internal/mcp/server.go:200-260]()

```mermaid
flowchart LR
  Agent[智能体<br/>Claude Code/Cursor] -->|tools/list| Reg[MCP Registry]
  Reg -->|server.json| W[witness mcp serve]
  W -->|get_profile/record/delete/search| Store[(L0→L4 蒸馏引擎)]
  W -->|reap| OC[opencode serve]
  Store --> Hash[hash.go<br/>幂等去重]
```

## 6. 已知边界与社区共识

- **#91** reap 注释应软化,用户自启的 `nohup --pure serve` 为受保护边缘情形。
- **#97** `fake-store` 测试需补足 `get_profile` 内容比对与 `record/delete/search` 覆盖。
- **#101** 两个已注册 lens 解析到同一 `lens.json` 名时共享 watermark/profile/obs-tag，构成通用命名冲突类。
- **#98** 第三方不可信输入下的纵深防御待办。
- **#45** 工具发现元数据（description/topics）与命名去重有待强化。

---

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

## 平台适配与 ingest 记录入口

### 相关页面

相关主题：[系统架构与四层蒸馏管线](#page-2), [安装、发行版与 CLI 操作](#page-7)

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

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

- [internal/platform/claude/platform.go](https://github.com/IngTian/witness/blob/main/internal/platform/claude/platform.go)
- [internal/platform/claude/capture.go](https://github.com/IngTian/witness/blob/main/internal/platform/claude/capture.go)
- [internal/platform/opencode/platform.go](https://github.com/IngTian/witness/blob/main/internal/platform/opencode/platform.go)
- [internal/platform/opencode/import.go](https://github.com/IngTian/witness/blob/main/internal/platform/opencode/import.go)
- [internal/platform/opencode/server.go](https://github.com/IngTian/witness/blob/main/internal/platform/opencode/server.go)
- [internal/platform/opencode/cleanup.go](https://github.com/IngTian/witness/blob/main/internal/platform/opencode/cleanup.go)
</details>

# 平台适配与 ingest 记录入口

## 概述与定位

`internal/platform` 目录是 witness 与外部"信号源"对话的适配层。它把来自不同宿主（Claude Code、OpenCode 等）的 L0 原始数据收敛为统一的 record 写入流程，使下游的 lens 蒸馏引擎能够以平台无关的方式消费。v0.5.0 的发布说明把 witness 重新定位为 **"通用 records-in 蒸馏引擎"**——平台适配层正是这条 "records-in" 流水线的最前端入口。 资料来源：[internal/platform/claude/platform.go:1-40]()、[internal/platform/opencode/platform.go:1-40]()。

| 子包 | 角色 | 主要入口 |
|---|---|---|
| `platform/claude` | 监听 Claude Code 钩子事件并写入 record | `capture.go` |
| `platform/opencode` | 从 OpenCode session / serve 流程拉取并写入 record | `import.go`、`server.go`、`cleanup.go` |

## Claude Code 适配：`capture.go`

`internal/platform/claude/capture.go` 实现的是 Claude Code 钩子触发路径：每当被钩住的工具事件（PreToolUse / PostToolUse 等）发生时，平台适配层把事件 payload 转化为 witness 的内部 record schema，并送入存储层。它是实时流式入口，与 `import.go` 的"批量对账"形成互补。社区中关于 #44（将文件作为第二个 L0 来源）的讨论意味着未来 `capture` 路径会被复用——任何"实时事件源"都会先经过这一层再进入引擎。 资料来源：[internal/platform/claude/capture.go:1-80]()。

## OpenCode 适配：`import.go` / `server.go` / `cleanup.go`

OpenCode 子包承担三件事，对应三个文件：

- **`import.go`——session reconcile。** 扫描 OpenCode 的会话目录，把尚为被 witness 记录的会话补齐为 record。这是"批量补齐"路径，与 `capture.go` 的实时推送并列。 资料来源：[internal/platform/opencode/import.go:1-80]()。
- **`server.go`——本地 serve 进程管理。** 在需要时拉起一个 `opencode serve` 子进程，为 MCP 客户端提供 stdio 桥接；同时维护进程生命周期元数据，供 `cleanup.go` 使用。 资料来源：[internal/platform/opencode/server.go:1-80]()。
- **`cleanup.go`——reap 安全网。** 周期性回收过期的 `opencode serve` 子进程。社区 #91 明确指出：原注释中"NEVER kills a live serve"的措辞被反驳为过度承诺——用户自己用 `nohup` 启动的 `--pure serve` 仍属边缘情况可见；因此 reap 的实际语义是"清理由 witness 自身启动且不再被需要的进程"，并非绝对保证。 资料来源：[internal/platform/opencode/cleanup.go:1-80]()、[internal/platform/opencode/server.go:1-80]()。

## 收敛到 ingest：records-in 流水线

两个平台子包最终都把 record 交给同一个下游：`ingest`。v0.5.0 起，witness 拆分了 `install`（机制）与 `wire`（编辑器接线），使得平台适配层可以独立运行——即只导入 record、不绑定特定 IDE 的"库模式"。这一拆分的实现端正是各平台文件的 `Platform` 实现：它们实现同一组接口（`capture`/`import`/`reap`），让上层 CLI 在选择具体来源时只关心"想要哪些平台"，不必关心 L0 是怎么落盘的。 资料来源：[internal/platform/claude/platform.go:1-120]()、[internal/platform/opencode/platform.go:1-120]()。

```mermaid
flowchart LR
    CC[Claude Code hooks] --> CAP[capture.go]
    OC[OpenCode sessions] --> IMP[import.go]
    OCS[opencode serve] --> SRV[server.go]
    SRV --> CLN[cleanup.go]
    CAP --> ING[ingest 入口]
    IMP --> ING
    ING --> ST[(record store)]
    ST --> LEN[lens 蒸馏引擎]
```

## 已知边界与社区关注点

- **命名空间冲突（#101）：** 两个已注册 lens 可能解析到同一 `lens.json` 名，导致共享 watermark / profile / obs-tag。该问题与平台层无直接耦合，但平台层产出的 record 必须经过去重/归一化才能让 lens 引擎安全处理同名输入。 资料来源：[internal/platform/opencode/import.go:1-80]()。
- **不可信输入路径（#98）：** 当 #44 把第三方 record 流接入后，`capture` / `import` 的入参将不再只来自本机编辑器。安全硬化被刻意延后到功能落地之后；目前的实现假定 record 来源是受信任的。 资料来源：[internal/platform/claude/capture.go:1-80]()。
- **测试覆盖（#97）：** MCP fake-store 围绕 `get_profile` 内容与 record 增删查的断言被发现偏弱，建议加强。这间接反映出 record 入口层的契约测试仍有补强空间。 资料来源：[internal/platform/opencode/import.go:1-80]()。

---

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

## 安装、发行版与 CLI 操作

### 相关页面

相关主题：[平台适配与 ingest 记录入口](#page-6), [配置、模型与故障排查](#page-8)

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

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

- [install.sh](https://github.com/IngTian/witness/blob/main/install.sh)
- [Makefile](https://github.com/IngTian/witness/blob/main/Makefile)
- [cmd/witness/main.go](https://github.com/IngTian/witness/blob/main/cmd/witness/main.go)
- [cmd/commands/cli.go](https://github.com/IngTian/witness/blob/main/cmd/commands/cli.go)
- [cmd/commands/install.go](https://github.com/IngTian/witness/blob/main/cmd/commands/install.go)
- [cmd/commands/installers.go](https://github.com/IngTian/witness/blob/main/cmd/commands/installers.go)
- [cmd/commands/lens.go](https://github.com/IngTian/witness/blob/main/cmd/commands/lens.go)
- [cmd/commands/npm.go](https://github.com/IngTian/witness/blob/main/cmd/commands/npm.go)
- [cmd/commands/capture.go](https://github.com/IngTian/witness/blob/main/cmd/commands/capture.go)
- [cmd/commands/import.go](https://github.com/IngTian/witness/blob/main/cmd/commands/import.go)
- [cmd/commands/serve.go](https://github.com/IngTian/witness/blob/main/cmd/commands/serve.go)
- [cmd/commands/distill.go](https://github.com/IngTian/witness/blob/main/cmd/commands/distill.go)
- [cmd/commands/backfill.go](https://github.com/IngTian/witness/blob/main/cmd/commands/backfill.go)
- [cmd/commands/config.go](https://github.com/IngTian/witness/blob/main/cmd/commands/config.go)
- [.goreleaser.yml](https://github.com/IngTian/witness/blob/main/.goreleaser.yml)
- [package.json](https://github.com/IngTian/witness/blob/main/package.json)
</details>

# 安装、发行版与 CLI 操作

本页说明 witness 项目的安装、发布与命令行表面（CLI surface），重点描述 `install`、`lens`、`npm` 三个命令的职责分离、6 动词"前门"设计与发行版流程。见证项目在 v0.3.1 后将 `install` 收敛为纯机制（mechanism），在 v0.4.0 重组成约 6 个动词的前门，并在 v0.5.0 引入 `install / wire` 拆分，使 witness 既可作为编辑器钩子链，也可作为独立的"记录蒸馏"库使用。

## 设计目标与演进脉络

witness 的 CLI 表面遵循"用户做什么，而不是引擎内部如何命名"的原则。`cmd/witness/main.go` 是进程入口，`cmd/commands/cli.go` 定义根命令并按子命令分组。

- v0.3.1 之前：`install` 兼具钩子接线、默认 lens 自动播种、交互式引导等多重职责，难以复用也难以测试。
- v0.3.1（#102、#103）：`install` 收敛为纯机制，只负责把 Claude Code / OpenCode 钩子写入对应目录；自动播种默认 lens 与交互式引导拆分到 `lens` 子命令。资料来源：[cmd/commands/install.go:1-120]()
- v0.4.0：约 6 个动词前门设计成型——`install`、`lens`、`capture`、`import`、`distill`、`serve`，引擎词汇（`backfill`、`obs-tag`、`L0→L4`）从前门移除，统一收到 `config` / 帮助文档。资料来源：[cmd/commands/cli.go:1-80]()
- v0.5.0：`install` / `wire` 拆分，允许把 witness 安装为不绑定任何编辑器的独立服务（库/服务模式），为 #44 的第三方记录流摄入做准备。资料来源：[cmd/commands/install.go:120-200]()

## 安装机制（install 是 mechanism，不是策略）

`install.sh` 是面向终端用户的 shell 引导脚本；其作用是下载预编译二进制并执行 `witness install`，而非重复实现钩子逻辑。所有真正的接线工作都收敛在 Go 端：

- `cmd/commands/install.go` 解析目标编辑器（Claude Code、OpenCode 等），调用 `cmd/commands/installers.go` 中的具体实现。资料来源：[cmd/commands/installers.go:1-140]()
- 接线结果写入 `~/.claude/settings.json` 之类的本地配置文件，钩子脚本再调用 `witness capture` 或 `witness import`。资料来源：[cmd/commands/capture.go:1-90]()
- `install` 不再创建、修改或删除任何 lens；这些行为完全归 `lens` 子命令所有。资料来源：[cmd/commands/lens.go:1-160]()

下表给出主要动词的职责分工：

| 动词 | 类别 | 职责 | 主要子命令文件 |
| --- | --- | --- | --- |
| `install` | 机制 | 仅做钩子/配置文件接线 | `install.go`、`installers.go` |
| `lens` | 数据/策略 | 注册、列出、删除 lens；管理默认种子 | `lens.go` |
| `npm` | 发行 | 把 witness / `@witness-ai/opencode` 发布到 npm | `npm.go` |
| `capture` | 摄取 | Claude Code 钩子调用，写入 L0 | `capture.go` |
| `import` | 摄取 | OpenCode 会话 reconcile，写入 L0 | `import.go` |
| `distill` | 引擎 | L0→L4 蒸馏 | `distill.go` |
| `serve` | 服务 | MCP 服务，对外暴露记录/档案 | `serve.go` |
| `backfill` / `config` | 引擎 | 统一回填与配置；从前门下沉 | `backfill.go`、`config.go` |

## CLI 操作的"前门"与子命令组织

`cmd/commands/cli.go` 中的根命令将动词分为三类：机制（`install`）、策略（`lens`、`npm`）、运行时（`capture`、`import`、`distill`、`serve`）。这种分类在帮助输出中以分组标题呈现，方便用户根据"我现在想做什么"而不是"引擎内部怎么命名"找到命令。

- 每个子命令文件实现 `cobra.Command`，长选项采用 `--no-…`、`--pure`、`--interactive` 等易读形式，v0.4.0 起统一了帮助文本风格。资料来源：[cmd/commands/cli.go:80-160]()
- 退出码遵循约定：成功为 0；用户取消交互为 130；参数错误为 64；底层存储或网络错误为 1。资料来源：[cmd/witness/main.go:1-80]()
- `capture` 与 `import` 是非交互的钩子入口，必须在毫秒级返回；较慢的工作（如 LLM 调用）由后台 `distill` 处理。资料来源：[cmd/commands/capture.go:30-90]()、[cmd/commands/import.go:30-90]()

```mermaid
flowchart LR
    A[用户] --> B[install.sh]
    B --> C[witness install]
    C --> D[钩子配置]
    D --> E[witness capture / import]
    E --> F[L0 存储]
    F --> G[witness distill]
    G --> H[L1-L4]
    H --> I[witness serve MCP]
```

## 发行版与 npm 同步

`Makefile` 与 `.goreleaser.yml` 负责 Go 端的交叉编译与 GitHub Release，而 npm 端通过 `cmd/commands/npm.go` 包装的脚本完成发布。两者必须保持版本号与 `mcpName` 字段同步——这是 v0.5.1 修复的关键问题：

- MCP Registry（schema `2025-12-11`）会校验 npm 包是否声明 `mcpName` 与服务器名一致，缺失即拒绝发布。
- `package.json` 中的 `mcpName` 字段在 v0.5.0 的 `@witness-ai/opencode` 子包中遗漏，导致 `mcp-publisher publish` 失败；npm 版本不可变，修复只能通过 v0.5.1 这一纯元数据补丁发布。资料来源：[package.json:1-40]()
- Go 端二进制与 npm 端的版本由 `Makefile` 中 `release` 目标统一提升，避免两端漂移。资料来源：[Makefile:1-60]()

## 相关社区讨论

- #102 / #103：把 `install` 收敛为纯机制，并把 lens/npm 命令表面的冗余路径清理掉，是本页描述的当前形态的直接来源。
- #98：跟踪未信任记录流的摄取硬化，建议在采用 npm 发行 + `serve` 路径时同步评审——本期 `install` / `npm` / `serve` 的边界划分正是为此预留接口。
- #45：让 witness 可被 agent 工具发现，CLI 帮助文本与 `package.json` 的描述/标签是被搜索系统抓取的主要字段；本节所述的统一帮助风格间接服务于该目标。

---

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

## 配置、模型与故障排查

### 相关页面

相关主题：[Lens 镜头系统与自定义领域](#page-4), [安装、发行版与 CLI 操作](#page-7)

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

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

- [internal/store/config.go](https://github.com/IngTian/witness/blob/main/internal/store/config.go)
- [cmd/commands/config.go](https://github.com/IngTian/witness/blob/main/cmd/commands/config.go)
- [cmd/commands/lens.go](https://github.com/IngTian/witness/blob/main/cmd/commands/lens.go)
- [internal/embed/embed.go](https://github.com/IngTian/witness/blob/main/internal/embed/embed.go)
- [internal/proc/proc.go](https://github.com/IngTian/witness/blob/main/internal/proc/proc.go)
- [internal/proc/proc_linux.go](https://github.com/IngTian/witness/blob/main/internal/proc/proc_linux.go)
</details>

# 配置、模型与故障排查

witness 在 v0.5.0 之后转型为「records-in 蒸馏引擎」，CLI 收敛为 ~6 动词前门（v0.4.0），并把 `install` 切分为纯机制、把 lens 切分为可删除的普通实体（v0.3.1）。这一切都依赖三套相互衔接的源码层：统一的存储配置、按 lens 维度组织的运行时模型选择，以及面向进程生命周期的故障排查工具。本页围绕这三个层面展开。

## 配置体系：CLI 与 store 的契约

`cmd/commands/config.go` 承担 `witness config` 这一动词的全部 getter/setter/list 三类职责，是用户面与存储面的唯一边界。`internal/store/config.go` 负责把每个字段（lens 路由、蒸馏等级、模型选择、OpenCode/Claude Code 接入点等）序列化到统一 schema 中，遵循 v0.4.0 引入的 "unified config" 约定。

资料来源：[cmd/commands/config.go:1-80]()
资料来源：[internal/store/config.go:1-120]()

路径化的访问形式（如 `witness config set lens.<name>.model`）在两个文件之间保持一致：当 CLI 解析路径后,store 层负责按段下钻到具体 lens 节点；当 `default` 从保留名降级为普通 lens（#99 / #102）后,这条路径中不能再依赖任何隐式特例。

## 模型与 Lens：每条 lens 独立的 runner + model

`cmd/commands/lens.go` 暴露 lens 的注册、列表、删除与选择入口；`internal/embed/embed.go` 把嵌入/生成模型与具体 lens 绑定。到 v0.5.0（#75 落地）为止,每条 lens 都拥有独立的 runner 与 model,运行时不再回退到全局默认。

资料来源：[cmd/commands/lens.go:1-120]()
资料来源：[internal/embed/embed.go:1-90]()

社区在 #101 中指出,两个注册 lens 可能解析到同一个 `lens.json` 名字,从而共享 `watermark`、`profile`、`obs-tag` 三个字段；实际行为按注册顺序覆盖,因此排查 "lens 行为异常" 时,优先核对 `cmd/commands/lens.go` 的注册顺序而非模型本身。

## 进程与故障排查：reap 与跨平台 proc

`internal/proc/proc.go` 定义平台无关的进程抽象（pid 是否存在、命令行匹配、parent 检测等），`internal/proc/proc_linux.go` 在 Linux 上读取 `/proc/<pid>/cmdline` 与 `/proc/<pid>/status` 做精确识别。`opencode reap` 走的就是这条路径。

资料来源：[internal/proc/proc.go:1-150]()
资料来源：[internal/proc/proc_linux.go:1-150]()

#91 指出,旧注释中 "NEVER kills a live serve" 实属口语化表达；当用户自己通过 `nohup` 启动了一个 `--pure serve` 进程时,reap 仅凭命令行指纹难以与 witness 自己的 serve 区分,这是一个真实存在的边界。故障排查时不应把这条注释当作保证。

## 常见故障与排查路径

| 现象 | 优先查看 | 关联讨论 |
| --- | --- | --- |
| lens 行为异常 / 名字冲突 | `cmd/commands/lens.go` | #101 |
| 模型调用失败 | `internal/embed/embed.go` | #75 per-lens runner+model |
| 进程被 reap 误杀 | `internal/proc/proc_linux.go` | #91 (`nohup --pure serve` 边界) |
| `witness config` 读写异常 | `internal/store/config.go` + `cmd/commands/config.go` | v0.4.0 unified config |
| 安装后未自动 seed | `cmd/commands/config.go` | v0.3.1 `install` 仅是机制 |

针对 ingest 路径上未受信任输入,#98 已经把安全加固（#98 defense-in-depth）列为快速跟进项,但在 feature-first 阶段暂未落地；排查时不要把 "已加固" 作为默认假设。#97 跟进 MCP 假存储断言强度,若测试出现间歇失败,优先回看该改动是否引入了 `get_profile` / `record` / `delete` / `search` 路径上的新断言。

---

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

---

## Doramagic 踩坑日志

项目：IngTian/witness

摘要：发现 34 个潜在踩坑项，其中 1 个为 high/blocking；最高优先级：能力坑 - 能力证据存在缺口。

## 1. 能力坑 · 能力证据存在缺口

- 严重度：high
- 证据强度：source_linked
- 发现：Sandbox install result is missing.
- 对用户的影响：缺口未补前，Doramagic 不能把该能力当作可靠推荐卖点。
- 证据：evidence.evidence_gaps | https://github.com/IngTian/witness | Sandbox install result is missing.

## 2. 安装坑 · 可能需要本地编译工具链

- 严重度：medium
- 证据强度：runtime_trace
- 发现：安装入口或说明出现本地编译相关关键词：make install
- 对用户的影响：Windows/macOS 用户可能卡在编译依赖上。
- 复现命令：`make install`
- 证据：identity.distribution | https://github.com/IngTian/witness | make install

## 3. 安装坑 · 失败模式：installation: Make witness discoverable by agents doing tool-discovery (empty description/topics; name coll...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: Make witness discoverable by agents doing tool-discovery (empty description/topics; name collision)
- 对用户的影响：Developers may fail before the first successful local run: Make witness discoverable by agents doing tool-discovery (empty description/topics; name collision)
- 证据：failure_mode_cluster:github_issue | https://github.com/IngTian/witness/issues/45 | Make witness discoverable by agents doing tool-discovery (empty description/topics; name collision)

## 4. 安装坑 · 失败模式：installation: cleanup: tighten install/lens/npm command surface — install=mechanism, seed+interactivity sep...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: cleanup: tighten install/lens/npm command surface — install=mechanism, seed+interactivity separate (post-#44-slice1a)
- 对用户的影响：Developers may fail before the first successful local run: cleanup: tighten install/lens/npm command surface — install=mechanism, seed+interactivity separate (post-#44-slice1a)
- 证据：failure_mode_cluster:github_issue | https://github.com/IngTian/witness/issues/102 | cleanup: tighten install/lens/npm command surface — install=mechanism, seed+interactivity separate (post-#44-slice1a)

## 5. 安装坑 · 失败模式：installation: v0.1.0 — Claude Code

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.1.0 — Claude Code
- 对用户的影响：Upgrade or migration may change expected behavior: v0.1.0 — Claude Code
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.1.0 | v0.1.0 — Claude Code

## 6. 安装坑 · 失败模式：installation: v0.2.0 — Windows (Claude Code) + hardening

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.2.0 — Windows (Claude Code) + hardening
- 对用户的影响：Upgrade or migration may change expected behavior: v0.2.0 — Windows (Claude Code) + hardening
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.2.0 | v0.2.0 — Windows (Claude Code) + hardening

## 7. 安装坑 · 失败模式：installation: v0.2.1 — module rename, export, npm auto-publish

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.2.1 — module rename, export, npm auto-publish
- 对用户的影响：Upgrade or migration may change expected behavior: v0.2.1 — module rename, export, npm auto-publish
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.2.1 | v0.2.1 — module rename, export, npm auto-publish

## 8. 安装坑 · 失败模式：installation: v0.2.3 — parallel mining · opencode idle-reconcile · discovery

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.2.3 — parallel mining · opencode idle-reconcile · discovery
- 对用户的影响：Upgrade or migration may change expected behavior: v0.2.3 — parallel mining · opencode idle-reconcile · discovery
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.2.3 | v0.2.3 — parallel mining · opencode idle-reconcile · discovery

## 9. 安装坑 · 失败模式：installation: v0.2.4 — audit fixes: worker livelock, watermark CAS, hardening

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.2.4 — audit fixes: worker livelock, watermark CAS, hardening
- 对用户的影响：Upgrade or migration may change expected behavior: v0.2.4 — audit fixes: worker livelock, watermark CAS, hardening
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.2.4 | v0.2.4 — audit fixes: worker livelock, watermark CAS, hardening

## 10. 安装坑 · 失败模式：installation: v0.3.0 — per-lens tuning, cross-runtime distillation, architecture hardening

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.3.0 — per-lens tuning, cross-runtime distillation, architecture hardening
- 对用户的影响：Upgrade or migration may change expected behavior: v0.3.0 — per-lens tuning, cross-runtime distillation, architecture hardening
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.3.0 | v0.3.0 — per-lens tuning, cross-runtime distillation, architecture hardening

## 11. 安装坑 · 失败模式：installation: v0.3.1 — install=mechanism · deletable auto-seeded default · unified backfill

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.3.1 — install=mechanism · deletable auto-seeded default · unified backfill
- 对用户的影响：Upgrade or migration may change expected behavior: v0.3.1 — install=mechanism · deletable auto-seeded default · unified backfill
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.3.1 | v0.3.1 — install=mechanism · deletable auto-seeded default · unified backfill

## 12. 安装坑 · 失败模式：installation: v0.4.0 — CLI surface diet: a ~6-verb front door, unified config, readable help

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.4.0 — CLI surface diet: a ~6-verb front door, unified config, readable help
- 对用户的影响：Upgrade or migration may change expected behavior: v0.4.0 — CLI surface diet: a ~6-verb front door, unified config, readable help
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.4.0 | v0.4.0 — CLI surface diet: a ~6-verb front door, unified config, readable help

## 13. 安装坑 · 失败模式：installation: v0.5.0 — witness ingest (records-in engine) + install/wire split

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.5.0 — witness ingest (records-in engine) + install/wire split
- 对用户的影响：Upgrade or migration may change expected behavior: v0.5.0 — witness ingest (records-in engine) + install/wire split
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.5.0 | v0.5.0 — witness ingest (records-in engine) + install/wire split

## 14. 安装坑 · 失败模式：installation: v0.5.1

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this installation risk before relying on the project: v0.5.1
- 对用户的影响：Upgrade or migration may change expected behavior: v0.5.1
- 证据：failure_mode_cluster:github_release | https://github.com/IngTian/witness/releases/tag/v0.5.1 | v0.5.1

## 15. 安装坑 · 安装命令尚未沙箱验证

- 严重度：medium
- 证据强度：runtime_trace
- 发现：当前 install_status=documented，还只是文档/元数据线索。
- 对用户的影响：命令可能缺步骤、过期或依赖本地环境，不能直接作为用户承诺。
- 复现命令：`make install`
- 证据：downstream_validation.install_status | https://github.com/IngTian/witness | install_status=documented; command=make install

## 16. 安装坑 · 来源证据：cleanup: tighten install/lens/npm command surface — install=mechanism, seed+interactivity separate (post-#44-slice1a)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：cleanup: tighten install/lens/npm command surface — install=mechanism, seed+interactivity separate (post-#44-slice1a)
- 对用户的影响：可能影响升级、迁移或版本选择。
- 证据：community_evidence:github | https://github.com/IngTian/witness/issues/102 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 17. 安装坑 · 来源证据：opencode reap: soften "NEVER kills a live serve" comment — user's own nohup'd --pure serve is an edge case

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：opencode reap: soften "NEVER kills a live serve" comment — user's own nohup'd --pure serve is an edge case
- 对用户的影响：可能阻塞安装或首次运行。
- 证据：community_evidence:github | https://github.com/IngTian/witness/issues/91 | 来源讨论提到 macos 相关条件，需在安装/试用前复核。

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

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

## 19. 配置坑 · 失败模式：configuration: feat: files as a 2nd L0 source — apply the distillation engine (lenses + L0→L4) to files, not...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: feat: files as a 2nd L0 source — apply the distillation engine (lenses + L0→L4) to files, not just chats
- 对用户的影响：Developers may misconfigure credentials, environment, or host setup: feat: files as a 2nd L0 source — apply the distillation engine (lenses + L0→L4) to files, not just chats
- 证据：failure_mode_cluster:github_issue | https://github.com/IngTian/witness/issues/44 | feat: files as a 2nd L0 source — apply the distillation engine (lenses + L0→L4) to files, not just chats

## 20. 配置坑 · 失败模式：configuration: lens: two registered lenses can resolve to the same lens.json name (share watermark/profile/o...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: lens: two registered lenses can resolve to the same lens.json name (share watermark/profile/obs-tag) — general resolved-name collision
- 对用户的影响：Developers may misconfigure credentials, environment, or host setup: lens: two registered lenses can resolve to the same lens.json name (share watermark/profile/obs-tag) — general resolved-name collision
- 证据：failure_mode_cluster:github_issue | https://github.com/IngTian/witness/issues/101 | lens: two registered lenses can resolve to the same lens.json name (share watermark/profile/obs-tag) — general resolved-name collision

## 21. 配置坑 · 失败模式：configuration: opencode reap: soften "NEVER kills a live serve" comment — user's own nohup'd --pure serve is...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: opencode reap: soften "NEVER kills a live serve" comment — user's own nohup'd --pure serve is an edge case
- 对用户的影响：Developers may misconfigure credentials, environment, or host setup: opencode reap: soften "NEVER kills a live serve" comment — user's own nohup'd --pure serve is an edge case
- 证据：failure_mode_cluster:github_issue | https://github.com/IngTian/witness/issues/91 | opencode reap: soften "NEVER kills a live serve" comment — user's own nohup'd --pure serve is an edge case

## 22. 配置坑 · 失败模式：configuration: security: harden the ingestion + MCP-serve path for UNTRUSTED input (defense-in-depth; deferr...

- 严重度：medium
- 证据强度：source_linked
- 发现：Developers should check this configuration risk before relying on the project: security: harden the ingestion + MCP-serve path for UNTRUSTED input (defense-in-depth; deferred, feature-first)
- 对用户的影响：Developers may misconfigure credentials, environment, or host setup: security: harden the ingestion + MCP-serve path for UNTRUSTED input (defense-in-depth; deferred, feature-first)
- 证据：failure_mode_cluster:github_issue | https://github.com/IngTian/witness/issues/98 | security: harden the ingestion + MCP-serve path for UNTRUSTED input (defense-in-depth; deferred, feature-first)

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

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

## 24. 运行坑 · Quick Start 尚未实际跑通

- 严重度：medium
- 证据强度：source_linked
- 发现：quickstart_status=not_attempted。
- 对用户的影响：用户只能看到安装线索，不能确信 10 分钟内能形成最小可试路径。
- 证据：downstream_validation.quickstart_status | https://github.com/IngTian/witness | quickstart_status=not_attempted; sandbox_quickstart_status=missing

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

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

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

## 27. 安全/权限坑 · 存在安全注意事项

- 严重度：medium
- 证据强度：source_linked
- 发现：No sandbox install has been executed yet; downstream must verify before user use.
- 对用户的影响：用户安装前需要知道权限边界和敏感操作。
- 证据：risks.safety_notes | https://github.com/IngTian/witness | No sandbox install has been executed yet; downstream must verify before user use.

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

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

## 29. 安全/权限坑 · 来源证据：Make witness discoverable by agents doing tool-discovery (empty description/topics; name collision)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Make witness discoverable by agents doing tool-discovery (empty description/topics; name collision)
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/IngTian/witness/issues/45 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 30. 安全/权限坑 · 来源证据：feat: files as a 2nd L0 source — apply the distillation engine (lenses + L0→L4) to files, not just chats

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：feat: files as a 2nd L0 source — apply the distillation engine (lenses + L0→L4) to files, not just chats
- 对用户的影响：可能阻塞安装或首次运行。
- 证据：community_evidence:github | https://github.com/IngTian/witness/issues/44 | 来源类型 github_issue 暴露的待验证使用条件。

## 31. 安全/权限坑 · 来源证据：lens: two registered lenses can resolve to the same lens.json name (share watermark/profile/obs-tag) — general resolved…

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：lens: two registered lenses can resolve to the same lens.json name (share watermark/profile/obs-tag) — general resolved-name collision
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/IngTian/witness/issues/101 | 来源类型 github_issue 暴露的待验证使用条件。

## 32. 安全/权限坑 · 来源证据：security: harden the ingestion + MCP-serve path for UNTRUSTED input (defense-in-depth; deferred, feature-first)

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：security: harden the ingestion + MCP-serve path for UNTRUSTED input (defense-in-depth; deferred, feature-first)
- 对用户的影响：可能阻塞安装或首次运行。
- 证据：community_evidence:github | https://github.com/IngTian/witness/issues/98 | 来源讨论提到 macos 相关条件，需在安装/试用前复核。

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

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

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

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

<!-- canonical_name: IngTian/witness; human_manual_source: deepwiki_human_wiki -->
