- name
- auto-wiki
- metadata
- {"version":"0.4.4+survey.2.scaling.2"}
- description
- 把源材料增量编译为持久化 Markdown + SQLite wiki,实现跨会话知识积累。用于建立或使用个人/领域知识库、Obsidian wiki,以及取材、编译、查询和治理已有 wiki。八模式按意图路由:
survey(我已经有笔记了、勘察存量、冷启动、看看我现有的资料)→ 只读结构扫已有目录,反推 init 提案与种子草案,不建库不写盘;
init(初始化、从零建库、搭建 Obsidian)→ 访谈真实工作流并创建首个领域;
source(取材、找资料、按清单搜)→ fan-out 搜集,收口 Inbox/raw,不碰正典;
recall(打开 wiki、基于积累、之前研究过)→ 持续加载已有知识;
ingest(整理、消化、归档、加入知识库)→ 比较新旧后编译材料;
query(根据 wiki 回答、查查看)→ 单次查询;
lint(检查健康、矛盾、断链、重复)→ 治理知识库;
deep-dive(查漏补缺、上强度)→ lint 找缺口,经确认后搜索并 ingest。
无 wiki 且用户要建库时走 init;有新材料走 ingest;人给索引并要求找资料走 source;只提 wiki/既有领域知识走 recall。不确定则询问。
# 知识编译器
> Agent 做研究、拉数据、写报告——wiki 把这些产出串起来。Agent 越用越懂你的领域。
## 运行时依赖与权限声明
| 依赖 | 必需? | 说明 |
|------|--------|------|
| **Python 3.8+** | 必需 | `schema.py`、`store.py`、`precheck.py`、`new_domain.py` 等确定性工具 |
| **pydantic + pyyaml** | 必需 | frontmatter 校验和实例配置解析。`python3 -m pip install pydantic pyyaml` |
| **文件系统写入** | 必需 | 在 `wiki/{domain}/` 下创建 Markdown 与 SQLite;选择 Obsidian 时另写 `.obsidian/`。init 写入前先确认提案 |
| **WebSearch / WebFetch** | 可选 | 主动模式(Agent 自主搜索材料)需要。被动模式(用户提供文件)不需要 |
| **外部校验器(MCP)** | 可选 | 仅当 wiki 声明了 validator 时 lint 会尝试调用。不可达时静默跳过,零影响。**不需要用户提供任何凭证**——`Mcp-Session-Id` 是标准 MCP 协议的会话握手,由 Agent 自动完成 |
| **搜索类 MCP** | 可选 | deep-dive 和主动 ingest 可用域数据 MCP 增强搜索质量。没有时退化为 WebSearch |
> **核心承诺**:被动模式(用户提供文件 → Agent 编译)只需要 Python 3 + 文件读写,零网络依赖。所有网络调用都是可选增强,且会在首次使用时通过环境检查告知用户。
## Quick Start
```
用户: /auto-wiki init
Agent: 你拿到一份新材料后通常怎么处理、最后要产出什么?
再举三个以后会反复问这个知识库的问题。
用户: 我读书后想沉淀概念和论点,以后会问……
Agent: [再问第一份材料、更新节奏、查看器和数据边界 → 展示提案 → 用户确认]
Agent: 已建库并完成首次 ingest。图谱报告:wiki/books/_report.html
```
## 核心理念
Agent 每天帮你做研究、写报告、拉数据——但做完就忘。下次问同样领域的问题,又从零开始。
这个 Skill 解决一件事:**给 Agent 一个可以持续积累的知识库。**
不是 RAG(每次从文档堆里临时检索),是编译——Agent 读完源文件后,把关键信息写进 wiki 已有页面,和旧知识比较、合并、标注冲突。下次执行任何任务前,先读 wiki,从积累的基础上工作。
## 八个模式
| 模式 | 触发 | Agent 做什么 |
|------|------|-------------|
| **survey** | `survey` / “我已经有笔记了” / “勘察存量” / “冷启动” | 只读结构扫已有目录 → 反推提案 → 问出禁混规则 → 出报告+提案草案+种子草案,**不建库、不写用户任何文件** |
| **init** | `init` / “从零建库” / “搭建 Obsidian” | 访谈真实工作流 → 展示提案 → 建领域与契约 → 首次 ingest → 用真实问题验收 |
| **source** | `source` / "根据索引找资料" / "取材" | 解析索引/钩子清单 → 动用全部取材通道 fan-out 搜原料 → 整合带溯源 → **落 Inbox/raw(不碰 wiki)** |
| **recall** | `recall` / `recall {topic}` | 加载 wiki 上下文,后续所有问题先查 wiki 再回答 |
| **ingest** | 用户提供源文件或文本 | 读源文件 → 搜索已有 wiki → 比较新旧 → 更新/创建页面 → 更新索引 |
| **query** | 用户提问(单次) | 读 hub 定位类型 → 子索引/全文检索找页面 → 综合回答 → 有价值的分析可归档 |
| **lint** | 用户说"检查 wiki" | 扫描全部页面 → 合并重复 → 归档过时 → 报告矛盾和健康度 |
| **deep-dive** | `deep-dive` / "上强度" | 运行 Coverage lint → 展示缺口报告 → 用户确认 → 搜索 + ingest 填补缺口 |
> **source 与 deep-dive 都涉及向外搜索,但方向相反**:deep-dive 由 `lint(Coverage)` 自动找 wiki **内部缺口**、搜回来**直接 ingest**;source 由**人给的索引**驱动、向外 fan-out 取材、**停在 Inbox/raw 闸前**。source 的产出正是 ingest / deep-dive 的输入。deep-dive 不是独立模式(= lint+ingest 组合管道);source 是独立模式(管道最前端的取材相)。
recall 模式 vs query 的区别:query 是单次操作(问一个问题,查一次 wiki)。recall 模式是持续状态——进入后,这轮对话里的每个问题都先过 wiki。
---
## survey 模式(存量勘察)
**详细协议见 `references/survey-protocol.md`。**
站在 `init` 之前的取证相:人指一个**已经存在的**笔记库或工作目录,Agent
**只读结构不读正文**地扫一遍,反推出 init 提案草案与种子草案,**不建库、
不写用户任何文件**。
有存量的人是多数,而 init 第一轮要人凭空说出领域、节点类型、路由词和三个
反复问的问题——冷着答只能给场面话。他已有的目录名就是他的分类学,文件名
高频词就是他的路由词,改动时间分布就区分了动态与稳定知识。先扫再问,提案
质量不是一个量级。
```bash
python references/survey.py <目录> [--frontmatter] [--top 30]
```
三条硬边界:**不读正文**(默认零内容暴露,要读须逐次授权)、**不导入存量**
(守 init「不导入整批历史资料」那条,读结构不是导入)、**不写用户既有目录**
(一个字节都不写)。
上下文纪律:存量库动辄上万文件,**一次扫全库灌满上下文就没有下一步了**。
`survey.py` 各节按 `--top` 截断,输出长度不随语料规模增长;绝不打印文件清单,
只出聚合量;下钻按用户点名,一次一个子目录重跑,不要拉进来再筛。
**禁混规则挖不到**——产物是收敛后的结果,混淆痕迹已被抹掉。那只能问人,而且
要问对:**「你带新人时反复纠正过哪几组概念?」** 这比问「有哪些容易混的概念」
好答十倍。
---
## init 模式(首次建库)
**详细协议见 `references/init-protocol.md`。**
init 不让用户先学本体术语,而是从真实工作流和反复问题反推第一个领域、节点类型与关系。写入前只做一次提案确认;确认后复用 `new_domain.py`,按需应用 seed,完成首份材料 ingest,并用一个真实问题验收。实例约束落在 `{ops_dir}/onboarding.md`,供后续 source/ingest 读取。
若用户只是想体验,使用 `examples/bookshelf/`;若用户要建立自己的库,不把示例知识混入用户数据。
---
## source 模式(取材 / 采集)
**详细协议见 `references/source-protocol.md`。**
管道最前端的取材相:人给一份**索引/钩子清单**,Agent 动用**全部取材通道** fan-out 搜原料,整合带溯源后**落 `Inbox/raw/`,不碰 wiki**(守 ingest 闸)。产出正是 ingest / deep-dive 的输入。
简要流程:
0. **路由**:读 `wiki/_index.md`,把索引每条钩子命中到域,按库配置决定取材通道。
1. **拆索引**为原子查询(可检索的具体问题),列给用户过目可增删。
2. **fan-out 取材**:按钩子命中选通道并行检索——**取材通道按库配置,见库内 CLAUDE.md「取材通道」节**;无库配置时用通用通道(WebSearch/WebFetch 等)兜底。一条查询尽量交叉 2+ 通道互证;数值走数据源工具不凭记忆。
3. **收口整合**:每条原子查询一段「发现 + 溯源(标题+机构/作者+日期+链接) + 渠道可信度档」;多源冲突并列标 `contested`,**不在此裁决**。
4. **落 Inbox/raw**:追加到来源笔记,或新建 `{date}-{slug}-取材.md`,frontmatter `compiled: false` + `取材通道` + `索引来源`。
5. **报告**:每条钩子找到几条材料、覆盖/缺口、哪几条够 ingest 了。
**纪律**:不碰 wiki、不动 data.db;溯源以「标题+机构+日期」为准(链接会过期);渠道分档(一手 > 二手·权威 > 二手,黑名单跳过;库特有分档纪律见库内 CLAUDE.md);不裁决分歧。
---
## recall 模式
### 进入
用户说 `/auto-wiki recall` 或 `/auto-wiki recall {topic}` 时触发。
Agent 执行:
1. **扫描 `wiki/` 目录**,列出可用的 wiki 主题
2. 如果用户指定了主题 → 加载该 wiki;如果没指定 → 列出可选主题让用户选
3. **读 hub 页面**(`{主题中文名}.md`)→ **只用于导航**:拿到类型与计数,不是拿全部页面清单。
页面明细在 `{类型}/_index.md`,按需只读相关类型那一份;页数 > 500 时改用 `python references/fts_index.py wiki/{topic} search "关键词"`。
**上下文纪律:任何时候都不要把整库清单读进来**——它随库大小线性增长,是上下文膨胀的唯一入口。
4. **读 data.db 摘要** → `python references/store.py dump wiki/{topic}/`,获取数据点数、关系数、contested 数
5. **向用户报告**:
```
已进入recall 模式:{主题}
- 页面:{N}(sources: X, entities: Y, concepts: Z)
- 数据点:{N} | 关系:{N} | Contested:{N}
接下来的问题我会先查 wiki 再回答。说"退出recall 模式"恢复正常。
```
### 回答流程
进入recall 模式后,每次收到用户问题:
1. **从问题中提取关键词**(实体名、概念名、指标名)
2. **定位相关页面**:读 hub 判断落在哪个类型 → 只读该类型的 `_index.md` 匹配(标题 + 一行描述);大库直接用 `fts_index.py search`
3. **在 data.db 中查询**相关数据点:
```sql
SELECT * FROM data_points WHERE field LIKE '%关键词%' OR page_slug LIKE '%关键词%'
```
4. **读取匹配的 wiki 页面**(通常 2-5 个),沿 wikilink 展开一层
5. **综合回答**,必须:
- 引用具体页面:`[[slug]]`
- 引用具体数据:值 + 单位 + 时段 + 来源
- 如果涉及 contested 信息,主动标注
- 如果 wiki 中信息不足,明确说"wiki 中没有这方面的积累,建议 ingest XX",
并**登记 query-miss**(见 `query-protocol.md`「query-miss 登记」——误拒侧唯一观测点,漏记 = 检索质量永远无法度量)
6. **不编造 wiki 中没有的信息**。宁可说"不知道"也不要假装 wiki 里有
### 退出
用户说 `exit recall`、切换到其他操作(ingest/lint)、或开始新话题时退出。
---
## 执行流程
### Phase 0: 识别目标领域与本体类型
收到用户输入后,判断三件事:**操作类型**、**目标领域 wiki**、**本体类型**。
> **wiki 按领域(domain)组织,不按研究课题(topic)。** 研究课题(如"美联储加息周期")降级为 `{domain}/分析/` 下一页,不再各自开 wiki。先识别这条知识属于哪个领域(macro / credit / …),再落到该领域目录。详见 `references/storage-spec.md`。
| 用户输入 | 操作 | 目标领域 wiki | 本体类型 |
|---------|------|-----------|---------|
| "帮我整理这篇货币政策研报" + 文件 | ingest | macro | domain |
| "ingest 到宏观" + 文件 | ingest | macro | domain |
| "研究一下 Charlie Munger" + 材料 | ingest | charlie-munger | cognitive |
| "央行降准空间还有多少" | query | macro | — |
| "检查一下 macro wiki" | lint | macro | — |
**本体类型**决定 wiki 的节点类型与采集策略:
| 本体类型 | 研究对象 | 节点类型 | 权威契约 / 参考 |
|---------|---------|---------|------|
| **domain** | 领域(机构、工具、指标、机制、事件) | 实体(机构/工具/指标) · 概念-机制 · 事件 · 分析 · 来源 | 各领域 `wiki/{domain}/_ontology.md` + `references/ontology-types/domain.md` |
| **cognitive** | 人(思维模型、决策方式) | mental-model · 概念 · 来源 · 分析 | `references/ontology-types/cognitive.md` |
**每个领域 wiki 的本体由它自己的 `wiki/{domain}/_ontology.md` 契约定义**(节点类型、受控关系词表、6 档时间模型、退役协议);ingest/recall 前先读它。一个领域只用一种本体类型,不在同一领域里混用 cognitive 与 domain 结构。
**如果 wiki 目录不存在**,切换到 init,按 `references/init-protocol.md` 先访谈、展示提案并确认,再创建初始结构。不得跳过 init 直接猜用户的领域与关系。
**领域种子(seed)**:如果目标领域有对应的种子文件(`seeds/{name}.md`),在 meta.yaml 中声明 `seed: {name}`。种子提供标准术语词表、关系模板和禁混规则,让 wiki 从规范化的起点开始生长。没有种子的领域,wiki 自由生长——两种路径都能跑。种子是社区可贡献的插件,任何人可以为自己的垂直领域写一个 markdown 文件。详见 `references/seed-ontologies.md`。
**首次使用时**,执行环境检查(见 `references/source-validation.md`),告知用户当前可用的能力(被动模式 vs 主动模式)。
### Reference 加载策略
不要一次读完所有 reference。按操作类型按需加载:
| 操作 | 必读 | 首次时读 | 有工具时读 |
|------|------|---------|-----------|
| **survey** | `survey-protocol.md`, `survey.py`(跑,不必读) | `init-protocol.md`(要出提案草案时), `seed-ontologies.md`(要起草种子时) | — |
| **init** | `init-protocol.md`, `storage-spec.md` | `seed-ontologies.md` + 适用的 `seeds/{name}.md` | — |
| **source** | `source-protocol.md` | — | `source-validation.md`(渠道分档/黑名单) |
| **ingest** | `ingest-protocol.md`, `wiki-format.md`, `schema.py`, `precheck.py`(跑,不必读) | `storage-spec.md`(wiki 不存在时), `seed-ontologies.md` + `seeds/{name}.md`(meta.yaml 声明了 seed 时) | `fact-check.md`, `source-validation.md` |
| **query** | `query-protocol.md` | — | — |
| **lint** | `lint-protocol.md`, `schema.py` | — | `validators/{name}.md`(seed 声明了 validator 时) |
| **deep-dive** | `lint-protocol.md`, `ingest-protocol.md`, `source-validation.md`, `wiki-format.md`, `schema.py` | `storage-spec.md`(wiki 不存在时) | `fact-check.md` |
**不需要读的**:`scaling.md` 仅当页面数 > 500 时才相关;`ontology-types/` 仅当新建 wiki 需判断类型时。
### Phase 1: Ingest(知识编译)
**这是核心操作。** 详细协议见 `references/ingest-protocol.md`。
简要流程:
1. **读取源文件**,提取关键信息
2. **校验关键数据**(如有可用工具)— 详见 `references/fact-check.md`
3. **写 source 摘要页**(`sources/{date}-{slug}.md`)
4. **搜索 wiki 中已有的相关页面**(读 hub 定位类型 → 只读该类型 `_index.md`,或 `fts_index.py search`;grep 关键实体名;机器辅助:`python references/precheck.py dup "{候选名}" --wiki wiki/{domain}` 输出同类型撞车候选——命中后建新页须在 log 写明不合并理由)
5. **逐页比较新旧信息**:
- 新信息**支持**已有结论 → 加引用,提升 confidence
- 新信息**推翻**已有结论 → 数值写入 data.db(旧值自动进 history 表),改写正文分析
- 新信息**矛盾**且无法判断 → 并列两种说法,confidence → `contested`
6. **创建新页面**(仅当涉及 wiki 中没有的实体/概念)
7. **重建索引 + 追加 log.md** —— `python references/regen_index.py wiki/{domain}`(重建各类型 `_index.md` 与顶层导航计数;超阈值会打 WARN,按提示上 `fts_index.py`)。**不要手写清单进 hub。**
8. **五试预检**——对本次创建/修改的所有页面运行 `python references/precheck.py page {page.md}`(镜头S = schema 硬闸 + R11 四病根:双 yaml 块/枚举夹注/relations 键名/必填缺失)。error 必须修复再落库;镜头D 的撞车提示是 advisory,不拦截,但要回到第 5 步复核是否该合并
Ingest 完成后向用户报告:
```
已 ingest 到 {主题} wiki:
- 新建:{N} 页(列出)
- 更新:{N} 页(列出 + 简述变更原因)
- 冲突:{N} 处(列出矛盾点)
- 校验:{N} 页全部通过 / {M} 页有问题(列出)
```
### Phase 2: Query(知识查询)
**详细协议见 `references/query-protocol.md`。**
1. 读 hub 定位类型 → 只读相关类型的 `_index.md` 识别候选页面(大库用 `fts_index.py search`)
2. 读取匹配页面 + 沿 wikilink 展开一层关联页面
3. 基于页面内容综合回答,**引用来源页面**:
```
根据 wiki 中 5 篇源文件的积累:
... 分析内容 ...
来源:[[alpha-corp]]、[[2026-policy-doc]]
```
4. 如果涉及 contested 信息,明确标注矛盾
5. 如果回答中包含有价值的新分析,提示用户归档
**如果 wiki 中信息不足以回答**,明确说明缺口,并按 `query-protocol.md`「query-miss 登记」在 ops 目录记一行(路径经 `python references/instance.py .` 解析,不要猜):
```
wiki 中关于 XX 的信息不足,目前只有 2 篇相关源文件。
建议 ingest 更多关于 XX 的材料。
```
### Phase 3: Lint(知识治理)
**详细协议见 `references/lint-protocol.md`(7 项检查 + 健康报告格式)。**
Lint 分两档:
| 档位 | 触发 | 检查项 | 代价 |
|------|------|--------|------|
| **结构档**(默认) | `lint` / `检查 wiki` | Validation, Orphan, Broken Link, Staleness | 全量扫描,确定性 |
| **语义档**(按需) | `深度 lint` / `检查矛盾` | Contradiction, Duplication, Coverage | Agent 语义理解,按范围控制 |
1. **结构档**:自动扫描全部页面,修复格式、断链、孤页、过时标注
2. **语义档**(用户触发时):检测矛盾、重复、覆盖度缺口。wiki < 50 页全量扫描,50-200 页只扫最近 30 天 ingest 触及的页面,> 200 页须用户指定范围
3. **报告健康度**:
```
Wiki 健康报告:{主题}
- 页面总数:42(entities: 15, concepts: 10, sources: 12, analyses: 5)
- 健康度:良好
- 结构修复:修复 1 个断链,归档 1 个过时页面
- [语义] 待人工确认:2 处矛盾(列出)
- 建议:XX 领域源文件较少(仅 1 篇),建议补充
```
### Phase 4: Deep-Dive(知识补全管道)
**deep-dive = lint(Coverage) + ingest(搜索填充)**。不是独立模式,是组合管道。
**前提条件**:需要搜索工具(主动模式)。无搜索工具时,只输出缺口报告,不执行自动填充。提示用户手动 ingest。
**流程**:
```
1. 运行 lint Coverage 检查(5 类缺口检测)
→ 输出结构化 Gap Report(见 lint-protocol.md)
2. 展示 Gap Report,请用户确认
→ 用户可以:全部接受 / 选择子集 / 限定范围 / 取消
→ 这一步不可跳过——防止无监督的批量写入
3. 对确认的每个缺口,执行 from-lint ingest 流程
→ 搜索 → 用户确认来源 → 标准 ingest
GitHub에서 보기