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

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

### 菜单 0 — 🚀 从0开始全自动构建知识库与知识地图

> 🔴🔴 **loop 驱动（★ 2026-08-13 起）**：本菜单的全自动阶段由 `kb.md`「🔴 全自动流水线 loop 执行」统一驱动——
> 阶段间自动衔接、失败自动重试（≤5 次）、中断自动续跑，**全程不向用户下指令**。
> - **进入判定**：先运行 `python {skill_dir}/kb/scripts/ahkb.py pipeline-status --workspace <工作空间绝对路径>`：
>   - 返回 `next_action` ∈ phase1/phase2/phase3（上次构建未完成）→ **自动续跑**：告知用户"检测到上次构建未完成
>     （<阶段>），自动从断点继续"，直接进入下方「Step 2 全自动流水线 loop 执行」，**跳过**初始化/清库/扫描/B0/顺序等交互（抽取模式复用状态文件记录的 mode，不再询问）；
>   - 返回 `done` / `error` / 无状态文件 → 全新开始，正常走下方「初始化与命名」及交互步骤。
> - **全新开始时的交互**：初始化与命名、Step 0 清库、Step 1 扫描、Step 1.4（B0 抽取模式）、Step 1.5（处理顺序）仅在全新开始执行；B0 选择通过 `pipeline-mark start --mode <sequential|parallel>` 记录。
> - 🔴 **并行模式跳过 Step 1.5**（均衡分组已自动按工作量排序组内文件）；顺序模式保留 Step 1.5。
>
> ⚠️ 另有「初始化与命名」步骤位于 Step 0 之前：进入全自动前必须确认一次知识库名称。**注意「知识库」是系统缺省占位符（`init` 不带 `--name` 时自动写入，见 ahkb.py `cmd_init`），检测到它即等同"未命名"**。因此：真实已命名（非空且 ≠「知识库」）→ 询问「保留原名 / 修改」；未命名（缺失或 =「知识库」）→ **必须直接要求用户给出名称**，不得显示"保留原名称「知识库」"这种选项。用户不提供新名则回退「知识库」。该命名交互不属于 Phase 1 断点，而是进入全自动前的必要准备。

#### ▶ 自动续跑检测（★ 2026-08-13 起 loop 自动接管，取代旧的"断点恢复询问"）

> 🔴🔴 **背景**：并行抽取中途重启/中断后，若直接进入 Step 0（清除旧记录）会把上次已写盘的知识元与 processed 清单全部清掉，进度尽毁。**2026-08-13 起由 `pipeline-status` 全流程判定，中断后自动续跑、不再询问用户。**

1. 运行：`python {skill_dir}/kb/scripts/ahkb.py pipeline-status --workspace <工作空间绝对路径>`。
2. **返回 `next_action` ∈ phase1/phase2/phase3** → **自动续跑**：告知用户后直接进入「Step 2 全自动流水线 loop 执行」，跳过 Step 0 清库与全部交互（mode 复用状态文件记录）。
3. **返回 `done` 或 `error` 或无状态文件** → 正常进入下方「初始化与命名」→ Step 0 清库 → 全新开始。
4. 🔴 **任何"全标记但未跑过质量闸门"的文件都不算真正完成**——续跑进入 Phase1 时一律以 `verify-units --pending` 复查为准（由 loop 的 phase1 执行细节覆盖）。

#### ▶ 初始化与命名（🔴 仅全新开始执行；续跑时跳过）

> 🔴 本步骤完成两件事，且必须在全自动不中断开始之前完成：
> 1. **创建知识库文件目录结构**（幂等，已存在则跳过）；
> 2. **确认 / 询问知识库名称**。

**① 初始化目录结构：**
```bash
python {skill_dir}/kb/scripts/ahkb.py init --workspace <工作空间绝对路径>
```
该命令创建 `原始文件/ 知识元/ 图片及其他资源/ chunks/ 临时工作文件/ 产品成果/ 系统设置/` 等目录与配置文件（含依赖自检）。

