> 完整主菜单与全局铁律见 `kb/kb.md`。以下为本菜单的执行细节（按需加载）。

> 📌 本菜单涉及文档抽取（A–F 循环），执行前请先读取 `kb/extraction.md` 获取 A–F 具体操作。

### 菜单 1 — 🔨 全自动完全重建知识库

> 🔴🔴 **loop 驱动（★ 2026-08-13 起）**：本菜单是"完全重建"，**每次都是全新开始**（用户选本菜单即明确要重来，不做自动续跑、不沿用未完成流水线）。清库（Step 5）后全自动阶段由 `kb.md`「🔴 全自动流水线 loop 执行」统一驱动：phase1 → phase2 → phase3 自动衔接、失败自动重试（≤5 次），**全程不向用户下指令**。Step 9/10/11 分别是 loop 中 phase1/2/3 的执行细节。

> 清除全部知识元和资源，从零重新处理所有文档，**默认保留已设定的知识库名称，但会先询问是否修改（决策④）**；若 `kb_name` 为系统缺省占位符「知识库」（即尚未真正命名），则必须要求用户命名（用户不提供则回退「知识库」）。详见 kb.md「知识库名称管理」全局规则。
>
> 🔴🔴 **决策前置（★ 铁律）**：所有需要用户决策的步骤——确认重建（Step 1）、扫描查看待处理文档（Step 2）、选择处理顺序（Step 3）、选择抽取模式（Step 4，B0）、**知识库名称决策（Step 4.5）**——必须**集中在清库（Step 5，破坏性删除）之前**全部完成。决策齐备后才开始清库，从 Step 5 到 Step 11 全部子步骤**全程无中断，严禁中途停下询问用户或等待确认**。目的：避免用户在长耗时重建中途被反复打断，也避免先破坏性清库、再让用户干等。
>
> 🔴🔴🔴 **重建必须从头开始，严禁任何形式的简化处理（★ 铁律中的铁律）**
> - **重建 = 推倒重来**：`purge-kb` 后旧知识库已不存在——你的任务是重新构建一套全新知识库，不是"修复"或"补充"。
> - **🔴 严禁简化处理**：不得以"内容太多""时间太长"为由跳过任何文档的逐段分析。11 个文档必须产出 11 份完整分析。
> - **🔴 严禁敷衍**：重建的产出必须与首次构建同等质量——该拆的知识元一个不能少，该写的正文一个字不能省。不允许出现"重建后知识元数反而比之前少很多"的情况。
> - **🔴 全程遵循 A→F 流水线**：每个文件必须完整走完 extract → 归档 → 逐段分析 → 写入知识元 → verify-units（含命名质量检查：编号/括号/纯数字等不合规名称会 fail） → mark-processed，**不得跳步、不得简化、不得合并处理**。

#### Step 1 — 双重确认

**先提醒用户手动备份**，然后向用户展示确认选项（🔴 输入数字 1 或 2，严禁图形/卡片式选择菜单，包括 AskUserQuestion 工具）：

> 🔴 **全自动重建需要智能体具有完全访问权限（Full Access）**，用于删除旧的根节点文件、知识地图、知识元等。如果权限不足，旧数据无法清除，新知识库无法重建。请确认智能体已授予**完全访问权限**。

**⚠️ 此操作将清除全部知识元、资源和关联数据（`原始文件/` 中的文档本身不受影响）。是否继续？**

1. ✅ 确认重建 — 清除全部数据，从零开始
2. ➡️ 取消 — 返回模块主菜单

#### Step 2 — 扫描所有文档（非破坏性，仅展示 + 决策依据）

```bash
python {skill_dir}/kb/scripts/ahkb.py scan
```

> 🔴 本步骤仅读取原始文件目录，**不清除任何知识元/资源**，用于让用户看到待处理文档清单与预计耗时，为后续"选择处理顺序"提供依据。
> 🔴 **必须将 `estimated_minutes` 的估算时间用文字明确告知用户**，必须在自然语言消息中直接说"预计 X ~ Y 分钟"。
> 得到总数 N 与每份文档的类型/文字量分布。

#### Step 3 — 选择处理顺序（决策②，必选）

