# pi-kb — 通用知识库扩展（渐进式披露）

为 [Pi](https://github.com/earendil-works/pi)（AI coding agent）提供渐进式披露的通用知识库，**复用与 DSH `dsh-kb` 插件完全相同的知识库**（`~/.agents/kb`，目录即分类 + front-matter + 正文 markdown）：分类树、知识点、踩坑日志一套知识两处共享，无需重复维护。

适用场景：企业知识库（业务口径/组织架构/踩坑日志）、个人知识库（读书笔记/灵感/技能）、项目资料库（规范/FAQ/复盘）…… 分类、标签、内容全部由你决定。

## 能力

Pi 会话注入八个工具 + prompt 引导：

| 工具 | 用途 |
|------|------|
| `kb_categories` | 分类管理：`list` 免确认；`add`（目录即分类，父级自动创建）、`update`（改 title/description/order/**enabled 生效开关**，或 `new_path` 重命名/移动整棵子树）、`remove`（仅空分类）——增删改需 `user_approved: true` |
| `kb_list` | 无 category：分类树（title(path)：description ｜ 条目数，含子树聚合，空目录标注）；有：该分类子树全部条目。**【硬要求】知识相关工作第一步先调用它/kb_categories list** |
| `kb_search` | 关键词检索：匹配 name/summary/tags/related/所属分类（含分类标题与描述）+ **正文**；词元拆分 + 量词后缀兜底；强匹配标 ★ 排前；支持子树/标签过滤；命中自动附 related；未命中自动留痕 + 附分类树索引 |
| `kb_get` | 读取单个条目完整正文，自动附 related 摘要；未找到自动留痕 |
| `kb_validate` | 校验知识目录：分类树与 categories.yml 一致性（残影/未登记）、条目 front-matter 完整性、命名一致、全库唯一、空正文、未分类根条目 |
| `kb_pending` | 管理待补池（进程内存、按会话隔离、重启即清空）：list / add / remove；补录走 `kb_create` |
| `kb_create` | 新增知识条目（写入 `<分类>/<条目名>.md` 并自动校验）。默认需 `user_approved: true`；白名单分类免确认；停用分类拒绝写入；`from_pending` 成功后自动删待补条目 |
| `kb_update` | 更新已有条目：只更新传入字段；`category` 变更=移动文件到目标分类；门控同上；删缺必填字段被拦 |

引导约束（注入 pi system prompt）：
- **知识库权威**：`~/.agents/kb`（目录即分类 + front-matter markdown 条目）是分类/知识点/踩坑经验的权威来源，做知识相关工作以它为准，不凭印象直接搜或写；
- 涉及知识检索/写入**第一步必须先 `kb_categories list` / `kb_list`**，不要凭印象直接搜或写；
- **标准链路**：`kb_list`（分类树/子树条目）→ `kb_search`（关键词，支持分类子树/标签过滤，匹配正文）→ `kb_get`（读单个条目完整正文）；
- **未命中自动留痕**：`kb_search`/`kb_get` 未命中自动留痕到本会话待补池（`kb_pending list` 查看），任务收尾经用户同意后 `kb_create` 补录；
- **写入默认需 `user_approved: true`**（`PI_KB_AUTO_APPROVE_CATEGORIES` 白名单分类免确认）；停用分类拒绝写入。

## 安装

```bash
# 本地源码目录（改代码即生效，无需重装）
pi install /path/to/pi-kb

# 或发布后
pi install npm:pi-kb
```

查看：`pi list`；启用/停用单个资源：`pi config`。

## 配置

- **数据目录**：默认 `~/.agents/kb`（与 DSH kb 插件同一份知识库）。可用环境变量 `PI_KB_DATA_DIR` 覆盖到其它路径。
- **自动记录白名单**：`PI_KB_AUTO_APPROVE_CATEGORIES`（逗号分隔分类路径，支持前缀匹配）内的分类，`kb_create`/`kb_update` **免确认自动记录**（沿用旧「主动知识记录/踩坑必记」习惯）；白名单外的分类写入必须 `user_approved: true`。空则全部写入需确认。
- 知识文件由你在 `~/.agents/kb` 自行维护，新增后无需改扩展。

## 知识库格式（与 DSH dsh-kb 一致）

```
~/.agents/kb/
├── README.md              # 种子说明（自动生成，含规范）
├── categories.yml         # 可选元数据叠加层：分类路径 → {title, description, order, enabled}
└── <分类路径>/            # 多级目录树，每个目录即分类
    └── <条目名>.md        # 每个知识点一个文件
```

- **目录即分类**：磁盘目录树是分类的唯一事实来源，路径即分类 id（可多级）；`categories.yml` 仅为可选元数据叠加层（缺失时 title=目录名、enabled=true）。人工建文件夹=建分类、拖拽文件=改分类，与工具操作永远一致。
- **条目 front-matter（必填 3 项）**：`name`（与文件名一致，全库唯一）、`summary`（一句话摘要）、`tags`（多标签，逗号分隔）；可选 `related`（相关条目名，检索/读取自动附带）、`status`、`updated`。条目分类 = 文件所在目录，front-matter 不存 category。

```yaml
---
name: 商行=小商行firm_s
summary: 常用维度简称「商行」默认指小商行
tags: 口径, 商行, 维度
related: 调改店经营SKU数
---
正文
```

### categories.yml 元数据叠加层（可选）

```yaml
categories:
  data/biz-caliber:
    title: 业务口径
    description: 指标定义、计算口径、数据来源
    order: 11
```

## 分类生效开关（启用/停用）

- categories.yml 中某分类 `enabled: false`（或用 `kb_categories update enabled: false`）→ 该分类**及其整棵子树**停用。
- 停用后：`kb_list`、`kb_search`、`kb_get` 默认**完全忽略**（相关条目视作不存在）；`kb_categories list` 始终显示全部分类并标注「⛔已停用」；`kb_list`/`kb_search` 传 `include_disabled: true` 可强制查看。
- 停用分类**拒绝写入**新条目；恢复 `enabled: true`（或删掉该行）后自动生效，**数据零删除**。
- 典型用法：离职后把旧公司相关分类停用，相关知识整体失效、不影响日常检索；未来再启用即可。

## 开发

```bash
npm install            # 安装 typebox（工具 schema 依赖）
node --experimental-strip-types --check extensions/index.ts   # TS 语法
npm test               # 单元测试（mock pi 捕获工具 + 临时合成知识库断言，不触碰真实库）
```

## 说明

- 读工具（list/search/get/validate/categories list）为只读；写工具（create/update/categories 增删改）直接改 `~/.agents/kb`。
- **创建/更新规范**：`kb_create`/`kb_update` 遵循 front-matter 规范（必填 name/summary/tags），正文字段名与事实一致；**默认必须先征得用户明确同意后以 `user_approved: true` 调用**，`PI_KB_AUTO_APPROVE_CATEGORIES` 白名单分类免确认；停用分类拒绝写入。
- **待补池**：`kb_search`/`kb_get` 未命中自动留痕到进程内存待补池（按会话隔离、不写文件、重启即清空），经用户同意后 `kb_create` 补录。
- 也建议先在 DSH 侧用 `kb_pending`/`kb_create` 管理待补与确认流程；本扩展直接读写同一份知识库。
- 知识库位置通过 `os.homedir()` 计算，不硬编码绝对路径。

## 许可

MIT