**② 询问知识库名称（🔴 进入全自动前必须确认一次，且要把系统缺省名「知识库」视作"未命名"）：**

> 🔴🔴 「知识库」只是系统缺省占位符（执行 `init` 不带 `--name` 时自动写入 `kb_name`，见 ahkb.py `cmd_init`）。**检测到的名称若为「知识库」，等同"尚未命名"——绝不能把"保留原名称「知识库」"当作一个合理选项呈现给用户。** 只有"非空且 ≠「知识库」"才叫真实已命名。

- 读取 `系统设置/project_settings.json` 的 `kb_name` 字段。
- **若 `kb_name` 真实已命名（非空且 ≠「知识库」）** → 询问是否沿用或修改（🔴 不得默认跳过）：
  ```
  检测到当前知识库名称为「<名称>」。是否保留该名称，还是修改？
    1. 🔒 保留原名称「<名称>」
    2. ✏️ 修改名称
  请回复数字 1 或 2（若选 2，可直接连同新名称一起回复，例如「2 大系统观知识库」）：
  ```
  - 选 1 → 直接进入 Step 0（名称不变）。
  - 选 2 → 询问「请输入新的知识库名称：」，用户回复后执行：
    ```bash
    python {skill_dir}/kb/scripts/ahkb.py init --name "<用户输入的新名称>" --workspace <工作空间绝对路径>
    ```
- **若未命名（`kb_name` 缺失 / 为空，或 =「知识库」缺省占位符）** → 🔴 **必须直接要求用户命名**（严禁显示"保留原名称「知识库」"选项，因为那不是真实名称；🔴 **严禁调用 AskUserQuestion 或任何选项卡片**，直接以纯文字给出输入提示行，用户以文字回复名称）：
  ```
  当前尚未为知识库命名（当前为系统缺省名「知识库」）。请为知识库命名，将用于根节点与知识地图文件名（例如「大系统观知识库」或「大系统观管理哲学知识库」）：
  ```
  - 用户回复了具体名称 → 执行：
    ```bash
    python {skill_dir}/kb/scripts/ahkb.py init --name "<用户输入的名称>" --workspace <工作空间绝对路径>
    ```
  - 用户直接回车 / 留空（未提供新名）→ 回退使用系统缺省三字「知识库」，不询问、不报错，直接进入 Step 0：
    ```bash
    python {skill_dir}/kb/scripts/ahkb.py init --workspace <工作空间绝对路径>
    ```
  > ⚠️ 无论哪种，名称最终都会写入 `project_settings.json`（与 `_processed_docs.json`），并派生出 `<名称>(根).md` 与 `<名称>-知识地图.html`。「知识库」三字作为缺省名同样能正常生成这些文件。

> 🔴 名称一旦设定，全程以此为 `<知识库名称>`；后续 `build-graph` / `build-kg-html` / 浏览器打开均使用该名称。

#### Step 0 — 清除旧处理记录（🔴 仅全新开始执行；续跑时禁止清库）

> 🔴 **从零开始必须清除旧记录**，否则已处理文件会被跳过。

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

#### Step 1 — 扫描所有文档（🔴 仅全新开始执行；续跑时由 loop 的 phase1 执行自行扫描）

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

> 🔴 **必须将 `estimated_minutes` 的估算时间用文字明确告知用户，不允许隐藏或仅放在代码块中。必须在自然语言消息中直接说"预计 X ~ Y 分钟"。**
> ```
> 📊 发现 N 个文档待处理，预计需要 X ~ Y 分钟
> ```

> 如有 `pending_files`（已提取 chunks 但未完成关联），优先处理：直接 mark-processed，跳过 A→F 提取阶段。

#### Step 1.4 — 抽取模式选择（B0 必选，🔴 仅全新开始执行；续跑时复用状态文件记录的 mode）

