From 1196f409d86bc61e7596eb274840244a62ce84ba Mon Sep 17 00:00:00 2001
From: ai_xiaopei <xiaopei@aisim.cn>
Date: Wed, 29 Jul 2026 14:58:19 +0800
Subject: [PATCH] feat: config priority over env vars, export LoadConfig, add review feature

---
 cmd/draft.go |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 105 insertions(+), 8 deletions(-)

diff --git a/cmd/draft.go b/cmd/draft.go
index f16da92..4341371 100644
--- a/cmd/draft.go
+++ b/cmd/draft.go
@@ -1,6 +1,7 @@
 package cmd
 
 import (
+	"encoding/json"
 	"fmt"
 	"os"
 
@@ -12,15 +13,35 @@
 var draftCmd = &cobra.Command{
 	Use:   "draft",
 	Short: "草稿管理",
-	Long:  `kb-cli draft create # 创建草稿(AI 生成 tags + 合并指示)`,
+	Long: `# draft - 草稿管理
+kb-cli draft create --type <类型> --title <标题> --content-file <文件> [--source <来源>] [--force] # 创建草稿(AI 提取 tags + 生成合并指示)
+kb-cli draft list [--json] # 列出待审阅区的所有活跃草稿
+kb-cli draft convert [目录名] # 转换老格式单文件草稿到新格式(NNN-标题/draft.md + merge.md)`,
 }
 
 var draftCreateCmd = &cobra.Command{
 	Use:   "create",
 	Short: "创建草稿",
-	Long:  `# draft create - 创建草稿
+	Long: `# draft create - 创建草稿
 kb-cli draft create --type <类型> --title <标题> --content-file <文件> [--source <来源>] [--force] # 创建草稿,自动提取 tags 并生成合并指示`,
 	RunE: runDraftCreate,
+}
+
+var draftListCmd = &cobra.Command{
+	Use:   "list",
+	Short: "列出所有活跃草稿",
+	Long: `# draft list - 列出所有活跃草稿
+kb-cli draft list [--json] # 列出待审阅区的所有草稿(目录结构 + 老格式单文件)`,
+	RunE: runDraftList,
+}
+
+var draftConvertCmd = &cobra.Command{
+	Use:   "convert [目录名]",
+	Short: "转换老格式草稿到新格式",
+	Long: `# draft convert - 转换老格式草稿到新格式
+kb-cli draft convert # 扫描所有待审阅子目录,转换老格式单文件
+kb-cli draft convert TAPD提取 # 只转换指定子目录`,
+	RunE: runDraftConvert,
 }
 
 var tagsCmd = &cobra.Command{
@@ -38,13 +59,15 @@
 }
 
 var (
-	draftType       string
-	draftTitle      string
+	draftType        string
+	draftTitle       string
 	draftContentFile string
-	draftSource     string
-	draftForce      bool
-	tagsLimit       int
-	tagsDryRun      bool
+	draftSource      string
+	draftForce       bool
+	draftJSON        bool
+	tagsLimit        int
+	tagsDryRun       bool
+	convertTarget    string
 )
 
 func init() {
@@ -58,7 +81,14 @@
 	draftCreateCmd.MarkFlagRequired("title")
 	draftCreateCmd.MarkFlagRequired("content-file")
 
+	// draft list 命令
+	draftListCmd.Flags().BoolVar(&draftJSON, "json", false, "JSON 格式输出")
+
+	// draft convert 命令(无额外参数,target 从 args 读取)
+
 	draftCmd.AddCommand(draftCreateCmd)
+	draftCmd.AddCommand(draftListCmd)
+	draftCmd.AddCommand(draftConvertCmd)
 
 	// tags rebuild 命令
 	tagsRebuildCmd.Flags().IntVar(&tagsLimit, "limit", 0, "限制处理文档数量(0=全部)")
@@ -117,3 +147,70 @@
 
 	return nil
 }
+
+// runDraftList 列出所有活跃草稿
+func runDraftList(cmd *cobra.Command, args []string) error {
+	// 创建草稿录入器
+	intake := draft.NewIntake(vaultPath, nil)
+
+	// 列出草稿
+	drafts, err := intake.ListDrafts()
+	if err != nil {
+		return fmt.Errorf("列出草稿失败: %w", err)
+	}
+
+	if draftJSON {
+		// JSON 输出
+		output := struct {
+			Drafts []draft.DraftInfo `json:"drafts"`
+			Total  int               `json:"total"`
+		}{
+			Drafts: drafts,
+			Total:  len(drafts),
+		}
+		encoder := json.NewEncoder(os.Stdout)
+		encoder.SetIndent("", "  ")
+		return encoder.Encode(output)
+	}
+
+	// 表格输出
+	if len(drafts) == 0 {
+		fmt.Println("没有活跃草稿")
+		return nil
+	}
+
+	fmt.Printf("找到 %d 个活跃草稿:\n\n", len(drafts))
+	for _, d := range drafts {
+		mergeStatus := "❌"
+		if d.HasMergeHint {
+			mergeStatus = "✅"
+		}
+		fmt.Printf("• %s\n", d.Title)
+		fmt.Printf("  路径: %s\n", d.Filepath)
+		fmt.Printf("  类型: %s | 状态: %s | 合并指示: %s\n", d.Type, d.Status, mergeStatus)
+		fmt.Printf("  创建: %s\n\n", d.Created)
+	}
+
+	return nil
+}
+
+// runDraftConvert 转换老格式草稿到新格式
+func runDraftConvert(cmd *cobra.Command, args []string) error {
+	// 可选参数:指定子目录
+	target := ""
+	if len(args) > 0 {
+		target = args[0]
+	}
+
+	// 创建草稿录入器
+	intake := draft.NewIntake(vaultPath, nil)
+
+	// 转换草稿
+	converted, err := intake.ConvertOldDrafts(target)
+	if err != nil {
+		return fmt.Errorf("转换草稿失败: %w", err)
+	}
+
+	fmt.Printf("\n✅ 成功转换 %d 个草稿\n", converted)
+	return nil
+}

--
Gitblit v1.9.1