scan 已返回每个文件的 `ext`、`text_chars` 和 `size`，向用户展示**完整的「选择处理顺序」菜单**（与菜单 0 Step 1.5 完全一致，含 6 个选项 + 文件类型分布）。
> 🔴 **必须等待用户选择**，不得默认执行。选项 1~6 的行为同菜单 0 Step 1.5。

#### Step 4 — 抽取模式选择（决策③，B0 必选）

> 🔴 必须等待用户选择，不得默认执行。见上方 **B0. 抽取模式选择**：1（顺序单线程，推荐）/ 2（并行子代理抽取），严格按用户选择决定后续是否使用子代理。

请选择抽取模式（🔴 必须输入数字 1 或 2，严禁使用图形/卡片式选择菜单，包括 AskUserQuestion 工具）：

1. 顺序单线程（推荐） — 逐文件 / 逐批由主 agent 亲自顺序处理；跨批一致性最好（概念索引顺序去重天然稳），速度不变。
2. 并行子代理抽取 — 先用 `phase1-group` 按预估工作量**均衡分组（默认上限 4 组）**：大文件独占一组、小文件打包给同一子代理顺序处理；每组由一个子代理并发处理，速度近似线性提升；靠「🔴 写前查盘合并（★ 强制）」规则在落盘前合并同名知识元，无需事后全库去重。

你的选择（输入数字 1 或 2）：

#### Step 4.3 — 抽取要求确认（★ 2026-08-14 新增，可跳过；选择抽取模式与处理顺序之后、开始抽取 chunk 之前）

> 🔴 **必须询问用户对抽取是否还有其他要求**（位于 Step 4 抽取模式 / Step 3 处理顺序之后、Step 5 清库之前；用户要求将注入抽取指导与子代理提示词，优先级最高）。

**① 询问**（🔴 自由文本输入，不是数字选项；严禁图形/卡片式选择菜单）：
```
📋 知识元抽取要求确认（可跳过）
除默认参数（cGranularity / cTextAmount）外，你对本次知识元抽取还有其他要求吗？
可说明（任选或全部）：
  · 抽取原则 —— 如"宁缺毋滥，只抽真正独立的概念"、"人物一律单独成元"
  · 颗粒度 —— 如"偏粗，按章节主题合并"、"偏细，把每个定义都拆开"
  · 总体数量 —— 如"全库控制在 200 个左右"、"这一批不超过 50 个"
  · 知识元内部文字数量 —— 如"每个知识元正文 100~200 字"、"只写要点"
  · 其他任何对抽取的要求

没有额外要求请直接回复 0；有则直接输入你的要求：
```

**② 处理用户回复：**
- 用户输入了具体要求 → 执行：
  ```bash
  python {skill_dir}/kb/scripts/ahkb.py set-extraction-requirements "<用户输入的要求>" --workspace <工作空间绝对路径>
  ```
- 用户回复 0 / "没有" / "无" → 执行清空（保证上次遗留要求不误用）：
  ```bash
  python {skill_dir}/kb/scripts/ahkb.py set-extraction-requirements 0 --workspace <工作空间绝对路径>
  ```

**③ 生效方式（★ 用户要求优先级最高）：**
- 顺序模式：主代理在 A→F 的 C 步分析 chunk 时严格遵守（`extract` 返回的 `guidance.instruction` 已追加用户要求）；
- 并行模式：派发子代理时把 `系统设置/project_settings.json` 的 `extraction_requirements` 填入子代理提示词模板的 `<抽取要求>` 占位符（无则写「无」）。

#### Step 4.5 — 知识库名称决策（决策④，必选，🔴 位于清库之前）

> 🔴 本决策必须在 Step 5 破坏性清库之前完成（遵循「决策前置」铁律）。重建默认沿用旧名称，但必须先询问用户是否修改。
>
> 🔴🔴 「知识库」是系统缺省占位符（非真实名称）。若检测到 `kb_name` 为「知识库」，等同"尚未命名"，**不得呈现"保留原名称「知识库」"选项**，必须要求用户命名（用户不提供则回退「知识库」）。详见 kb.md「知识库名称管理」全局规则。