> 🔴 必须等待用户选择，不得默认执行。此即 `kb.md` 的 **B0. 抽取模式选择**：进入 Phase 1 前必须向用户提问二选一，不可自行默认。用户选定后记入 `pipeline-mark start --mode <sequential|parallel>`。

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

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

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

> 🔴 用户选定后：选 1 → 由主 agent 亲自顺序处理（每批分析 chunk → 创建知识元 → 执行 `update-concept-index`）；选 2 → 各文件并发交由子代理处理，主代理按其「🔴 并行模式完成门控」`phase1-wait` 脚本等待 + `phase1-peek` 轻量播报驱动。两种模式均须在所有文件完成 A→F + mark-processed 后才进入 Phase 2 关联。

#### Step 1.5 — 选择处理顺序（🔴 仅全新开始 + 顺序模式执行；并行模式跳过）

> 🔴 并行模式（Step 1.4 选 2）**跳过本步骤**：`phase1-group` 均衡分组已自动按工作量降序决定组内处理顺序。
> 🔴 顺序模式（选 1）必须等待用户选择，不得默认执行、不得替用户决策。scan 已返回每个文件的 `ext`、`text_chars` 和 `size`，向用户展示以下处理顺序选择：

```
📊 发现 N 个文档待处理（含 M 个已有 chunks），预计 X ~ Y 分钟

📂 文件类型分布：
  · pptx: X 个  · docx: X 个  · pdf: X 个  · md: X 个  · xlsx: X 个  · html: X 个  · txt: X 个

请选择处理顺序：
1. 🔼 文字量从多到少 — 优先处理内容丰富的文档，先建知识库骨架
2. 🔽 文字量从少到多 — 优先处理短小文档，再集中精力处理长篇
3. 📁 按文件类型分组 — 同类型文档集中处理（按类型优先级：pptx→docx→pdf→md→xlsx→html→txt，组内文字量从多到少）
4. 🏷️ 指定文件类型优先 — 你指定哪些类型先处理，其余类型后处理
5. ⏭ 按原有顺序 — 不做排序，按扫描发现顺序处理
6. ✏️ 自定义顺序 — 你告诉我怎么排

你的选择（输入数字 1~6）：
```

> 🔴 **必须等待用户选择**，不得默认执行，不得替用户决策。
> 🔴 AI 严禁预设或推荐任何选项为默认值——用户必须明确选择。
> - 选 1 或 2：按 `text_chars` 排序
> - 选 3：按扩展名分组，组内按 `text_chars` 降序
> - 选 4：询问用户"你想优先处理哪些文件类型？（如 pptx、docx、pdf 等）"，用户指定后将该类型排在前面，其余类型按原有顺序排后
> - 选 5：保持 scan 返回的顺序
> - 选 6：询问用户"请按你想要的顺序列出文件（每行一个，或输入编号列表）"
>
> 排序时 pending_files 始终排在同类最前面。用户选择后，AI 按指定顺序逐个执行 A→F。

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

#### Step 1.6 — 抽取要求确认（★ 2026-08-14 新增，可跳过；位于开始抽取 chunk 之前）

> 🔴 **选择抽取模式（1.4）与处理顺序（1.5，顺序模式）之后、开始抽取 chunk 之前，必须询问用户对抽取是否还有其他要求**（并行模式跳过 1.5 时，本环节紧随 1.4 之后）。用户的要求将注入抽取指导与子代理提示词，**优先级最高**。

**① 询问**（🔴 自由文本输入，不是数字选项；严禁图形/卡片式选择菜单）：
```
📋 知识元抽取要求确认（可跳过）
除默认参数（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` 已追加用户要求；也可直接运行 `knowledge-gen-guidance` 查看）；
- 并行模式：派发子代理时把 `系统设置/project_settings.json` 的 `extraction_requirements` 填入子代理提示词模板的 `<抽取要求>` 占位符（无则写「无」）。

