# Batch C Worker B：GFM AST 尾项小包

> 执行日期：2026-05-21
> 执行人：Reasonix Code (deepseek-v4-flash)

---

## 修改文件列表

| 文件 | 操作 | 说明 |
|------|------|------|
| `rust/crates/mnote-web/src/routes/local_markdown_parser.rs` | 编辑 | 新增 2 个解析测试 |
| `rust/crates/mnote-web/src/routes/local_folder_source.rs` | 编辑 | 给 3 个写侧函数加过渡注释 |
| `rust/crates/mnote-web/src/routes/web_shell.rs` | 编辑 | 测试断言扩展 + JS 适配层过渡注释 |
| `design/03-rust-web/process/3-13-rust-web-local-markdown-gfm-ast-parser-migration-v1.md` | 编辑 | 更新 checklist 状态 |
| `.codex/reasonix-tasks/results/batch-c-worker-b-gfm-tail.md` | 新建 | 本报告文件 |

---

## 关闭/追认的 3-13 尾项

### ✅ 11.2 空表格单元格 / 空引用块处理规则

- **追加测试** `markdown_empty_blockquote_parse`：验证 `>` / `> ` 输出 `type=quote, content=[]`
- **追加测试** `markdown_table_empty_cells_parse`：验证空表头/数据单元格的 `paragraph.content` 为 `[]`
- 行为固定为 comrak 默认输出，不再无规则

### ✅ 11.4 legacy→Tiptap→legacy marks 不丢 marks

- `document_shell_bootstrap_preserves_inline_mark_conversion` 原仅断言 `code` / `link`
- **已扩展断言**：`bold`, `italic`, `underline`, `strike`, `code`, `link` 全部 6 种 core marks 的 JS 生成代码均存在于 HTML 中

### ✅ 11.8 web shell 单测：legacy↔Tiptap 不丢 marks

- 同上 — 测试名称不变但断言已补全

### ✅ 11.9 手写 parser 标记为过渡实现

- `inline_nodes_to_markdown`（`local_folder_source.rs:7004`）：加中文过渡注释
- `editor_blocks_to_markdown_for_file`（`local_folder_source.rs:6221`）：加中文过渡注释
- `editor_blocks_to_markdown_with_rewrite`（`local_folder_source.rs:6393`）：加中文过渡注释

### 📌 11.9 web_shell.rs 临时适配分支

- **未删除**，但加了过渡注释 `// 过渡适配（TODO step-4）`
- 完整标记了 `legacyStylesToTiptapMarks` / `legacyMarkArrayToTiptapMarks` / `mergeTiptapMarks` / `legacyInlineContentToTiptap` 四函数组的迁移计划

---

## 验证命令与结果

### 命令 1：`local_markdown` 测试组

```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web local_markdown -- --test-threads=1
```

**结果：30 passed, 0 failed**

新测试确认通过：
- `routes::local_markdown_parser::tests::markdown_empty_blockquote_parse`
- `routes::local_markdown_parser::tests::markdown_table_empty_cells_parse`

### 命令 2：`web_shell` 测试组

```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web web_shell -- --test-threads=1
```

**结果：10 passed, 0 failed**

核心测试确认通过：
- `routes::web_shell::tests::document_shell_bootstrap_preserves_inline_mark_conversion`

---

## 未完成项与风险

### 未完成项（保持 [ ] 状态）

| 项 | 说明 | 原因 |
|----|------|------|
| 11.2 标题优先级 frontmatter > H1 > 文件名 | 任务明确排除 | 本包不做 frontmatter title 优先级修复 |
| 11.6 降级策略测试 | 仅部分完成 | 列对齐已追认、空单元格已补测试；但 `unsupported → paragraph` 等降级策略无专项测试 |
| 11.7 保存失败状态保留 | 未触及 | 需要前端侧 error handler + 状态保留测试，属不同责任域 |
| 11.9 web_shell.rs 临时适配分支移除 | 未删除 | 仅加过渡注释 — JS 侧函数仍需等 Step 4 才能移除 |
| 11.9 process→done | 未移动 | 以上 [ ] 项全部关闭后执行 |

### 风险

1. **空单元格解析层 vs 回写层行为可能不一致**：解析层测试已验证空的 `paragraph.content = []`，但回写侧 `editor_blocks_to_markdown_with_rewrite` 对空单元格的处理未覆盖测试（它的流程是 `inline_nodes_to_markdown` → 空字符串 → `.trim().to_string()` → 空 → `replace('\n', " ")` → 保持空）。建议后续补 save 侧空单元格 round-trip 测试。
2. **过渡注释不产生编译期警告**：当前使用普通 `//` 注释而非 `#[deprecated]`，不会在编译时提醒迁移。如要严格追踪，建议未来 Step 4 前统一加 `#[deprecated(note = "...")]`。
3. **新加但未整体编译验证**：两个测试组均通过，但未执行 `cargo test -p mnote-web` 全量。局部风险较低。