读取当前知识库名称（`系统设置/project_settings.json` 的 `kb_name`）。

- **若 `kb_name` 真实已命名（非空且 ≠「知识库」）** → 请用户选择（🔴 输入数字 1 或 2，严禁图形/卡片式选择菜单）：

  1. 🔒 保留原名称「<旧名称>」 — 重建后继续使用现有知识库名称
  2. ✏️ 修改名称 — 重建后改用新名称

  你的选择（输入数字 1 或 2）：

  > 🔴 必须等待用户选择，不得默认。
  - 选 1 → 记录「沿用旧名称：<旧名称>」，进入 Step 5。
  - 选 2 → 询问用户「请输入新的知识库名称：」，用户回复后记录新名称，进入 Step 5。

- **若 `kb_name` 未命名（缺失或 =「知识库」缺省占位符）** → 🔴 **必须要求用户命名**（不呈现"保留默认名"选项；🔴 **严禁调用 AskUserQuestion 或任何选项卡片**，直接以纯文字给出输入提示行，用户以文字回复名称）：
  ```
  当前尚未为知识库命名（当前为系统缺省名「知识库」）。请为知识库命名（例如「大系统观知识库」），重建后将以此命名；直接回车则沿用缺省「知识库」：
  ```
  - 用户回复了具体名称 → 记录该新名称，进入 Step 5。
  - 用户留空 → 记录沿用缺省「知识库」，进入 Step 5。

记录下的名称（旧或新）将在 Step 6 写入配置，重建全程以此命名。

【✅ 以上所有用户决策（确认 / 顺序 / 模式 / 名称）已齐备，以下进入破坏性 + 全自动阶段，不再询问用户】

> 🔴 **启动流水线状态（★ loop 前置）**：在 Step 5 清库前先初始化流水线状态（记录 Step 4 选定的抽取模式，供 loop 复用；只写状态文件、不碰数据）：
> ```bash
> python {skill_dir}/kb/scripts/ahkb.py pipeline-mark start --pipeline menu1 --mode <sequential|parallel> --workspace <工作空间绝对路径>
> ```

> 🔴🔴 **进入全自动阶段提示（★ 必说，缺一不可）**：在 Step 5 开始清库、进入全自动阶段前，**必须在本条回复中用自然语言明确告知用户以下四点**（不得省略、不得只放在代码块里）：
> 1. **耗时长**：接下来从清库到重建知识地图全程自动化，结合待处理文档规模（scan 的 `estimated_minutes`），**预计需要 X ~ Y 分钟**才能完成；
> 2. **无需值守**：只要不出现意外，全程**不需要用户做任何操作**，请勿在屏幕前干等或反复确认；
> 3. **可以离开**：用户**可以离开一会儿**去处理别的事，预计 **X ~ Y 分钟后** 回来即可看到完整重建后的知识库与知识地图；
> 4. **异常才打扰**：仅当中途出现必须人工介入的真问题（如旧文件无法删除需手动清理、stuck 自动重派仍失败等）时，智能体才会主动提示用户。
>
> 示例措辞："✅ 所有决策已确认，开始全自动重建。整个流程预计需要 X ~ Y 分钟，期间无需您任何操作，您可以离开一会儿，稍后回来即可看到重建完成的完整知识库与知识地图。除非遇到必须人工处理的问题，我不会打扰您。"

#### Step 5 — 清除知识库

> 🔴 **优先批量删除，失败则由 AI 手动逐个清理。**

先执行批量删除：

```bash
python {skill_dir}/kb/scripts/ahkb.py purge-kb
```

检查输出中的 `deleted` 字段。如果发现残留文件（如报错或删除计数为 0 但实际有旧文件），**AI 必须手动将残留文件移入回收站**：

