# Make-to-Markdown 运维参考手册

> 本文档为 SKILL.md 的补充内容，包含平台兼容性、后置清洗细节、完整反模式清单、回归测试等运维参考资料。Agent 运行时核心逻辑见 SKILL.md。

## 1. 后置清洗与 RAG 优化（详细）

`convert.py` 内联了后置清洗逻辑，无需单独调用 `post_clean.py`。以下为完整清洗项说明。

### 1.1 自动清洗项

| 清洗项 | 匹配模式 |
|--------|---------|
| 工具水印 | `[Generated by ...]`、`Converted by markitdown`、`[Created with ...]`、`Powered by ... markitdown` |
| 页码标记 | `Page X of Y`、`[PAGE X]`、`--- Page X ---` |
| 机密标记 | `Confidential`、`DRAFT`、`Internal Use Only`、`For Review Only` |
| 版权声明 | `© YYYY`、`All Rights Reserved` |
| 空白压缩 | 连续 3 行以上空行 → 2 行 |
| 行尾空格 | 移除 |

### 1.2 标题层级修复（v2.6+）

- 多个 H1：仅保留第一个，其余降级为 H2
- 标题越级（如 H2 → H4）：自动插入过渡标题

### 1.3 表格修复（v2.6+）

- 检测缺失分隔符（`|---|---|`）的表格，自动补全
- 避免将引用块（`>`）误判为数据行

### 1.4 文档摘要注入

自动提取第一个 H1 和 H2 标题，统计章节和表格数量，在文件头部注入：

```markdown
> **文档摘要**
> 本文档「xxx」，涵盖 N 个章节，包含 M 个数据表格。
```

### 1.5 结构校验（post_clean.py --check-only）

- 缺少 H1 顶层标题
- 多个 H1 标题（建议仅 1 个）
- 标题越级（如 H2 直接跳到 H4）

---

## 2. 输出质量自检清单 (Post-Conversion Quality Checklist)

转换完成后，按以下 7 项快速自检输出 Markdown 质量。任一项失败时标注 `quality_flag` 并告知用户：

- [ ] **标题完整性**：H1 无空标题且数量 ≥ 预期（Word/PDF 无标题则此项 N/A）
- [ ] **表格可读性**：所有表格均有表头分隔线（`|---|`），无因合并单元格导致的错位
- [ ] **水印/页码残留**：正文无 "仅供内部使用" / 水印文本 / 独立页码行
- [ ] **编码正确**：中文/特殊字符无乱码（常见于 PDF OCR 输出）
- [ ] **链接/引用保留**：原文档的超链接已转为 Markdown `[text](url)` 格式，图片引用路径有效
- [ ] **代码块完整**：原文档的代码示例未被截断或格式化为纯文本
- [ ] **空白合理**：无连续 3 行以上空白，无段落间异常断行

> **注意**：本清单不替代后置清洗的自动化处理，而是作为清洗后的人工抽查速览。

---

## 3. 平台兼容性

| 平台 | 状态 | 说明 |
|------|------|------|
| Windows | 完全支持 | Office COM 预处理（需 `pywin32`）+ LibreOffice 回退；`uv` 工具链原生可用 |
| Linux | 完全支持 | LibreOffice 预处理；`uv` 通过 `~/.local/bin` 定位 markitdown |
| macOS | 完全支持 | 同 Linux；Apple Silicon 需 Rosetta 2 运行 x86 LibreOffice |

