Files
deep_research/.opencode/skills/output-hygiene/SKILL.md
T
kai 09f681beb5 v0.7.2: 前置件排版重构 + emoji 禁令 + 引文核查
用户反馈 7 个 bug 修复:

1. 禁止 LLM 使用 emoji(全链路)
   - scripts/prompts/translate_system.txt 增加规则 12
   - scripts/prompts/polish_system.txt 增加规则 7
   - .opencode/agents/dr-analyst.md Hard Rules 增加第 10 条(同时把 prompt 自身的  改为 MUST / MUST NOT)
   - .opencode/agents/dr-editor-in-chief.md 禁止事项加入 emoji 条款
   - .opencode/skills/output-hygiene/SKILL.md 新增 §J emoji 强制禁用

2. 术语表位置错误(应在目录之后)
   重构 build_body 为两阶段:
   (a) 扫描所有前置件(第一个正文 H1 前的所有 H1/H2),按 title_kind 分组收集
   (b) 按固定顺序渲染:免责声明 → 执行摘要 → 目录 → 术语表 → 正文 → 参考文献
   无论 Markdown 原文顺序如何,排版都一致。

3. 执行摘要/术语表提升为一级标题 + 分页空页 bug
   统一所有独立章节(disclaimer/executive_summary/toc/glossary/references)用 h1 样式,
   章节前 PageBreak;但第一个独立章节不 PageBreak(封面后已换页,避免空白)。
   去掉 build_toc 内部末尾 PageBreak(原双 PageBreak 夹出空白页)。

4. 参考文献分页
   已作为独立章节自动分页。

5. 附录章节自动删除
   _title_kind 识别 "appendix" / "version_history" / "abstract" 全部跳过。
   正文中若写了这些章节,模板直接丢弃。

6. 信源完整性核查
   新增 scripts/check_citations.py:
   - 孤立引用(正文有 sources 无)检测
   - 孤岛信源(sources 有正文无)检测
   - emoji 扫描
   - 实测发现项目中 61 条孤立引用(dr-analyst 编造的占位符)+ 5 条孤岛信源

7. git commit message 中文转义 bug
   之前 commit 用 shell 双引号 + 反斜杠导致 \uXXXX 字面保留。
   本 commit 用 heredoc 保证中文以 UTF-8 直接写入。
   已 push 的历史不改,之后都用本 commit 的写法。

PDF 验证结果:55 页,0 空白页。
章节起始页:封面(1) - 免责声明(2) - 执行摘要(3) - 目录(5) - 术语表(7) -
第一章(12) - 第十章(48) - 参考文献(52)。
2026-04-22 16:31:01 +08:00

