From 3d32162df6f0af1b89004140fd3191ba8753fb1d Mon Sep 17 00:00:00 2001
From: ai_xiaopei <xiaopei@aisim.cn>
Date: Sun, 26 Jul 2026 08:14:44 +0800
Subject: [PATCH] docs: add kb-cli enhancement implementation plan

---
 docs/superpowers/plans/2026-07-26-kb-cli-enhancement.md | 1047 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,047 insertions(+), 0 deletions(-)

diff --git a/docs/superpowers/plans/2026-07-26-kb-cli-enhancement.md b/docs/superpowers/plans/2026-07-26-kb-cli-enhancement.md
new file mode 100644
index 0000000..a4f851a
--- /dev/null
+++ b/docs/superpowers/plans/2026-07-26-kb-cli-enhancement.md
@@ -0,0 +1,1047 @@
+# kb-cli 增强功能实现计划
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 为 kb-cli 添加 `--with-content` 和 `--with-links` 功能,并调整 kb-search 技能优先使用 kb-cli
+
+**Architecture:** 在现有 SearchResult 结构体上添加可选字段 Content 和 Links,通过 SearchOptions 控制是否填充这些字段。修改输出格式化器支持新字段的展示。
+
+**Tech Stack:** Go 1.22, SQLite FTS5, Cobra CLI
+
+## Global Constraints
+
+- 所有新功能必须有单元测试
+- JSON 输出使用 `omitempty` 标签
+- 保持向后兼容(不破坏现有命令)
+- 性能目标:< 100ms(包含内容和链接获取)
+
+---
+
+## Task 1: 添加 GetNodeLinks 数据库方法
+
+**Files:**
+- Modify: `internal/index/sqlite.go:120-140`
+- Test: `internal/index/sqlite_test.go`
+
+**Interfaces:**
+- Consumes: `Store.db` (SQLite 连接)
+- Produces: `GetNodeLinks(nodeID int64) ([]string, error)` 方法
+
+- [ ] **Step 1: 编写失败测试**
+
+在 `internal/index/sqlite_test.go` 添加:
+
+```go
+func TestGetNodeLinks(t *testing.T) {
+	store := setupTestStore(t)
+	defer store.Close()
+
+	// 插入测试节点
+	node1 := &graph.Node{
+		Path:    "FAQ/001-测试.md",
+		Title:   "测试文档",
+		Section: "FAQ",
+		Content: "# 测试\n\n内容",
+	}
+	node2 := &graph.Node{
+		Path:    "FAQ/002-相关.md",
+		Title:   "相关文档",
+		Section: "FAQ",
+		Content: "# 相关\n\n内容",
+	}
+	
+	id1, err := store.InsertNode(node1)
+	require.NoError(t, err)
+	
+	id2, err := store.InsertNode(node2)
+	require.NoError(t, err)
+
+	// 插入 wikilink 边
+	edge := &graph.Edge{
+		FromNode: id1,
+		ToNode:   id2,
+		Relation: "wikilink",
+		Label:    "相关文档",
+	}
+	err = store.InsertEdge(edge)
+	require.NoError(t, err)
+
+	// 测试获取链接
+	links, err := store.GetNodeLinks(id1)
+	require.NoError(t, err)
+	assert.Len(t, links, 1)
+	assert.Equal(t, "FAQ/002-相关.md", links[0])
+
+	// 测试无链接的节点
+	links, err = store.GetNodeLinks(id2)
+	require.NoError(t, err)
+	assert.Len(t, links, 0)
+}
+```
+
+- [ ] **Step 2: 运行测试确认失败**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/index -run TestGetNodeLinks -v
+```
+
+Expected: FAIL - "store.GetNodeLinks undefined"
+
+- [ ] **Step 3: 实现 GetNodeLinks 方法**
+
+在 `internal/index/sqlite.go` 的 `GetNodeContent` 方法后添加:
+
+```go
+// GetNodeLinks 获取节点的关联链接(wikilink 目标)
+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, fmt.Errorf("查询链接失败: %w", err)
+	}
+	defer rows.Close()
+
+	var links []string
+	for rows.Next() {
+		var path string
+		if err := rows.Scan(&path); err != nil {
+			return nil, fmt.Errorf("扫描链接失败: %w", err)
+		}
+		links = append(links, path)
+	}
+	
+	if err := rows.Err(); err != nil {
+		return nil, fmt.Errorf("遍历链接失败: %w", err)
+	}
+	
+	return links, nil
+}
+```
+
+- [ ] **Step 4: 运行测试确认通过**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/index -run TestGetNodeLinks -v
+```
+
+Expected: PASS
+
+- [ ] **Step 5: 提交**
+
+```bash
+cd ~/workspace/kb-cli
+git add internal/index/sqlite.go internal/index/sqlite_test.go
+git commit -m "feat: add GetNodeLinks method for wikilink retrieval"
+```
+
+---
+
+## Task 2: 扩展 SearchResult 结构体
+
+**Files:**
+- Modify: `internal/search/engine.go:15-25`
+- Test: `internal/search/engine_test.go`
+
+**Interfaces:**
+- Consumes: 无
+- Produces: 扩展的 `SearchResult` 结构体(Content, Links 字段)
+
+- [ ] **Step 1: 编写失败测试**
+
+在 `internal/search/engine_test.go` 添加:
+
+```go
+func TestSearchResultJSON_OmitEmpty(t *testing.T) {
+	// 测试无内容和链接时,JSON 不包含这些字段
+	result := SearchResult{
+		ID:      1,
+		Path:    "test.md",
+		Title:   "测试",
+		Section: "FAQ",
+		Score:   10,
+	}
+	
+	jsonBytes, err := json.Marshal(result)
+	require.NoError(t, err)
+	
+	jsonStr := string(jsonBytes)
+	assert.NotContains(t, jsonStr, "content")
+	assert.NotContains(t, jsonStr, "links")
+
+	// 测试有内容时,JSON 包含 content 字段
+	result.Content = "# 测试内容"
+	jsonBytes, err = json.Marshal(result)
+	require.NoError(t, err)
+	
+	jsonStr = string(jsonBytes)
+	assert.Contains(t, jsonStr, `"content":"# 测试内容"`)
+	
+	// 测试有链接时,JSON 包含 links 字段
+	result.Links = []string{"related.md"}
+	jsonBytes, err = json.Marshal(result)
+	require.NoError(t, err)
+	
+	jsonStr = string(jsonBytes)
+	assert.Contains(t, jsonStr, `"links":["related.md"]`)
+}
+```
+
+- [ ] **Step 2: 运行测试确认失败**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/search -run TestSearchResultJSON_OmitEmpty -v
+```
+
+Expected: FAIL - "Content undefined" 或测试失败(因为字段不存在)
+
+- [ ] **Step 3: 扩展 SearchResult 结构体**
+
+修改 `internal/search/engine.go` 中的 `SearchResult` 结构体:
+
+```go
+// SearchResult 搜索结果
+type SearchResult struct {
+	ID      int64    `json:"id"`
+	Path    string   `json:"path"`
+	Title   string   `json:"title"`
+	Section string   `json:"section"`
+	Score   int      `json:"score"`
+	
+	// 可选字段(omitempty)
+	Content string   `json:"content,omitempty"` // --with-content 时填充
+	Links   []string `json:"links,omitempty"`   // --with-links 时填充
+}
+```
+
+- [ ] **Step 4: 运行测试确认通过**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/search -run TestSearchResultJSON_OmitEmpty -v
+```
+
+Expected: PASS
+
+- [ ] **Step 5: 提交**
+
+```bash
+cd ~/workspace/kb-cli
+git add internal/search/engine.go internal/search/engine_test.go
+git commit -m "feat: extend SearchResult with Content and Links fields"
+```
+
+---
+
+## Task 3: 扩展 SearchOptions 并修改 Search 函数
+
+**Files:**
+- Modify: `internal/search/engine.go:30-40, 80-120`
+- Test: `internal/search/engine_test.go`
+
+**Interfaces:**
+- Consumes: `Store.GetNodeContent`, `Store.GetNodeLinks` (Task 1)
+- Produces: 扩展的 `SearchOptions` 和增强的 `Search` 函数
+
+- [ ] **Step 1: 编写失败测试**
+
+在 `internal/search/engine_test.go` 添加:
+
+```go
+func TestSearch_WithContent(t *testing.T) {
+	store := setupTestStore(t)
+	defer store.Close()
+
+	// 插入测试节点
+	node := &graph.Node{
+		Path:    "FAQ/001-测试.md",
+		Title:   "测试文档",
+		Section: "FAQ",
+		Content: "# 测试\n\n这是测试内容",
+	}
+	id, err := store.InsertNode(node)
+	require.NoError(t, err)
+	
+	err = store.CreateFTS()
+	require.NoError(t, err)
+	err = store.PopulateFTS()
+	require.NoError(t, err)
+
+	// 测试带内容的搜索
+	opts := SearchOptions{
+		TopN:        5,
+		WithContent: true,
+	}
+	results, err := Search(store, []string{"测试"}, opts)
+	require.NoError(t, err)
+	require.Len(t, results, 1)
+	assert.Equal(t, id, results[0].ID)
+	assert.Equal(t, "# 测试\n\n这是测试内容", results[0].Content)
+
+	// 测试不带内容的搜索
+	opts.WithContent = false
+	results, err = Search(store, []string{"测试"}, opts)
+	require.NoError(t, err)
+	require.Len(t, results, 1)
+	assert.Empty(t, results[0].Content)
+}
+
+func TestSearch_WithLinks(t *testing.T) {
+	store := setupTestStore(t)
+	defer store.Close()
+
+	// 插入两个节点
+	node1 := &graph.Node{
+		Path:    "FAQ/001-测试.md",
+		Title:   "测试文档",
+		Section: "FAQ",
+		Content: "# 测试",
+	}
+	node2 := &graph.Node{
+		Path:    "FAQ/002-相关.md",
+		Title:   "相关文档",
+		Section: "FAQ",
+		Content: "# 相关",
+	}
+	
+	id1, err := store.InsertNode(node1)
+	require.NoError(t, err)
+	id2, err := store.InsertNode(node2)
+	require.NoError(t, err)
+
+	// 插入 wikilink 边
+	edge := &graph.Edge{
+		FromNode: id1,
+		ToNode:   id2,
+		Relation: "wikilink",
+		Label:    "相关文档",
+	}
+	err = store.InsertEdge(edge)
+	require.NoError(t, err)
+
+	err = store.CreateFTS()
+	require.NoError(t, err)
+	err = store.PopulateFTS()
+	require.NoError(t, err)
+
+	// 测试带链接的搜索
+	opts := SearchOptions{
+		TopN:      5,
+		WithLinks: true,
+	}
+	results, err := Search(store, []string{"测试"}, opts)
+	require.NoError(t, err)
+	require.Len(t, results, 1)
+	assert.Equal(t, id1, results[0].ID)
+	assert.Len(t, results[0].Links, 1)
+	assert.Equal(t, "FAQ/002-相关.md", results[0].Links[0])
+
+	// 测试不带链接的搜索
+	opts.WithLinks = false
+	results, err = Search(store, []string{"测试"}, opts)
+	require.NoError(t, err)
+	require.Len(t, results, 1)
+	assert.Empty(t, results[0].Links)
+}
+```
+
+- [ ] **Step 2: 运行测试确认失败**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/search -run "TestSearch_WithContent|TestSearch_WithLinks" -v
+```
+
+Expected: FAIL - "WithContent undefined" 或测试失败
+
+- [ ] **Step 3: 扩展 SearchOptions 并修改 Search 函数**
+
+修改 `internal/search/engine.go`:
+
+```go
+// SearchOptions 搜索选项
+type SearchOptions struct {
+	Expanded    []string
+	Symptom     []string
+	TopN        int
+	WithContent bool // 新增:是否返回内容
+	WithLinks   bool // 新增:是否返回链接
+}
+
+// Search 执行搜索
+func Search(store *index.Store, keywords []string, opts SearchOptions) ([]SearchResult, error) {
+	// 合并所有关键词
+	allKeywords := append(keywords, opts.Expanded...)
+	allKeywords = append(allKeywords, opts.Symptom...)
+
+	// FTS5 搜索
+	ftsResults, err := store.FTSSearch(allKeywords, 100)
+	if err != nil {
+		return nil, err
+	}
+
+	// 评分
+	scoreMap := make(map[int64]int)
+	for _, r := range ftsResults {
+		score := 0
+		for _, kw := range keywords {
+			score += scoreResult(r, kw, ScoreNormal)
+		}
+		for _, kw := range opts.Expanded {
+			score += scoreResult(r, kw, ScoreExpanded)
+		}
+		for _, kw := range opts.Symptom {
+			score += scoreResult(r, kw, ScoreSymptom)
+		}
+		scoreMap[r.ID] = score
+	}
+
+	// 转换为结果列表
+	var results []SearchResult
+	for _, r := range ftsResults {
+		results = append(results, SearchResult{
+			ID:      r.ID,
+			Path:    r.Path,
+			Title:   r.Title,
+			Section: r.Section,
+			Score:   scoreMap[r.ID],
+		})
+	}
+
+	// 按分数排序
+	sort.Slice(results, func(i, j int) bool {
+		return results[i].Score > results[j].Score
+	})
+
+	// 限制返回数量
+	if opts.TopN > 0 && len(results) > opts.TopN {
+		results = results[:opts.TopN]
+	}
+
+	// 增强结果(新增)
+	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
+}
+```
+
+- [ ] **Step 4: 运行测试确认通过**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/search -run "TestSearch_WithContent|TestSearch_WithLinks" -v
+```
+
+Expected: PASS
+
+- [ ] **Step 5: 运行所有测试确认无回归**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./... -v
+```
+
+Expected: 所有测试通过
+
+- [ ] **Step 6: 提交**
+
+```bash
+cd ~/workspace/kb-cli
+git add internal/search/engine.go internal/search/engine_test.go
+git commit -m "feat: add WithContent and WithLinks options to Search"
+```
+
+---
+
+## Task 4: 添加 CLI flags 并传递给 SearchOptions
+
+**Files:**
+- Modify: `cmd/search.go:20-50`
+
+**Interfaces:**
+- Consumes: `SearchOptions.WithContent`, `SearchOptions.WithLinks` (Task 3)
+- Produces: 新增 `--with-content` 和 `--with-links` flags
+
+- [ ] **Step 1: 添加 flag 变量**
+
+在 `cmd/search.go` 的变量声明区域添加:
+
+```go
+var (
+	withContent bool
+	withLinks   bool
+)
+```
+
+- [ ] **Step 2: 注册 flags**
+
+在 `init()` 函数中添加:
+
+```go
+func init() {
+	searchCmd.Flags().StringSliceVar(&expanded, "expanded", nil, "扩展词(提升相关实体权重)")
+	searchCmd.Flags().StringSliceVar(&symptom, "symptom", nil, "症状词(针对具体症状)")
+	searchCmd.Flags().IntVar(&topN, "top", 10, "返回前 N 条结果")
+	searchCmd.Flags().BoolVar(&jsonOut, "json", false, "JSON 格式输出")
+	
+	// 新增 flags
+	searchCmd.Flags().BoolVar(&withContent, "with-content", false, "返回完整文件内容")
+	searchCmd.Flags().BoolVar(&withLinks, "with-links", false, "显示关联文档链接")
+}
+```
+
+- [ ] **Step 3: 传递 flags 到 SearchOptions**
+
+修改 `runSearch` 函数:
+
+```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)
+	// ... 现有代码 ...
+}
+```
+
+- [ ] **Step 4: 构建并测试 help 输出**
+
+```bash
+cd ~/workspace/kb-cli
+go build -o bin/kb .
+./bin/kb search --help
+```
+
+Expected: 显示 `--with-content` 和 `--with-links` flags
+
+- [ ] **Step 5: 提交**
+
+```bash
+cd ~/workspace/kb-cli
+git add cmd/search.go
+git commit -m "feat: add --with-content and --with-links CLI flags"
+```
+
+---
+
+## Task 5: 修改输出格式化器支持新字段
+
+**Files:**
+- Modify: `internal/output/formatter.go`
+- Test: `internal/output/formatter_test.go`
+
+**Interfaces:**
+- Consumes: `SearchResult.Content`, `SearchResult.Links` (Task 2)
+- Produces: 增强的 `FormatTable` 和 `FormatJSON` 方法
+
+- [ ] **Step 1: 编写失败测试**
+
+在 `internal/output/formatter_test.go` 添加:
+
+```go
+func TestFormatTable_WithContent(t *testing.T) {
+	results := []search.SearchResult{
+		{
+			ID:      1,
+			Path:    "FAQ/001-测试.md",
+			Title:   "测试文档",
+			Section: "FAQ",
+			Score:   10,
+			Content: "# 测试\n\n这是内容",
+		},
+	}
+	
+	output := FormatTable(results)
+	assert.Contains(t, output, "FAQ/001-测试.md")
+	assert.Contains(t, output, "--- 内容 ---")
+	assert.Contains(t, output, "# 测试")
+}
+
+func TestFormatTable_WithLinks(t *testing.T) {
+	results := []search.SearchResult{
+		{
+			ID:      1,
+			Path:    "FAQ/001-测试.md",
+			Title:   "测试文档",
+			Section: "FAQ",
+			Score:   10,
+			Links:   []string{"FAQ/002-相关.md"},
+		},
+	}
+	
+	output := FormatTable(results)
+	assert.Contains(t, output, "--- 关联文档 ---")
+	assert.Contains(t, output, "FAQ/002-相关.md")
+}
+
+func TestFormatTable_WithBoth(t *testing.T) {
+	results := []search.SearchResult{
+		{
+			ID:      1,
+			Path:    "FAQ/001-测试.md",
+			Title:   "测试文档",
+			Section: "FAQ",
+			Score:   10,
+			Content: "# 测试",
+			Links:   []string{"FAQ/002-相关.md"},
+		},
+	}
+	
+	output := FormatTable(results)
+	assert.Contains(t, output, "--- 内容 ---")
+	assert.Contains(t, output, "--- 关联文档 ---")
+}
+
+func TestFormatJSON_WithContentAndLinks(t *testing.T) {
+	results := []search.SearchResult{
+		{
+			ID:      1,
+			Path:    "FAQ/001-测试.md",
+			Title:   "测试文档",
+			Section: "FAQ",
+			Score:   10,
+			Content: "# 测试",
+			Links:   []string{"FAQ/002-相关.md"},
+		},
+	}
+	
+	output, err := FormatJSON(results)
+	require.NoError(t, err)
+	assert.Contains(t, output, `"content":"# 测试"`)
+	assert.Contains(t, output, `"links":["FAQ/002-相关.md"]`)
+}
+```
+
+- [ ] **Step 2: 运行测试确认失败**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/output -run "TestFormatTable_With|TestFormatJSON_With" -v
+```
+
+Expected: FAIL - 测试失败(输出不包含新字段)
+
+- [ ] **Step 3: 修改 FormatTable 方法**
+
+修改 `internal/output/formatter.go` 中的 `FormatTable` 函数:
+
+```go
+// FormatTable 格式化表格输出
+func FormatTable(results []search.SearchResult) string {
+	if len(results) == 0 {
+		return "未找到匹配结果\n"
+	}
+
+	var buf bytes.Buffer
+	
+	// 表头
+	buf.WriteString(fmt.Sprintf("%-50s %-30s %-10s %s\n", "路径", "标题", "板块", "得分"))
+	buf.WriteString(strings.Repeat("-", 100) + "\n")
+	
+	// 每行结果
+	for _, r := range results {
+		title := r.Title
+		if len(title) > 28 {
+			title = title[:28] + ".."
+		}
+		buf.WriteString(fmt.Sprintf("%-50s %-30s %-10s %d\n", r.Path, title, r.Section, r.Score))
+		
+		// 输出内容(如果有)
+		if r.Content != "" {
+			buf.WriteString("\n--- 内容 ---\n")
+			buf.WriteString(r.Content)
+			buf.WriteString("\n")
+		}
+		
+		// 输出关联文档(如果有)
+		if len(r.Links) > 0 {
+			buf.WriteString("\n--- 关联文档 ---\n")
+			for _, link := range r.Links {
+				buf.WriteString(fmt.Sprintf("- %s\n", link))
+			}
+		}
+	}
+	
+	buf.WriteString(fmt.Sprintf("\n共 %d 条结果\n", len(results)))
+	return buf.String()
+}
+```
+
+- [ ] **Step 4: 运行测试确认通过**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./internal/output -run "TestFormatTable_With|TestFormatJSON_With" -v
+```
+
+Expected: PASS
+
+- [ ] **Step 5: 运行所有测试确认无回归**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./... -v
+```
+
+Expected: 所有测试通过
+
+- [ ] **Step 6: 提交**
+
+```bash
+cd ~/workspace/kb-cli
+git add internal/output/formatter.go internal/output/formatter_test.go
+git commit -m "feat: enhance output formatter with content and links support"
+```
+
+---
+
+## Task 6: 集成测试与性能验证
+
+**Files:**
+- 无新文件(使用现有测试数据)
+
+**Interfaces:**
+- Consumes: 所有之前的任务
+- Produces: 验证完整功能链
+
+- [ ] **Step 1: 构建最新版本**
+
+```bash
+cd ~/workspace/kb-cli
+go build -o bin/kb .
+```
+
+- [ ] **Step 2: 测试基础搜索(无增强)**
+
+```bash
+./bin/kb search 充装 --top 3
+```
+
+Expected: 显示 3 条结果,不包含内容和链接
+
+- [ ] **Step 3: 测试带内容搜索**
+
+```bash
+./bin/kb search 充装 --with-content --top 3
+```
+
+Expected: 显示 3 条结果,每条后跟 `--- 内容 ---` 和文件内容
+
+- [ ] **Step 4: 测试带链接搜索**
+
+```bash
+./bin/kb search 充装 --with-links --top 3
+```
+
+Expected: 显示 3 条结果,有链接的显示 `--- 关联文档 ---`
+
+- [ ] **Step 5: 测试两者都有**
+
+```bash
+./bin/kb search 充装 --with-content --with-links --top 3
+```
+
+Expected: 显示 3 条结果,同时包含内容和链接
+
+- [ ] **Step 6: 测试 JSON 输出**
+
+```bash
+./bin/kb search 充装 --with-content --with-links --json --top 3
+```
+
+Expected: JSON 格式输出,包含 `content` 和 `links` 字段
+
+- [ ] **Step 7: 性能测试**
+
+```bash
+time ./bin/kb search 充装 --with-content --with-links --top 10
+```
+
+Expected: 总耗时 < 100ms
+
+- [ ] **Step 8: 提交(如有修复)**
+
+```bash
+cd ~/workspace/kb-cli
+git add -A
+git commit -m "test: integration tests for enhanced search"
+```
+
+---
+
+## Task 7: 更新 kb-search 技能文档
+
+**Files:**
+- Modify: `~/.hermes/skills/kb-knowledge/kb-search/SKILL.md`
+
+**Interfaces:**
+- Consumes: kb-cli 新功能
+- Produces: 更新的技能文档
+
+- [ ] **Step 1: 备份现有文档**
+
+```bash
+cp ~/.hermes/skills/kb-knowledge/kb-search/SKILL.md ~/.hermes/skills/kb-knowledge/kb-search/SKILL.md.bak
+```
+
+- [ ] **Step 2: 修改核心工具部分**
+
+将 `## 核心工具` 部分从:
+
+```markdown
+## 核心工具
+
+**kb-search.py**:知识库搜索
+```
+
+改为:
+
+```markdown
+## 核心工具
+
+**kb-cli**:知识库搜索(优先使用)
+
+**完整路径**:`~/go/bin/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
+
+# JSON 输出
+kb search "关键词" --json --top 5
+```
+
+**kb-search.py**:知识库搜索(降级方案,仅当 kb-cli 不可用时)
+```
+
+- [ ] **Step 3: 修改执行流程部分**
+
+将 `## 执行流程` 部分的命令示例从 `python3 kb-search.py` 改为 `kb`:
+
+```bash
+# 方式1: 基础搜索
+kb search "用户问题关键词" --top 3
+
+# 方式2: 带内容(推荐)
+kb search "用户问题关键词" --with-content --top 3
+
+# 方式3: 带内容和链接
+kb search "用户问题关键词" --with-content --with-links --top 3
+
+# 方式4: 带扩展词和症状词
+kb search "关键词" --expanded "扩展词" --symptom "症状词" --with-content --top 3
+```
+
+- [ ] **Step 4: 添加降级方案章节**
+
+在文档末尾添加:
+
+```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 当前有索引问题,可能返回空结果。优先使用 kb-cli。
+```
+
+- [ ] **Step 5: 验证文档格式**
+
+```bash
+cat ~/.hermes/skills/kb-knowledge/kb-search/SKILL.md | head -50
+```
+
+Expected: 显示更新后的文档,核心工具为 kb-cli
+
+- [ ] **Step 6: 提交到知识库**
+
+```bash
+cd ~/aisim/note/001/笔记001
+git add .
+git commit -m "docs: update kb-search skill to prioritize kb-cli"
+git push
+```
+
+---
+
+## Task 8: 最终验证与文档更新
+
+**Files:**
+- Modify: `~/workspace/kb-cli/README.md`
+
+**Interfaces:**
+- Consumes: 所有功能
+- Produces: 完整的文档和验证
+
+- [ ] **Step 1: 更新 README**
+
+在 `~/workspace/kb-cli/README.md` 的 `## 使用方法` 部分添加新功能示例:
+
+```markdown
+### 高级搜索
+
+```bash
+# 带文件内容
+kb search 充装规格 --with-content --top 3
+
+# 带关联文档
+kb search 充装规格 --with-links --top 3
+
+# 带内容和关联
+kb search 充装规格 --with-content --with-links --top 3
+
+# 带扩展词和症状词
+kb search 充装 --expanded "重量 规格" --symptom "报错" --with-content --top 3
+```
+```
+
+- [ ] **Step 2: 运行完整测试套件**
+
+```bash
+cd ~/workspace/kb-cli
+go test ./... -v
+```
+
+Expected: 所有测试通过
+
+- [ ] **Step 3: 构建并安装**
+
+```bash
+cd ~/workspace/kb-cli
+go build -o bin/kb .
+cp bin/kb ~/go/bin/
+```
+
+- [ ] **Step 4: 最终功能验证**
+
+```bash
+# 测试所有功能
+kb search 充装 --top 3
+kb search 充装 --with-content --top 3
+kb search 充装 --with-links --top 3
+kb search 充装 --with-content --with-links --top 3
+kb search 充装 --with-content --json --top 3
+```
+
+Expected: 所有命令正常工作
+
+- [ ] **Step 5: 提交所有更改**
+
+```bash
+cd ~/workspace/kb-cli
+git add README.md
+git commit -m "docs: update README with new features"
+git push
+```
+
+- [ ] **Step 6: 创建发布说明**
+
+```bash
+cat > RELEASE_NOTES.md << 'EOF'
+# kb-cli v1.1.0 发布说明
+
+## 新功能
+
+- `--with-content`: 搜索时返回完整文件内容
+- `--with-links`: 搜索时显示关联文档链接
+
+## 使用示例
+
+```bash
+# 带内容搜索
+kb search 充装规格 --with-content --top 3
+
+# 带关联文档
+kb search 充装规格 --with-links --top 3
+
+# 两者都有
+kb search 充装规格 --with-content --with-links --top 3
+```
+
+## 性能
+
+- 搜索 + 内容 + 链接:< 100ms
+- 向后兼容:现有命令不受影响
+
+## 技能调整
+
+- kb-search 技能现在优先使用 kb-cli
+- kb-search.py 降级为备选方案
+EOF
+```
+
+- [ ] **Step 7: 提交发布说明**
+
+```bash
+cd ~/workspace/kb-cli
+git add RELEASE_NOTES.md
+git commit -m "docs: add release notes for v1.1.0"
+git push
+```
+
+---
+
+## 完成标准
+
+所有任务完成后,必须满足:
+
+1. ✅ 所有单元测试通过
+2. ✅ 集成测试通过
+3. ✅ 性能 < 100ms
+4. ✅ kb-search 技能文档已更新
+5. ✅ README 已更新
+6. ✅ 发布说明已创建
+7. ✅ 代码已推送到远程仓库
+
+---
+
+## 执行选项
+
+**Plan complete and saved to `docs/superpowers/plans/2026-07-26-kb-cli-enhancement.md`. Two execution options:**
+
+**1. Subagent-Driven (recommended)** - I dispatch a fresh subagent per task, review between tasks, fast iteration
+
+**2. Inline Execution** - Execute tasks in this session using executing-plans, batch execution with checkpoints
+
+**Which approach?**

--
Gitblit v1.9.1