**关键兼容约束**：
- **平台感知路由（v2.8）**：`convert.py` 启动时自动调用 `platform_detect.py` 检测 OS/版本/架构/WSL/COM/LibreOffice 可用性
- **网络驱动器**：涉及 E:\Marvis_Data 等网络驱动器路径时，使用 `python_executor` 执行脚本而非 `shell_executor`
- **路径分隔符**：全部脚本使用 `pathlib.Path`，自动适配 Windows（`\`）和 Unix（`/`）

---

## 4. 反模式与禁止清单（完整版）

以下做法已知会导致转换失败、输出质量下降或流程卡死，**严禁使用**。

| # | 反模式 | 正确做法 |
|:---|:---|:---|
| 1 | **绕过 convert.py 直接裸调 markitdown** | 始终使用 `python scripts/convert.py input.docx` |
| 2 | **手动安装 markitdown extras** | 让 convert.py 自动处理 |
| 3 | **用 shell_executor 执行网络驱动器上的脚本** | 用 `python_executor` 执行脚本 |
| 4 | **转换后不检查输出质量** | 检查输出的前 20 行 |
| 5 | **对加密文档反复重试** | 首次失败后立即终止 |
| 6 | **.doc/.ppt 无预处理环境时强行转换** | 告知用户安装 Office 或 LibreOffice |
| 7 | **转换过程中修改源文件** | 转换前关闭源文件的所有打开实例 |
| 8 | **批量转换时不设 --ext 过滤** | 明确指定 `--ext .pdf .docx .pptx` |
| 9 | **重复清洗已清洗过的输出** | 不要对 convert.py 输出再次调用 post_clean.py |
| 10 | **不备份直接覆盖输出** | 转换前确认输出路径是否已存在 |

### 4.1 禁止操作

- **禁止**将 `post_clean.py` 的输出再次作为 `convert.py` 的输入
- **禁止**在 `shell_executor` 中直接引用 E:\Marvis_Data 等网络驱动器路径
- **禁止**跳过 `convert.py` 的 `--no-summary` 后又手动调用 `post_clean.py --summary`
- **禁止**对 `.xls` 文件使用 COM 预处理
- **禁止**在批量转换中指定不存在或为空的 `--ext` 参数
- **禁止**对已经通过 convert.py 成功转换的输出再次调用 convert.py

---

## 5. 可验证性检查表 - 扩展

### 5.1 最小化回归测试用例

| 用例 | 源文件 | 预期输出特征 | 验证要点 |
|:---|:---|:---|:---|
| RT1 | 任意 .docx（含 H1-H3 + 表格 + 图片） | 输出 .md 含与源文档等量的 H1/H2/H3、表格有 `|---|` 分隔符 | V1+V2+V3+V4+V5 |
| RT2 | 任意 .pdf（纯文本/扫描 OCR） | 输出 .md 分页标记已清除，正文连续无断裂 | V1+V2+V3 |
| RT3 | 批量 5 个不同格式混合 → 单目录 | 输出目录含 5 个 .md 文件，每个文件命名对应源文件名 | V1+V6 |

### 5.2 快速验证脚本

单文件模式：

```bash
python -c "import os, re; f='<输出.md>'; assert os.path.exists(f), 'FAIL'; t=open(f,encoding='utf-8').read(); assert not re.search(r'Generated by|Page \d+ of \d+',t), 'FAIL: watermarks'; hs=re.findall(r'^(#{1,6})\s',t,re.M); levels=[len(h) for h in hs]; assert len(hs)>0 and levels[0]==1, 'FAIL: bad headings'; jumps=[i for i in range(1,len(levels)) if levels[i]-levels[i-1]>1]; assert not jumps, f'FAIL: level jump {jumps}'; print('PASS (6/6)')"
```

批量模式（文件计数）：`python -c "import os; n=len(os.listdir('<输出目录>')); print(f'{n} files')"`

---

## 6. 更新记录

| 版本 | 日期 | 变更 |
|------|------|------|
| v3.6 | 2026-06-07 | darwin-skill Phase 2 R4-R6：dim9 标题与 frontmatter 双重同步至 3.6 彻底统一；dim6 §11.4 幽灵引用替换为内联 oneliner；非核心章节拆分至 README.md |
| v3.5 | 2026-06-07 | darwin-skill Phase 2 R1-R3：dim6 幽灵引用修复；dim9 版本号统一；dim4 检查点 +2 |
| v3.1 | 2026-06-07 | darwin-skill 优化：§5.1 新增 CHECKPOINT 块；§6 新增反馈格式固定模板 |
| v2.9 | 2026-06-07 | 名称统一为 Make-to-Markdown |
| v2.8 | 2026-06-07 | 新增 `platform_detect.py` 平台检测模块 |
| v2.7 | 2026-06-07 | 新增平台兼容性章节；增加 uv 可用性检查 |
| v2.6 | 2026-06-07 | 内联清洗新增标题层级修复和表格分隔符补全 |
| v2.5 | 2026-06-07 | markitdown extras 改为 uv tool install 安装 |
| v2.4 | 2026-06-07 | 添加 .ppt 旧格式支持 |
| v2.3 | 2026-06-07 | 添加 .doc 旧格式支持 |
| v2.2 | 2026-06-07 | convert.py 智能转换引擎 |
| v2.1 | 2026-06-07 | 添加 batch_convert.py、post_clean.py |
| v2.0 | 2026-06-07 | 初始技能创建 |

---

## 7. 静默失败防护（详细）

> 本章节为 SKILL.md §5.2 的详细补充，列出历史版本中容易无声失败的错误及其检测机制。

| 静默失败形态 | 检测机制 |
|:---|:---|
| convert.py 内联清洗跳过某些噪声模式 | §4.1 噪声模式库覆盖 15+ 正则 |
| 降级转换器输出与 markitdown 输出格式不一致 | 降级输出同样经过后置清洗（§3.2） |
| 批量转换某文件失败但未记录 | `_conversion_errors.log` 汇总 |
| 标题层级修复误触发（已修复的标题再次被"修复"） | v2.6+ 标题修复仅执行一次，有状态标记 |
| markitdown extras 缺失但转换仍"成功"（输出质量差） | convert.py 启动时检测全部可选依赖 |