267 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: output-hygiene
description: 报告输出卫生检查。禁止词清单(调度元数据、占位符残留、待验证标注)、格式异常检测、参考文献完整性校验。dr-polisher 在润色最后一步必跑;dr-reporter 出稿前复查一次。
---
# 输出卫生清单(Output Hygiene Checklist
## 目的
拦截"调度元数据"和"中间产物残留"进入最终报告。9MW1911 那份报告之所以干净,是因为过滤掉了一切过程性内容,只留最终成品。
---
## 一、禁止出现在最终报告正文中的字样(元数据黑名单)
以下字符串在 final.md / final_zh.md / final_en.md 里**一旦出现即为缺陷**dr-polisher 必须清除:
### A. 调度元数据
- `章节定位`
- `字数配额`
- `研究员:dr-analyst`
- `研究员:dr-searcher`
- `生成时间:2026-`(Year-MM 生成日期只在版本信息页出现一次)
- `P0 核心章` / `P1` / `P2`(这些是内部分级,不给读者看)
- `dr-plan` / `dr-pm` / `dr-analyst` / `dr-verifier` / `dr-chief-editor` / `dr-editor-in-chief` / `dr-polisher` / `dr-reporter` / `dr-translator`
- `Phase 1` / `Phase 2` / `Phase 3` / `Phase 4`(除非在"方法论说明"附录讨论研究流程时)
### B. 占位符残留
- `[由 dr-reporter 自动生成]`
- `[待填]` / `[TBD]` / `[TODO]`
- `<slug>` / `<topic>` / `<N>` / `<X>` 等模板占位符
- `{{ ... }}` / `${...}` 变量语法残留
### C. 中间产物引用
- `参考信源:[src_101] [src_120] (详见 sources.jsonl ch02 条目)`
- `详见 phase2/evidence/chXX-evidence.md`
- `详见 sources.jsonl`
- `本章信源索引:...(详见 ...)`
- `⚠️ 待验证` / `⚠️ [待验证]`(这是过程性标注;如必须保留某个"存疑观点"的提示,应改为正式语言如"该数据仅有 X 个来源支持,建议人工核实")
### D. 研究思路泄漏
- `研究思路:`
- `核心研究问题:`
- `初步假设:`
- `预期信源:`
- `预期篇幅:`
这些是 framework.md 里给 dr-analyst 看的规划信息,不能出现在读者版。
### E. Agent 交付汇报语
- `产出:` / `完成后返回:`
- `任务:` / `硬性要求:`
- `必读 skill`
- `章节小结:` (改为自然段落收尾)
---
## 二、格式异常检测
### F. SCQA 显式标注(已禁止的机械模式)
以下组合**不应在最终报告中成对出现**(用 grep 扫):
- `**Situation(背景)**` + `**Complication(张力)**`
- `**S(背景)**` + `**C(挑战)**` + `**Q(问题)**` + `**A(答案)**`
- `Answer-First` 显式标注
- `**核心结论(Answer-First**`
SCQA 要写得隐式融合(见 mckinsey-method skill)。
### G. 三级以上嵌套标题乱用
正文正式章节标题不要超过 3 级:
- `# 第 X 章` (报告级)
- `## X.Y 节` (章内节)
- `### X.Y.Z 小节` (节内小节)
禁止 `####` `#####` `######`。如果需要 4 级以上,重新组织结构。
### H. 引用格式不统一
所有引用统一 `[src_XXX]` 格式(3 位数字)。禁止混用:
- `[src_1]`(没补零)
- `[source_001]`(变形)
- `(src_001)`(圆括号)
- `[ref_1]` / `[r1]`(其他简写)
### I. 中英文标点混用
中文正文里的标点应是**中文标点**:
- `` 不是 `,`
- `。` 不是 `.`
- `` 不是 `;`
- `` 不是 `:`
- `"..."` 不是 `"..."`(除了直接引用英文)
- `...` 不是 `(...)`
例外:行内英文术语、代码、URL、数据单位前后保持英文标点合理。
### J. Emoji(强制禁用)
**正文与表格中严禁使用任何 emoji / 彩色符号**
禁用清单(但不限于):
`✅ ❌ ✔ ✖ 🔶 🔷 ⭐ 🟢 🔴 🟡 🟠 ⚠️ ⚠ 💡 📌 🔑 📊 📈 📉 🔥 ✨ 🎯 🎉 ➔ ➜`
**原因**:PDF 使用的思源字体子集不包含这些字符的 glyph,渲染为空白方框(□)。
**替代写法**
- 表格标记"有/无":用 `✓` `×`(思源字体支持)或中文字 `是` / `否`
- 强调状态:用 `◆` `●` 等几何符号(字体支持)
- 警示:用 `注:` `警告:` `※` 等文字前缀
- 重点:用 **粗体** 或引用块,不用 emoji
扫描命令:
```bash
python3 -c "
import re
txt = open('final_zh_polished.md').read()
pat = re.compile(r'[\u2700-\u27BF]|[\U0001F300-\U0001F9FF]|[\u2B00-\u2BFF]')
hits = [(i, m.group()) for i, m in enumerate(pat.finditer(txt))]
print(f'emoji 命中:{len(hits)} 处')
for i, c in hits[:10]:
print(f' 位置 {i}: {c!r} (U+{ord(c):04X})')
"
```
---
## 三、参考文献完整性校验(最关键)
dr-reporter 出稿前**必须**执行:
```bash
# 1. 从 final.md 提取所有引用的 src_id
grep -oE '\[src_[0-9]+\]' projects/<slug>/phase4/final.md | sort -u > /tmp/cited.txt
# 2. 从 citations.md / sources.jsonl 提取所有已登记的 src_id
grep -oE 'src_[0-9]+' projects/<slug>/phase4/citations.md | sort -u > /tmp/registered.txt
# 或从 sources.jsonl
python3 -c "
import json
with open('projects/<slug>/phase2/sources.jsonl') as f:
for line in f:
d = json.loads(line)
print(d['id'])
" | sort -u > /tmp/registered.txt
# 3. 差集:cited 里有但 registered 里没有 → 严重错误
comm -23 /tmp/cited.txt <(sed 's/[][]//g' /tmp/registered.txt) > /tmp/missing.txt
# 4. 反向差集:registered 有但从未被 cited → 孤立信源,可剔除
comm -13 /tmp/cited.txt <(sed 's/[][]//g' /tmp/registered.txt) > /tmp/orphan.txt
```
### 处理规则
- 有 missing 信源(引用了但无记录)→ **致命错误**dr-reporter 拒绝出稿,抛回上游排查
- 有 orphan 信源(有记录但未被引用)→ 警告,从 citations.md 剔除
- final.md 里的"参考文献"段落**必须包含完整的编号清单**,不能是 `[由 dr-reporter 自动生成]` 之类的占位符
- 如果 final.md 的参考文献段落是占位符 → 读 citations.md 内容回填
---
## 四、标题规范
### 章标题
- 观点型判断句,不是"概述/现状/背景"
- 长度 15-40 字(中)/ 10-25 词(英)
- 不以动词开头(如"分析/探讨/研究"),改为判断句
**反例**
- 第 2 章 分析中国 GLP-1 市场的现状
- 第 3 章 探讨 NEB 产品的竞争优势
**正例**
- 第 2 章 中国 GLP-1 市场 2025 年已跨越 10 亿美元门槛
- 第 3 章 NEB 的 30 年专利丛林将在 2028 年后开始瓦解
### 节标题
- 同样要求观点型
- 长度 10-25 字 / 8-15 词
- 禁止 `2.1 背景 / 2.2 现状 / 2.3 趋势` 这种模板化结构
---
## 五、图表与数据卫生
### 表格
- 表头第一行要有单位(金额 USD / 百分比 % / 年份等)
- 所有数据有来源标注(行内 [src_xxx] 或表脚注)
- 避免超过 10 列宽表(PDF 会被截断)
### 图表标题
格式:`图 X-Y<内容描述>(数据来源:[src_xxx]`
### 数字规范
- 阿拉伯数字 + 中文量词:`12 项研究` / `3.2 亿元`
- 大数字三位分节:`12,000` 而非 `12000`
- 百分比带 `%`,不写"百分之十二"
- 时间范围用连字符:`2020-2025 年` 不是 `2020 至 2025 年`
---
## 六、自动化检查脚本(dr-polisher / dr-reporter 必跑)
```python
# hygiene_check.py
import re, sys
BLACKLIST_ZH = [
"章节定位", "字数配额", "研究员:dr-",
"P0 核心章", "P1 主干章", "P2 辅助章",
"Phase 1", "Phase 2", "Phase 3", "Phase 4",
"dr-plan", "dr-pm", "dr-analyst", "dr-verifier",
"dr-chief-editor", "dr-editor-in-chief", "dr-polisher",
"dr-reporter", "dr-translator",
"[由 dr-reporter 自动生成]", "[待填]", "[TBD]", "[TODO]",
"详见 phase2/", "详见 sources.jsonl",
"本章信源索引", "⚠️ 待验证", "⚠️ [待验证]",
"**Situation(背景)**", "**Complication(张力)**",
"**Question(问题)**", "**Answer(答案)**",
"**S(背景)**", "**C(挑战)**",
"Answer-First", "核心结论(Answer-First",
"研究思路:", "核心研究问题:", "初步假设:",
"预期信源:", "预期篇幅:",
"硬性要求:", "必读 skill", "产出:",
]
path = sys.argv[1]
text = open(path, encoding='utf-8').read()
issues = []
for pattern in BLACKLIST_ZH:
if pattern in text:
count = text.count(pattern)
issues.append(f" × '{pattern}' 出现 {count} 次")
if issues:
print(f"{path} 存在 {len(issues)} 项卫生问题:")
for i in issues:
print(i)
sys.exit(1)
else:
print(f"{path} 输出卫生检查通过")
sys.exit(0)
```
---
## 七、硬规则
1. ✅ dr-polisher 润色的最后一步跑 hygiene_check
2. ✅ dr-reporter 出稿前再跑一次 hygiene_check + 参考文献完整性校验
3. ✅ 任何禁止词残留都必须修正,不能"放过一马"
4. ✅ 参考文献段落必须包含完整编号清单,不允许占位符
5. ❌ 禁止把"⚠️ 待验证"这种过程标注留到读者版
6. ❌ 禁止三级以上嵌套标题