From dc838ce88af4a9437550255092db81e9dbff8c56 Mon Sep 17 00:00:00 2001
From: ai_xiaopei <xiaopei@aisim.cn>
Date: Sun, 26 Jul 2026 08:11:52 +0800
Subject: [PATCH] docs: add kb-cli enhancement design spec
---
docs/superpowers/specs/2026-07-26-kb-cli-enhancement-design.md | 441 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 441 insertions(+), 0 deletions(-)
diff --git a/docs/superpowers/specs/2026-07-26-kb-cli-enhancement-design.md b/docs/superpowers/specs/2026-07-26-kb-cli-enhancement-design.md
new file mode 100644
index 0000000..07f7c67
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-26-kb-cli-enhancement-design.md
@@ -0,0 +1,441 @@
+# kb-cli 增强与 kb-search 技能调整设计
+
+**日期:** 2026-07-26
+**状态:** 已批准
+
+---
+
+## 1. 背景与目标
+
+### 1.1 背景
+
+kb-cli(Go 实现)已完成基础功能,与 Python 版 kb-search.py 对比测试显示:
+- **kb-cli 优势:** 索引正常(768 文件),搜索快速(8ms),结果准确
+- **kb-search.py 问题:** 索引为空(update-index 返回 0 条),搜索返回空结果
+
+用户决策:优先使用 kb-cli,Python 脚本暂时保留作为备选。
+
+### 1.2 目标
+
+1. **给 kb-cli 增加两个功能:**
+ - `--with-content`:搜索时返回完整文件内容
+ - `--with-links`:搜索时显示关联文档链接
+
+2. **调整 kb-search 技能:**
+ - 优先使用 kb-cli
+ - Python 脚本降级为备选方案
+
+---
+
+## 2. 方案选择
+
+### 2.1 候选方案
+
+| 方案 | 描述 | 优点 | 缺点 |
+|------|------|------|------|
+| **A. 最小改动** | 在 SearchResult 结构体上加可选字段 | 改动小,向后兼容,逻辑清晰 | 无 |
+| B. 分层增强 | 创建 Enhancer 接口,搜索管道模式 | 扩展性强 | 过度设计 |
+| C. 独立命令 | 新增 `kb search-detail` 子命令 | 职责清晰 | 重复代码多 |
+
+### 2.2 决策
+
+**选择方案 A:最小改动**
+
+理由:
+1. 改动最小,只改 `search.go` 和 `output/formatter.go`
+2. 向后兼容,现有脚本不受影响
+3. 逻辑简单,容易理解和维护
+4. 不需要过度设计
+
+---
+
+## 3. 数据结构改动
+
+### 3.1 SearchResult 结构体
+
+**文件:** `internal/search/engine.go`
+
+```go
+type SearchResult struct {
+ ID int64 `json:"id"`
+ Path string `json:"path"`
+ Title string `json:"title"`
+ Section string `json:"section"`
+ Score int `json:"score"`
+
+ // 新增可选字段
+ Content string `json:"content,omitempty"` // --with-content 时填充
+ Links []string `json:"links,omitempty"` // --with-links 时填充
+}
+```
+
+### 3.2 SearchOptions 结构体
+
+**文件:** `internal/search/engine.go`
+
+```go
+type SearchOptions struct {
+ Expanded []string
+ Symptom []string
+ TopN int
+ WithContent bool // 新增
+ WithLinks bool // 新增
+}
+```
+
+### 3.3 Search 函数逻辑
+
+```go
+func Search(store *index.Store, keywords []string, opts SearchOptions) ([]SearchResult, error) {
+ // 1. 执行 FTS5 搜索
+ ftsResults, err := store.FTSSearch(allKeywords, 100)
+ if err != nil {
+ return nil, err
+ }
+
+ // 2. 评分和排序
+ results := scoreAndSort(ftsResults, keywords, opts)
+
+ // 3. 限制返回数量
+ if opts.TopN > 0 && len(results) > opts.TopN {
+ results = results[:opts.TopN]
+ }
+
+ // 4. 增强结果(新增)
+ for i := range results {
+ // 获取内容
+ if opts.WithContent {
+ content, _, _, err := store.GetNodeContent(results[i].ID)
+ if err == nil {
+ results[i].Content = content
+ }
+ }
+
+ // 获取关联链接
+ if opts.WithLinks {
+ links, err := store.GetNodeLinks(results[i].ID)
+ if err == nil {
+ results[i].Links = links
+ }
+ }
+ }
+
+ return results, nil
+}
+```
+
+---
+
+## 4. 数据获取逻辑
+
+### 4.1 内容获取
+
+**已有方法:** `store.GetNodeContent(id)`
+
+```go
+func (s *Store) GetNodeContent(id int64) (string, []string, []string, error)
+```
+
+返回:`(content, tags, entities, error)`
+
+### 4.2 关联链接获取
+
+**新增方法:** `store.GetNodeLinks(nodeID)`
+
+```go
+func (s *Store) GetNodeLinks(nodeID int64) ([]string, error) {
+ query := `
+ SELECT n.path
+ FROM edges e
+ JOIN nodes n ON n.id = e.to_node
+ WHERE e.from_node = ? AND e.relation = 'wikilink'
+ `
+ rows, err := s.db.Query(query, nodeID)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var links []string
+ for rows.Next() {
+ var path string
+ if err := rows.Scan(&path); err != nil {
+ return nil, err
+ }
+ links = append(links, path)
+ }
+ return links, nil
+}
+```
+
+**查询逻辑:**
+- 查询 `edges` 表,`relation='wikilink'`
+- 返回目标节点的 `path`(即关联文档路径)
+
+---
+
+## 5. CLI 命令改动
+
+### 5.1 新增 flag
+
+**文件:** `cmd/search.go`
+
+```go
+var (
+ withContent bool
+ withLinks bool
+)
+
+func init() {
+ // ... 现有 flag
+ searchCmd.Flags().BoolVar(&withContent, "with-content", false, "返回完整文件内容")
+ searchCmd.Flags().BoolVar(&withLinks, "with-links", false, "显示关联文档链接")
+}
+```
+
+### 5.2 传递给 SearchOptions
+
+```go
+func runSearch(cmd *cobra.Command, args []string) error {
+ opts := search.SearchOptions{
+ Expanded: expanded,
+ Symptom: symptom,
+ TopN: topN,
+ WithContent: withContent,
+ WithLinks: withLinks,
+ }
+
+ results, err := search.Search(store, args, opts)
+ // ...
+}
+```
+
+---
+
+## 6. 输出格式化改动
+
+### 6.1 表格输出
+
+**文件:** `internal/output/formatter.go`
+
+**基础输出(无增强):**
+```
+路径 标题 板块 得分
+--------------------------------------------------
+FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
+```
+
+**带内容(--with-content):**
+```
+路径 标题 板块 得分
+--------------------------------------------------
+FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
+
+--- 内容 ---
+# 扫码验证气瓶充装
+
+## 问题描述
+...
+```
+
+**带链接(--with-links):**
+```
+路径 标题 板块 得分
+--------------------------------------------------
+FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
+
+--- 关联文档 ---
+- 典型案例/充装异常案例.md
+- 文档/电子秤平台/平台文档/023-充装统计与票据核对.md
+```
+
+**两者都有(--with-content --with-links):**
+```
+路径 标题 板块 得分
+--------------------------------------------------
+FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6
+
+--- 内容 ---
+# 扫码验证气瓶充装
+...
+
+--- 关联文档 ---
+- 典型案例/充装异常案例.md
+```
+
+### 6.2 JSON 输出
+
+```json
+[
+ {
+ "id": 1577,
+ "path": "FAQ/充装类/087-xxx.md",
+ "title": "扫码验证气瓶充装",
+ "section": "FAQ",
+ "score": 6,
+ "content": "# 扫码验证气瓶充装\n\n## 问题描述\n...",
+ "links": [
+ "典型案例/充装异常案例.md",
+ "文档/电子秤平台/平台文档/023-充装统计与票据核对.md"
+ ]
+ }
+]
+```
+
+---
+
+## 7. kb-search 技能调整
+
+### 7.1 优先级策略
+
+1. **优先使用 kb-cli:** `kb search "关键词" --with-content --top 3`
+2. **降级到 kb-search.py:** 仅当 kb-cli 不可用时
+
+### 7.2 技能文档改动
+
+**核心工具:**
+- 从 `kb-search.py` 改为 `kb`
+
+**命令示例:**
+```bash
+# 基础搜索
+kb search "充装规格" --top 5
+
+# 带内容
+kb search "充装规格" --with-content --top 3
+
+# 带链接
+kb search "充装规格" --with-links --top 3
+
+# 带扩展词和症状词
+kb search "充装" --expanded "重量 规格" --symptom "报错 无法启动" --with-content --top 3
+```
+
+**保留内容:**
+- `--expanded`、`--symptom` 用法说明
+- 搜索策略(术语映射、关键词选择)
+- 最佳实践(决策树、案例)
+
+**移到降级方案:**
+- kb-search.py 完整用法移到"降级方案"章节
+
+### 7.3 降级方案
+
+```markdown
+## 降级方案
+
+仅当 kb-cli 不可用时,使用 kb-search.py:
+
+```bash
+export KB_VAULT=/home/aisim-p/aisim/note/001/笔记001
+python3 ~/.hermes/skills/kb-knowledge/kb-search/scripts/kb-search.py search "关键词" --with-content --top 3
+```
+
+注意:kb-search.py 当前有索引问题,可能返回空结果。
+```
+
+---
+
+## 8. 测试计划
+
+### 8.1 单元测试
+
+- 测试 `SearchResult` 结构体的 JSON 序列化(`omitempty` 行为)
+- 测试 `GetNodeLinks` 方法
+
+### 8.2 集成测试
+
+```bash
+# 测试基础搜索
+kb search "充装" --top 5
+
+# 测试带内容
+kb search "充装" --with-content --top 3
+
+# 测试带链接
+kb search "充装" --with-links --top 3
+
+# 测试两者都有
+kb search "充装" --with-content --with-links --top 3
+
+# 测试 JSON 输出
+kb search "充装" --with-content --json --top 3
+```
+
+### 8.3 对比测试
+
+与 Python 版对比:
+```bash
+# Go 版
+kb search "充装" --with-content --top 3
+
+# Python 版
+python3 kb-search.py search "充装" --with-content --top 3
+```
+
+---
+
+## 9. 实施步骤
+
+1. **数据结构改动**
+ - 修改 `SearchResult` 结构体
+ - 修改 `SearchOptions` 结构体
+ - 实现 `GetNodeLinks` 方法
+
+2. **搜索逻辑改动**
+ - 修改 `Search` 函数,增加内容获取和链接获取逻辑
+
+3. **CLI 命令改动**
+ - 新增 `--with-content` 和 `--with-links` flag
+ - 传递给 `SearchOptions`
+
+4. **输出格式化改动**
+ - 修改 `FormatTable` 和 `FormatJSON` 方法
+ - 支持内容和链接的输出
+
+5. **测试**
+ - 单元测试
+ - 集成测试
+ - 对比测试
+
+6. **技能文档更新**
+ - 更新 kb-search 技能文档
+ - 调整优先级策略
+
+---
+
+## 10. 风险与缓解
+
+| 风险 | 缓解措施 |
+|------|----------|
+| 内容获取慢(大量文件) | 限制 `--top N`,默认 10 |
+| 链接查询慢 | 使用索引,查询 `edges` 表 |
+| JSON 输出过大 | `omitempty` 标签,不填充时不输出 |
+| 向后兼容 | 新增字段为可选,不影响现有脚本 |
+
+---
+
+## 11. 成功标准
+
+1. ✅ kb-cli 支持 `--with-content` 和 `--with-links`
+2. ✅ 输出格式正确(表格和 JSON)
+3. ✅ 性能可接受(< 100ms)
+4. ✅ kb-search 技能文档更新完成
+5. ✅ 对比测试通过(优于 Python 版)
+
+---
+
+## 12. 附录
+
+### 12.1 相关文件
+
+- `internal/search/engine.go` - 搜索逻辑
+- `internal/index/sqlite.go` - 数据库操作
+- `internal/output/formatter.go` - 输出格式化
+- `cmd/search.go` - CLI 命令
+- `~/.hermes/skills/kb-knowledge/kb-search/SKILL.md` - 技能文档
+
+### 12.2 参考
+
+- Python 版 kb-search.py:`~/.hermes/skills/kb-knowledge/kb-search/scripts/kb-search.py`
+- SQLite 数据模型:`docs/superpowers/specs/2026-07-26-kb-cli-design.md`
--
Gitblit v1.9.1