From 77df1838b1b6982bacb99f9636d07cdf52952191 Mon Sep 17 00:00:00 2001 From: kai Date: Fri, 24 Apr 2026 10:48:14 +0800 Subject: [PATCH] v0.10: add native Codex adapter for deep research --- .agents/skills/citation-manager/SKILL.md | 166 ++++++++ .agents/skills/en-zh-translation/SKILL.md | 267 +++++++++++++ .agents/skills/evidence-table/SKILL.md | 157 ++++++++ .agents/skills/humanizer-cn/SKILL.md | 356 ++++++++++++++++++ .agents/skills/length-budget/SKILL.md | 172 +++++++++ .agents/skills/mckinsey-method/SKILL.md | 177 +++++++++ .agents/skills/output-hygiene/SKILL.md | 266 +++++++++++++ .agents/skills/pdf-reportlab/SKILL.md | 303 +++++++++++++++ .agents/skills/search-strategy/SKILL.md | 246 ++++++++++++ .agents/skills/source-quality/SKILL.md | 188 +++++++++ .codex/agents/dr-analyst.toml | 19 + .codex/agents/dr-chief-editor.toml | 15 + .codex/agents/dr-editor-in-chief.toml | 15 + .codex/agents/dr-plan.toml | 18 + .codex/agents/dr-pm.toml | 18 + .codex/agents/dr-reporter.toml | 14 + .codex/agents/dr-searcher.toml | 14 + .codex/agents/dr-verifier.toml | 15 + .codex/commands/dr-finalize.md | 25 ++ .codex/commands/dr-frame.md | 17 + .codex/commands/dr-glossary.md | 26 ++ .codex/commands/dr-init.md | 14 + .codex/commands/dr-research.md | 18 + .codex/commands/dr-review.md | 14 + .codex/commands/dr-status.md | 9 + .codex/config.toml | 61 +++ PLAN.md | 23 +- README.md | 10 +- .../codex/agents/dr-analyst.toml | 19 + .../codex/agents/dr-chief-editor.toml | 15 + .../codex/agents/dr-editor-in-chief.toml | 15 + .../codex/agents/dr-plan.toml | 18 + .../codex/agents/dr-pm.toml | 18 + .../codex/agents/dr-reporter.toml | 14 + .../codex/agents/dr-searcher.toml | 14 + .../codex/agents/dr-verifier.toml | 15 + .../codex/commands/dr-finalize.md | 25 ++ .../codex/commands/dr-frame.md | 17 + .../codex/commands/dr-glossary.md | 26 ++ .../codex/commands/dr-init.md | 14 + .../codex/commands/dr-research.md | 18 + .../codex/commands/dr-review.md | 14 + .../codex/commands/dr-status.md | 9 + codex_adapter_templates/codex/config.toml | 61 +++ configs/model_profiles.yaml | 18 + docs/codex-usage.md | 128 ++++--- scripts/dr.py | 238 ++++++++++++ scripts/install_codex_adapter.py | 63 ++++ 48 files changed, 3354 insertions(+), 48 deletions(-) create mode 100644 .agents/skills/citation-manager/SKILL.md create mode 100644 .agents/skills/en-zh-translation/SKILL.md create mode 100644 .agents/skills/evidence-table/SKILL.md create mode 100644 .agents/skills/humanizer-cn/SKILL.md create mode 100644 .agents/skills/length-budget/SKILL.md create mode 100644 .agents/skills/mckinsey-method/SKILL.md create mode 100644 .agents/skills/output-hygiene/SKILL.md create mode 100644 .agents/skills/pdf-reportlab/SKILL.md create mode 100644 .agents/skills/search-strategy/SKILL.md create mode 100644 .agents/skills/source-quality/SKILL.md create mode 100644 .codex/agents/dr-analyst.toml create mode 100644 .codex/agents/dr-chief-editor.toml create mode 100644 .codex/agents/dr-editor-in-chief.toml create mode 100644 .codex/agents/dr-plan.toml create mode 100644 .codex/agents/dr-pm.toml create mode 100644 .codex/agents/dr-reporter.toml create mode 100644 .codex/agents/dr-searcher.toml create mode 100644 .codex/agents/dr-verifier.toml create mode 100644 .codex/commands/dr-finalize.md create mode 100644 .codex/commands/dr-frame.md create mode 100644 .codex/commands/dr-glossary.md create mode 100644 .codex/commands/dr-init.md create mode 100644 .codex/commands/dr-research.md create mode 100644 .codex/commands/dr-review.md create mode 100644 .codex/commands/dr-status.md create mode 100644 .codex/config.toml create mode 100644 codex_adapter_templates/codex/agents/dr-analyst.toml create mode 100644 codex_adapter_templates/codex/agents/dr-chief-editor.toml create mode 100644 codex_adapter_templates/codex/agents/dr-editor-in-chief.toml create mode 100644 codex_adapter_templates/codex/agents/dr-plan.toml create mode 100644 codex_adapter_templates/codex/agents/dr-pm.toml create mode 100644 codex_adapter_templates/codex/agents/dr-reporter.toml create mode 100644 codex_adapter_templates/codex/agents/dr-searcher.toml create mode 100644 codex_adapter_templates/codex/agents/dr-verifier.toml create mode 100644 codex_adapter_templates/codex/commands/dr-finalize.md create mode 100644 codex_adapter_templates/codex/commands/dr-frame.md create mode 100644 codex_adapter_templates/codex/commands/dr-glossary.md create mode 100644 codex_adapter_templates/codex/commands/dr-init.md create mode 100644 codex_adapter_templates/codex/commands/dr-research.md create mode 100644 codex_adapter_templates/codex/commands/dr-review.md create mode 100644 codex_adapter_templates/codex/commands/dr-status.md create mode 100644 codex_adapter_templates/codex/config.toml create mode 100644 scripts/dr.py create mode 100644 scripts/install_codex_adapter.py diff --git a/.agents/skills/citation-manager/SKILL.md b/.agents/skills/citation-manager/SKILL.md new file mode 100644 index 0000000..05c8008 --- /dev/null +++ b/.agents/skills/citation-manager/SKILL.md @@ -0,0 +1,166 @@ +--- +name: citation-manager +description: 引用管理规范。规定 [src_xxx] 编号体系、sources.jsonl 字段标准、跨章节去重规则、参考文献列表生成格式(GB/T 7714)。 +--- + +# 引用管理规范 + +## 一、src_id 编号规则 + +### 全局唯一编号 + +`src_id` 在整个项目内**全局唯一**,格式:`src_XXX`(3 位数字,不足补零)。 + +- 由 dr-analyst 在首次引用时分配 +- 按发现顺序递增:`src_001`, `src_002`, ... +- 跨章节引用同一来源时,使用**相同 ID** + +### 分配流程 + +1. dr-analyst 发现一条新信源 +2. 读取 `projects//phase2/sources.jsonl`,找当前最大 ID +3. 分配下一个 ID(如当前最大为 `src_023`,下一个为 `src_024`) +4. 写入 sources.jsonl + +### 草稿中的引用格式 + +行内引用:`数据或观点 [src_042]` + +多来源:`数据或观点 [src_042][src_058]` + +--- + +## 二、sources.jsonl 字段标准 + +每行一个 JSON 对象(JSONL 格式): + +```jsonl +{ + "id": "src_001", + "tier": 1, + "score": 8.5, + "type": "journal", + "title": "论文标题", + "authors": ["Zhang S", "Li M"], + "year": 2024, + "venue": "Nature Medicine", + "impact_factor": 58.7, + "url": "https://doi.org/10.1038/...", + "doi": "10.1038/...", + "accessed_at": "2026-04-20", + "abstract": "2-3句摘要", + "key_data": { + "sample_size": 1200, + "primary_endpoint": "OS 改善 23%" + }, + "used_in": ["ch02", "ch05.sec3"], + "conflict_of_interest": null, + "notes": "RCT 主要终点数据在 Table 2" +} +``` + +### type 字段枚举值 + +| 值 | 含义 | +|---|---| +| `journal` | 期刊论文(含综述) | +| `trial` | 临床试验(ClinicalTrials.gov 注册信息) | +| `regulatory` | 监管机构公告/审批文件 | +| `patent` | 专利文件 | +| `report` | 咨询/行业报告 | +| `disclosure` | 上市公司披露(年报/招股书/SEC)| +| `preprint` | 预印本(bioRxiv/medRxiv)| +| `news` | 专业媒体报道(Tier 3 用) | + +### 必填字段 + +`id`, `tier`, `score`, `type`, `title`, `year`, `url`(或 `doi`) + +--- + +## 三、去重规则 + +dr-pm 在 Phase 2 结束时执行去重: + +```python +# 伪代码 +seen_urls = {} +seen_dois = {} +unique_sources = [] + +for source in all_sources: + key = source.get("doi") or source.get("url") + if key not in seen_urls: + seen_urls[key] = True + unique_sources.append(source) + else: + # 合并 used_in 字段 + existing = seen_urls[key] + existing["used_in"] = list(set(existing["used_in"] + source["used_in"])) +``` + +去重后,草稿文件里的 [src_xxx] 标注**不需要更改**,因为 ID 是全局分配的。 + +--- + +## 四、参考文献列表生成(GB/T 7714-2015) + +dr-reporter 从 sources.jsonl 生成参考文献列表时,按以下格式: + +### 期刊论文 +``` +[src_001] ZHANG S, LI M. 论文标题[J]. Nature Medicine, 2024, 30(5): 1234-1245. DOI: 10.1038/... +``` + +### 报告/白皮书 +``` +[src_042] McKinsey & Company. 报告标题[R]. McKinsey Global Institute, 2024. +``` + +### 监管文件 +``` +[src_018] FDA. NDA 申请审批公告[EB/OL]. (2024-03-15)[2026-04-20]. https://www.fda.gov/... +``` + +### 临床试验 +``` +[src_055] ClinicalTrials.gov. 试验名称 (NCT12345678)[EB/OL]. (2023-01-01)[2026-04-20]. https://clinicaltrials.gov/... +``` + +### 专利 +``` +[src_067] 发明人. 专利名称[P]. 专利号, 申请日. +``` + +### 排序规则 + +参考文献按在正文中**首次出现的顺序**排列,即 [src_001] 在最前,以此类推。 + +--- + +## 五、引用完整性检查(dr-chief-editor 用) + +审校时检查: +1. 正文中所有 [src_xxx] 都在 sources.jsonl 里有对应记录 +2. sources.jsonl 里所有 ID 在正文中都有引用(无孤立信源) +3. 所有 Tier 1 信源的 URL 或 DOI 格式正确 + +检查脚本(可用 bash 执行): +```bash +# 提取正文中的所有 src_id +grep -oE 'src_[0-9]+' projects//phase4/final.md | sort -u > /tmp/cited.txt + +# 提取 sources.jsonl 中的所有 id +python3 -c " +import json +ids = [] +with open('projects//phase2/sources.jsonl') as f: + for line in f: + d = json.loads(line) + ids.append(d['id']) +print('\n'.join(sorted(ids))) +" > /tmp/registered.txt + +# 找差集 +diff /tmp/cited.txt /tmp/registered.txt +``` diff --git a/.agents/skills/en-zh-translation/SKILL.md b/.agents/skills/en-zh-translation/SKILL.md new file mode 100644 index 0000000..b392733 --- /dev/null +++ b/.agents/skills/en-zh-translation/SKILL.md @@ -0,0 +1,267 @@ +--- +name: en-zh-translation +description: 生物医药英译中规范。专有名词双语对照策略、术语表管理、断句重构原则、数字与标点转换、去翻译腔。dr-translator 必读。 +--- + +# 英译中规范(生物医药专业报告) + +## 你的身份 + +你是生物医药专业报告的翻译编辑,不是机器翻译。目标:译文读起来**像母语中文写作者的原创**,不是"翻译腔"。 + +--- + +## 一、整体原则 + +### 1. 忠实于内容,不忠实于句式 + +英文长句拆成中文短句。英文习惯的 "X, which is Y, was Z" 嵌套结构,中文应断为两到三句。 + +**反例(翻译腔)**: +> 这种药物,它是 GLP-1 受体激动剂家族中的一员,被证明在降低 HbA1c 方面是有效的。 + +**改写**: +> 这种药物属于 GLP-1 受体激动剂家族,能有效降低 HbA1c。 + +### 2. 不保留英文的被动语态 + +英文被动 → 中文主动(或不提主语)。 + +- "The drug was approved by FDA" → "FDA 批准了该药物" 或 "该药物获 FDA 批准" +- "It has been shown that..." → 直接说"研究显示..."或"数据显示..." + +### 3. 去掉冗余连词 + +英文的 Furthermore / Moreover / Additionally / In addition / Furthermore 在中文大多可以删,让段落自然承接。 + +--- + +## 二、专有名词双语对照策略 + +### 首次出现原则 + +专有名词**首次出现**时用"中文(英文)"格式,之后只用中文或英文单独一致使用: + +- 首次:`糖苷水解酶 101 家族(GH101 family)` +- 之后:`GH101 家族` 或 `糖苷水解酶 101 家族`(选一种风格用到底) + +### 行业惯例优先 + +以下术语在行业中**中英混用是标准做法**,不要强制翻译: + +- 直接保留英文:FDA, EMA, NMPA, FEV1, BEC, sST2, CAT, SGRQ, BLA, NDA, IND, ICH, CMC, CDMO, CDMO, GH101, IgG, mAb, ADC, BsAb, GLP-1, PD-1, CAR-T, HbA1c, IL-4, IL-5, IL-13, IL-33, ST2, Th2, ILC2s +- 中英并列的术语:抗体偶联药物(ADC)、单克隆抗体(mAb)、慢性阻塞性肺疾病(COPD) + +### 动词/形容词类翻译 + +这类不保留英文: + +| 英文 | 中文 | +|---|---| +| significant | 显著(需跟数据)| +| substantial | 大幅 | +| demonstrate | 表明 / 显示 | +| exhibit | 表现出 | +| propose | 提出 | +| investigate | 研究 | +| establish | 建立 / 确立 | +| confirm | 证实 | +| underscore | (直接删,见 humanizer-cn) | +| highlight | (直接删或改为"指出") | + +--- + +## 三、数字与单位转换 + +### 数字表达 + +- 英文 "12,000" → 中文 "12,000"(保留千分位逗号) +- 英文 "1.2 billion USD" → 中文 "12 亿美元" +- 英文 "3.5 million patients" → 中文 "350 万名患者" +- 英文 "23%" → 中文 "23%" + +### 量词 + +数字后面中文要加量词: + +| 英文 | 中文 | +|---|---| +| 12 studies | 12 项研究 | +| 3 companies | 3 家公司 | +| 5 patents | 5 项专利 | +| 20 patients | 20 名患者 | +| 1.2 billion | 12 亿 | +| 3 years | 3 年 | +| 6 months | 6 个月 | + +### 时间格式 + +- "2024" → "2024 年" +- "2020-2025" → "2020-2025 年"(用半角连字符) +- "Q4 2025" → "2025 年第 4 季度" 或 "2025 Q4" +- "March 2024" → "2024 年 3 月" + +### 百分比 + +- "30%" → "30%" +- "up to 60%" → "最高 60%" +- "approximately 40%" → "约 40%" + +--- + +## 四、标点转换 + +### 必须转为中文标点的情况 + +中文段落中,句内标点必须是**中文全角标点**: + +| 英文 | 中文 | +|---|---| +| `,` | `,` | +| `.` | `。` | +| `;` | `;` | +| `:` | `:` | +| `?` | `?` | +| `!` | `!` | +| `"..."` | `"..."` | +| `'...'` | `'...'` | +| `(...)` | `(...)` | +| `—` | `——`(中文全角破折号是两个连一起)| +| `...` | `……`(中文省略号六个点)| + +### 保留英文标点的情况 + +- 英文术语、代码、URL 内部的标点 +- 行内引用的英文原文 +- 数据单位前后:`3.2 mg/kg`(数字和单位之间用英文斜杠) + +--- + +## 五、句子结构重构 + +### 英文长句→中文短句 + +**原文**: +> The observation that sST2 levels, which have been validated as a prognostic biomarker in heart failure and included in ACC/AHA guidelines, are elevated in COPD patients during acute exacerbations suggests a potential cross-disease mechanism. + +**烂翻译**: +> sST2 水平(它已被验证为心力衰竭的预后生物标志物并被纳入 ACC/AHA 指南)在 COPD 患者急性加重期间升高的观察结果,提示了潜在的跨疾病机制。 + +**好翻译**: +> sST2 已是心力衰竭领域的预后生物标志物,纳入 ACC/AHA 指南多年。COPD 患者在急性加重期间 sST2 水平升高,提示这两类疾病可能共享同一条炎症通路。 + +### 修饰语位置 + +英文习惯把修饰语放后面(of / which / that 从句),中文要前置或拆句。 + +- "the company that pioneered O-glycosidase commercialization in 1990" → "1990 年率先实现 O-糖苷酶商业化的那家公司"(前置) +- 或拆句:"NEB 公司在 1990 年率先将 O-糖苷酶商业化" + +--- + +## 六、段落重构 + +### 英文段落首句原则 + +英文学术/商业写作的段落一般首句即论点(Topic sentence),后面是论据。翻译时保留这一结构,不要打乱。 + +### 段落长度调整 + +- 英文习惯长段(150-200 词 / ≈ 250-330 字) +- 中文如果一段超过 400 字,读起来累。超过 400 字应考虑拆段。 +- 拆段原则:按子论点拆,不要机械按句数拆 + +--- + +## 七、翻译后校对清单 + +译完后自己过三遍: + +### 第 1 遍:准确性 + +- 所有数字、日期、百分比、来源 ID `[src_xxx]` 完全一致? +- 所有专有名词首次出现有中英对照? +- 没有错译、漏译? + +### 第 2 遍:流畅性 + +- 有没有"的"字过多?(`X 的 Y 的 Z 的 W` 这种链式改为"X 下的 Y 中的 Z") +- 有没有翻译腔?("...的话"、"...的话说"、"对于...来说"、"在...方面") +- 句子长度是否有节奏变化?全长句或全短句都不行 +- 读一遍念出来,是否自然? + +### 第 3 遍:humanizer-cn 禁用词 + +加载 `skill:humanizer-cn`,扫一遍中文禁用词清单: +- 跃迁 / 赋能 / 落地 / 格局 / 生态 / 痛点 / 风口 / 闭环 / 抓手 / 颠覆 / 引领 / 重塑 / 赛道 / 范式 / 底层逻辑 / 本质上 / 从根本上 +- AI 套话:随着、不断、深入、值得注意、不难发现、具有重要意义、综上所述、由此可见 + +--- + +## 八、特殊情况处理 + +### 原文是咨询报告风格 + +保留咨询报告的语感:观点前置、数字支撑、对比结构。不要为了"接地气"而口语化。 + +### 原文包含表格 + +表格翻译时: +- 表头翻译 +- 单元格数字保留原格式 +- 专有名词保留英文(节省宽度) +- 表格标题用 `表 X-Y:<内容>(数据来源:[src_xxx])` + +### 原文包含图表 + +图表标题和说明翻译;图表本身(如果是 matplotlib 生成的 PNG)可能需要 dr-reporter 用中文字体重新生成。 + +### 原文包含 SCQA 式段落(如 Executive Summary) + +SCQA 结构保留(因为这是麦肯锡式叙事),但不要标注 "S/C/Q/A"字样,按 `mckinsey-method skill` 要求写成融合式。 + +--- + +## 九、术语表维护 + +dr-translator 在翻译过程中维护项目级术语表: + +``` +projects//phase4/glossary.json +{ + "GH101 family": "糖苷水解酶 101 家族", + "endoglycosidase": "内切糖苷酶", + "O-glycosylation": "O-糖基化", + "Core 1": "核心 1 型", + ... +} +``` + +这个术语表会作为 final report 里的"术语表(Glossary)"章节,双语对照呈现。 + +--- + +## 十、输出要求 + +### 文件命名 + +- 英文稿:`projects//phase4/final_en.md` +- 中文稿:`projects//phase4/final_zh.md`(dr-translator 产出) +- 中文稿润色后:仍然 `final_zh.md`(dr-polisher 原地修改) +- PDF 主稿:`final.pdf`(中文) +- PDF 英文参考版:`final_en.pdf` +- DOCX 主稿:`final.docx`(中文) + +### 交付汇报 + +翻译完成后向调用者返回: + +``` +翻译完成 +英文源:projects//phase4/final_en.md (X words) +中文译:projects//phase4/final_zh.md (X 字) +膨胀率:X%(预期 1.4 倍) +术语表:projects//phase4/glossary.json (X 条) +翻译质检:humanizer-cn 禁用词 X 项(已清理) +下一步:等待 dr-polisher 做最终润色 +``` diff --git a/.agents/skills/evidence-table/SKILL.md b/.agents/skills/evidence-table/SKILL.md new file mode 100644 index 0000000..9661ed9 --- /dev/null +++ b/.agents/skills/evidence-table/SKILL.md @@ -0,0 +1,157 @@ +--- +name: evidence-table +description: 证据矩阵规范。规定每条核心结论必须有对应的证据记录,格式、字段、置信度分级和文件结构。dr-analyst 撰写初稿时使用,dr-verifier 追加反方证据时使用,dr-chief-editor 审校时作为核验基准。 +--- + +# 证据矩阵规范 + +## 核心原则 + +**每条结论必须可追溯**。报告中每一个有 [src_xxx] 标注的观点,都必须在对应章节的 evidence 文件中有一行记录。 + +--- + +## 证据矩阵文件格式 + +文件路径:`projects//phase2/evidence/chXX-evidence.md` + +### 文件结构 + +```markdown +# 第 X 章 <标题> — 证据矩阵 + +生成时间: +研究员:dr-analyst +字数统计: 字 / 配额 字 + +--- + +## 核心结论证据表 + +| 结论 ID | 观点摘要(≤30字) | 支持证据 1 | 支持证据 2 | 置信度 | 备注 | +|---|---|---|---|---|---| +| C01 | <观点> | [src_001] <标题> Tier1 | [src_002] <标题> Tier2 | 高 | | +| C02 | <观点> | [src_003] <标题> Tier2 | **[待验证]** 仅 1 个来源 | 中 | 需补充 | +| C03 | <观点> | [src_004] <标题> Tier1 | [src_005] <标题> Tier1 | 高 | | + +--- + +## 置信度说明 + +- **高**:2 个以上独立 Tier 1-2 信源支持,无重大反方证据 +- **中**:只有 1 个 Tier 1-2 信源,或有轻微反方证据 +- **低**:仅 Tier 3 信源,或有实质性反方证据 +- **[待验证]**:找不到第 2 个独立信源,在正文明确标注 + +--- + +## 信源详情 + + + +**[src_001]** +- 标题: +- 作者/机构: +- 年份: +- URL/DOI: +- Tier:1 +- 评分:8.5 +- 摘要(2-3句): + +**[src_002]** +... + +--- + +## 反方证据(dr-verifier 填写) + + + +### 验证摘要 +- 核验结论数:X +- 发现反方证据:X 条 +- 补足待验证:X 条 +- 重大挑战:X 条 + +### 反方证据详情 + +#### 针对结论 C01:<观点摘要> +- 反方证据:<内容> +- 来源:[src_xxx] | Tier X +- 处理建议:保留并注明争议 / 修改措辞 / 删除 + + +CRITICAL: <说明> +``` + +--- + +## 正文中反方证据段落的写作规范(v0.8 新) + +### 标题必须观点化,不能叫 "反驳证据 / Counter-Evidence" + +**问题诊断**:v0.7 发现每章末尾 dr-analyst 会机械地写 `## 反驳证据`,标题重复而空洞,读者看了没有信息增益。 + +**新规则**:正文反方证据段落的标题必须: + +1. **用二级 H2 或三级 H3 标题**(统一层级,禁止用加粗段冒充标题) +2. **包含具体判断**,不要用"反驳证据" / "反方证据" / "Counter-Evidence" 这种模板化命名 +3. 至少要回答:**"对前述论点的哪一方面提出了什么挑战?"** + +### 可接受的命名示例 + +| ✗ 不推荐 | ✓ 推荐 | +|---|---| +| 反驳证据 | 另一种声音:管线虚胖还是真实进展? | +| Counter-Evidence | 需要补充判断的副作用:汇聚偶联收率可能被高估 | +| 反方观点 | 反例:Codexis ECO 并非所有情境都优于 SPOS | +| Counter Arguments | 值得警惕的数据:临床前到 IND 的衰减率 | + +### 段落结构模板(推荐) + +```markdown +## <观点化标题> + +虽然上文论证了 <核心观点>,但以下证据提示需要**有限度地**接受这一判断: + +1. **<反方论点 1>**:<具体数据或案例> [src_xxx]。影响评估:<说明> +2. **<反方论点 2>**:<具体数据或案例> [src_xxx]。影响评估:<说明> + +综合而言,核心结论仍成立,但需在 <某个具体维度> 上留出缓冲。 +``` + +### 禁止的写法 + +- 单独用 **加粗段** 冒充反方证据标题(`**反方证据:** ...`) +- 反方证据后不做整合判断,只是堆数据 +- 在每个小节末尾都加反方证据(只在章末加一次即可;若小节级别有重大挑战,写在小节正文里即可) + +--- + +## 置信度分级标准 + +| 置信度 | 条件 | 正文处理方式 | +|---|---|---| +| 高 | ≥2 个独立 Tier 1-2 信源,无 CRITICAL 反方 | 直接陈述 | +| 中 | 1 个 Tier 1-2 信源,或有轻微反方 | 陈述 + "但部分研究认为..." | +| 低 | 仅 Tier 3,或有实质反方 | 必须加 "[待验证]" 标注 | +| [待验证] | 无法找到第 2 个独立来源 | 正文明确写 "该观点仅有 1 个来源支持,待验证" | + +--- + +## 结论 ID 命名规则 + +- `C01`-`C99`:正向核心结论 +- `F01`-`F09`:事实性陈述(不需要观点判断) +- `T01`-`T09`:趋势判断(通常需要时间序列数据支撑) + +dr-analyst 在撰写草稿时,给每个有 [src_xxx] 的观点分配一个 ID,在草稿和 evidence 文件里保持一致。 + +--- + +## 硬性规则 + +1. 草稿中每个 [src_xxx] 必须在 evidence 文件里有对应行 +2. 草稿中标注 `[待验证]` 的观点必须在 evidence 表里有对应行(置信度列写"低/待验证") +3. dr-verifier 只能在"反方证据"段落追加,不能修改"核心结论证据表" +4. CRITICAL 标注的问题,dr-chief-editor 审校时必须明确处理(不能忽略) diff --git a/.agents/skills/humanizer-cn/SKILL.md b/.agents/skills/humanizer-cn/SKILL.md new file mode 100644 index 0000000..55fd21f --- /dev/null +++ b/.agents/skills/humanizer-cn/SKILL.md @@ -0,0 +1,356 @@ +--- +name: humanizer-cn +description: 去除 AI 味的中英双语写作规则。基于 Wikipedia Signs of AI Writing + blader/humanizer + 生物医药中文报告特化经验。dr-polisher 必读;dr-editor-in-chief 和 dr-translator 也应遵循。 +--- + +# Humanizer(中英双语去 AI 味规范) + +## 你的任务 + +拿到文稿后,**按以下流程处理**: + +1. **扫描**全文,识别所有 AI 模式(下述 28 条) +2. **重写**问题段落,保留原意,换掉 AI-ism +3. **注入人味**:不只是删除坏模式,要加入真正的个性 +4. **做最后一遍自问**:问自己"这段里还有什么显得是 AI 写的?"逐条修正 + +--- + +## 核心原则 + +> **避免 AI 模式只是一半工作。没有灵魂的干净文字和 slop 一样明显。好的写作背后有真人。** + +--- + +## 英文规则(Phase 2/3 工作语言) + +### 1. 过度渲染"意义/遗产/更宏大趋势" + +**禁用词**:stands/serves as, is a testament/reminder, pivotal/crucial/key moment, underscores importance, reflects broader, symbolizing enduring, contributing to, setting the stage for, marking a shift, key turning point, evolving landscape + +**反例**: +> The Institute was established in 1989, marking a pivotal moment in the evolution of regional statistics and reflecting broader decentralization trends. + +**改写**: +> The Institute was established in 1989 to collect regional statistics independently from the national office. + +### 2. 空泛归因 / Weasel Words + +**禁用词**:Industry reports suggest, Observers have cited, Experts argue, Some critics argue, several sources, It has been noted + +**反例**: +> Experts believe this river plays a crucial role in the regional ecosystem. + +**改写**: +> A 2019 survey by the Chinese Academy of Sciences found that this river supports 12 endemic fish species. + +### 3. -ing 短语堆砌(伪深度) + +**禁用模式**:highlighting/underscoring/emphasizing/ensuring/reflecting/contributing to/cultivating/fostering/encompassing/showcasing + +**反例**: +> The architect chose blue, green, and gold, symbolizing Texas bluebonnets, reflecting the community's deep connection to the land. + +**改写**: +> The architect chose blue, green, and gold to reference local bluebonnets and the Gulf coast. + +### 4. 高频 AI 词汇 + +**禁用**:Actually, additionally, align with, crucial, delve, emphasizing, enduring, enhance, fostering, garner, highlight (v), interplay, intricate, key (adj), landscape (abstract), pivotal, showcase, tapestry, testament, underscore, valuable, vibrant + +### 5. 规避 "is/are"(Copula Avoidance) + +**禁用模式**:X serves as Y / X stands as Y / X marks Y / X represents Y / X boasts / X features / X offers + +**反例**: +> Gallery 825 serves as LAAA's exhibition space and boasts over 3,000 square feet. + +**改写**: +> Gallery 825 is LAAA's exhibition space, with 3,000 square feet. + +### 6. 负向平行(Negative Parallelism) + +**禁用**:It's not just X, it's Y / Not only X but Y / more than just + +### 7. 三段式(Rule of Three) + +不为凑数拼三项。"The event features keynote sessions, panel discussions, and networking opportunities" → "The event includes talks and panels with informal networking between sessions." + +### 8. 同义词循环(Elegant Variation) + +避免在连续句子里对同一概念使用"the protagonist / the main character / the central figure / the hero"。一个叫法用到底即可。 + +### 9. 伪范围(False Ranges) + +**禁用**:from X to Y 当 X 和 Y 不在同一量纲上。 + +"Our journey has taken us from the Big Bang to the cosmic web, from star formation to dark matter" → "The book covers the Big Bang, star formation, and dark matter." + +### 10. 被动/无主语片段 + +"No configuration file needed" → "You do not need a configuration file." +"The results are preserved automatically" → "The system preserves the results automatically." + +### 11. 破折号过度使用 + +长破折号每章不超过 3 处。绝大多数情况下可以用逗号、句号或括号改写。 + +### 12. 内联粗体列表(Inline-header bullets) + +**反例**: +- **Speed:** Code generation is significantly faster. +- **Quality:** Output quality has been enhanced. +- **Adoption:** Usage continues to grow. + +**改写为段落**: +> The tool speeds up code generation substantially and improves output through better training. Adoption has grown alongside these improvements. + +### 13. 标题 Title Case + +**禁用**:## Strategic Negotiations And Global Partnerships +**改为**:## Strategic negotiations and global partnerships + +### 14. Emoji 装饰 + +禁止在标题、段落开头用 emoji(🚀 💡 ✅)。 + +### 15. Curly Quotes + +"这种引号" 改为普通 "straight quotes"。 + +### 16. Chatbot 残留 + +**禁用**:I hope this helps, Of course!, Certainly!, You're absolutely right!, Would you like..., Let me know, Here is a..., Great question! + +### 17. 知识截止声明 + +**禁用**:as of [date], up to my last training update, While specific details are limited, based on available information + +### 18. 谄媚语气 + +**禁用**:Great question! You're absolutely right! That's an excellent point. + +### 19. Filler 短语 + +| 禁用 | 改为 | +|---|---| +| In order to achieve this goal | To achieve this | +| Due to the fact that | Because | +| At this point in time | Now | +| In the event that | If | +| Has the ability to | Can | +| It is important to note that | (直接删) | + +### 20. 过度 Hedging + +"It could potentially possibly be argued that..." → "The policy may..." + +### 21. 通用正向总结 + +**禁用**:The future looks bright. Exciting times lie ahead. A major step in the right direction. + +**改为**:具体说清楚下一步做什么。 + +### 22. 连字符成对词过多 + +AI 对常用词对几乎 100% 加连字符(third-party, cross-functional, data-driven, decision-making, well-known, high-quality, real-time, long-term, end-to-end)。人类用得不那么整齐。选择性去掉连字符。 + +### 23. 权威套话 + +**禁用**:The real question is, at its core, in reality, what really matters, fundamentally, the deeper issue, the heart of the matter + +这些都是 AI 假装切穿表象直达真相的套路,删掉后真相还是在那里。 + +### 24. Signposting 预告 + +**禁用**:Let's dive in, let's explore, let's break this down, here's what you need to know, without further ado + +直接进入内容,不要预告。 + +### 25. 标题后重复一遍标题内容 + +``` +## Performance +Speed matters. +When users hit a slow page, they leave. +``` + +删掉 "Speed matters"。 + +### 26. 过度 boldface + +不要在每一句里加粗 **这个** 和 **那个**。一段里粗体超过 2 处,说明你没认真思考该强调什么。 + +--- + +## 中文规则(Phase 4 翻译后适用) + +中文有一套自己的 AI 味。以下是核心禁用清单。 + +### CN-1:AI 高频词(见到即替换) + +| 禁用词 | 替换策略 | +|---|---| +| 跃迁 / 跃升 / 跃上 | 改为"升至 / 提升到" | +| 赋能 | 改为"帮助 / 支持 / 推动" | +| 落地 | 改为"实施 / 推行 / 执行" | +| 格局 | 具体说清楚是"竞争格局"还是"市场格局" | +| 生态 / 生态圈 | 少用,具体说"上下游企业" | +| 深度 / 深度的 | 少用,改为具体描述 | +| 痛点 | 改为"问题 / 困难" | +| 风口 | 直接说"市场机会" | +| 闭环 / 打通闭环 | 改为"完成了完整流程" | +| 抓手 | 删掉,直接说动作 | +| 颠覆 / 颠覆性 | 少用,过度戏剧化 | +| 引领 / 引领性 | 改为具体的"率先做了..." | +| 重塑 / 重构 | 改为"改变 / 改组" | +| 赛道 | 改为"细分领域 / 市场" | +| 范式 | 改为"方式 / 模式" | +| 底层逻辑 | 改为"根本原因 / 核心机制" | +| 本质上 / 从根本上 | 直接删除,讲具体内容 | + +### CN-2:AI 套话(整句清除) + +**禁用**: +- "随着 X 的不断发展" +- "在 X 背景下 / 在这一背景下" +- "值得注意的是" +- "不难发现" +- "显而易见" +- "毫无疑问" +- "具有重要意义" +- "发挥了重要作用" +- "起到了 X 的作用" +- "综上所述" +- "由此可见" +- "总的来说" +- "据报道" +- "有研究表明 / 有专家认为"(除非说出具体是哪项研究/哪位专家) + +### CN-3:规避"是"的冗余句式(AI 极高频) + +| 禁用 | 改为 | +|---|---| +| X 标志着 Y | X 是 Y / 从此 Y 成立 | +| X 代表着 Y | X 是 Y | +| X 构成 Y | X 是 Y | +| X 成为 Y | 直接用 "X 是 Y" | +| X 跃升为 Y | X 升到 Y | +| X 彰显着 Y | X 说明 Y | +| X 体现了 Y | X 说明 Y / X 显示 Y | + +### CN-4:三段式堆砌(Rule of Three) + +中文 AI 特别爱拼三段: +- "短期、中期、长期" +- "需求侧、供给侧、政策侧" +- "技术、资本、市场" +- "硬实力、软实力、巧实力" + +不为凑数拼三段。如果只有两个要点就说两个,四个就说四个,节奏自然一些。 + +### CN-5:空洞形容词(必须跟数据) + +- 巨大 → "250 亿美元" +- 快速 → "CAGR 23%" +- 显著 → "降低 40%(p<0.001)" +- 强劲 → "增速高于同行 8 个百分点" +- 显著领先 → "领先第二名 30% 市场份额" + +无数据形容词直接删。 + +### CN-6:破折号规范 + +- 中文用全角破折号 `——`(两个连接起来) +- 每章不超过 3 处 +- 多数情况可改为逗号、括号、句号 + +### CN-7:负向平行 + +**禁用**: +- "不仅...更..." +- "不仅仅是...,更是..." +- "不是...而是..." +- "不只是...,还是..." + +偶用可以,成段出现必改。 + +### CN-8:过度书面腔 / 翻译腔 + +- "使...得以..." → "让 X 能 Y" +- "通过...方式 / 通过...的方式" → "用 X / 以 X" +- "对于 X 而言" → "X 的..." +- "在 X 方面" → 具体说哪方面 +- "就 X 来说" → 删 + +### CN-9:内联粗体小标题(每段开头都加粗) + +**反例**: +- **技术层面**:xxx +- **商业层面**:xxx +- **风险层面**:xxx + +改为叙述段落。保留加粗的前提是:真的是关键强调,而不是装饰。 + +### CN-10:章节标题 / 小节标题禁止用符号开头 + +禁止:🚀 / ✅ / 💡 / ⚠️ 等 emoji 开头。如果是正式提示标志,在正文中用文字表述。 + +--- + +## 注入人味(Add Soul) + +干净但没灵魂的文字和 AI slop 一样明显。合格的报告要有: + +### 有立场 + +不要只报告事实——对事实有判断。"定价策略存在风险"比"定价策略有利有弊"好。 + +### 节奏变化 + +短句。再长一些的句子慢慢把意思讲清楚。混着用。 + +### 承认不确定 + +真人会说"我不确定",AI 不会。允许出现"这个趋势能否持续还需观察"、"目前数据尚不足以做判断"这种诚实表达。 + +### 具体而非抽象 + +- "用户体验有待改善" → "首次打开页面要 8 秒,用户很可能就离开了" +- "存在风险" → "最大风险是 NEB 可能用专利诉讼拖延 18-24 个月" + +### 有节制的第一人称 + +研究报告一般不用"我",但是"我们认为 / 本报告认为"比"一般认为"好。 + +--- + +## 最后的自审流程 + +写完一段后,问自己三个问题: + +1. **这句话是真人会说的吗?** 读出来听听看是否拗口做作 +2. **能更具体吗?** 任何抽象词都问能否换成数据/案例 +3. **删掉这句会失去什么?** 如果没损失,删 + +--- + +## Process Summary(给调用 agent 的操作清单) + +拿到一份待润色的稿子后: + +1. **扫描并标记**:全文搜索上述禁用词和模式 +2. **逐段重写**:按规则替换 +3. **检查节奏**:段落长短、句子长短是否有变化 +4. **删减冗余**:空话 / 套话 / 无数据形容词 +5. **核对格式**:没有 emoji、粗体不过度、标题 sentence case、破折号节制 +6. **So What 检验**:每段都得有价值 +7. **最后一遍自问**:这段还有哪里像 AI?针对性再改一轮 + +--- + +## 参考 + +- Wikipedia: Signs of AI writing (WikiProject AI Cleanup) +- blader/humanizer SKILL v2.5.1 +- 9MW1911 综合战略报告(中文风格参考) diff --git a/.agents/skills/length-budget/SKILL.md b/.agents/skills/length-budget/SKILL.md new file mode 100644 index 0000000..05ae3a3 --- /dev/null +++ b/.agents/skills/length-budget/SKILL.md @@ -0,0 +1,172 @@ +--- +name: length-budget +description: 报告字数预算分配与执行校验。支持 4 种字数模式(自动/简明/详细/深度),英中互换规则(英文词数 ≈ 中文字数 × 0.7),章节配额算法与补写策略。Phase 1 用于设定预算,Phase 2/4 用于自检。 +--- + +# 字数预算系统 + +## 一、四种字数模式(Phase 1 访谈时选择) + +用户在 /dr-init 访谈时选定其中一种,写入 manifest.word_budget_mode: + +| 模式 | 中文字数目标 | 英文词数目标 | 章节数 | 适用场景 | +|---|---|---|---|---| +| `auto` | 按类型默认 | 按类型默认 | 8-12 | 不明确时默认 | +| `concise` | 8,000-12,000 | 5,600-8,400 | 6-8 | 高管一阅即过 | +| `detailed` | 20,000-35,000 | 14,000-24,500 | 10-12 | 标准专业报告 | +| `deep` | 50,000-80,000 | 35,000-56,000 | 12-15 | 深度研究/行业专著 | + +**auto 模式的默认字数**(按报告类型): + +| 报告类型 | 中文字数 | 英文词数 | 章节数 | +|---|---|---|---| +| 综述 | 12,000 | 8,400 | 8-10 | +| 研究 | 35,000 | 24,500 | 10-12 | +| 投资 | 22,000 | 15,400 | 10-12 | +| 管理/工艺 | 18,000 | 12,600 | 9-11 | + +**字数只是参考,以把问题讲清楚为第一优先**。过少则内容单薄,过多则注水。目标区间±20% 内都可接受。 + +--- + +## 二、英文-中文字数换算 + +**核心换算率**:1 个英文词 ≈ 1.4-1.5 个中文字 + +Phase 2 产出英文,Phase 4 翻译为中文后字数会自然膨胀约 40%。预算时: +- Phase 2 英文稿:按英文词数目标 × 1.0 写 +- Phase 4 中文稿:英文词数 × 1.4 应落在中文字数目标的 ±15% 内 + +自动换算工具: + +```python +def en_words_to_zh_chars(en_words: int) -> int: + return int(en_words * 1.4) + +def zh_chars_to_en_words(zh_chars: int) -> int: + return int(zh_chars / 1.4) +``` + +--- + +## 三、章节配额分配(dr-plan 在 Phase 1 用) + +### 三层优先级 + +``` +P0(核心章,2-3 章):每章 = 总字数 × 13-16% +P1(主干章,3-5 章):每章 = 总字数 × 8-11% +P2(辅助章,2-3 章):每章 = 总字数 × 5-7% +引言 / 结论章:各 = 总字数 × 6-8% +``` + +### 约束 + +- 章节字数差距 ≤ ±30%(防止头重脚轻) +- 结论章 ≥ 总字数 × 10% +- 每节 ≥ 600 字(英文 ≥ 420 词),不足则合并节 + +### 示例:30,000 字研究报告分配 + +| 章 | 定位 | 中文配额 | 英文配额 | +|---|---|---|---| +| 第 1 章 引言 | intro | 1,800 | 1,260 | +| 第 2 章 核心论点 | P0 | 4,500 | 3,150 | +| 第 3 章 机制剖析 | P0 | 4,500 | 3,150 | +| 第 4 章 临床证据 | P1 | 3,300 | 2,310 | +| 第 5 章 竞争格局 | P1 | 3,000 | 2,100 | +| 第 6 章 产业链 | P1 | 2,700 | 1,890 | +| 第 7 章 政策监管 | P1 | 2,400 | 1,680 | +| 第 8 章 风险 | P2 | 1,800 | 1,260 | +| 第 9 章 国际对比 | P2 | 1,500 | 1,050 | +| 第 10 章 趋势判断 | P1 | 2,100 | 1,470 | +| 第 11 章 结论与建议 | conclusion | 2,400 | 1,680 | +| **合计** | | **30,000** | **21,000** | + +--- + +## 四、Phase 2 执行校验 + +dr-analyst 每章交稿前自检,dr-pm 每批校验。 + +### 英文字数统计 + +```bash +# 英文词数 +wc -w projects//phase2/drafts/chXX.md +``` + +### 中文字数统计(未来用) + +```python +def count_chinese_words(text: str) -> int: + import re + cn = sum(1 for c in text if '\u4e00' <= c <= '\u9fff') + text_no_cn = re.sub(r'[\u4e00-\u9fff]', ' ', text) + en = len(re.findall(r"[A-Za-z]+(?:[-'][A-Za-z]+)*", text_no_cn)) + return cn + en +``` + +### 校验逻辑 + +``` +1. 读 chXX.md 统计英文词数 +2. 对照 framework 中该章配额 +3. 判断: + 实际/配额 < 0.7 → 不合格,继续挖掘证据补写 + 0.7 ≤ 比值 < 0.85 → 警告,建议补足 + 0.85 ≤ 比值 ≤ 1.3 → 合格 + 比值 > 1.3 → 超纲,考虑精简或拆分 +``` + +--- + +## 五、字数不足的正确补救路径 + +**绝对禁止为凑数注水**("在此背景下"、"随着...的不断发展"等空话)。字数不足的应对顺序: + +1. **检查证据覆盖**:该章观点是否有 ≥2 独立 Tier 1-2 信源?若无 → 检索补证据 +2. **展开数据细节**:把表格里的数字展开成文字分析(趋势、拐点、对比) +3. **增加案例**:用 1-2 个具体公司/产品案例佐证抽象观点 +4. **补反方证据**:把反方证据段落写详细(500-800 字) +5. **延伸推论**:对核心判断做"若成立则..."和"若不成立则..."分支 +6. **国际对比**:若原文只讲中国,加一段国际对比 + +--- + +## 六、manifest 字段规范 + +```json +{ + "word_budget_mode": "detailed", + "target_words_zh": 30000, + "target_words_en": 21000, + "min_words_zh": 24000, + "chapter_quotas_en": [ + {"index": 1, "title": "...", "en_words": 1260, "priority": "intro"}, + {"index": 2, "title": "...", "en_words": 3150, "priority": "P0"} + ] +} +``` + +--- + +## 七、Phase 4 翻译后中文字数校验 + +翻译完成后: +1. 读 final_zh.md,按中英混排规则统计字数 +2. 对照 manifest.target_words_zh +3. 落在 ±15% 区间内 → 合格 +4. 不合格 → dr-polisher 在润色时适度扩展/压缩 + +--- + +## 八、硬规则 + +1. ✅ auto 模式按类型默认,其他模式按用户选择 +2. ✅ 章节字数差距 ≤ ±30% +3. ✅ 结论章 ≥ 全文 10% +4. ✅ Phase 2 英文稿每章自检,不足 70% 配额必须补 +5. ✅ Phase 4 中文稿整体字数校验在 ±15% 内 +6. ❌ 禁止为凑数注水(AI 套话、重复表述) +7. ❌ 禁止对字数"打折"交稿 diff --git a/.agents/skills/mckinsey-method/SKILL.md b/.agents/skills/mckinsey-method/SKILL.md new file mode 100644 index 0000000..096b962 --- /dev/null +++ b/.agents/skills/mckinsey-method/SKILL.md @@ -0,0 +1,177 @@ +--- +name: mckinsey-method +description: 顶级咨询公司(麦肯锡/BCG/德勤)研究报告写作方法论。金字塔原理、MECE、观点型标题、证据-数据-案例三要素、So What 自检。SCQA 仅用于 Executive Summary 和各章引入段,严禁每节机械套用。所有写作类 agent(dr-analyst/dr-editor-in-chief/dr-polisher)必读。 +--- + +# 顶级咨询报告写作方法论(精炼版) + +## 核心定位 + +本文档是报告写作的**唯一风格准则**。读过 9MW1911 综合战略报告吗?那是目标风格。读起来像咨询公司资深合伙人在跟董事会讲话,不像 AI 生成的综述。 + +--- + +## 一、金字塔原理(Pyramid Principle) + +**结论先行,论据支撑,论据之间 MECE。** + +``` +章标题(= 一句判断) + ↓ +章首 2-3 段:直接给出本章结论 + 核心逻辑 + ↓ +节 2.1(= 支撑论点 1) + 节首 1 段:本节论点 + 核心证据 + 数据/事实/案例(带 [src_xxx]) + So What:这意味着什么 + ↓ +节 2.2(= 支撑论点 2) + ... +``` + +**章标题即判断**(强制): +- ✗ "第 2 章 市场现状" +- ✓ "第 2 章 中国 GLP-1 市场 2025 年已跨越 10 亿美元门槛,增速仍在加速" + +**节标题即子判断**(强制): +- ✗ "2.1 竞争格局" +- ✓ "2.1 双寡头格局将在 3 年内被国产厂商打破" + +--- + +## 二、SCQA 的正确使用(关键纠正) + +**SCQA 不是每章每节都套的格式,是整份报告的开篇叙事工具。** + +### 允许使用的位置(仅以下三处) + +1. **Executive Summary 开头**(最重要):用 SCQA 引出报告核心命题 +2. **第 1 章引言**:用 SCQA 建立整份报告的分析框架 +3. **决策性关键章引入段**(可选):当某章提出重大判断或政策建议时 + +### 禁止使用的位置 + +- ✗ 每一节的开头都写 SCQA +- ✗ 任何位置显式标注 "**Situation(背景)**" "**Complication(张力)**" 等字样 +- ✗ 三级小节还套用 SCQA + +### 正确的 SCQA(隐式、融合式) + +> 生物药 pipeline 的爆炸式扩张与 CMC 合规要求的层层抬高,正将 O-糖苷酶从一个依赖唾液酸预处理的专业试剂,推向覆盖 ADC 开发、双特异性抗体表征的工作流必选组分。然而,30 年来主导市场的 NEB 经典产品,对唾液酸化底物无活性这一根本局限始终未被突破。这就引出了一个核心问题:当下一代工程酶在 2019-2024 年集中商业化、市场标准正在重构时,后来者的进入窗口是否真实存在?本报告认为,窗口存在,但持续时间不超过 36 个月。 + +(这段里有 S/C/Q/A 四个要素,但没有任何显式标注,读起来像一段自然的论述。) + +### 错误的 SCQA(显式标注式) + +> **Situation(背景)**:生物药 pipeline 扩张... +> **Complication(张力)**:NEB 经典产品局限... +> **Question(问题)**:窗口是否存在? +> **Answer(答案)**:本章认为... + +(这种写法是典型的 AI 套路,在最终报告里绝对禁止出现。) + +--- + +## 三、MECE(章节划分铁律) + +**Mutually Exclusive, Collectively Exhaustive — 互斥且穷尽。** + +自检: +- 如果读者读完第 3 章再读第 5 章,会不会觉得"刚才好像说过这个"?有 → 合并或重划 +- 对照分析框架列出所有应覆盖的维度,有遗漏 → 补章节 + +常用框架: +- 市场:需求侧 / 供给侧 / 竞争格局 / 监管环境 +- 技术:原理 / 验证 / 产业化 / 壁垒 +- 投资:市场空间 / 竞争壁垒 / 财务模型 / 风险 + +--- + +## 四、观点 + 证据的写作单元 + +每个段落的标准结构: + +``` +[论点句] 具体判断,1 句话。 +[证据 1] 根据 <具体来源>,<数据> [src_xxx]。 +[证据 2] 进一步,<案例/对比> [src_xxx]。 +[So What] 这意味着 <对上层论点的意义>。 +``` + +### 数据引用规范 + +| 类型 | 写法示例 | +|---|---| +| 市场规模 | "120 亿美元(2024 年)[src_042]" | +| 增长率 | "CAGR 23%(2023-2030)[src_018]" | +| 临床数据 | "OS 改善 23%(95% CI: 13.8-16.6,p<0.001,N=1,200)[src_007]" | +| 成功率 | "FDA 获批率 41%(N=127 项 NDA,2020-2024)[src_033]" | + +### 禁止写法 + +- "市场规模巨大" → 必须写具体数字 +- "研究表明" → 必须写是哪项研究(来源 ID) +- "近年来" → 必须写具体年份 +- "有专家认为" → 必须写哪位专家(或删去,用数据代替) + +--- + +## 五、So What 自检(每段都做) + +每写完一段,问自己:"所以呢?这对读者有什么意义?" + +- 答案是"只是客观描述" → **要么删,要么补 So What 句** +- So What 句通常放段尾,1-2 句,明确点出这段内容对上层论点的贡献 + +示例: +- "这意味着,先发厂商在 2026 年之前建立的渠道优势将难以被后来者复制。" +- "因此,判断一个 GLP-1 管线的商业价值,给药频率比疗效终点更关键。" + +--- + +## 六、报告整体结构(11 件套) + +参考 9MW1911 综合战略报告的组织方式: + +1. **封面**:主标题 + 副标题 + 保密标识 + 编制日期 +2. **Executive Summary / 执行摘要**(≈800 字):SCQA 开篇 + 核心结论 4 条 + 关键行动优先级 +3. **Abstract / 摘要**(500-600 字):独立一页,叙事式,面向广义读者 +4. **Glossary / 术语表**(双语对照) +5. **Table of Contents / 目录** +6. **正文章节**(8-15 章) +7. **结论与建议章** +8. **附录**(2-5 个,如 CMC、临床对比、合并症分析) +9. **参考文献**([src_xxx] 编号格式) +10. **免责声明** +11. **版本信息** + +--- + +## 七、章节写作 Checklist(每章完成后自检) + +- [ ] 章标题是观点型判断,不是"概述/现状/背景" +- [ ] 章首 2-3 段给出结论和逻辑 +- [ ] 各节互斥且穷尽(MECE) +- [ ] 每节标题也是观点型判断 +- [ ] 每个数字/事实后接 [src_xxx] +- [ ] 每段末尾有 So What 句 +- [ ] 没有显式标注 "S/C/Q/A" +- [ ] 没有"巨大/快速/显著/强劲"等无数据形容词 +- [ ] 没有"本章定位/字数配额/研究员"等调度元数据 +- [ ] 没有占位符 [待验证](除非确实找不到第二个信源) + +--- + +## 八、严禁出现的写作坏习惯(humanizer 已列,此处精简) + +**AI 套话**:随着、不断、深入、值得注意、不难发现、显而易见、具有重要意义、发挥重要作用、显著、巨大、快速发展、在此背景下、综上所述、由此可见、总的来说 + +**规避 "是" 的冗余结构**(AI 高频):标志着 / 代表着 / 构成 / 成为 / 跃升为 → 直接用 "是" + +**三段式堆砌**:不要为凑数硬拼"需求侧 / 供给侧 / 政策侧"、"短期 / 中期 / 长期" + +**破折号过用**:长破折号每章不超过 3 处 + +**负向平行**:不要"不仅...更..."、"不是...而是..."(偶用可,成段出现不可) + +完整规则见 `skill:humanizer-cn`。 diff --git a/.agents/skills/output-hygiene/SKILL.md b/.agents/skills/output-hygiene/SKILL.md new file mode 100644 index 0000000..ee827a0 --- /dev/null +++ b/.agents/skills/output-hygiene/SKILL.md @@ -0,0 +1,266 @@ +--- +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]` +- `` / `` / `` / `` 等模板占位符 +- `{{ ... }}` / `${...}` 变量语法残留 + +### 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//phase4/final.md | sort -u > /tmp/cited.txt + +# 2. 从 citations.md / sources.jsonl 提取所有已登记的 src_id +grep -oE 'src_[0-9]+' projects//phase4/citations.md | sort -u > /tmp/registered.txt +# 或从 sources.jsonl +python3 -c " +import json +with open('projects//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. ❌ 禁止三级以上嵌套标题 diff --git a/.agents/skills/pdf-reportlab/SKILL.md b/.agents/skills/pdf-reportlab/SKILL.md new file mode 100644 index 0000000..153c37d --- /dev/null +++ b/.agents/skills/pdf-reportlab/SKILL.md @@ -0,0 +1,303 @@ +--- +name: pdf-reportlab +description: 用 ReportLab 生成专业中文 PDF 研究报告。集中样式管理、紧凑分页(widows/orphans/keepWithNext)、颜色层次、封面保密标识、页眉页脚简洁化。基于 9MW1911 综合战略报告的编排参考。 +--- + +# ReportLab 中文 PDF 模板使用指南(v0.5) + +## 一、为什么是 ReportLab + +- **完全可控**:每个字号、行距、颜色由代码说了算,不被引擎意外改动 +- **中文字体一次搞定**:`pdfmetrics.registerFont` 注册后全局可用,子集嵌入 PDF,无授权问题 +- **分页规则精确**:支持 widows/orphans、keepWithNext、splitByRow 等避免孤行/寡行 +- **图表嵌入高质量**:matplotlib 300 DPI PNG,速度快 +- **样式集中在 StyleSheet**:避免字号不一 + +--- + +## 二、模板入口 + +脚本:`.opencode/templates/report-template.py` + +调用: +```bash +uv run python .opencode/templates/report-template.py \ + --input projects//phase4/final.md \ + --manifest projects//manifest.json \ + --output projects//phase4/final.pdf \ + --fonts-dir .opencode/templates/fonts +``` + +首次使用前: +```bash +bash .opencode/templates/fonts/download-fonts.sh +``` + +--- + +## 三、字体注册(7 个字重) + +``` +SrcSerif-Regular 思源宋体 Regular 正文 +SrcSerif-Bold 思源宋体 Bold 正文粗体 +SrcSans-Light 思源黑体 Light 页眉页脚 +SrcSans-Medium 思源黑体 Medium 三级标题/图表 +SrcSans-Bold 思源黑体 Bold 一二级标题 +SrcSans-Heavy 思源黑体 Heavy 封面大标题 +Kai 霞鹜文楷 Regular 摘要/引文 +``` + +--- + +## 四、样式表(StyleSheet,集中管理) + +| 样式名 | 字体 | 字号 | 行高 | 颜色 | 备注 | +|---|---|---|---|---|---| +| `body` | SrcSerif | 10.5 | 18 | `#1a1a1a` | 正文,首行缩进 21pt | +| `body-bold` | SrcSerif-Bold | 10.5 | 18 | `#1a1a1a` | 行内加粗 | +| `h1` | SrcSans-Bold | 18 | 28 | `#1e3a8a` | 章标题,前强制分页 | +| `h2` | SrcSans-Bold | 14 | 22 | `#2c5282` | 节标题 | +| `h3` | SrcSans-Medium | 12 | 18 | `#374151` | 小节标题 | +| `quote` | Kai | 10.5 | 18 | `#4b5563` | 引文 | +| `caption` | SrcSans-Medium | 9 | 13 | `#6b7280` | 图表标题 | +| `footnote` | SrcSerif | 9 | 13 | `#374151` | 脚注/参考文献 | +| `header-footer` | SrcSans-Light | 8 | 12 | `#9ca3af` | 页眉页脚 | +| `cover-title` | SrcSans-Heavy | 28 | 40 | `#0f172a` | 封面主标题 | +| `cover-subtitle` | SrcSans-Medium | 15 | 24 | `#475569` | 封面副标题 | +| `cover-confidential` | SrcSans-Bold | 11 | 16 | `#dc2626` | 封面保密标识(红色)| +| `cover-meta` | SrcSerif | 11 | 18 | `#334155` | 封面元信息 | +| `summary` | SrcSerif | 11 | 20 | `#1a1a1a` | 执行摘要 | + +--- + +## 五、分页规则(关键升级点) + +### 章(h1) + +- `pageBreakBefore=1`(每章新起一页) +- `keepWithNext=1`(标题和下一段不分离) + +### 节(h2) + +- **禁止单独触发分页** +- `keepWithNext=1`(标题紧跟内容) + +### 小节(h3) + +- 同 h2,`keepWithNext=1` + +### 段落 + +- `widows=2, orphans=2`(避免寡行/孤行) +- 每段之间 `spaceBefore=6, spaceAfter=6` + +### 表格 + +- `TableStyle` 中启用 `splitByRow=True`(长表格按行分页) +- `repeatRows=1`(表头在分页后重复) +- 单元格 padding 统一 4-6pt + +### 摘要/术语表/目录/参考文献 + +- 每个独占起始页(用 `PageBreak`) + +--- + +## 六、封面模板(参考 9MW1911) + +封面独立一页,无页眉页脚,布局: + +``` +(上 30% 空白) + + 主标题(cover-title,黑色,居中) + 副标题(cover-subtitle,深灰,居中) + +(中部 40% 空白) + + [机密 | 仅供 XX 内部决策使用] (cover-confidential,红色,居中) + +(下部 20%) + + 类型:研究类 + 作者:Deep Research 系统 / <公司名> + 编制日期:YYYY 年 M 月 + 版本:v1.0 +``` + +字段来源: +- `manifest.report_title` / `report_subtitle` +- `manifest.confidentiality` (如 "机密 | 仅供迈威生物内部决策使用") +- `manifest.author` / `manifest.date` / `manifest.version` + +--- + +## 七、页眉页脚(简洁化) + +### 页眉 + +左边:报告简称(从 `manifest.report_title` 取前 15 字) +右边:章节名(动态,从当前 h1 内容取) +底线:`#e5e7eb` 浅灰分隔线 + +### 页脚 + +居中:页码(格式 `— X —`) +字号:8pt,`#9ca3af` 浅灰 + +### 特殊页 + +- 封面:无页眉页脚 +- 免责声明:无页眉,仅页脚 +- 其他(摘要/术语表/目录/正文/附录/参考文献):有页眉页脚 + +--- + +## 八、报告结构(11 件套) + +ReportLab 按以下顺序组装: + +1. **封面**(cover PageTemplate) +2. **免责声明**(normal PageTemplate,单页) +3. **Executive Summary / 执行摘要**(summary PageTemplate,1-2 页) +4. **Abstract / 摘要**(normal,单页) +5. **Glossary / 术语表**(normal) +6. **Table of Contents / 目录**(TOC,自动生成) +7. **正文各章**(normal,每章 h1 强制分页) +8. **结论与建议**(正文的一部分) +9. **附录**(normal) +10. **参考文献**(bibliography PageTemplate,footnote 样式) +11. **版本信息**(normal,单页) + +--- + +## 九、Markdown 支持范围 + +| Markdown | ReportLab 渲染 | +|---|---| +| `# 第 X 章 ...` | h1(新起一页,深蓝色)| +| `## X.Y ...` | h2(节,蓝色,不分页)| +| `### X.Y.Z ...` | h3(小节,深灰)| +| `**粗体**` | inline `` | +| `*斜体*` | inline `` | +| `` `代码` `` | 等宽字体 | +| `> 引文` | quote 样式(楷体,浅底色)| +| `- 项` / `1. 项` | 项目符号列表 | +| 表格 `\| \| \|` | Table,自动列宽 + splitByRow | +| `![caption](path)` | 图片 + caption 样式 | +| `[src_001]` | 上标引用 | +| `---` | 分页符 | + +**不支持**:HTML 标签、数学公式、代码块高亮。 + +--- + +## 十、图表嵌入 + +不用 ReportLab 原生绘图,全部预渲染为 PNG: + +```python +import matplotlib.pyplot as plt +import matplotlib.font_manager as fm + +font_path = '.opencode/templates/fonts/SourceHanSansSC-Medium.otf' +fm.fontManager.addfont(font_path) +plt.rcParams['font.family'] = 'Source Han Sans SC' +plt.rcParams['axes.unicode_minus'] = False + +fig, ax = plt.subplots(figsize=(6, 4), dpi=300) +# ... +plt.savefig('projects//phase4/figures/fig_01_XXX.png', dpi=300, bbox_inches='tight') +``` + +Markdown 中引用:`![图 1-1:2020-2025 GLP-1 市场规模(数据来源:[src_042])](figures/fig_01_XXX.png)` + +--- + +## 十一、manifest 必需字段 + +```json +{ + "slug": "...", + "report_title": "自研 O-糖苷酶立项可行性研究报告", + "report_subtitle": "对标 NEB 与 Merck 经典产品的技术路径、IP 壁垒与差异化战略", + "confidentiality": "机密 | 仅供内部决策使用", + "author": "Deep Research 系统", + "date": "2026-04-21", + "version": "1.0", + "type": "研究类", + "disclaimer": "本报告基于公开信息与 AI 辅助研究生成,仅供参考..." +} +``` + +--- + +## 十二、常见坑与对策 + +| 坑 | 对策 | +|---|---| +| 中文字号不一 | 集中 StyleSheet,不在 Paragraph 里 inline 改 fontSize | +| 行距太挤 | 行高 = 字号 × 1.5~1.7 | +| 换行断错 | `wordWrap='CJK'` 必设 | +| 表格被截断 | `splitByRow=True, repeatRows=1` | +| 标题孤行(页末一个标题后直接新页)| `keepWithNext=1` | +| 段落寡行(末段只剩一行在下页)| `widows=2, orphans=2` | +| 图片变形 | 先 matplotlib 出 300 DPI PNG,再 `Image(path, width=..., kind="proportional")` | +| 生成慢 | matplotlib 图表预渲染,不要在 PDF 生成阶段现算 | +| 参考文献丢失 | dr-reporter 出稿前检查:读 citations.md,确认内容已写入 final.md | + +--- + +## 十三、dr-reporter 调用流程 + +``` +1. 环境检查 + - 字体 ≥6 个 OTF 文件 + - final.md 存在 + - manifest.json 有必需字段 + +2. 回填参考文献(关键步骤,修复 v0.4 的 bug) + - 读 citations.md 内容 + - 在 final.md 中找到"## 参考文献"段落 + - 如果段落内容是占位符(如 "[由 dr-reporter 自动生成]" 或为空) + → 替换为 citations.md 的完整内容 + - 写回 final.md + +3. 图表检查 + - 扫描 final.md 中所有 ![...](path) 图片引用 + - 验证每个 path 在 figures/ 目录下存在 + - 缺失图片 → 警告并继续,但汇报中注明 + +4. 生成 PDF + uv run python .opencode/templates/report-template.py \ + --input projects//phase4/final.md \ + --manifest projects//manifest.json \ + --output projects//phase4/final.pdf \ + --fonts-dir .opencode/templates/fonts + +5. 生成 DOCX(可选) + pandoc projects//phase4/final.md \ + --from markdown --to docx \ + --output projects//phase4/final.docx \ + --toc --toc-depth=3 + +6. 验证 + - PDF 文件大小 > 500KB(太小说明字体没嵌) + - PDF 页数合理(按字数估算) + - "参考文献"章节存在且非空 + +7. 汇报 +``` + +--- + +## 十四、输出卫生检查(必跑) + +生成 PDF 前: + +```bash +# 加载 skill:output-hygiene +python3 .opencode/templates/hygiene_check.py projects//phase4/final.md +``` + +禁止词残留 → 抛回 dr-polisher 再润色一轮。 diff --git a/.agents/skills/search-strategy/SKILL.md b/.agents/skills/search-strategy/SKILL.md new file mode 100644 index 0000000..27f27da --- /dev/null +++ b/.agents/skills/search-strategy/SKILL.md @@ -0,0 +1,246 @@ +--- +name: search-strategy +description: 生物医药深度研究的统一检索策略。规定信源优先级金字塔、检索轮次、关键词策略、API 调用顺序,以及何时切换到专业信源。所有做信息收集的 agent(dr-searcher/dr-analyst/dr-verifier/dr-plan)必须加载此技能。 +--- + +# 检索策略总纲(Deep Research 黄金法则) + +## 一、信源优先级金字塔 + +**永远从上至下尝试,不要从 Tier 4 开始**: + +``` + ╱ Tier 1 ╲ 最高权重 + ╱ (一手) ╲ + ╱──────────────╲ + ╱ Tier 2 ╲ 标准权重 + ╱ (权威二手) ╲ + ╱──────────────────╲ + ╱ Tier 3 ╲ 辅助权重 +╱ (预印本/会议/券商) ╲ +───────────────────────── + Tier 4 仅做发现入口 + (通用搜索 + Wiki) +───────────────────────── + 【黑名单】禁用 +``` + +### Tier 1(优先使用,加权 1.2x) +- **论文**:PubMed、Cochrane、顶刊(NEJM/Lancet/Nature/Science/Cell/JAMA/NatMed) +- **监管**:FDA/EMA/NMPA/PMDA 官网、openFDA +- **临床试验**:ClinicalTrials.gov、ChiCTR、EU CTR +- **专利**:USPTO、EPO、CNIPA、Google Patents、PatentsView +- **披露**:SEC(10-K/10-Q/S-1)、港交所、沪深交易所年报 + +### Tier 2(可用,标准权重) +- **咨询**:McKinsey/BCG/Deloitte/IQVIA/Evaluate Pharma/Frost & Sullivan/沙利文 +- **综述**:系统综述、Cochrane Review、Meta 分析 +- **协会**:PhRMA、BIO、中国医药工业协会、中国医药创新促进会 +- **专业媒体**:BioSpace、Endpoints News、FiercePharma、STAT、医药魔方、Insight 数据库 + +### Tier 3(辅助,需 Tier 1-2 支撑) +- **预印本**:bioRxiv、medRxiv、SSRN(必须标注"未同行评审") +- **券商**:中金/中信/高盛/摩根士丹利生物医药(注意利益冲突) +- **会议**:AACR/ASCO/ASH/JPM Healthcare Conference 摘要 + +### Tier 4(仅做入口) +- Tavily / Brave / Exa 返回的普通网页 → **只用来发现 Tier 1-2 URL**,不做结论佐证 +- Wikipedia → **只做术语理解**,结论不得引用 + +### 黑名单(禁用为证据) +- 百家号、头条号、大部分公众号自媒体 +- 未署名行业博客 +- Retraction Watch 标记的撤稿论文 +- "据业内人士透露"类无来源文章 +- >5 年的综述(机制研究可放宽) + +--- + +## 二、检索 4 轮法则 + +对任何一个 section/chapter,**必须至少 4 轮检索**: + +### 第 1 轮:Tier 1 直命中 +- 先用**精确查询**去 PubMed / ClinicalTrials / openFDA 打 +- 关键词用 MeSH Term(医学主题词)+ 布尔逻辑 +- 例:`(GLP-1[MeSH] OR "glucagon-like peptide-1") AND (obesity[MeSH]) AND ("2023"[PDAT]:"2026"[PDAT])` + +### 第 2 轮:Tier 2 综述扫描 +- 去 McKinsey Insights / BCG / Deloitte 官网搜 industry-overview +- Evaluate Pharma / IQVIA 白皮书(通常需注册) +- 目标:获取市场规模、竞争格局、趋势判断 + +### 第 3 轮:反方/证伪检索 +- 主动搜索与初步结论相反的关键词 +- 例:研究"GLP-1 成为减重首选"→ 反方要搜 "GLP-1 limitations" "semaglutide side effects" "discontinuation rate" +- 至少 3-5 条反方证据 + +### 第 4 轮:Tavily/Brave/Exa 补漏 +- 仅用于发现前 3 轮遗漏的 URL +- 发现后**必须**回溯到原始 Tier 1-2 来源(论文 DOI、监管公告原文) +- 不得直接引用搜索返回的二次报道 + +--- + +## 三、API 调用顺序(技术栈,v0.8 更新) + +**按"查询类型"路由到最合适的 API**,而不是一律走通用搜索。 + +``` +┌──────────────────────────────────────────────────────────────┐ +│ 查询类型 首选 备选 │ +├──────────────────────────────────────────────────────────────┤ +│ 专利 Serper Patents Google Patents 爬页 │ +│ (site:patents.google.com) │ +│ │ +│ 学术论文 Serper Scholar PubMed E-utils │ +│ (带引用数/年份/期刊) (原始数据库) │ +│ │ +│ 新闻 / 行业动态 Serper News Tavily │ +│ (时效性敏感) │ +│ │ +│ 临床试验 ClinicalTrials.gov ChiCTR │ +│ (原始 API) │ +│ │ +│ 监管公告 openFDA / FDA 搜索 EMA / NMPA 官网 │ +│ │ +│ 公司/机构识别 Exa Tavily │ +│ (LinkedIn/官网召回强) │ +│ │ +│ 通用网页 Exa Tavily / Brave │ +└──────────────────────────────────────────────────────────────┘ +``` + +### Serper(google.serper.dev)使用模板 + +**专利检索**: +```python +from scripts.lib.search_client import SearchClient +with SearchClient() as c: + hits = c.patents("dual-target siRNA GalNAc", num_results=10) +``` + +**学术论文**: +```python +hits = c.scholar("dual-target RNAi 2024", num_results=10, year_low=2023) +# hits[i].snippet 里包含引用数和期刊信息 +``` + +**新闻(时效性)**: +```python +hits = c.news("Arrowhead ARO-DIMER-PA clinical trial", time_range="w") # 最近一周 +``` + +### Tavily MCP 调用模板(通用网页 - Phase 1 初扫) +``` +工具名:tavily_search +参数: + query: "<关键词>" + search_depth: "advanced" + max_results: 10 + include_domains: ["pubmed.ncbi.nlm.nih.gov", "nejm.org", "lancet.com"] + exclude_domains: ["baijiahao.baidu.com", "toutiao.com"] + time_range: "year" +``` + +### 何时用哪个 + +- **专利相关问题**("谁拥有技术 X"、"FTO 自由度分析")→ `c.patents()`,**永远先走 Google Patents** +- **需要引用数排序的论文**("找影响力最大的 N 篇")→ `c.scholar()` +- **近期新闻**("2025 年 Q4 交易"、"上月 IND 批准")→ `c.news(..., time_range="m")` +- **快速概念验证 / 术语理解** → `c.search()`(通用) + +### PubMed E-utils(bash 调用示例) +```bash +# 1. esearch 拿 PMID 列表 +curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=GLP-1+obesity&retmax=20&api_key=$NCBI_API_KEY&retmode=json" + +# 2. efetch 拿摘要 +curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=PMID1,PMID2&rettype=abstract&retmode=xml&api_key=$NCBI_API_KEY" +``` + +### ClinicalTrials.gov v2 API +```bash +curl -s "https://clinicaltrials.gov/api/v2/studies?query.term=semaglutide&pageSize=20&format=json" +``` + +### openFDA +```bash +curl -s "https://api.fda.gov/drug/event.json?search=patient.drug.medicinalproduct:semaglutide&count=patient.reaction.reactionmeddrapt.exact&limit=20" +``` + +--- + +## 四、关键词策略 + +### 中英双语必备 +- 任何生物医药主题**必须同时用中英文检索** +- 中文关键词去找:中国监管(NMPA)、A股研报、医药魔方、Insight +- 英文关键词去找:PubMed、FDA、顶刊、欧美研报 + +### MeSH Term 优先于自由词 +- PubMed 查询必须用 MeSH Term(医学主题词表) +- MeSH Term 能自动扩展同义词,召回更全 +- 例:`obesity[MeSH]` 会自动包含 `adiposity`, `body weight, excess` 等 + +### 布尔逻辑 + 时间过滤 +- 默认加 `("2023"[PDAT]:"2026"[PDAT])` 时间窗 +- 机制研究可放宽到 10 年,新药/市场/政策必须近 3 年 + +### 反方关键词清单(备忘) +- `limitations` / `adverse events` / `side effects` / `discontinuation` +- `failed trial` / `FDA rejection` / `withdrawn` +- `conflict of interest` / `industry-funded` +- `retraction` / `replication failure` + +--- + +## 五、每条信源的提取字段(标准化) + +任何信源进 `sources.jsonl` 必须有以下字段: + +```jsonl +{ + "id": "src_001", + "tier": 1, + "score": 9.2, + "type": "journal" | "trial" | "regulatory" | "patent" | "report" | "news", + "url": "https://...", + "doi": "10.xxxx/...", + "title": "...", + "authors": ["...", "..."], + "year": 2025, + "venue": "NEJM", + "impact_factor": 176.0, + "accessed_at": "2026-04-20", + "abstract": "...", + "key_data": { + "market_size_2025": "12.3B USD", + "cagr": "23%" + }, + "used_in": ["ch01", "ch03.sec2"], + "notes": "关键图表见 Fig 2" +} +``` + +--- + +## 六、失败兜底 + +- 某个 API 限流/超时:**等 5s 重试 3 次**,仍失败则跳过并在日志标注 +- 某个信源 404:在 sources.jsonl 标 `"dead_link": true`,不删除(审计用) +- 关键数据查不到:**不要编造**,在正文写 "该数据暂未找到公开来源(截至 2026-04)" + +--- + +## 七、硬规则总结 + +1. ✅ 每 section 至少 4 轮检索 +2. ✅ 中英双语必查 +3. ✅ PubMed 用 MeSH Term +4. ✅ 反方关键词必查 +5. ✅ Tier 4 结果只做发现,不做佐证 +6. ✅ 所有信源写入 sources.jsonl 并评分 +7. ❌ 不得引用 Wikipedia 做结论 +8. ❌ 不得编造数据、URL、DOI +9. ❌ 不得使用黑名单信源 diff --git a/.agents/skills/source-quality/SKILL.md b/.agents/skills/source-quality/SKILL.md new file mode 100644 index 0000000..e96b8f3 --- /dev/null +++ b/.agents/skills/source-quality/SKILL.md @@ -0,0 +1,188 @@ +--- +name: source-quality +description: 信源质量评分系统(0-10 分制)与黑名单机制。规定每个信源入库前的评估维度、硬性淘汰规则、利益冲突检测。所有收集信源的 agent 都必须用此技能给每条信源打分后写入 sources.jsonl。 +--- + +# 信源质量评分(0-10 分制) + +## 一、评分维度(满分 10 分) + +| 维度 | 满分 | 判断标准 | +|---|---|---| +| 权威性 | 3 | 期刊 IF、机构排名 | +| 时效性 | 2 | 发表时间 vs 主题 | +| 一手性 | 2 | 一手数据 > 综述 > 二次解读 | +| 可验证性 | 2 | 有 DOI/URL/原始数据 | +| 无利益冲突 | 1 | 厂商自发降权 | + +### 维度 1:权威性(0-3 分) + +| 分值 | 情形 | +|---|---| +| 3.0 | IF ≥ 30(NEJM/Lancet/Nature/Science/Cell/JAMA)、FDA/EMA/NMPA 官方、SEC 披露 | +| 2.5 | IF 10-30(NatMed/NatBiotech/BMJ/AnnOncol 等)、顶级咨询(MKS/BCG/Deloitte) | +| 2.0 | IF 5-10(JCO/CircRes/AJRCCM)、IQVIA/EvaluatePharma、系统综述 | +| 1.5 | IF 3-5、券商研报、行业协会白皮书 | +| 1.0 | IF 1-3、专业媒体(BioSpace/Endpoints News) | +| 0.5 | 预印本(bioRxiv/medRxiv)、会议摘要 | +| 0 | 自媒体、百家号、未署名博客 | + +### 维度 2:时效性(0-2 分) + +| 主题类型 | 满分年限 | 每老 1 年扣分 | +|---|---|---| +| 市场 / 监管 / 临床 | 3 年内 | -0.5 | +| 作用机制 / 基础研究 | 10 年内 | -0.2 | +| 政策法规 | **以最新版本为准** | 过时版本 0 分 | +| 历史追溯(有意为之) | 不限 | 不扣 | + +### 维度 3:一手性(0-2 分) + +| 分值 | 情形 | +|---|---| +| 2.0 | 一手数据(原始 RCT 论文、监管公告、年报原文、专利原文) | +| 1.5 | 系统综述 / Meta 分析 | +| 1.0 | 叙述性综述 / Review | +| 0.5 | 二次解读(新闻报道、券商改写) | +| 0 | 三次传播以上("据报道"/"业内人士") | + +### 维度 4:可验证性(0-2 分) + +| 分值 | 情形 | +|---|---| +| 2.0 | 有 DOI + 原始数据可下载(如 ClinicalTrials 的 CSR 附件) | +| 1.5 | 有 DOI 或稳定 URL,全文可访问 | +| 1.0 | URL 稳定但需付费墙 | +| 0.5 | 仅有 URL,无唯一标识符 | +| 0 | URL 失效 / 404 / 无法验证 | + +### 维度 5:利益冲突(0-1 分) + +| 分值 | 情形 | +|---|---| +| 1.0 | 独立研究(学术机构、政府)、无资助声明冲突 | +| 0.5 | 有 industry funding 但已声明且方法独立 | +| 0 | 厂商自发报告 / 直接商业软文 | +| **-1**(惩罚) | 声明冲突但方法可疑、或对比实验明显偏向资助方 | + +--- + +## 二、综合评分硬规则 + +| 评分 | 可用性 | +|---|---| +| 8.0+ | 可作为核心论据,单独支撑结论 | +| 6.0-7.9 | 可用,但结论需 ≥2 个独立信源 | +| 4.0-5.9 | 仅作为参考,**不得作为唯一支撑** | +| < 4.0 | **禁止**用于结论佐证,只能入发现库 | + +--- + +## 三、黑名单(直接拒绝入库) + +以下信源**无论评分多少都禁用**: + +### 1. 明确劣质信源 +- 百家号(baijiahao.baidu.com) +- 头条号(toutiao.com 非原创栏目) +- 知乎回答(除非作者本人为业内专家且有实名背书) +- 小红书、抖音笔记 +- 未署名作者的 wordpress / medium 博客 + +### 2. 被撤稿论文 +- 查询 Retraction Watch 数据库(https://retractionwatch.com/) +- Crossref API 检查论文状态:`https://api.crossref.org/works/` + +### 3. 明显软文/PR 稿 +识别特征(命中任意 2 条即拒): +- 标题含 "重磅发布" "首创" "引领" 等夸张词 +- 通篇无具体数据,只有 CEO/专家口头引述 +- 发布渠道是企业官网的"新闻中心"且无交叉第三方验证 +- 仅讲优势不讲局限 + +### 4. 时效过期 +- 综述 > 5 年(机制研究可放宽) +- 政策/监管 > 1 年(以最新版本为准) +- 市场数据 > 2 年 + +### 5. 维基百科 +- **仅可作术语理解入口** +- 结论永不引用 +- 如从 Wiki 发现了参考文献,**回溯到原始来源**再引用 + +--- + +## 四、利益冲突检测要点 + +### 常见利益冲突场景 +- 药企赞助的 RCT 对自家产品评价极高 → 查对比剂、盲法、样本量 +- 咨询公司报告引用自家客户数据 → 查 acknowledgment 段 +- 行业协会报告涉及会员企业 → 查资助方名单 +- 券商研报 + 该券商是相关公司的保荐人 → 查 IPO/承销记录 + +### 操作方法 +每条信源入库前检查: +1. 作者/机构是否与被评估的公司/产品有商业关联? +2. 资助声明(funding statement)里提到什么? +3. 利益披露(disclosure)是否完整? + +**发现强利益冲突**:评分 ≤ 3(等同废弃);写入 `sources.jsonl` 的 `"conflict_of_interest": "..."` 字段。 + +--- + +## 五、评分执行流程(伪代码) + +``` +for each candidate_source in search_results: + # 1. 黑名单快筛 + if is_blacklisted(candidate_source): + log("BLACKLIST: " + source.url); continue + + # 2. 撤稿检查 + if has_doi(source) and is_retracted(source.doi): + log("RETRACTED: " + source.doi); continue + + # 3. 评分 + score = 0 + score += authority_score(source) # 0-3 + score += recency_score(source, topic) # 0-2 + score += primacy_score(source) # 0-2 + score += verifiability_score(source) # 0-2 + score += coi_score(source) # 0-1 or -1 + + # 4. Tier 加权 + if source.tier == 1: score *= 1.2 + + # 5. 入库 + if score >= 4.0: + append_to_sources_jsonl(source, score) + else: + log("LOW SCORE (" + score + "): " + source.url) +``` + +--- + +## 六、输出字段(写入 sources.jsonl) + +```jsonl +{ + "id": "src_042", + "score": 8.6, + "tier": 1, + "authority": 3.0, + "recency": 2.0, + "primacy": 2.0, + "verifiability": 2.0, + "coi": 1.0, + "conflict_of_interest": null, + "blacklist_checked": true, + "retraction_checked": true, + "notes": "NEJM 2025 原文,RCT 独立研究" +} +``` + +--- + +## 七、审计留痕 + +所有被**拒绝**的信源,也要写入 `projects//phase2/rejected-sources.jsonl`(注明原因)。这是事后复盘的关键,不要静默丢弃。 diff --git a/.codex/agents/dr-analyst.toml b/.codex/agents/dr-analyst.toml new file mode 100644 index 0000000..8b398a0 --- /dev/null +++ b/.codex/agents/dr-analyst.toml @@ -0,0 +1,19 @@ +name = "dr-analyst" +description = "Chapter deep-research agent that writes English chapter drafts and evidence matrices." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-analyst. +Work in English. Own exactly one assigned chapter. +Load skills: search-strategy, source-quality, length-budget, evidence-table, mckinsey-method, humanizer-cn. +Write: +- projects//phase2/drafts/chXX.md +- projects//phase2/evidence/chXX-evidence.md +- append structured sources to projects//phase2/sources.jsonl +Every claim and numerical fact needs [src_xxx]. +Every conclusion needs at least two independent Tier 1-2 sources, or must be explicitly marked as under-verified. +End each chapter with a concrete counter-evidence or limitation section title, not a generic 'Counter-Evidence' label. +Do not include scheduling metadata, quota notes, agent names, or SCQA labels in the chapter body. +""" +nickname_candidates = ["Analyst A", "Analyst B", "Analyst C", "Analyst D"] diff --git a/.codex/agents/dr-chief-editor.toml b/.codex/agents/dr-chief-editor.toml new file mode 100644 index 0000000..c8292ca --- /dev/null +++ b/.codex/agents/dr-chief-editor.toml @@ -0,0 +1,15 @@ +name = "dr-chief-editor" +description = "Phase 3 read-only editorial reviewer for whole-report logic, evidence, MECE, and quality." +model = "gpt-5.4" +model_reasoning_effort = "xhigh" +sandbox_mode = "read-only" +developer_instructions = """ +You are dr-chief-editor. +You are Phase 3 only and read-only except when explicitly asked by the parent to produce phase3/critique.md. +Review all English drafts, evidence files, sources.jsonl, framework.md, and manifest.json. +Assess central thesis coherence, logic, MECE, evidence sufficiency, counter-evidence handling, word count, point-of-view strength, and AI-pattern risks. +Do not rewrite drafts. +Do not enter Phase 4. +Do not spawn subagents. +""" +nickname_candidates = ["Chief Editor"] diff --git a/.codex/agents/dr-editor-in-chief.toml b/.codex/agents/dr-editor-in-chief.toml new file mode 100644 index 0000000..3512193 --- /dev/null +++ b/.codex/agents/dr-editor-in-chief.toml @@ -0,0 +1,15 @@ +name = "dr-editor-in-chief" +description = "Phase 4 lead editor for English final assembly and deterministic script orchestration." +model = "gpt-5.4" +model_reasoning_effort = "xhigh" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-editor-in-chief. +Own Phase 4 creative assembly only: +- Merge phase2 drafts into phase4/final_en.md. +- Write Executive Summary, Abstract, Glossary, transitions, and final structure. +- Remove scheduling metadata and output-hygiene violations. +Do not translate the whole report yourself. Use scripts/dr.py finalize or the underlying Python scripts for translate, glossary, apply_glossary, polish, and build_report. +Keep citations intact. +""" +nickname_candidates = ["Editor in Chief"] diff --git a/.codex/agents/dr-plan.toml b/.codex/agents/dr-plan.toml new file mode 100644 index 0000000..f8e4bd2 --- /dev/null +++ b/.codex/agents/dr-plan.toml @@ -0,0 +1,18 @@ +name = "dr-plan" +description = "Deep Research framework planner for Phase 1 interview, initial scan synthesis, and bilingual research framework." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-plan for the biomedical Deep Research system. +Work in Chinese with the user, but write framework research thinking in English. +Follow AGENTS.md and load the relevant skills: search-strategy, source-quality, length-budget, mckinsey-method, humanizer-cn. +Your responsibilities are /dr-init and /dr-frame equivalents: +- Interview the user before framework generation. +- Propose formal report titles. +- Spawn dr-searcher subagents in parallel when asked to perform initial scans. +- Generate phase1/framework.md with bilingual chapter titles, English research thinking, word quotas, central thesis, and alternative frameworks. +Do not perform Phase 2 chapter deep research yourself. +Do not enter Phase 4. +""" +nickname_candidates = ["Planner Alpha", "Planner Beta", "Planner Gamma"] diff --git a/.codex/agents/dr-pm.toml b/.codex/agents/dr-pm.toml new file mode 100644 index 0000000..5e1beb9 --- /dev/null +++ b/.codex/agents/dr-pm.toml @@ -0,0 +1,18 @@ +name = "dr-pm" +description = "Deep Research project manager for Phase 2 batching, analyst/verifier orchestration, and project status." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-pm for the biomedical Deep Research system. +Use English for Phase 2 working outputs. +Follow AGENTS.md and load skills: search-strategy, source-quality, length-budget, evidence-table, mckinsey-method. +Your responsibilities: +- Read manifest.json and phase1/framework.md. +- Plan Phase 2 batches, keeping 3 chapters or fewer per batch unless a chapter is large. +- Spawn dr-analyst subagents in parallel for chapter drafts. +- Spawn dr-verifier subagents after analyst completion for counter-evidence. +- Maintain manifest progress summaries and avoid carrying detailed batch chatter forward. +- Never write final reports directly. +""" +nickname_candidates = ["PM Alpha", "PM Beta", "PM Gamma"] diff --git a/.codex/agents/dr-reporter.toml b/.codex/agents/dr-reporter.toml new file mode 100644 index 0000000..35556af --- /dev/null +++ b/.codex/agents/dr-reporter.toml @@ -0,0 +1,14 @@ +name = "dr-reporter" +description = "Report production agent for PDF/DOCX rendering and final output checks." +model = "gpt-5.4-mini" +model_reasoning_effort = "medium" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-reporter. +You are an execution-focused report producer. +Use scripts/build_report.py and .opencode/templates/report-template.py to render PDF/DOCX from final_zh_polished.md or the specified Markdown. +Run output hygiene checks and citation checks where available. +Do not change research conclusions. +Do not invent missing references. +""" +nickname_candidates = ["Reporter"] diff --git a/.codex/agents/dr-searcher.toml b/.codex/agents/dr-searcher.toml new file mode 100644 index 0000000..e1ac931 --- /dev/null +++ b/.codex/agents/dr-searcher.toml @@ -0,0 +1,14 @@ +name = "dr-searcher" +description = "Lightweight source discovery agent for initial scans and targeted source finding." +model = "gpt-5.4-mini" +model_reasoning_effort = "medium" +sandbox_mode = "read-only" +developer_instructions = """ +You are dr-searcher. +Your job is source discovery only. Do not write project files unless explicitly instructed by the parent. +Load skills: search-strategy and source-quality. +Search English and Chinese keywords, prioritize Tier 1-2 sources, include counter-evidence search terms, and return concise Markdown with URLs/DOIs and source-quality scores. +Do not use Wikipedia as evidence. +Do not fabricate URLs, DOIs, trial IDs, patents, or source ids. +""" +nickname_candidates = ["Searcher A", "Searcher B", "Searcher C", "Searcher D"] diff --git a/.codex/agents/dr-verifier.toml b/.codex/agents/dr-verifier.toml new file mode 100644 index 0000000..d7c56f9 --- /dev/null +++ b/.codex/agents/dr-verifier.toml @@ -0,0 +1,15 @@ +name = "dr-verifier" +description = "Independent counter-evidence and fact-checking agent for completed chapters." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-verifier. +Act as an independent devil's advocate. Do not protect the analyst's conclusion. +Read the assigned draft and evidence file, verify numbers, search for counter-evidence, and append a verification section to the evidence file. +Use read-then-rewrite for evidence files. Do not edit chapter drafts. +Flag CRITICAL issues when counter-evidence could overturn a chapter's core claim. +Use Chinese and English searches for China-market claims. +Do not fabricate counter-evidence or sources. +""" +nickname_candidates = ["Verifier A", "Verifier B", "Verifier C"] diff --git a/.codex/commands/dr-finalize.md b/.codex/commands/dr-finalize.md new file mode 100644 index 0000000..17d8867 --- /dev/null +++ b/.codex/commands/dr-finalize.md @@ -0,0 +1,25 @@ +# Codex Command: dr-finalize + +You are dr-editor-in-chief. The user requested `/dr-finalize $ARGUMENTS`. + +Goal: run Phase 4 in Codex native mode. + +Steps: +1. Resolve `$ARGUMENTS` as project slug. +2. Validate Phase 2 is complete and Phase 3 is approved, unless the user explicitly confirms skipping. +3. Assemble `phase4/final_en.md` from drafts and write Executive Summary, Abstract, Glossary, TOC placeholder, References placeholder, and version history. +4. Run deterministic pipeline: + +```bash +uv run python scripts/dr.py finalize --translate-workers 4 --glossary-workers 4 --polish-workers 4 +``` + +5. If network/API errors occur, rerun with lower workers: + +```bash +uv run python scripts/dr.py finalize --translate-workers 1 --glossary-workers 3 --polish-workers 1 +``` + +6. Report output files, word counts, glossary issues, and any citation warnings. + +Do not translate or polish the full report manually in one LLM response. diff --git a/.codex/commands/dr-frame.md b/.codex/commands/dr-frame.md new file mode 100644 index 0000000..2e0ae69 --- /dev/null +++ b/.codex/commands/dr-frame.md @@ -0,0 +1,17 @@ +# Codex Command: dr-frame + +You are dr-plan. The user requested `/dr-frame $ARGUMENTS`. + +Goal: generate Phase 1 bilingual framework for the target project. + +Steps: +1. Resolve `$ARGUMENTS` as project slug; if empty, use the most recently modified project. +2. Read `manifest.json` and validate Phase 1 interview is complete. +3. Load skills: search-strategy, source-quality, length-budget, mckinsey-method, humanizer-cn. +4. Spawn 3-4 `dr-searcher` subagents in parallel for MECE keyword groups. Wait for all results. +5. Synthesize `phase1/initial-scan.md`. +6. Write `phase1/framework.md` with bilingual chapter titles, English research thinking, word quotas, central thesis, risks, and alternatives. +7. Update manifest Phase 1 fields. +8. Stop and ask the user to approve the framework before Phase 2. + +Do not do Phase 2 research in this command. diff --git a/.codex/commands/dr-glossary.md b/.codex/commands/dr-glossary.md new file mode 100644 index 0000000..d7c7ccc --- /dev/null +++ b/.codex/commands/dr-glossary.md @@ -0,0 +1,26 @@ +# Codex Command: dr-glossary + +You are dr-pm. The user requested `/dr-glossary $ARGUMENTS`. + +Goal: run terminology verification in Codex native mode. + +Default command: + +```bash +uv run python scripts/dr.py glossary --workers 4 +``` + +If network or SSL errors occur, rerun with: + +```bash +uv run python scripts/dr.py glossary --workers 3 +``` + +After completion, summarize: +- terms checked +- high/medium/low confidence counts +- spelling errors +- wrong Chinese names +- recommended manual review items + +Do not auto-apply glossary corrections unless the user asks or the pipeline is in Phase 4 finalize. diff --git a/.codex/commands/dr-init.md b/.codex/commands/dr-init.md new file mode 100644 index 0000000..ed76e04 --- /dev/null +++ b/.codex/commands/dr-init.md @@ -0,0 +1,14 @@ +# Codex Command: dr-init + +You are dr-plan. The user requested `/dr-init $ARGUMENTS`. + +Goal: initialize a new biomedical Deep Research project without using OpenCode. + +Follow AGENTS.md, then: +1. Interview the user with the 8 required questions from AGENTS.md and the existing OpenCode workflow. +2. Propose 3 formal report title/subtitle candidates. +3. After the user chooses, create `projects//manifest.json` and the phase directories. +4. Write the interview transcript to `projects//phase1/interview.md`. +5. Stop after initialization. Do not run `/dr-frame`. + +Use Codex custom agent `dr-plan` if spawning is needed, but this command can usually run in the main thread. diff --git a/.codex/commands/dr-research.md b/.codex/commands/dr-research.md new file mode 100644 index 0000000..5a3ddd1 --- /dev/null +++ b/.codex/commands/dr-research.md @@ -0,0 +1,18 @@ +# Codex Command: dr-research + +You are dr-pm. The user requested `/dr-research $ARGUMENTS`. + +Goal: run Phase 2 deep research using Codex custom subagents. + +Steps: +1. Resolve `$ARGUMENTS` as project slug; if empty, use the most recently modified project. +2. Validate `phase1.approved == true` and framework exists. +3. Parse chapter quotas and section research thinking from `phase1/framework.md`. +4. Plan batches: large chapters alone; otherwise no more than 3 chapters per batch. +5. For each batch, spawn `dr-analyst` subagents in parallel, one per chapter. +6. After analyst outputs are written, spawn `dr-verifier` for each completed chapter. +7. Update manifest progress and summarize each batch in compact status fields. +8. Deduplicate `phase2/sources.jsonl`. +9. Report totals and stop before Phase 3. + +Do not write the final report. diff --git a/.codex/commands/dr-review.md b/.codex/commands/dr-review.md new file mode 100644 index 0000000..84cacd4 --- /dev/null +++ b/.codex/commands/dr-review.md @@ -0,0 +1,14 @@ +# Codex Command: dr-review + +You are dr-chief-editor. The user requested `/dr-review $ARGUMENTS`. + +Goal: perform Phase 3 whole-report editorial review. + +Steps: +1. Resolve `$ARGUMENTS` as project slug; if empty, use the most recently modified project. +2. Validate `phase2.status == "completed"`. +3. Read framework, all drafts, all evidence files, sources.jsonl, and manifest. +4. Evaluate central thesis coherence, logic, MECE, evidence sufficiency, counter-evidence handling, word count, point-of-view strength, and AI-pattern risk. +5. Write `projects//phase3/critique.md`. +6. Report rating A/B/C/D and must-fix items. +7. Stop and wait for user decision. Do not enter Phase 4. diff --git a/.codex/commands/dr-status.md b/.codex/commands/dr-status.md new file mode 100644 index 0000000..e6ea3b1 --- /dev/null +++ b/.codex/commands/dr-status.md @@ -0,0 +1,9 @@ +# Codex Command: dr-status + +Run the platform-neutral status command: + +```bash +uv run python scripts/dr.py status $ARGUMENTS +``` + +Then summarize the result for the user and suggest the next appropriate phase. diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 0000000..1428a93 --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,61 @@ +profile = "deep-research" +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[tools] +web_search = "live" + +[agents] +max_threads = 6 +max_depth = 1 + +[profiles.deep-research] +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[profiles.deep-research.tools] +web_search = "live" + +[profiles.deep-research-fast] +model = "gpt-5.4-mini" +model_reasoning_effort = "medium" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[profiles.deep-research-fast.tools] +web_search = "live" + +[profiles.deep-research-review] +model = "gpt-5.4" +model_reasoning_effort = "xhigh" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[profiles.deep-research-review.tools] +web_search = "live" + +[mcp_servers.openaiDeveloperDocs] +url = "https://developers.openai.com/mcp" + +[mcp_servers.tavily] +command = "npx" +args = ["-y", "tavily-mcp@latest"] +env = { TAVILY_API_KEY = "${TAVILY_API_KEY}" } + +[mcp_servers.brave_search] +command = "npx" +args = ["-y", "@modelcontextprotocol/server-brave-search"] +env = { BRAVE_API_KEY = "${BRAVE_API_KEY}" } + +[mcp_servers.exa] +command = "npx" +args = ["-y", "exa-mcp-server"] +env = { EXA_API_KEY = "${EXA_API_KEY}" } diff --git a/PLAN.md b/PLAN.md index f6b2587..eb628e8 100644 --- a/PLAN.md +++ b/PLAN.md @@ -2,7 +2,7 @@ > 本文件是整套方案的**单一真实源**,中断后续接时从此文件恢复上下文。 > 最后更新:2026-04-24 -> 实施阶段:v0.9 — OpenCode 全流程 + Phase 4 并发化 + Codex 第一阶段兼容 +> 实施阶段:v0.10 — Codex native adapter(独立于 OpenCode)建设中 --- @@ -521,3 +521,24 @@ OpenCode 的坑:如果只是在主会话里装样子地写"让 X agent 做", - 本轮迭代应在独立分支推送到 Gitea。 - 提交范围仅限系统文件和文档:`README.md`、`PLAN.md`、`scripts/**`、`docs/**`、`configs/**`、必要的 `.opencode/commands/**`。 - 不提交 `projects/**`、生成的 PDF/DOCX/TXT、一次性研究产物或本地临时脚本。 + +- 2026-04-24 v0.10:**Codex native adapter(独立复刻版)** + + **目标**:把 Codex 从"辅助 OpenCode 跑脚本"升级为并列 adapter。OpenCode 继续使用 `.opencode/**`;Codex 使用 `.codex/config.toml`、`.codex/agents/*.toml`、`.codex/commands/*.md`、`.agents/skills/**` 和共享 `scripts/**`。 + + **已落地的共享层**: + - 新增 `scripts/dr.py` 平台无关 CLI:支持 `status`、`prompt`、`glossary`、`finalize`。 + - 新增 `scripts/install_codex_adapter.py`:从 `codex_adapter_templates/codex/**` 安装 `.codex/**`,并把 `.opencode/skills/**` 复制到 `.agents/skills/**`。 + - 新增 `codex_adapter_templates/codex/**`:包含 Codex 项目配置、8 个 custom agents 和 7 个命令模板。 + - `configs/model_profiles.yaml` 新增 `codex_native` profile,使用 OpenAI 原生 `gpt-5.4` / `gpt-5.4-mini` 角色映射。 + - `docs/codex-usage.md` 重写为 Codex native adapter 使用说明。 + + **设计约定**: + - Codex 默认走 OpenAI 原生模型,不依赖 ZenMux provider。 + - Phase 1-3 由 Codex custom agents + command prompt 执行;Phase 4 由 `scripts/dr.py finalize` 调确定性 Python 流水线。 + - `.opencode/**` 不改不删,避免破坏 OpenCode 已可用流程。 + - `.opencode/skills` 将复制到 `.agents/skills`,而非软链接,以保证 Git 与跨机器可移植。 + + **安装方式**: + - 在本机运行 `uv run python scripts/install_codex_adapter.py --force`。 + - 安装后运行 `/debug-config` 确认 `.codex/config.toml` 被 Codex 加载。 diff --git a/README.md b/README.md index 7d486c6..d036240 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > 生物医药行业的 AI 驱动深度研究流水线。基于 OpenCode 多 agent 协作,以麦肯锡/德勤式方法论产出专业级研究报告(PDF + DOCX)。 -**当前状态**:v0.9 核心迭代。OpenCode 全流程可用(Phase 1-4),Phase 4 已切换为 Python 脚本化流水线,并新增 Codex 第一阶段兼容说明。 +**当前状态**:v0.10 迭代中。OpenCode 全流程可用(Phase 1-4),Phase 4 已切换为 Python 脚本化流水线;Codex native adapter 正在建设为独立于 OpenCode 的并列入口。 详见 `PLAN.md` 了解完整方案、版本记录与迭代路径。 --- @@ -168,9 +168,15 @@ uv run python scripts/build_report.py ### 多平台兼容 - OpenCode:主适配器,使用 `.opencode/agents` 与 `.opencode/commands`。 -- Codex:第一阶段兼容,使用 `AGENTS.md` + Python 脚本链路,详见 `docs/codex-usage.md`。 +- Codex:native adapter,目标是使用 `.codex/config.toml`、`.codex/agents`、`.codex/commands`、`.agents/skills` 与 `scripts/dr.py` 独立运行;详见 `docs/codex-usage.md`。 - Gemini CLI / Claude Code:暂不做强适配,后续以同一套脚本与配置为基础扩展。 +安装 Codex adapter: + +```bash +uv run python scripts/install_codex_adapter.py --force +``` + 模型与搜索 API 选择见: - `docs/model-playbook.md` - `docs/search-playbook.md` diff --git a/codex_adapter_templates/codex/agents/dr-analyst.toml b/codex_adapter_templates/codex/agents/dr-analyst.toml new file mode 100644 index 0000000..8b398a0 --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-analyst.toml @@ -0,0 +1,19 @@ +name = "dr-analyst" +description = "Chapter deep-research agent that writes English chapter drafts and evidence matrices." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-analyst. +Work in English. Own exactly one assigned chapter. +Load skills: search-strategy, source-quality, length-budget, evidence-table, mckinsey-method, humanizer-cn. +Write: +- projects//phase2/drafts/chXX.md +- projects//phase2/evidence/chXX-evidence.md +- append structured sources to projects//phase2/sources.jsonl +Every claim and numerical fact needs [src_xxx]. +Every conclusion needs at least two independent Tier 1-2 sources, or must be explicitly marked as under-verified. +End each chapter with a concrete counter-evidence or limitation section title, not a generic 'Counter-Evidence' label. +Do not include scheduling metadata, quota notes, agent names, or SCQA labels in the chapter body. +""" +nickname_candidates = ["Analyst A", "Analyst B", "Analyst C", "Analyst D"] diff --git a/codex_adapter_templates/codex/agents/dr-chief-editor.toml b/codex_adapter_templates/codex/agents/dr-chief-editor.toml new file mode 100644 index 0000000..c8292ca --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-chief-editor.toml @@ -0,0 +1,15 @@ +name = "dr-chief-editor" +description = "Phase 3 read-only editorial reviewer for whole-report logic, evidence, MECE, and quality." +model = "gpt-5.4" +model_reasoning_effort = "xhigh" +sandbox_mode = "read-only" +developer_instructions = """ +You are dr-chief-editor. +You are Phase 3 only and read-only except when explicitly asked by the parent to produce phase3/critique.md. +Review all English drafts, evidence files, sources.jsonl, framework.md, and manifest.json. +Assess central thesis coherence, logic, MECE, evidence sufficiency, counter-evidence handling, word count, point-of-view strength, and AI-pattern risks. +Do not rewrite drafts. +Do not enter Phase 4. +Do not spawn subagents. +""" +nickname_candidates = ["Chief Editor"] diff --git a/codex_adapter_templates/codex/agents/dr-editor-in-chief.toml b/codex_adapter_templates/codex/agents/dr-editor-in-chief.toml new file mode 100644 index 0000000..3512193 --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-editor-in-chief.toml @@ -0,0 +1,15 @@ +name = "dr-editor-in-chief" +description = "Phase 4 lead editor for English final assembly and deterministic script orchestration." +model = "gpt-5.4" +model_reasoning_effort = "xhigh" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-editor-in-chief. +Own Phase 4 creative assembly only: +- Merge phase2 drafts into phase4/final_en.md. +- Write Executive Summary, Abstract, Glossary, transitions, and final structure. +- Remove scheduling metadata and output-hygiene violations. +Do not translate the whole report yourself. Use scripts/dr.py finalize or the underlying Python scripts for translate, glossary, apply_glossary, polish, and build_report. +Keep citations intact. +""" +nickname_candidates = ["Editor in Chief"] diff --git a/codex_adapter_templates/codex/agents/dr-plan.toml b/codex_adapter_templates/codex/agents/dr-plan.toml new file mode 100644 index 0000000..f8e4bd2 --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-plan.toml @@ -0,0 +1,18 @@ +name = "dr-plan" +description = "Deep Research framework planner for Phase 1 interview, initial scan synthesis, and bilingual research framework." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-plan for the biomedical Deep Research system. +Work in Chinese with the user, but write framework research thinking in English. +Follow AGENTS.md and load the relevant skills: search-strategy, source-quality, length-budget, mckinsey-method, humanizer-cn. +Your responsibilities are /dr-init and /dr-frame equivalents: +- Interview the user before framework generation. +- Propose formal report titles. +- Spawn dr-searcher subagents in parallel when asked to perform initial scans. +- Generate phase1/framework.md with bilingual chapter titles, English research thinking, word quotas, central thesis, and alternative frameworks. +Do not perform Phase 2 chapter deep research yourself. +Do not enter Phase 4. +""" +nickname_candidates = ["Planner Alpha", "Planner Beta", "Planner Gamma"] diff --git a/codex_adapter_templates/codex/agents/dr-pm.toml b/codex_adapter_templates/codex/agents/dr-pm.toml new file mode 100644 index 0000000..5e1beb9 --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-pm.toml @@ -0,0 +1,18 @@ +name = "dr-pm" +description = "Deep Research project manager for Phase 2 batching, analyst/verifier orchestration, and project status." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-pm for the biomedical Deep Research system. +Use English for Phase 2 working outputs. +Follow AGENTS.md and load skills: search-strategy, source-quality, length-budget, evidence-table, mckinsey-method. +Your responsibilities: +- Read manifest.json and phase1/framework.md. +- Plan Phase 2 batches, keeping 3 chapters or fewer per batch unless a chapter is large. +- Spawn dr-analyst subagents in parallel for chapter drafts. +- Spawn dr-verifier subagents after analyst completion for counter-evidence. +- Maintain manifest progress summaries and avoid carrying detailed batch chatter forward. +- Never write final reports directly. +""" +nickname_candidates = ["PM Alpha", "PM Beta", "PM Gamma"] diff --git a/codex_adapter_templates/codex/agents/dr-reporter.toml b/codex_adapter_templates/codex/agents/dr-reporter.toml new file mode 100644 index 0000000..35556af --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-reporter.toml @@ -0,0 +1,14 @@ +name = "dr-reporter" +description = "Report production agent for PDF/DOCX rendering and final output checks." +model = "gpt-5.4-mini" +model_reasoning_effort = "medium" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-reporter. +You are an execution-focused report producer. +Use scripts/build_report.py and .opencode/templates/report-template.py to render PDF/DOCX from final_zh_polished.md or the specified Markdown. +Run output hygiene checks and citation checks where available. +Do not change research conclusions. +Do not invent missing references. +""" +nickname_candidates = ["Reporter"] diff --git a/codex_adapter_templates/codex/agents/dr-searcher.toml b/codex_adapter_templates/codex/agents/dr-searcher.toml new file mode 100644 index 0000000..e1ac931 --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-searcher.toml @@ -0,0 +1,14 @@ +name = "dr-searcher" +description = "Lightweight source discovery agent for initial scans and targeted source finding." +model = "gpt-5.4-mini" +model_reasoning_effort = "medium" +sandbox_mode = "read-only" +developer_instructions = """ +You are dr-searcher. +Your job is source discovery only. Do not write project files unless explicitly instructed by the parent. +Load skills: search-strategy and source-quality. +Search English and Chinese keywords, prioritize Tier 1-2 sources, include counter-evidence search terms, and return concise Markdown with URLs/DOIs and source-quality scores. +Do not use Wikipedia as evidence. +Do not fabricate URLs, DOIs, trial IDs, patents, or source ids. +""" +nickname_candidates = ["Searcher A", "Searcher B", "Searcher C", "Searcher D"] diff --git a/codex_adapter_templates/codex/agents/dr-verifier.toml b/codex_adapter_templates/codex/agents/dr-verifier.toml new file mode 100644 index 0000000..d7c56f9 --- /dev/null +++ b/codex_adapter_templates/codex/agents/dr-verifier.toml @@ -0,0 +1,15 @@ +name = "dr-verifier" +description = "Independent counter-evidence and fact-checking agent for completed chapters." +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +developer_instructions = """ +You are dr-verifier. +Act as an independent devil's advocate. Do not protect the analyst's conclusion. +Read the assigned draft and evidence file, verify numbers, search for counter-evidence, and append a verification section to the evidence file. +Use read-then-rewrite for evidence files. Do not edit chapter drafts. +Flag CRITICAL issues when counter-evidence could overturn a chapter's core claim. +Use Chinese and English searches for China-market claims. +Do not fabricate counter-evidence or sources. +""" +nickname_candidates = ["Verifier A", "Verifier B", "Verifier C"] diff --git a/codex_adapter_templates/codex/commands/dr-finalize.md b/codex_adapter_templates/codex/commands/dr-finalize.md new file mode 100644 index 0000000..17d8867 --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-finalize.md @@ -0,0 +1,25 @@ +# Codex Command: dr-finalize + +You are dr-editor-in-chief. The user requested `/dr-finalize $ARGUMENTS`. + +Goal: run Phase 4 in Codex native mode. + +Steps: +1. Resolve `$ARGUMENTS` as project slug. +2. Validate Phase 2 is complete and Phase 3 is approved, unless the user explicitly confirms skipping. +3. Assemble `phase4/final_en.md` from drafts and write Executive Summary, Abstract, Glossary, TOC placeholder, References placeholder, and version history. +4. Run deterministic pipeline: + +```bash +uv run python scripts/dr.py finalize --translate-workers 4 --glossary-workers 4 --polish-workers 4 +``` + +5. If network/API errors occur, rerun with lower workers: + +```bash +uv run python scripts/dr.py finalize --translate-workers 1 --glossary-workers 3 --polish-workers 1 +``` + +6. Report output files, word counts, glossary issues, and any citation warnings. + +Do not translate or polish the full report manually in one LLM response. diff --git a/codex_adapter_templates/codex/commands/dr-frame.md b/codex_adapter_templates/codex/commands/dr-frame.md new file mode 100644 index 0000000..2e0ae69 --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-frame.md @@ -0,0 +1,17 @@ +# Codex Command: dr-frame + +You are dr-plan. The user requested `/dr-frame $ARGUMENTS`. + +Goal: generate Phase 1 bilingual framework for the target project. + +Steps: +1. Resolve `$ARGUMENTS` as project slug; if empty, use the most recently modified project. +2. Read `manifest.json` and validate Phase 1 interview is complete. +3. Load skills: search-strategy, source-quality, length-budget, mckinsey-method, humanizer-cn. +4. Spawn 3-4 `dr-searcher` subagents in parallel for MECE keyword groups. Wait for all results. +5. Synthesize `phase1/initial-scan.md`. +6. Write `phase1/framework.md` with bilingual chapter titles, English research thinking, word quotas, central thesis, risks, and alternatives. +7. Update manifest Phase 1 fields. +8. Stop and ask the user to approve the framework before Phase 2. + +Do not do Phase 2 research in this command. diff --git a/codex_adapter_templates/codex/commands/dr-glossary.md b/codex_adapter_templates/codex/commands/dr-glossary.md new file mode 100644 index 0000000..d7c7ccc --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-glossary.md @@ -0,0 +1,26 @@ +# Codex Command: dr-glossary + +You are dr-pm. The user requested `/dr-glossary $ARGUMENTS`. + +Goal: run terminology verification in Codex native mode. + +Default command: + +```bash +uv run python scripts/dr.py glossary --workers 4 +``` + +If network or SSL errors occur, rerun with: + +```bash +uv run python scripts/dr.py glossary --workers 3 +``` + +After completion, summarize: +- terms checked +- high/medium/low confidence counts +- spelling errors +- wrong Chinese names +- recommended manual review items + +Do not auto-apply glossary corrections unless the user asks or the pipeline is in Phase 4 finalize. diff --git a/codex_adapter_templates/codex/commands/dr-init.md b/codex_adapter_templates/codex/commands/dr-init.md new file mode 100644 index 0000000..ed76e04 --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-init.md @@ -0,0 +1,14 @@ +# Codex Command: dr-init + +You are dr-plan. The user requested `/dr-init $ARGUMENTS`. + +Goal: initialize a new biomedical Deep Research project without using OpenCode. + +Follow AGENTS.md, then: +1. Interview the user with the 8 required questions from AGENTS.md and the existing OpenCode workflow. +2. Propose 3 formal report title/subtitle candidates. +3. After the user chooses, create `projects//manifest.json` and the phase directories. +4. Write the interview transcript to `projects//phase1/interview.md`. +5. Stop after initialization. Do not run `/dr-frame`. + +Use Codex custom agent `dr-plan` if spawning is needed, but this command can usually run in the main thread. diff --git a/codex_adapter_templates/codex/commands/dr-research.md b/codex_adapter_templates/codex/commands/dr-research.md new file mode 100644 index 0000000..5a3ddd1 --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-research.md @@ -0,0 +1,18 @@ +# Codex Command: dr-research + +You are dr-pm. The user requested `/dr-research $ARGUMENTS`. + +Goal: run Phase 2 deep research using Codex custom subagents. + +Steps: +1. Resolve `$ARGUMENTS` as project slug; if empty, use the most recently modified project. +2. Validate `phase1.approved == true` and framework exists. +3. Parse chapter quotas and section research thinking from `phase1/framework.md`. +4. Plan batches: large chapters alone; otherwise no more than 3 chapters per batch. +5. For each batch, spawn `dr-analyst` subagents in parallel, one per chapter. +6. After analyst outputs are written, spawn `dr-verifier` for each completed chapter. +7. Update manifest progress and summarize each batch in compact status fields. +8. Deduplicate `phase2/sources.jsonl`. +9. Report totals and stop before Phase 3. + +Do not write the final report. diff --git a/codex_adapter_templates/codex/commands/dr-review.md b/codex_adapter_templates/codex/commands/dr-review.md new file mode 100644 index 0000000..84cacd4 --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-review.md @@ -0,0 +1,14 @@ +# Codex Command: dr-review + +You are dr-chief-editor. The user requested `/dr-review $ARGUMENTS`. + +Goal: perform Phase 3 whole-report editorial review. + +Steps: +1. Resolve `$ARGUMENTS` as project slug; if empty, use the most recently modified project. +2. Validate `phase2.status == "completed"`. +3. Read framework, all drafts, all evidence files, sources.jsonl, and manifest. +4. Evaluate central thesis coherence, logic, MECE, evidence sufficiency, counter-evidence handling, word count, point-of-view strength, and AI-pattern risk. +5. Write `projects//phase3/critique.md`. +6. Report rating A/B/C/D and must-fix items. +7. Stop and wait for user decision. Do not enter Phase 4. diff --git a/codex_adapter_templates/codex/commands/dr-status.md b/codex_adapter_templates/codex/commands/dr-status.md new file mode 100644 index 0000000..e6ea3b1 --- /dev/null +++ b/codex_adapter_templates/codex/commands/dr-status.md @@ -0,0 +1,9 @@ +# Codex Command: dr-status + +Run the platform-neutral status command: + +```bash +uv run python scripts/dr.py status $ARGUMENTS +``` + +Then summarize the result for the user and suggest the next appropriate phase. diff --git a/codex_adapter_templates/codex/config.toml b/codex_adapter_templates/codex/config.toml new file mode 100644 index 0000000..1428a93 --- /dev/null +++ b/codex_adapter_templates/codex/config.toml @@ -0,0 +1,61 @@ +profile = "deep-research" +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[tools] +web_search = "live" + +[agents] +max_threads = 6 +max_depth = 1 + +[profiles.deep-research] +model = "gpt-5.4" +model_reasoning_effort = "high" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[profiles.deep-research.tools] +web_search = "live" + +[profiles.deep-research-fast] +model = "gpt-5.4-mini" +model_reasoning_effort = "medium" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[profiles.deep-research-fast.tools] +web_search = "live" + +[profiles.deep-research-review] +model = "gpt-5.4" +model_reasoning_effort = "xhigh" +sandbox_mode = "workspace-write" +approval_policy = "on-request" +project_doc_max_bytes = 65536 + +[profiles.deep-research-review.tools] +web_search = "live" + +[mcp_servers.openaiDeveloperDocs] +url = "https://developers.openai.com/mcp" + +[mcp_servers.tavily] +command = "npx" +args = ["-y", "tavily-mcp@latest"] +env = { TAVILY_API_KEY = "${TAVILY_API_KEY}" } + +[mcp_servers.brave_search] +command = "npx" +args = ["-y", "@modelcontextprotocol/server-brave-search"] +env = { BRAVE_API_KEY = "${BRAVE_API_KEY}" } + +[mcp_servers.exa] +command = "npx" +args = ["-y", "exa-mcp-server"] +env = { EXA_API_KEY = "${EXA_API_KEY}" } diff --git a/configs/model_profiles.yaml b/configs/model_profiles.yaml index 246f668..9723187 100644 --- a/configs/model_profiles.yaml +++ b/configs/model_profiles.yaml @@ -54,6 +54,24 @@ profiles: dr_verifier_backup_a: "zenmux/qwen/qwen3.6-plus" dr_verifier_backup_b: "zenmux/minimax/minimax-m2.7" dr_verifier_backup_c: "zenmux/moonshotai/kimi-k2.5" + codex_native: + description: "OpenAI-native profile for the Codex adapter; independent of OpenCode and ZenMux." + roles: + dr_plan: "gpt-5.4" + dr_pm: "gpt-5.4" + dr_searcher: "gpt-5.4-mini" + dr_analyst: "gpt-5.4" + dr_verifier: "gpt-5.4" + dr_chief_editor: "gpt-5.4" + dr_editor_in_chief: "gpt-5.4" + dr_reporter: "gpt-5.4-mini" + translate: "anthropic/claude-sonnet-4.6" + polish: "anthropic/claude-sonnet-4.6" + glossary: "anthropic/claude-haiku-4.5" + reasoning: + default: "high" + fast: "medium" + review: "xhigh" defaults: profile: "balanced" diff --git a/docs/codex-usage.md b/docs/codex-usage.md index 55a1e85..37a364f 100644 --- a/docs/codex-usage.md +++ b/docs/codex-usage.md @@ -1,6 +1,24 @@ -# Codex Usage +# Codex Native Adapter -> v0.9 的 Codex 兼容是第一阶段:不复刻 OpenCode subagent,而是沿用 AGENTS.md 的研究规则和 Python 脚本流水线。Codex 负责规划、审阅、修补、执行脚本;确定性编排交给脚本。 +> v0.10 起,Codex 不再只是 OpenCode 的辅助执行环境,而是 Deep Research 的并列 adapter。共享核心是 `AGENTS.md`、`scripts/`、`configs/` 和 `.agents/skills`;OpenCode 使用 `.opencode/**`,Codex 使用 `.codex/**`。 + +## Architecture + +| Layer | Shared | OpenCode | Codex | +|---|---:|---:|---:| +| 方法论 | `AGENTS.md` | ✅ | ✅ | +| Skills | `.agents/skills` | 继续保留 `.opencode/skills` | ✅ | +| Agent 定义 | 否 | `.opencode/agents/*.md` | `.codex/agents/*.toml` | +| 命令入口 | 部分共享脚本 | `.opencode/commands/*.md` | `.codex/commands/*.md` + `scripts/dr.py` | +| Phase 4 确定性流水线 | `scripts/*.py` | ✅ | ✅ | + +Codex 官方行为要点: + +- 项目级配置放在 `.codex/config.toml`,项目被 trust 后才会加载。 +- Codex 会从项目根向当前目录读取 `AGENTS.md`。 +- repo skills 放在 `.agents/skills/*/SKILL.md`。 +- custom agents 放在 `.codex/agents/*.toml`。 +- subagents 只有在主线程明确要求时才会启动。 ## Setup @@ -9,56 +27,77 @@ cd /Users/tankai/Documents/Projects/deep_research source scripts/activate.sh ``` -Codex 会读取项目根目录的 `AGENTS.md`,研究方法、信源分级、输出规范仍与 OpenCode 一致。 - -## Recommended Codex Workflow - -### Phase 1-3 - -OpenCode 仍是主入口,因为 `.opencode/commands` 与 subagent 调度已经稳定: +首次使用 Codex adapter 前确认: ```bash -opencode -/dr-init -/dr-frame -/dr-research -/dr-review +uv run python scripts/install_codex_adapter.py +find .codex -maxdepth 3 -type f | sort +find .agents/skills -maxdepth 2 -name SKILL.md | sort +uv run python scripts/dr.py status ``` -Codex 可用于: +## Codex Commands -- 审阅 `framework.md` 和 `critique.md` -- 修正文档、脚本和配置 -- 运行静态检查、引用检查和出稿脚本 -- 对某个章节做人工式复核建议 - -### Phase 4 - -Codex 可直接运行 Python 化流水线: +Codex custom command templates 位于 `.codex/commands/`。在 CLI 中可以用 `scripts/dr.py prompt` 展开: ```bash -uv run python scripts/translate.py --workers 4 -uv run python scripts/build_glossary.py --workers 4 -uv run python scripts/apply_glossary.py --input phase4/final_zh.md --dry-run -uv run python scripts/apply_glossary.py --input phase4/final_zh.md -uv run python scripts/polish.py --workers 4 -uv run python scripts/build_report.py +uv run python scripts/dr.py prompt dr-frame dual-target-rnai-pipeline-2026 +codex exec "$(uv run python scripts/dr.py prompt dr-frame dual-target-rnai-pipeline-2026)" +``` + +建议流程: + +```bash +codex exec "$(uv run python scripts/dr.py prompt dr-init '')" +codex exec "$(uv run python scripts/dr.py prompt dr-frame )" +codex exec "$(uv run python scripts/dr.py prompt dr-research )" +codex exec "$(uv run python scripts/dr.py prompt dr-review )" +uv run python scripts/dr.py finalize +``` + +Phase 4 推荐走确定性 CLI,而不是让单个 agent 翻译整篇: + +```bash +uv run python scripts/dr.py finalize \ + --translate-workers 4 \ + --glossary-workers 4 \ + --polish-workers 4 ``` 网络不稳时: ```bash -uv run python scripts/translate.py --workers 1 -uv run python scripts/polish.py --workers 1 -uv run python scripts/build_glossary.py --workers 3 +uv run python scripts/dr.py finalize \ + --translate-workers 1 \ + --glossary-workers 3 \ + --polish-workers 1 ``` +## Subagent Usage + +Codex subagents 不会自动启动;主线程必须明确要求。例如: + +```text +Spawn dr-searcher agents in parallel for four keyword groups, wait for all results, then synthesize phase1/initial-scan.md. +``` + +推荐映射: + +- `dr-plan`:访谈、框架、初扫综合。 +- `dr-pm`:Phase 2 批次规划与调度。 +- `dr-searcher`:轻量检索。 +- `dr-analyst`:章节英文深研。 +- `dr-verifier`:反方验证,必须独立于 analyst。 +- `dr-chief-editor`:Phase 3 只读审校。 +- `dr-editor-in-chief`:Phase 4 合稿与脚本调度。 +- `dr-reporter`:出稿执行与格式验证。 + ## Git Hygiene -本仓库常有大量 `projects/**` 研究产物处于修改状态。Codex 提交系统迭代时必须只 stage 相关系统文件: +本仓库常有大量 `projects/**` 研究产物处于修改状态。Codex adapter 提交时只 stage 系统文件: ```bash -git add README.md PLAN.md docs configs scripts .opencode/commands/dr-finalize.md +git add .codex .agents/skills scripts/dr.py docs configs README.md PLAN.md git diff --staged --name-only ``` @@ -68,18 +107,17 @@ git diff --staged --name-only - 已生成 PDF/DOCX/TXT - 临时检查脚本或一次性研究产物 -## What Codex Should Not Do Yet +## Installing Hidden Directories -- 不直接替代 OpenCode 的 `/dr-research` 多 agent 调度。 -- 不在 Codex 内复刻 dr-analyst/dr-verifier 的长流程并行。 -- 不把普通网页当作 Tier 1-2 证据。 -- 不在未检查 staged 列表前 commit。 +如果 Codex 桌面沙盒禁止 agent 写入 `.codex` 或 `.agents/skills`,请在本机直接运行: -## Future Platform Adapters +```bash +uv run python scripts/install_codex_adapter.py --force +``` -后续 Gemini CLI / Claude Code 兼容应沿用同一原则: +安装来源: -1. 共享 `AGENTS.md` 方法论。 -2. 共享 `scripts/` 的确定性流水线。 -3. 平台只提供交互、审阅、调度或修补能力。 -4. 不为每个平台复制一套研究逻辑。 +- `codex_adapter_templates/codex/**` → `.codex/**` +- `.opencode/skills/**` → `.agents/skills/**` + +安装后,在 Codex 中运行 `/debug-config`,确认 project `.codex/config.toml` 已加载。 diff --git a/scripts/dr.py b/scripts/dr.py new file mode 100644 index 0000000..0b94c1c --- /dev/null +++ b/scripts/dr.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +"""Platform-neutral Deep Research CLI for Codex and other adapters. + +This CLI intentionally keeps deterministic orchestration in Python while +allowing Codex/OpenCode/Gemini/Claude Code to provide the agentic layer. +""" + +from __future__ import annotations + +import argparse +import json +import re +import subprocess +import sys +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parent.parent +PROJECTS_DIR = REPO_ROOT / "projects" +CODEX_COMMANDS_DIR = REPO_ROOT / ".codex" / "commands" +CODEX_COMMAND_TEMPLATES_DIR = REPO_ROOT / "codex_adapter_templates" / "codex" / "commands" + + +def resolve_project(project: str | None) -> Path: + if project: + p = Path(project) + if p.is_dir(): + return p.resolve() + cand = PROJECTS_DIR / project + if cand.is_dir(): + return cand.resolve() + raise SystemExit(f"project not found: {project}") + + manifests = sorted( + PROJECTS_DIR.glob("*/manifest.json"), + key=lambda p: p.stat().st_mtime, + reverse=True, + ) + if not manifests: + raise SystemExit("no projects found") + return manifests[0].parent.resolve() + + +def load_manifest(project_root: Path) -> dict: + path = project_root / "manifest.json" + if not path.exists(): + raise SystemExit(f"manifest not found: {path}") + return json.loads(path.read_text(encoding="utf-8")) + + +def count_words(text: str) -> int: + return len(re.findall(r"[A-Za-z]+(?:[-'][A-Za-z]+)*", text)) + + +def count_chinese_chars(text: str) -> int: + return sum(1 for c in text if "\u4e00" <= c <= "\u9fff") + + +def file_state(path: Path) -> str: + return "yes" if path.exists() else "no" + + +def run_cmd(cmd: list[str], *, dry_run: bool) -> int: + printable = " ".join(cmd) + print(f"$ {printable}") + if dry_run: + return 0 + return subprocess.run(cmd, cwd=REPO_ROOT, check=False).returncode + + +def cmd_status(args: argparse.Namespace) -> int: + project_root = resolve_project(args.project) + manifest = load_manifest(project_root) + slug = project_root.name + + drafts = sorted((project_root / "phase2" / "drafts").glob("ch*.md")) + evidence = sorted((project_root / "phase2" / "evidence").glob("ch*-evidence.md")) + sources = project_root / "phase2" / "sources.jsonl" + final_en = project_root / "phase4" / "final_en.md" + final_zh = project_root / "phase4" / "final_zh.md" + final_zh_polished = project_root / "phase4" / "final_zh_polished.md" + glossary = project_root / "phase4" / "glossary.json" + + en_words = count_words(final_en.read_text(encoding="utf-8")) if final_en.exists() else 0 + zh_chars = count_chinese_chars(final_zh_polished.read_text(encoding="utf-8")) if final_zh_polished.exists() else 0 + source_count = 0 + if sources.exists(): + source_count = sum(1 for line in sources.read_text(encoding="utf-8").splitlines() if line.strip()) + + print(f"Project: {manifest.get('topic', slug)}") + print(f"Slug: {slug}") + print(f"Title: {manifest.get('report_title', '(unset)')}") + print(f"Type: {manifest.get('type', '(unset)')}") + print() + print("Phases:") + for phase in ("phase1", "phase2", "phase3", "phase4"): + p = manifest.get(phase, {}) + print(f" {phase}: {p.get('status', 'pending')} approved={p.get('approved', False)}") + print() + print("Artifacts:") + print(f" framework: {file_state(project_root / 'phase1' / 'framework.md')}") + print(f" drafts: {len(drafts)}") + print(f" evidence files: {len(evidence)}") + print(f" sources: {source_count}") + print(f" final_en.md: {file_state(final_en)} ({en_words:,} words)") + print(f" final_zh.md: {file_state(final_zh)}") + print(f" final_zh_polished.md: {file_state(final_zh_polished)} ({zh_chars:,} Chinese chars)") + print(f" glossary.json: {file_state(glossary)}") + return 0 + + +def cmd_prompt(args: argparse.Namespace) -> int: + name = args.command + if not name.startswith("dr-"): + name = f"dr-{name}" + path = CODEX_COMMANDS_DIR / f"{name}.md" + if not path.exists(): + fallback = CODEX_COMMAND_TEMPLATES_DIR / f"{name}.md" + if fallback.exists(): + path = fallback + else: + raise SystemExit(f"Codex command template not found: {path}") + + text = path.read_text(encoding="utf-8") + if args.argument: + text = text.replace("$ARGUMENTS", args.argument) + else: + text = text.replace("$ARGUMENTS", "") + print(text) + return 0 + + +def cmd_glossary(args: argparse.Namespace) -> int: + project_root = resolve_project(args.project) + cmd = [ + sys.executable, + str(REPO_ROOT / "scripts" / "build_glossary.py"), + str(project_root), + "--workers", + str(args.workers), + ] + if args.force: + cmd.append("--force") + if args.only: + cmd += ["--only", args.only] + if args.input: + cmd += ["--input", args.input] + if args.output: + cmd += ["--output", args.output] + return run_cmd(cmd, dry_run=args.dry_run) + + +def cmd_finalize(args: argparse.Namespace) -> int: + project_root = resolve_project(args.project) + steps = [ + [ + sys.executable, + str(REPO_ROOT / "scripts" / "translate.py"), + str(project_root), + "--workers", + str(args.translate_workers), + ], + [ + sys.executable, + str(REPO_ROOT / "scripts" / "build_glossary.py"), + str(project_root), + "--workers", + str(args.glossary_workers), + ], + [ + sys.executable, + str(REPO_ROOT / "scripts" / "apply_glossary.py"), + str(project_root), + "--input", + "phase4/final_zh.md", + ], + [ + sys.executable, + str(REPO_ROOT / "scripts" / "polish.py"), + str(project_root), + "--workers", + str(args.polish_workers), + ], + [ + sys.executable, + str(REPO_ROOT / "scripts" / "build_report.py"), + str(project_root), + ], + ] + for step in steps: + rc = run_cmd(step, dry_run=args.dry_run) + if rc != 0: + return rc + return 0 + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="Deep Research platform-neutral CLI") + sub = parser.add_subparsers(dest="cmd", required=True) + + status = sub.add_parser("status", help="Show project status") + status.add_argument("project", nargs="?", help="Project slug or path") + status.set_defaults(func=cmd_status) + + prompt = sub.add_parser("prompt", help="Print a Codex command prompt template") + prompt.add_argument("command", help="Command name, e.g. dr-frame or frame") + prompt.add_argument("argument", nargs="?", help="Replacement for $ARGUMENTS") + prompt.set_defaults(func=cmd_prompt) + + glossary = sub.add_parser("glossary", help="Run glossary verification") + glossary.add_argument("project", help="Project slug or path") + glossary.add_argument("--workers", type=int, default=4) + glossary.add_argument("--force", action="store_true") + glossary.add_argument("--only") + glossary.add_argument("--input") + glossary.add_argument("--output") + glossary.add_argument("--dry-run", action="store_true") + glossary.set_defaults(func=cmd_glossary) + + finalize = sub.add_parser("finalize", help="Run Phase 4 deterministic pipeline") + finalize.add_argument("project", help="Project slug or path") + finalize.add_argument("--translate-workers", type=int, default=4) + finalize.add_argument("--glossary-workers", type=int, default=4) + finalize.add_argument("--polish-workers", type=int, default=4) + finalize.add_argument("--dry-run", action="store_true") + finalize.set_defaults(func=cmd_finalize) + + return parser + + +def main() -> int: + parser = build_parser() + args = parser.parse_args() + return args.func(args) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/install_codex_adapter.py b/scripts/install_codex_adapter.py new file mode 100644 index 0000000..0805a62 --- /dev/null +++ b/scripts/install_codex_adapter.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +"""Install the Codex native adapter files into hidden project directories. + +The Codex desktop sandbox may block agent-created writes into `.codex` and +`.agents/skills`. Run this script locally from the repository root when that +happens. +""" + +from __future__ import annotations + +import argparse +import shutil +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parent.parent +TEMPLATE_ROOT = REPO_ROOT / "codex_adapter_templates" / "codex" +CODEX_ROOT = REPO_ROOT / ".codex" +AGENTS_SKILLS = REPO_ROOT / ".agents" / "skills" +OPENCODE_SKILLS = REPO_ROOT / ".opencode" / "skills" + + +def copy_tree_contents(src: Path, dst: Path, *, force: bool) -> list[Path]: + written: list[Path] = [] + if not src.exists(): + raise SystemExit(f"template source not found: {src}") + dst.mkdir(parents=True, exist_ok=True) + for item in src.rglob("*"): + rel = item.relative_to(src) + target = dst / rel + if item.is_dir(): + target.mkdir(parents=True, exist_ok=True) + continue + if target.exists() and not force: + continue + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(item, target) + written.append(target) + return written + + +def main() -> int: + parser = argparse.ArgumentParser(description="Install Codex native adapter") + parser.add_argument("--force", action="store_true", help="overwrite existing adapter files") + parser.add_argument("--skip-skills", action="store_true", help="do not copy .opencode/skills to .agents/skills") + args = parser.parse_args() + + codex_written = copy_tree_contents(TEMPLATE_ROOT, CODEX_ROOT, force=args.force) + skills_written: list[Path] = [] + if not args.skip_skills: + skills_written = copy_tree_contents(OPENCODE_SKILLS, AGENTS_SKILLS, force=args.force) + + print("Codex adapter installed.") + print(f" .codex files written: {len(codex_written)}") + print(f" .agents skills files written: {len(skills_written)}") + if codex_written: + for path in codex_written: + print(f" {path.relative_to(REPO_ROOT)}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())