```bash
python -c "import os, datetime
ws='<工作空间>'; ts=datetime.datetime.now().strftime('%Y%m%d_%H%M%S'); t=os.path.join(ws,'回收站'); os.makedirs(t,exist_ok=True)
for d in ['知识元','图片及其他资源','chunks']:
    p=os.path.join(ws,d)
    if os.path.isdir(p): os.rename(p,os.path.join(t,d+'_'+ts)); os.makedirs(p,exist_ok=True)
for f in ['<根节点名称>(根).md','<根节点名称>-知识地图.html']:
    p=os.path.join(ws,f)
    if os.path.isfile(p): os.rename(p,os.path.join(t,f+'_'+ts))"
python -c "import os, datetime
ws='<工作空间>'; ts=datetime.datetime.now().strftime('%Y%m%d_%H%M%S'); t=os.path.join(ws,'回收站'); os.makedirs(t,exist_ok=True)
p=os.path.join(ws,'原始文件','_processed_docs.json')
if os.path.isfile(p): os.rename(p,os.path.join(t,'_processed_docs.json_'+ts))"

> 🔴 **必须确保所有旧文件全部清除后才能进入下一步。** 如有残留，后续扫描会复用旧数据，导致重建失败。
>
> **如果 AI 也无法删除残留文件**（权限不足、文件被占用等），**必须提示用户手动删除**，告知用户具体路径：
> ```
> ⚠️ 以下文件无法自动删除，请手动删除后再继续：
>   C:\Users\xxx\Workspace\知识元\
>   C:\Users\xxx\Workspace\大系统观知识库.md
> ```
> 用户手动删除后，AI 再继续后续流程。

#### Step 6 — 🔴 写入知识库名称（使用 Step 4.5 已决策的名称）

> 🔴🔴 本步骤位于 Step 5 清库之后，属于「决策前置」铁律划定的"全程无中断"阶段，**严禁再向用户提问或等待输入**。名称已在 Step 4.5 由用户决策（沿用旧名或修改后新名），此处仅将决策结果写入配置。

据 Step 4.5 记录的名称执行：

```bash
python {skill_dir}/kb/scripts/ahkb.py set-kb-name "<决策的名称>" --workspace <工作空间绝对路径>
```

- 若 Step 4.5 选 1（沿用旧名）→ 写回原名称，确保配置一致，立即进入 Step 7。
- 若 Step 4.5 选 2（修改）→ 写入用户新输入的名称，立即进入 Step 7。

> 🔴 绝不可在此步骤再次询问用户；若 Step 4.5 因异常缺失决策结果，兜底使用系统缺省名「知识库」写回（仍不询问），避免全自动流程中断——这与全局规则「未命名且用户不给名则使用知识库三字」一致。

#### Step 7 — 创建根节点知识元

> 知识库名称已就绪，立即创建根节点 `.md` 文件（后续 maintain 完成后再填充完整数据）。

```bash
python {skill_dir}/kb/scripts/ahkb.py create-root-node
```

> 🔴 此步骤不可缺少——后续所有操作（扫描、A→F 处理、maintain、build-graph）均依赖根节点文件的存在。
>
> 🔴 `create-root-node` 创建空的根节点框架。后续 maintain 完成后，`build-graph`（Step 11）会自动填充完整的知识元列表和统计数据。

#### Step 8 — 扫描所有文档（清库后，准备处理）

> 🔴 清库（Step 5）已删除旧 chunks 与处理清单，此处再次 `scan` 以重新清空 `_processed_docs.json`、将全部文档置为待处理，并确认文档总数 N。**本步骤非决策点**——处理顺序已在 Step 3 由用户选定，抽取模式已在 Step 4 选定，此处仅做流水线准备。

```bash
python {skill_dir}/kb/scripts/ahkb.py scan
```

> 🔴 全部文档均为待处理。得到总数 N（应与 Step 2 扫描一致）。

#### Step 9 — loop 中 phase1（A→F 抽取）的执行细节（`next_action=phase1` 时执行；完成后 `pipeline-status` 确认 `phase1_complete:true` → `pipeline-mark done --phase phase1`）

对全部 N 个文档按 Step 3 选定的顺序逐个执行 A→F，显示 `[i/N]` 进度。

> 🔴🔴 **最高优先级：严禁恢复旧数据（★ 铁律）**
> 🔴 `purge-kb` 已彻底清除旧知识元、chunks、资源。此轮重建必须**全部从原始文件重新提取**，每一步 AI 分析都是全新的。
> 🔴 **严禁**从对话记忆中恢复上一轮的知识元内容、名称、标签、摘要等任何数据。
> 🔴 **严禁**引用 chunks/ 或知识元/ 中残留的任何文件（即使有残留也不能用）。
> 🔴 每一篇文档的处理结果必须只基于该文档的原始内容 + 当前 `cGranularity`/`cTextAmount` 参数——不参考上一轮的产出。
> 🔴 全部 N 个完成前禁止 maintain。

**并行模式（Step 4 选了 2）的标准处理流程（★ 2026-08-13 起为"均衡分组 ≤4"派发，方案 B）：**
0. 🔴 **先批量预抽取 + 均衡分组（★ 顺序铁律，不可跳过）**：
   - ① 对全部待处理文件各跑一次 `extract`（确定性、不消耗 LLM），把 `chunks/index.json` 建立起来，供分组取准确工作量：
     ```bash
     python {skill_dir}/kb/scripts/ahkb.py extract "原始文件/<文件>" --workspace <工作空间绝对路径>
     ```
   - ② 运行 `phase1-group --from-scan --max-groups 4` 得到 ≤4 组（大文件独占一组、小文件打包；工作量取 chunk word_count 总和，无 chunks 时按文件大小兜底）：
     ```bash
     python {skill_dir}/kb/scripts/ahkb.py phase1-group --from-scan --max-groups 4 --workspace <工作空间绝对路径>
     ```
0'. 🔴 **派发【之前】先建立派发锚点并自动拉起 wait（★ 2026-08-14 标准姿势，顺序铁律，不可颠倒）**：运行 `phase1-dispatch --auto-wait` 一步完成"写入 `phase1_dispatch` 锚点 + 自动启动 `phase1-wait` 子进程"。**锚点文件集合 = 各组的全部文件**（每个子代理对组内任一文件的心跳/标记都要命中锚点）：
   ```bash
   python {skill_dir}/kb/scripts/ahkb.py phase1-dispatch --files <组1全部文件...> --auto-wait --workspace <工作空间绝对路径>   # 可合并多组一次性 --files 传入
   # 或 --from-scan（仅在派发前、文件尚未 mark-processed 时调用才有效）
   ```
   > 🔴 绝不能"先派发、事后才 dispatch"——那样子代理的心跳会因锚点缺失而静默失效，`phase1-status` 也无法判定 stuck（2026-08-10 实战踩坑）。若 `phase1-heartbeat` 返回 `ok:false`（含 `anchor_missing:true` 或 `not_in_set:true`）或 `updated:false`（假成功），说明心跳实际未记录，立即停上并上报主代理，严禁当作成功继续。
1. **把 ≤4 组分别派发给对应子代理（每组一个子代理，顺序处理组内全部文件）**。每个子代理的提示词**必须直接套用上方「🔴 并行模式 B 的核心契约与完成门控」中①内的 🔴 子代理提示词模板（分组版，含"组内文件列表 + 每 chunk 心跳 + 长 chunk 每 30 秒定时心跳 + 按文件逐个跑完 mark-processed 才返回"硬约束）**，把 `<文件1相对路径>...<文件M相对路径>` / `<工作空间绝对路径>` / `<skill_dir>` 占位符替换为实际值后原样注入；**禁止口头简述契约、必须注入完整模板**，否则子代理不会写心跳、`phase1-wait` 会误判卡死。写知识元前仍须执行写前查盘合并。
2. 🔴 **派发即等待（★ 2026-08-14 铁律，loop 最强化）**：`phase1-dispatch --auto-wait` 已自动拉起 `phase1-wait`（返回 JSON 含 `wait.status=started` 与 PID；若为 `already_running` 则直接继续）。此后主代理**唯一合法动作就是每 2~3 分钟运行 `phase1-peek` 轻量播报循环**（详见 kb.md ③④）：
   ```bash
   python {skill_dir}/kb/scripts/ahkb.py phase1-peek --workspace <工作空间绝对路径>   # 每 2~3 分钟
   ```
   - `phase1-peek` 返回 `complete`（或 wait 退出 0）→ 运行 `phase1-dispatch --clear` 清除派发状态，进入 Step 10（maintain）。
   - 返回 `stuck`（exit 2，附 stuck 清单）→ 按 kb.md ③「stuck 处置规则」自动重派该文件子代理 / 主 agent 亲自降级补完（**补完必须含 verify-units + validate-units 两道闸门**），随后**再次运行 `phase1-wait`** 继续等待。
   - 返回 `timeout`（exit 3）→ 诊断：重派 stuck / 补收尾 / 汇报用户，随后再次 `phase1-wait` 或结束。
   - 返回 `running` → 把 `_display` 原文打印给用户，约 2~3 分钟后再次 `phase1-peek`。
   - 返回 `error` / `not_started` → 检查 `临时工作文件/_phase1_wait.pid` 与进度文件，必要时 `phase1-wait --clear` 后重新启动。
   - 🔴 若 `pipeline-status` 返回 `next_action: "phase1_wait_required"`（wait 守卫触发）→ **必须立即补执行 `phase1-wait` 再继续**，不得忽略。
   > 🔴 绝不得依赖"后台 agent 完成通知"或等子代理自行回报来判定结束——否则心跳门控形同虚设，`stuck` 无法被发现与重派（2026-08-10 实战踩坑）。**严禁**派发后结束回合、**严禁**派发后不启动 wait 就推进其他步骤。
3. 进入 Step 10 前，以 `maintain` 的 `phase1_incomplete` 硬关卡做最终确认（兜底防线）。

> 🔴 顺序模式（Step 4 选了 1）：沿用原逐文件/逐批主 agent 亲自处理流程，每文件跑完 A→F 后即时 `mark-processed`，无需 `phase1-dispatch`/`phase1-wait` 等待。

#### Step 10 — loop 中 phase2（maintain 关联）的执行细节（`next_action=phase2` 时执行；完成后 `pipeline-mark done --phase phase2`）

1. `python {skill_dir}/kb/scripts/ahkb.py update-concept-index`（可选，maintain 已自动执行）
2. 关联所有知识元：

   ```bash
   python {skill_dir}/kb/scripts/ahkb.py maintain --detached --workspace <工作空间绝对路径>
   ```
   > 此命令 1 秒内返回，GUI 窗口在独立进程中运行。

   🔴🔴 **LLM 必须执行轮询（不得跳过，不得直接进入 Step 11）。每回合运行以下命令检查一次：**

   ```bash
   python {skill_dir}/kb/scripts/ahkb.py check-maintain-status --workspace <工作空间绝对路径>
   ```

   🔴🔴 **收到 phase1_incomplete 状态时的处理：**
   - 输出含 `"status": "phase1_incomplete"` → **立即停止**，回到 Phase 1 完成剩余文档！

   返回 JSON 中 `_display` 字段可直接展示给用户。

   - `status: "complete"` → 汇总后进入 Step 11
   - `status: "cancelled"` → 返回主菜单
   - `status: "running"` / `"starting"` → 展示 `_display` 原文，约 10 秒后再次轮询
   - `status: "hung"` → 进度僵死（已自动清理），汇总异常信息，返回主菜单重跑 maintain
   - 🔴🔴 **其他状态 → 展示 `_display` 原文，等约 10 秒后再次轮询。禁止只内部检查不输出。**

```
🔴🔴 ═══════════════════════════════════════════════════
🔴🔴  硬阻断：必须轮询确认 maintain [完成] 后才能越过此线
🔴🔴  严禁在关联未完成时执行 build-graph 或 build-kg-html
🔴🔴 ═══════════════════════════════════════════════════
```

#### Step 11 — loop 中 phase3（构建根节点并重建知识地图）的执行细节（`next_action=phase3` 时执行；完成后 `pipeline-mark done --phase phase3` → loop 判定 done → `pipeline-mark finish`）

1. `python {skill_dir}/kb/scripts/ahkb.py build-graph`
2. `python {skill_dir}/kb/scripts/ahkb.py build-kg-html`
3. `python {skill_dir}/kb/scripts/ahkb.py set-graph-colors`
4. `python -c "import webbrowser; webbrowser.open('<知识库名称>-知识地图.html')"`

完成后返回模块主菜单。