#### Step 2 — 全自动流水线 loop 执行（★ 2026-08-13 起统一驱动，取代原"Step 2→3→4 顺序推进"）

> 🔴🔴 **本步骤即 `kb.md`「🔴 全自动流水线 loop 执行」**：进入循环后由 `pipeline-status` 判定
> `next_action`，按 phase1 → phase2 → phase3 自动推进、自动衔接；每阶段成功 →
> `pipeline-mark done --phase <阶段>`，失败 → `pipeline-mark fail --phase <阶段> --reason "<原因>"`
> （自动重试，≤5 次，无需用户确认）；全部完成 → 报告 + `pipeline-mark finish`。**循环期间不向用户下任何指令。**
> - 全新开始时先执行：`python {skill_dir}/kb/scripts/ahkb.py pipeline-mark start --pipeline menu0 --mode <sequential|parallel> --workspace <工作空间绝对路径>`
> - 自动续跑时跳过（状态文件已存在，mode 自动复用）。
> - 下方 Step 3 / Step 4 是 loop 中 phase2 / phase3 的执行细节，由本循环按 `next_action` 调用。

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

> 🔴 先列全所有待处理文件，得到总数 N。循环 i = 1 到 N。N 个全部处理完才允许进入下一阶段。
> 🔴 `pending_files` 中的文件已有 chunks，但需注意：`mark-processed` 会自动检查对应知识元是否存在。
> - 已有知识元 → 正常通过
> - **无知识元 → 被拒绝**，必须先完成 [C][D] 步骤再标记
> 🔴 **抽取模式**：顺序模式（mode=sequential）由主 agent 亲自逐文件顺序执行 A→F；并行模式（mode=parallel）按 `kb.md`「🔴 并行模式（选项 2）的核心契约与完成门控」**先 `phase1-group` 分组 → `phase1-dispatch --auto-wait` 建锚点并自动拉起 wait（★ 2026-08-14 标准姿势，防"派发后空转"）→ 派发子代理 → 由已启动的 wait 脚本等待驱动**（详见 kb.md ③），确保全部 mark-processed 才完成本阶段。**并行模式下主代理等待期间每 2~3 分钟运行一次 `phase1-peek` 把 `_display` 轻量播报给用户，收到 `complete`/`stuck`/`timeout` 终态立即处置（详见 kb.md ④），避免用户因屏幕长时间无输出误以为卡死。**
>
> 🔴🔴 **派发即等待（★ 2026-08-14 铁律，loop 最强化）**：并行模式下，`phase1-dispatch --auto-wait` 之后**主代理唯一合法动作就是进入 phase1-peek 播报循环**。**严禁**派发后结束回合、**严禁**空等"后台 agent 完成通知"、**严禁**派发后不启动 wait 就推进其他步骤。若 `pipeline-status` 返回 `next_action: "phase1_wait_required"`（wait 守卫触发），**必须立即补执行 `phase1-wait` 再继续**，不得忽略。

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

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

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

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

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

   🔴🔴 **收到 phase1_incomplete 状态时的处理（新增）：**
   - 输出含 `"status": "phase1_incomplete"` → **立即停止**，回到 Phase 1 完成剩余文档的 A→F 流水线！禁止强行继续。

   返回的 JSON 中 `_display` 字段包含人类可读的状态摘要，可直接展示给用户。

   - `status: "complete"` → 汇总后进入 Step 4
   - `status: "cancelled"` → 返回主菜单
   - `status: "running"` / `"starting"` → 把 `_display` 原文展示给用户，等约 10 秒后再次轮询
   - `status: "error"` / `"stale"` / `"hung"` → 汇总异常信息，返回主菜单
   - 🔴🔴 **其他任何状态 → 把 `_display` 原文展示给用户，等约 10 秒后再次轮询。禁止只内部检查不输出。**

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

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

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')"`

