feat(skill): brief 重定位为重要文献速览(论文列表+总结,只描述不给建议)+ 精简三文件 + bump 0.20.0

- 重定位:重要论文列表(各大期刊,Elsevier 数据库优先,每篇带简介/摘要概述)+ 内容总结;去掉建议/启示/热点聚类/判断
- 三路取数:research + documents 取文献为主力,web search 取政策·标准·产业动向单列(不混进论文总结)
- 精简 8→3 文件:SKILL.md 自包含(spec 字段/骨架/检索法/核验铁律/渲染说明)+ references/journals.md(各建材子领域主流期刊清单,Elsevier 标注 + 精确 publication_name + 0 命中降级)+ scripts/render_docx.py;删 templates/spec.md、templates/brief_outline.md、references/search_strategy.md、references/citation_verify.md、scripts/quality_check.py
- render_docx.py:论文列表段(标题含"论文列表/文献列表/参考文献")H3 期刊子标题下的 [n] 条目仍作锚点(只在 H1/H2 重判段类型);条目内 DOI 子串(末尾 "DOI: 10.xxx")也做 https://doi.org 超链接;smoke test 验证锚点/回链/外链/化学式下标全在

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-06-18 15:24:31 +08:00
parent 108351864e
commit 2b9a7febde
11 changed files with 174 additions and 602 deletions

View File

@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`
最后更新:2026-06-18(定时任务 v1:scheduled_jobs 表 + plain-asyncio 守护循环 + 3 工具 + send_email,DESIGN §8.5)
最后更新:2026-06-18(brief 简报重定位为「重要文献速览」+ 精简到三文件 + bump 0.20.0)
---
@ -21,6 +21,14 @@
## 已完成关键能力
### 2026-06-18 / brief 简报重定位「重要文献速览」+ 精简三文件(bump 0.20.0)
- 需求漂移收敛:brief 从"热点聚类趋势判断型简报"重定位为**「重要论文列表 + 内容总结」速览型** —— ①只描述不给建议(去掉启示/判断/空白争议);②开头一份重要期刊论文列表(各大相关刊、**Elsevier 数据库优先**),每篇带一段简介/摘要概述;③对这批论文做客观总结即可。
- 数据源:**research + documents 都是取文献主力**(research 逐刊精确取最新 Elsevier 论文 + DOI;documents 取内部材料库全文),web search 取动向**单列**不混进论文总结。
- **精简到三文件**(原 8 文件):`SKILL.md`(自包含:spec 字段/骨架/检索法/核验铁律/渲染说明)+ `references/journals.md`(各建材子领域主流期刊清单,Elsevier 标注 + 精确 publication_name + 0 命中降级)+ `scripts/render_docx.py`。删 `templates/spec.md`、`templates/brief_outline.md`、`references/search_strategy.md`、`references/citation_verify.md`、`scripts/quality_check.py`。
- `render_docx.py` 两处小改并已 smoke test 验证:①「重要论文列表」段(标题含"论文列表/文献列表/参考文献")H3 期刊子标题下的 `[n]` 条目仍作锚点(只在 H1/H2 重判段类型);②条目内 DOI 子串(末尾 "DOI: 10.xxx")也做 https://doi.org 超链接。验证:ref 锚点/内部回链/外部 DOI 链/化学式下标全在。
- 文件:`skills/brief/{SKILL.md,references/journals.md,scripts/render_docx.py}`;`core/__init__.py` 0.19.0→0.20.0;`SKILL_LIST.md`(brief 条目重写,总数仍 17)同步。
### 2026-06-18 / 定时任务 v1(scheduled_jobs,DESIGN §8.5)
- 需求:对话方式建"每天 X 点干 Y"的定时任务(跑 skill 出简报 / 发邮件 / 打招呼皆可)。调研 OpenClaw/Autobot/Claude Code/geta 四源收敛,定方案见 DESIGN §8.5。

View File

@ -23,7 +23,7 @@ zcbot 的"skill"是一份可加载的工作流脚本(`skills/<name>/SKILL.md` +
| 演示出图 | [plot_pub](#plot_pub) | 出版级 matplotlib 学术图(中文 + viridis + 矢量 + 投稿级复合图设计纪律) |
| 文献检索 | [research](#research) | 查 paper_server(OpenAlex 元数据 + Sci-Hub 下载) |
| 文献检索 | [documents](#documents) | 查内部 7 学科材料知识库(100W+ 论文,跨语言检索;host-side tool 持 key) |
| 文献检索 | [brief](#brief) | 科研方向简报:三路检索(内部库 + research + web)→ 热点聚类趋势简报 |
| 文献检索 | [brief](#brief) | 科研方向简报:三路检索(research + 内部库取文献 / web 取动向)→ 重要论文列表(带摘要概述)+ 内容总结,只描述不给建议 |
| 科研计算 | [pymatgen](#pymatgen) | 晶体结构 / XRD 模拟 / 相图 / Materials Project(host-side tool 持 key) |
| 科研计算 | [stats_ml](#stats_ml) | 配方-性能建模与机器学习(三库分工) |
| 内容生成 | [imagegen](#imagegen) | 豆包 Seedream 5.0 文生图 + 改图 i2i(¥0.22 / 张) |
@ -291,32 +291,32 @@ paper_server 是内部 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 S
---
### brief
**生成科研方向简报(文献计量趋势型简报)。**
**生成科研方向简报(重要文献速览)。**
给定一个研究方向 + 时间窗,用**三路真实数据**(documents 内部库取全文 / research 取近期 DOI 元数据 / web 取政策·会议·标准动向)产出一份**有判断、可溯源**的简报:热点聚类 + 新兴方法 + 关键进展 + 研究空白 + 产业政策动向。简报 ≠ 综述论文 —— 要**快、准、有取舍**("重要性优先于完整性"),帮决策者 / 课题组 520 分钟掌握一个方向近期态势
给定一个研究方向 + 时间窗,从各大相关期刊(**Elsevier 数据库优先**)挑选近期**重要论文**,产出两段式简报:**先一份重要论文列表(每篇带标题/作者/期刊/年月/DOI + 一段简介或摘要概述),再对这批论文做内容总结**。三路取数:research(逐刊精确取最新 Elsevier 论文 + DOI)+ documents(内部材料库取全文)取文献,web search 取政策·标准·产业动向(单列)。**只描述不给建议**——呈现"发了什么、讲了什么",判断留给读者。简报 ≠ 综述论文,要**快、准、客观**,520 分钟掌握一个方向近期发了哪些重要论文
**六阶段**:定题对齐 spec(方向+边界 / 时间窗 / 受众 / 深度 / 源开关 / 语言 / 关注点)→ 三路检索取数(中→英术语转译 + 跨源去重,证据表)→ 趋势分析(37 热点簇,对齐后再写)→ 逐段起草 → 引文核验(复用 paper 三层协议)→ 渲染验收。
**五阶段**:定题对齐 spec(方向+边界 / 时间窗 / 期刊范围 / 深度 / 数据源 / 语言 / 关注点)→ 三路取数(research+documents 取文献、web 取动向;中→英术语转译 + 跨源去重)→ 列清单(带摘要概述)+ 内容总结 → 引文核验 → 渲染验收。
**深度三档**:`flash` 快报(12 页)/ `standard` 标准(46 页)/ `deep` 深度(8+ 页,含机构-地理计量),各配字数 / 簇数 / 引文数预算
**深度三档(按篇数)**:`flash` 1020 篇 / `standard` 2040 篇 / `deep` 4080 篇
**何时用**:
- ✅ 用户要"简报 / 方向简报 / 研究动态 / 趋势报告 / 调研快报 / 跟踪某领域最新研究 / 某方向近期进展"
- ✅ 立项前想快速摸清一个方向近期态势再决定要不要做(产出可喂 proposal / analyze)
- ✅ 用户要"简报 / 方向简报 / 最新文献 / 重要论文列表 / 研究动态 / 某方向近期重要论文 / 跟踪某领域最新研究"
- ✅ 立项前想快速摸清一个方向近期发了哪些重要论文(产出可喂 proposal / analyze)
**何时不用**:
- ⛔ 只要文献清单 / DOI / PDF → research / documents
- ⛔ 要写可投稿的综述论文(几十页、定论)→ paper(review 类型)
- ⛔ 要把模糊科学问题拆成子问题 + 路线图 → analyze
- ⛔ 要写本子 → proposal
- ⛔ 要"对本院的建议" / 写本子 → proposal
**核心能力**:
- **三路检索分工 + 去重**(`search_strategy.md`):documents 全文首选、research 补 DOI 卡 year_gte、web 单列产业政策动向不混学术引文计数;中文方向→英文术语转译(SCM/LC3 等缩写展开)
- **趋势分析纪律**:热点聚成簇(主题句写判断不堆关键词)、新兴方法、争议空白、机构-地理格局(deep);取舍优先于穷尽
- **引文核验**(复用 paper 三层协议):存在性 / 三角印证 / 支撑度,编造零容忍;web 来源标 URL + 日期 + 文号
- `quality_check.py`:结构 / 簇数预算 / 过度宣称 / **无源句式**("据报道""有研究表明"无引文)/ 引文交叉核对
- **自带 `render_docx.py`**:商务红主题 + 正文 `[n]`/`[Wn]` 引文上标并锚到文末 + DOI/URL 可点击超链接 + 化学式下标(CO₂/C₃S...,白名单不误伤 LC3/Ca2+)+ TL;DR / 判断 callout 底纹;做 deck 转 ppt
- **逐刊取重要论文**(`references/journals.md`):各建材子领域主流期刊清单(Elsevier 优先),精确 `publication_name` + `year_gte` 取最新,0 命中降级到 keyword 搜;按重要性(期刊层级 + 主题相关性 + 发现分量)筛、按 publication_date 留最新
- **三路分工 + 去重**:research+documents 取文献(同 DOI 一条、documents 全文优先)、web 单列产业政策动向不混论文总结;中文方向→英文术语转译(SCM/LC3 等缩写展开)
- **每篇带摘要概述**:列表不只标题,每篇 24 句讲研究对象/方法/主要发现,基于 abstract 或全文、不夸张不评判
- **引文核验**:存在性 / DOI 真伪(以库返回字段为准)/ 支撑度(摘要概述与原文一致,partial 改概述迁就证据),编造零容忍
- **自带 `render_docx.py`**:商务红主题 + 论文列表 `[n]` 作锚点、正文 `[n]`/`[Wn]` 引文上标回链 + DOI/URL 可点击超链接(条目内 DOI 子串也链)+ 化学式下标(CO₂/C₃S...,白名单不误伤 LC3/Ca2+);做 deck 转 ppt
**典型产物**:`<方向>-简报.md`(默认)+ `evidence.md`(证据表)+ `CITATIONS.md`(引文核验台账);可选转 docx / deck。
**典型产物**:`<方向>-简报.md`(默认,含 `01_papers` 重要论文列表 + `02_summary` 内容总结)+ `evidence.md`(证据表);可选转 docx / deck。
---
@ -528,7 +528,7 @@ paper_server 是内部 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 S
- **写本子全流程**:analyze(拆问题) → research / documents(查文献) → stats_ml(算配方-性能模型出预实验数据) → plot_pub(出图) → proposal(写本子) → review(审稿)
- **写专利全流程**:patent(挖点 + 检索 + 起草) → research(查现有技术) → plot_pub(出附图) → review(终审)
- **写标准全流程**:analyze(定标准化对象) → stats_ml(配方-性能 / 精密度试验数据定指标) → research / documents(查国内外现有标准与现状) → standard(起草标准 + 编制说明) → plot_pub(出图) → review(送审前终审)
- **方向简报 → 立项**:brief(三路检索摸方向近期态势) → analyze(把方向拆成子问题 + 路线图) → proposal(写本子) / paper(写综述);简报要做成汇报 → ppt
- **方向简报 → 立项**:brief(三路取数,出重要论文列表 + 内容总结,只描述) → analyze(把方向拆成子问题 + 路线图) → proposal(写本子、给建议) / paper(写综述);简报要做成汇报 → ppt
- **PPT 汇报**:analyze(提炼论点) → research / documents(找数据 + 引文) → plot_pub(出图) → ppt(组装 deck) → imagegen(可选,做封面 / 引子页)
- **晶体计算**:pymatgen(算 XRD / 相图) → plot_pub(出图) → proposal / patent(写到本子 / 交底书里)
- **定制能力**:skill-creator(fork 某内置 skill,如 ppt / proposal) → 改造成本组 / 本人专属版本(术语 / 模板 / 默认值),之后日常任务直接用改造版

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。
__version__ = "0.19.0"
__version__ = "0.20.0"

View File

@ -1,114 +1,108 @@
---
name: brief
description: 生成科研方向简报(research direction briefing / 文献计量趋势型简报)。给定一个研究方向 + 时间窗,用三路真实数据(documents 内部库取全文 / research 取近期 DOI 元数据 / web 取政策·会议·标准动向),产出一份热点聚类 + 新兴方法 + 关键进展 + 研究空白 + 产业政策动向的可读简报,每条论断可溯源、不编造引文。当用户要"简报 / 方向简报 / 研究动态 / 趋势报告 / 调研快报 / 某方向近期进展 / 文献综述快讯 / 跟踪某领域最新研究"时使用。
description: 生成科研方向简报(research direction briefing / 重要文献速览)。给定一个研究方向 + 时间窗,从各大相关期刊(Elsevier 数据库优先)挑选近期重要论文,产出一份「重要论文列表 + 内容总结」的可读简报:先列清单(每篇带标题/作者/期刊/年月/DOI + 一段简介或摘要概述),再对这批论文做客观归纳。可溯源、不编造引文,**只描述不给建议**。当用户要"简报 / 方向简报 / 最新文献 / 重要论文列表 / 研究动态 / 某方向近期重要论文 / 跟踪某领域最新研究"时使用。
---
# 科研方向简报
# 科研方向简报(重要文献速览)
把"某研究方向最近发生了什么"变成一份**可读、可溯源、有判断**的简报。**先定题对齐 → 三路检索取数 → 趋势分析 → 逐段起草 → 引文核验渲染** —— 不要一口气出全文,定题和分析阶段先和用户对齐方向与边界
把"某方向近期发了哪些重要论文、都在讲什么"做成一份**可读、可溯源、客观**的简报。两段式:**先一份重要期刊论文列表(各大相关期刊、Elsevier 数据库优先;每篇带一段简介/摘要概述),再对这批论文做内容总结**
简报 ≠ 综述论文(paper review):综述要全面、深、给定论;简报要**快、准、有取舍**——"重要性优先于完整性",帮决策者 / 课题组 520 分钟掌握一个方向近期态势。
> **只描述、不给建议。** 简报呈现"发了什么、讲了什么",不给"本院应当……/可切入……/建议……"。判断留给读者。
>
> **"重要"怎么挑**:来自主流期刊(Elsevier 旗舰刊优先)、方向上居中而非边缘、有实质发现。近期论文引用尚少,故主要看**期刊层级 + 主题相关性 + 发现的分量**,不是单纯按引用数。控量靠"重要性 + 时新",不靠主观褒贬。
进度展示建议:用 `task_progress` 标记「定题对齐 / 三路检索 / 趋势分析 / 逐段起草 / 引文核验 / 渲染」关键阶段。
简报 ≠ 综述论文(paper review):综述要全面、深、给定论;简报要**快、准、客观**——520 分钟掌握一个方向近期发了哪些重要论文、各讲了什么
## 边界(先划清,免得和别的 skill 撞)
## 边界(免得和别的 skill 撞)
| 与谁区分 | 边界 |
|---|---|
| vs `research`/`documents` | 它们**只取文献**(候选清单 / 全文);brief 是消费方,把取回的文献**组织成有判断的趋势简报**,引文核验接到它们头上 |
| vs `paper`(review 类型) | paper-review 写**可投稿的综述论文**(IMRaD/主题式、几十页、定论);brief 出**轻量趋势简报**(几页、有取舍、面向决策),不投稿 |
| vs `analyze` | analyze 把**模糊科学问题**拆成子问题 + 路线图(不查文献);brief 围绕**一个已定方向**摸近期态势(重检索)。两者可互为上下游(先拆问题再摸态势,或先摸态势再拆) |
| vs `proposal` | proposal 写**本子**(立项依据);brief 只摸方向近期态势,不写立项依据。要立项 → 把简报喂给 proposal |
- vs `research`/`documents`:它们**只取文献**;brief 把取回的论文**组织成可读列表 + 客观总结**。
- vs `paper`(review):paper 写**可投稿综述**(几十页、定论);brief 出**轻量速览**(几页、客观、不给判断)。
- vs `analyze`:analyze 拆**科学问题**;brief 围绕**已定方向**列近期重要论文。
- vs `proposal`:proposal 写**本子、给建议**;brief 只列论文 + 客观总结。要"对本院的建议" → 转 proposal。
**何时不用**:只要文献清单 / DOI / PDF → research/documents;要写可投稿综述 → paper(review);要拆科学问题 → analyze;要写本子 → proposal。
## 资源(路径相对 `load_skill` 头里的 `dir=<绝对路径>`)
## 资源
- `references/journals.md` —— 各建材子领域主流期刊清单(Elsevier 数据库优先)+ 精确 `publication_name` + 0 命中降级法。**阶段二必读**。
- `scripts/render_docx.py` —— md→docx,商务红主题 + 列表 `[n]` 锚点 + 正文 `[n]`/`[Wn]` 引文上标回链 + DOI/URL 可点超链接 + 化学式下标白名单(CO2/C3S/Na2O...,不误伤 LC3/C595/Ca2+)。用 `.venv/Scripts/python.exe` 跑。
下面所有路径相对 **`<skill_dir>`** —— `load_skill` 返回头里的 `[skill=brief, dir=<绝对路径>]`,用这个绝对路径拼脚本/资源,不要假设 cwd
产物默认 `.md`;要 docx 用 render_docx.py;要 deck 转 `ppt` skill
**先读(always)**:
- `<skill_dir>/templates/brief_outline.md` —— 简报骨架 + 按深度(快报/标准/深度)的字数预算与簇数/引文数
- `<skill_dir>/references/search_strategy.md` —— 三路检索分工(documents/research/web)+ 跨源去重 + 中文方向→英文术语转译
## 阶段一:定题对齐(BLOCKING)
**阶段五必读**:
- `<skill_dir>/references/citation_verify.md` —— 引文核验协议(存在性 / 三角印证 / 支撑度,复用 paper 思路,接 documents/research/web)
写一份 task 级 spec(命名见 system prompt《task 级「宪法」文件命名约定》),填下面字段,**有歧义先反问、不替用户拍板**,写完复述确认再往下:
**模板**:
- `templates/spec.md` —— 七条定题对齐固定字段(复制到 task 级 spec 文件)
**脚本**(`.venv/Scripts/python.exe <skill_dir>/scripts/...`):
- `scripts/quality_check.py` —— `--depth {flash,standard,deep}`,结构完整性 / 占位符泄漏 / 过度宣称 / 无源句式 / 引文交叉核对(orphan/uncited/编号连续)
- `scripts/render_docx.py` —— md→docx,**简报专属版式**:商务红主题(`--no-color` 关)+ 正文 `[n]`/`[Wn]` 引文上标并锚到文末 + DOI/URL 可点击超链接 + 化学式下标白名单(CO2/C3S/Na2O...,不误伤 LC3/C595/Ca2+)+ TL;DR / 判断 行做底纹 callout
**产物与渲染**:简报默认产物是 `.md`。要 docx → 本 skill 自带 `render_docx.py`(见上);要做成汇报 deck → 转 `ppt` skill。
## 阶段一:定题对齐(写 spec)BLOCKING
产物:**task 级 spec 文件**,简报的"宪法",后续每阶段前重读。命名按 system prompt 的《task 级「宪法」文件命名约定》:
<task_dir>/<today>-<task_short_id>-<task_name>.spec.md
复制 `templates/spec.md` 填七条,**有歧义先反问,不要替用户拍板**:
1. **方向 + 边界**:具体到子方向(不是"水泥"而是"低碳水泥 SCM");明确**纳入/排除**(如"只看辅助胶凝材料替代,不含碱激发")
2. **时间窗**:默认**近 3 年**;用户说"最新/近期"→ 近 1 年;"这两年"→ 近 2 年。换算成 `year_gte`(今年是 system prompt 给的当前年)
3. **受众**:院领导汇报 / 课题组内部 / 立项前调研 / 对外交流 —— 决定语气与详略
4. **深度**:`flash` 快报(12 页)/ `standard` 标准(46 页)/ `deep` 深度(8+ 页,含机构-地理计量)—— 见 brief_outline.md 预算
5. **数据源开关**:documents(内部库,材料类首选)/ research(补 DOI 与近期元数据)/ web(政策·会议·标准·产业动向)—— 默认三路并用,用户可关
1. **方向 + 边界**:具体到子方向(不是"水泥"而是"低碳水泥 SCM");明确纳入/排除
2. **时间窗**:默认**近 1 年**(简报是"最新文献",窗口宜短);换算成 `year_gte`(今年见 system prompt)
3. **期刊范围**:默认按方向所属子领域取 `journals.md` 主流期刊(Elsevier 优先);用户可增删指定刊
4. **深度 / 篇数**:`flash` 1020 篇 / `standard`(默认)2040 篇 / `deep` 4080 篇
5. **数据源(默认三路并用)**:research + documents **都是获取文献的主力**(research 按期刊精确取最新 Elsevier 论文 + DOI;documents 取内部材料库全文),web search 取政策·标准·产业动向(**单列、不混进论文总结**)。某一路不可用时降级用其余两路,不整体放弃
6. **语言**:中文(默认)/ 英文
7. **特殊关注点**:用户特别想知道的(如"重点看 CCUS 与水泥结合""谁在做工业固废路线")—— 写进 spec,分析阶段重点回应
7. **特殊关注点**(可选):想重点呈现的材料体系 / 方法(仍只描述,不给建议)
写完把 spec 七条**复述给用户确认**,认可后进阶段二。
## 阶段二:三路取数(research + documents 取文献 / web 取动向)
## 阶段二:三路检索取数
**先读 `references/journals.md`**。**中文方向先转专业英文术语**(库主语料英文):低碳水泥→low-carbon cement / clinker substitution;SCM→supplementary cementitious materials / fly ash / GGBFS / calcined clay;LC3→limestone calcined clay cement;碳化养护→CO2 curing / carbonation。缩写与全称都试。
**先读 `references/search_strategy.md`**(三路分工 + 中→英术语 + 去重)。流程:
**research(逐刊取最新 Elsevier 论文 + DOI)** —— `run_python`:
1. **中文方向 → 英文检索词组**:库里主语料是英文,`SCM` 这类要展开(supplementary cementitious materials / fly ash / GGBFS / calcined clay / limestone calcined clay cement / LC3 ...)
2. **documents**(材料类首选):语义检索,中英 query 都行;胶凝材料库(classification_id=1)。取 `md_content` 备引文核验
3. **research**:`search(keyword=英文, year_gte=<>, limit=...)` 拉近期候选 + DOI;`has_pdf`/`is_oa` 按需 filter。看 list 自带 abstract 判切题
4. **web**(可选):政策(双碳、水泥行业碳配额)、标准(新国标/团标)、行业会议、企业中试/产线 —— web 的东西**单独标"产业/政策动向",不混进学术引文计数**
5. 汇成**证据表** `<task_dir>/evidence.md`(仿 lit_matrix):一行一条 = 来源 | 标题 | 年 | 一句话 takeaway | 归属簇 | 引文可用性(documents全文/DOI/web)
```python
from skills.research.paper import search
# 逐刊拉最新:publication_name 精确匹配 + 时间窗;list 自带 abstract,看前 200-400 字判切题与分量
for jname in ["Cement and Concrete Research", "Cement and Concrete Composites",
"Construction and Building Materials", "Journal of Cleaner Production"]:
papers = search(publication_name=jname, year_gte=2025, limit=50)
# 按 publication_date 倒序取最新若干;留重要的(主题居中 + 有实质发现),弃边缘
```
某刊精确名 0 命中 → 换 `keyword=<方向英文术语>` 再搜,从返回里挑 `publication_name` 命中目标刊的;仍空记"该刊本窗口库内无收录"。
收 2080 条(按深度),**不求穷尽**,够支撑各簇即可。命中 0 条先换同义词/放宽年份,3 次仍空如实告诉用户库未覆盖,**不脑补文献**。
**documents(内部材料库取全文,材料类首选)** —— host-side tool `document_search`,中英 query 都行(后端跨语言语义检索);胶凝材料库 `classification_id=1`。取 `md_content` 既做候选也供引文核验抓锚点最顺
## 阶段三:趋势分析(和用户对齐结构)BLOCKING-lite
**web search(取动向)** —— 政策(双碳/碳配额)、标准(新国标/团标)、行业会议、企业产线中试。**单列"其他动向",不混进论文列表与总结**。
把证据表**聚成 37 个热点簇**(按深度),给用户看簇划分 + 每簇代表文献,认可后再起草。每簇判断:
- 汇成证据表 `<task_dir>/evidence.md`:期刊 | 标题 | 第一作者(机构)| 年-月 | 摘要概述 | DOI | 来源(research/documents/web)。
- 跨源去重:同 DOI 一条(documents 全文优先,DOI 记自 research);web 不与论文去重、单列。
- **这个簇在做什么 / 解决什么问题**(一句话主题句,不是关键词堆砌)
- **代表性进展**(24 篇,带真实引文)
- **新兴方法 / 技术**(出现的新表征、新建模、新工艺)
- **争议 / 分歧 / 未解**(哪里还没共识)
> **库时效(必交代)**:research(OpenAlex)约 3 个月索引滞后,"最新"= 库内最新。窗口内 0 篇 → 如实告知库未收录该窗口,可用 web 补更近的非论文动向,**不脑补文献**。
横向再扫:**研究空白**(大家都没做的)、**机构-地理格局**(deep 才做,元数据够时:谁在领跑、中国占比)、**产业/政策动向**(来自 web)。
## 阶段三:列清单 + 内容总结(写 `<task_dir>/sections/*.md`)
> 取舍纪律:一个方向近期可能上百篇,简报只留**改变判断的**。重复验证性工作合并成一句"多篇验证了 X";边缘工作直接不收。宁缺毋滥。
骨架四段(`flash` 可省 `00`/`03`):
## 阶段四:逐段起草
- **`00_overview.md` 概览**:方向 + 纳入/排除边界 + 时间窗 + 覆盖了哪些期刊 + 收录多少篇。无引文。
- **`01_papers.md` 重要论文列表(主体)**:按期刊 `###` 分组,每篇一条,行首 `[n]`(渲染时此段作参考锚点、`[n]` 带 DOI 超链接):
```
### Cement and Concrete Research(Elsevier)
`brief_outline.md` 骨架写 `<task_dir>/sections/*.md`,**每段一个论断 + 证据**:
[1] <标题>. <第一作者> et al., Cement and Concrete Research, 2026-03. DOI: 10.1016/j.cemconres.2026.xxxxxx
- TL;DR 要点(5 行内,先给结论)→ 方向概览与边界 → 研究热点聚类(各簇)→ 新兴方法 → 近期标志性进展 → 研究空白与争议 → 产业/政策/标准动向(web,可选)→ 参考文献
- 起草时引文用占位 `[CITE-<keyword>]`,阶段五核验后映射真实条目并编号
- 数字 / 定量结论必须挂引文;"据报道""有研究表明"这种无源句式禁止
<简介/摘要概述:24 ,讲研究对象方法/表征主要发现与关键数据 基于 abstract 或全文,不夸张不评判>
```
`publication_date` 倒序,最新在前。每篇都要有摘要概述,不能只留标题。
- **`02_summary.md` 内容总结**:对这批论文**客观归纳**——主题分布、常涉材料体系、常用方法/表征、共同关注点;引具体论文挂 `[n]` 上标(回链到 01)。**只描述"这批论文在讲什么",不给"应当/建议/可切入"**。
- **`03_web.md` 其他动向(仅 spec 开 web 时)**:政策/标准/会议/产业,`[W1]` 标来源 + 日期,单列。
## 阶段五:引文核验(渲染前必跑)
数字/定量结论必须挂 `[n]`;"据报道""有研究表明"这类无源句式禁止。
**先读 `references/citation_verify.md`**,对所有引文逐条核验:存在性(两库/web 命中)→ 三角印证(关键论断 ≥2 源)→ 支撑度(抓原文锚点,partial 就改论断迁就证据)。台账写 `<task_dir>/CITATIONS.md`
## 阶段四:引文核验(渲染前必跑)
**铁律(同 paper)**:status 非 verified 的引文不得进最终稿;不为凑数编造文献;支撑不足改论断不改证据;两库/web 都查不到如实告诉用户。
论文直接来自 research/documents,DOI 以**库返回字段为准**(不沿用记忆、不编造)。逐条核验:
## 阶段六:渲染验收
1. **存在性**:`search()`/`get_paper(doi)` 或 documents 命中确认真实存在;查不到 → 标 `[未核实]`,告诉用户"找不到来源,请提供 DOI 或删去",**不编造**。
2. **支撑度**:摘要概述 / `[n]` 论断要和 abstract(或全文)一致;不一致 → **改概述迁就证据**,不是改证据。
3. **web**:记原始 URL + 访问日期 + 发布机构,标"截至 <日期>";不当学术结论引。
1. `quality_check.py --depth <flash|standard|deep>` 跑 sections:结构 / 簇数预算 / 占位符 / 过度宣称 / 无源句式 / 引文交叉核对
2. 用户要 docx → `.venv/Scripts/python.exe <skill_dir>/scripts/render_docx.py <sections_dir> -o <方向>-简报.docx`(商务红 + 引文上标超链接 + 化学式下标;`--no-color` 出黑白);要 deck → 转 ppt skill
4. 交付时一句话说清:覆盖了哪几路源、收了多少条证据、哪些被取舍、哪些点是单源待复核
台账可写 `<task_dir>/CITATIONS.md`。**铁律**:不为凑数编造文献;支撑不足改论断不改证据;查不到如实说。
## 阶段五:渲染验收
- 用户要 docx → `.venv/Scripts/python.exe <dir>/scripts/render_docx.py <sections_dir> -o <方向>-简报.docx`(`--no-color` 出黑白);要 deck → 转 ppt。
- 渲染前自查:`[CITE-]`/`<TODO>` 占位是否清干净、正文 `[n]` 与列表 `[n]` 是否对得上(无 orphan)、有没有混进"建议/启示/本院应当"措辞。
- 交付一句话说清:覆盖了哪些期刊、收了多少篇、时间窗、哪些刊本窗口库内无收录。
## 反模式
- ❌ 跳过定题直接检索 —— 方向边界没定,检索词发散,收一堆不相关
- ❌ 把命中的文献**全部**堆进简报 —— 简报是取舍的艺术,不是清单转储
- ❌ web 抓的资讯当学术结论引 —— web 动向单列,学术论断要文献支撑
- ❌ 编造 DOI / "据报道"无源句 —— 走 citation_verify,查不到就如实说
- ❌ 用中文 keyword 搜英文库 —— 先转专业英文术语(见 search_strategy.md)
- ❌ **给建议/启示/"本院应当"** —— 只描述论文讲了什么,判断留给读者
- ❌ 列表只留标题、没摘要概述 —— 每篇都要 24 句简介
- ❌ 跳过定题直接检索 / 用中文 keyword 搜英文库 / 期刊名不精确 —— 先定题、转英文术语、用精确 `publication_name`
- ❌ web 资讯混进论文列表/总结 —— 单列"其他动向"
- ❌ 编造 DOI / "据报道"无源句 —— 查不到就如实说

View File

@ -1,60 +0,0 @@
# 引文核验协议(简报版)
`paper` skill 的引文三角核验**同一套思路**,这里按简报场景收口。简报虽轻,但**编造引文 / 引而不实**同样致命——决策者会照着简报判断方向,假信息代价更高。
> 协议不是脚本——你(模型)拿 host-side tool 逐条执行。quality_check.py 只做机械的 orphan/uncited/编号核对,真伪与支撑度靠本协议。
## 何时跑
阶段四逐段起草后、阶段六渲染前,对所有 `[CITE-xx]` 占位逐条核验。用户自带的引文也要跑。
## 三层核验(逐条)
### 第 1 层 — 存在性
1. `documents` 语义检索 / `research``search()` / `get_paper(doi)` 确认文献真实存在
2. 命中 → 以**库里返回字段为准**记 DOI/作者/年/期刊,不沿用记忆
3. 两库都查不到 → 标 `[未核实]`,**不得编造**;告诉用户"这条找不到来源,请提供 DOI 或删去该论断"
### 第 2 层 — 三角印证
关键论断(趋势判断、定量结论、"标志性进展")至少 **2 个独立源**一致才稳:
- documents 命中 + research/DOI 一致 → 通过
- 仅单一来源 → 标"单源,谨慎",简报交付时点出"此点单源待复核"
- 来源字段冲突 → 以可验证 DOI 元数据为准
### 第 3 层 — 支撑度
文献存在但**不支撑你写的那句话**是最容易翻车的:
1. 抓 `md_content`(documents)/ `fetch_xml`/`fetch_pdf`(research)
2. 定位 ≤25 词原文锚点 + 段落位置
3. 三档:**support** 通过;**partial/需限定** → 改写论断迁就证据;**not-support/反向** → 删引用或换文献
4. 抓不到全文 → abstract 弱核验,标"仅摘要核验"
## web 来源的核验(简报特有)
web 资讯(政策/标准/产业)**不进学术引文三角**,但同样要可溯源:
- 记**原始 URL + 访问日期 + 发布机构**;优先官方源(政府/标委会/期刊/企业官网),而非二手转载
- 政策 / 标准类:能找到文号 / 标准号就记(如"GB/T xxxxx""国办发2025x号")
- web 信息标注"截至 <日期>",时效性内容明确边界——避免简报过期后误导
## 产出:核验台账 `CITATIONS.md`
```markdown
# 引文核验台账
- [1] <author> <year>, <journal> | exists:✓(documents+DOI) | triangulate:✓ | claim:support "<≤25词锚点>"(§x) | status: verified
- [2] <author> <year> | exists:✓ | claim:partial → 已把"大幅提升"改为"28d 提高约 15%" | status: verified-revised
- [W1] <机构> <标题>, <URL>, 访问 <日期> | 类型:政策动向 | status: web-sourced
- [3] <author> <year> | exists:✗ 两库未命中 | status: 待用户提供
```
## 铁律(同 paper)
- ❌ status 非 verified/verified-revised/用户确认的学术引文不得进最终稿
- ❌ 不为凑数编造"看起来合理"的文献
- ❌ web 资讯当学术结论引(单列动向段,标 URL+日期)
- ✅ 支撑不足**改论断迁就证据**,不是改证据迁就论断
- ✅ 两库/web 都查不到如实告诉用户,给"提供来源 / 删论断"两个选项

View File

@ -0,0 +1,58 @@
# 各建材子领域主流期刊清单(Elsevier 数据库优先)
逐刊取最新论文时用。**绝大多数是 Elsevier**(下表 `E` 标),少数主流非 Elsevier 刊也列上(标出版商),取数时 Elsevier 优先。
> **用法**:`search(publication_name="<下表精确名>", year_gte=<>, limit=50)`,按 `publication_date` 倒序取最新。
> **名字要精确**:OpenAlex 的期刊显示名就是下表这串,带副标题的(如 `Composites Part B: Engineering`)要带全。
> **0 命中降级**:精确名搜不到 → 换 `keyword=<期刊核心词>``keyword=<方向英文术语>` 搜,从返回里挑 `publication_name` 命中该刊的;仍空 → 记"该刊本窗口库内无收录",不脑补。
## 水泥 / 混凝土 / 胶凝材料(本院核心)
| 期刊 | 出版商 | 备注 |
|---|---|---|
| Cement and Concrete Research | E | 领域顶刊,机理与材料 |
| Cement and Concrete Composites | E | 复合胶凝、SCM、耐久 |
| Construction and Building Materials | E | 体量最大,工程材料广谱 |
| Cement | E | 较新 OA 刊,水泥专门 |
| Journal of Building Engineering | E | 建筑工程材料与结构 |
| Materials and Structures | Springer(RILEM) | 非 E 主流,RILEM 旗舰 |
| Cement, Concrete and Aggregates | ASTM | 非 E |
## 绿色 / 低碳 / 固废资源化
| 期刊 | 出版商 | 备注 |
|---|---|---|
| Journal of Cleaner Production | E | 低碳、生命周期、固废 |
| Resources, Conservation and Recycling | E | 工业固废资源化 |
| Journal of Environmental Management | E | 环境与固废处置 |
| Waste Management | E | 固废(矿渣/粉煤灰/赤泥)|
| Journal of CO2 Utilization | E | 碳化养护 / CCUS |
## 陶瓷 / 玻璃 / 耐火
| 期刊 | 出版商 | 备注 |
|---|---|---|
| Ceramics International | E | 陶瓷综合顶刊 |
| Journal of the European Ceramic Society | E | 陶瓷,欧洲旗舰 |
| Journal of Non-Crystalline Solids | E | 玻璃 / 非晶 |
| Journal of the American Ceramic Society | Wiley | 非 E,陶瓷顶刊(JACerS)|
| International Journal of Applied Glass Science | Wiley | 非 E,玻璃 |
## 复合材料 / 新型建材 / 通用材料
| 期刊 | 出版商 | 备注 |
|---|---|---|
| Composites Part B: Engineering | E | 复合材料(纤维增强等)|
| Composites Part A: Applied Science and Manufacturing | E | 复合材料 |
| Materials & Design | E | 材料设计广谱 |
| Journal of Materials Research and Technology | E | 材料制备表征 |
| Materials Today Communications | E | 材料快报 |
| Powder Technology | E | 粉体 / 颗粒 |
| Fuel | E | 燃煤灰渣相关 |
## 取数策略
- 按 spec 方向所属子领域,从上面对应表里取 **38 本主流刊**(Elsevier 优先),逐刊拉最新。
- 跨子领域的方向(如"低碳水泥固废路线")→ 水泥表 + 绿色表合并取。
- 每本刊取最新若干篇后,**按重要性筛**:主题居中、有实质发现的留,边缘/纯验证性的弃(控量见 SKILL.md 篇数预算)。
- 主流刊都覆盖到了就够,不必穷举所有刊。哪些刊本窗口库内 0 收录,交付时如实点出。

View File

@ -1,61 +0,0 @@
# 三路检索策略(documents / research / web)
简报数据底座最多三路并用。**三路分工不同、去重要做、学术与资讯分开计数**。
## 三路分工
| 路 | 拿什么 | 怎么调 | 强项 | 注意 |
|---|---|---|---|---|
| **documents** | 材料学科论文**全文 md**(胶凝材料库 classification_id=1) | host-side tool `document_search`,中英 query 都行(后端跨语言语义检索) | LLM 直接读全文、引文核验抓锚点最顺;材料类首选 | 需宿主配 `DOCUMENT_SEARCH_API_KEY`;只覆盖预收的 7 学科 |
| **research** | OpenAlex 元数据 + DOI + abstract,可拉 PDF/XML | `from skills.research.paper import search, get_paper, fetch_xml`,`run_python` 调 | 补近期文献与 DOI、`year_gte` 卡时间窗、`is_oa`/`has_pdf` filter | keyword **英文为主**;SearchFilter 匹配 title/author 不含 abstract |
| **web** | 政策 / 标准 / 会议 / 产业动向 | WebSearch / WebFetch | 时效性最强,学术库覆盖不到的非论文信息 | **不当学术结论引**;单列"产业/政策动向"段,标来源 + 日期 |
> documents / research 任一不可用(key 没配 / 服务器连不上)时**降级用另一路 + web**,别整体放弃。research 不持 key,通常是降级首选。
## 中文方向 → 英文术语(关键)
库里 95%+ 文献 title 是英文,中文 keyword 命中率很低。**中文方向先转专业英文词组再搜**,缩写要展开:
| 中文方向 | 英文检索词组(同义/展开) |
|---|---|
| 低碳水泥 | low-carbon cement / low-CO2 cement / clinker substitution |
| 辅助胶凝材料 SCM | supplementary cementitious materials / SCM / fly ash / GGBFS / ground granulated blast-furnace slag / calcined clay / silica fume / limestone powder |
| LC3 石灰石煅烧黏土水泥 | limestone calcined clay cement / LC3 / calcined clay cement |
| 水泥窑碳捕集 | cement CCUS / carbon capture cement kiln / oxyfuel cement |
| 工业固废资源化 | industrial solid waste / steel slag / red mud / phosphogypsum in cement |
| 碳化养护 | CO2 curing / carbonation curing / accelerated carbonation |
| 水化机理 | cement hydration / C-S-H / hydration kinetics |
转译策略:用领域标准英文术语;不确定就先英文 keyword 试一次看返回 title 是否相关;多个同义词分别搜一遍合并去重;缩写(SCM/LC3/GGBFS)与全称都搜。
## research 调用范式
```python
from skills.research.paper import search
# 时间窗 = 近1年 → year_gte=<当前年-1>;多个英文同义词分别搜
for kw in ["limestone calcined clay cement", "LC3 cement", "supplementary cementitious materials"]:
papers = search(keyword=kw, year_gte=2025, limit=15)
for p in papers:
# list 已带 abstract,直接看前 200-400 字判切题,不必再 get_paper
print(p["publication_year"], p["title"], p["doi"])
if p["abstract"]:
print(p["abstract"][:300])
```
要全文做引文核验:`has_fulltext_xml=True` 先 `fetch_xml`(结构化,LLM 友好),否则 `fetch_pdf`
## 跨源去重
同一篇 / 同一结论可能三路都出现:
- **同 DOI** → 一条(documents 全文优先,记 DOI 来自 research)
- **同结论不同文献**(多篇验证同一现象)→ 合并成一句"多篇(refN, refN)验证了 X",不逐条铺开
- **web 资讯 vs 学术论文** → 不去重、不混算;web 进"产业/政策动向"段,学术进簇与引文计数
- 证据表 `evidence.md` 一行一条标"来源(documents/research/web)",去重在表上做完再起草
## 收多少 / 收到什么程度
- 按深度收 2080 条候选(见 brief_outline 预算),**不求穷尽**——够支撑各簇判断即可
- 每簇至少 2 篇代表文献(关键论断 ≥2 源,接 citation_verify 三角印证)
- 命中 0 条:换同义词 / 展开缩写 / 放宽年份;3 次仍空 → 如实告诉用户库未覆盖该窗口,**不脑补**

View File

@ -1,270 +0,0 @@
"""科研方向简报质量检查 — 渲染前跑一遍。
检查项:
- 结构完整性: 按深度(flash/standard/deep)必备段落是否齐全
- 占位符泄漏: <TODO> / [CITE-xx] 占位是否还在
- 过度宣称: "国际领先 / 首次 / 颠覆 / unprecedented" 等无证据夸张词(简报要有判断但别吹)
- 无源句式: "据报道 / 有研究表明 / 业内普遍认为" 等不挂引文的论断(简报每条论断要可溯源)
- 引文交叉核对: 文中学术引 [n] 与参考文献清单 [n] 互查(orphan / uncited / 编号连续)
- web 来源计数: [W1].. 单独统计,提醒和学术引文分开
用法:
python quality_check.py <sections_dir> --depth standard
python quality_check.py <sections_dir> --depth flash --strict
"""
from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
# 各深度必备段落(stem 前缀匹配;references 单独判)
REQUIRED_SECTIONS: dict[str, list[str]] = {
"flash": ["00_tldr", "02_clusters", "references"],
"standard": ["00_tldr", "01_overview", "02_clusters", "05_gaps", "references"],
"deep": ["00_tldr", "01_overview", "02_clusters", "04_progress", "05_gaps", "references"],
}
# 各深度热点簇数预算(02_clusters 里 '### 簇' 计数)
CLUSTER_BUDGET: dict[str, tuple[int, int]] = {
"flash": (2, 3),
"standard": (3, 5),
"deep": (5, 7),
}
OVERCLAIM_PHRASES = [
"国际领先", "国际一流", "世界领先", "世界一流", "填补空白", "重大突破",
"划时代", "前所未有", "颠覆性", "革命性",
"world-first", "world-leading", "unprecedented", "groundbreaking",
"revolutionary", "state of the art",
]
# 无源句式: 出现这些但同段没有 [n]/[CITE-] 引文 → 论断悬空
UNSOURCED_PHRASES = [
"据报道", "有研究表明", "研究显示", "业内普遍认为", "众所周知",
"大量研究", "普遍认为", "据悉",
]
PLACEHOLDER_PATTERNS = [
r"<TODO[^>]*>",
r"\[CITE-[A-Za-z0-9_\-]+\]",
r"\bXX+\b",
]
_INTEXT_CITE_RE = re.compile(r"\[(\d[\d,\s\-]*)\]") # 学术引 [7] / [7-9] / [7,9]
_REF_ENTRY_RE = re.compile(r"^\s*\[(\d+)\]") # 参考文献条目 [n]
_WEB_CITE_RE = re.compile(r"\[W\d+\]") # web 来源 [W1]
_CITE_TOKEN_RE = re.compile(r"\[(?:\d[\d,\s\-]*|CITE-[A-Za-z0-9_\-]+)\]")
def _is_references_file(stem: str) -> bool:
s = stem.lower()
return "reference" in s or s.endswith("_refs") or "参考文献" in stem or "08_" in s
def check_structure(sections_dir: Path, depth: str) -> list[str]:
required = REQUIRED_SECTIONS.get(depth, [])
existing = {f.stem for f in sections_dir.glob("*.md")}
issues = []
for req in required:
if req == "references":
if not any(_is_references_file(s) for s in existing):
issues.append("缺段落: 参考文献 (08_references)")
continue
if not any(s.startswith(req) for s in existing):
issues.append(f"缺段落: {req}")
return issues
def check_clusters(sections_dir: Path, depth: str) -> list[str]:
lo, hi = CLUSTER_BUDGET.get(depth, (0, 999))
n = 0
for md in sections_dir.glob("*.md"):
if md.stem.startswith("02_clusters"):
n += len(re.findall(r"^#{2,4}\s*簇", md.read_text(encoding="utf-8"), re.MULTILINE))
if n == 0:
return ["02_clusters 里没找到 '### 簇N' 小节 — 热点聚类是简报主体"]
if n < lo:
return [f"热点簇 {n} 个, 少于 {depth} 档预算 {lo}-{hi} (簇太少, 方向覆盖可能不足)"]
if n > hi:
return [f"热点簇 {n} 个, 多于 {depth} 档预算 {lo}-{hi} (簇太多, 考虑合并 — 重要性优先于完整性)"]
return []
def check_phrases(text: str, label: str) -> list[str]:
issues = []
low = text.lower()
for phrase in OVERCLAIM_PHRASES:
if phrase in text or phrase.lower() in low:
issues.append(f"[{label}] 过度宣称: '{phrase}' — 换成可被数据支撑的具体表述")
return issues
def check_unsourced(text: str, label: str) -> list[str]:
"""无源句式: 整段出现却无任何引文标记 → 悬空论断。按段落(空行分隔)判。"""
issues = []
for para in re.split(r"\n\s*\n", text):
if _CITE_TOKEN_RE.search(para) or _WEB_CITE_RE.search(para):
continue # 本段有引文, 放过
for phrase in UNSOURCED_PHRASES:
if phrase in para:
snippet = para.strip().replace("\n", " ")[:40]
issues.append(f"[{label}] 无源论断: '{phrase}' 所在段无引文标记 — 挂 [n] 或删 (\"{snippet}...\")")
break
return issues
def check_placeholders(text: str, label: str) -> list[str]:
issues = []
for pat in PLACEHOLDER_PATTERNS:
for m in re.findall(pat, text):
issues.append(f"[{label}] 占位符未替换: '{m}'")
return issues
def _expand_cite_group(grp: str) -> set[int]:
out: set[int] = set()
for part in grp.split(","):
part = part.strip()
if not part:
continue
if "-" in part:
a, _, b = part.partition("-")
try:
lo, hi = int(a), int(b)
except ValueError:
continue
if 0 < lo <= hi <= 999:
out.update(range(lo, hi + 1))
else:
try:
out.add(int(part))
except ValueError:
continue
return out
def check_citations(sections_dir: Path) -> list[str]:
issues: list[str] = []
cited: set[int] = set()
ref_nums: list[int] = []
web_in_text = 0
web_refs = 0
for md in sorted(sections_dir.glob("*.md")):
text = md.read_text(encoding="utf-8")
if _is_references_file(md.stem):
for ln in text.splitlines():
m = _REF_ENTRY_RE.match(ln)
if m:
ref_nums.append(int(m.group(1)))
if re.match(r"^\s*\[W\d+\]", ln):
web_refs += 1
else:
for grp in _INTEXT_CITE_RE.findall(text):
cited.update(_expand_cite_group(grp))
web_in_text += len(_WEB_CITE_RE.findall(text))
if not ref_nums and not cited:
return ["未发现任何学术引文 (文中 [n] 和参考文献清单都为空) — 简报论断需文献支撑"]
ref_set = set(ref_nums)
orphan = sorted(cited - ref_set)
if orphan:
issues.append(f"orphan cite — 文中引了 {orphan} 但参考文献清单缺对应条目 (编造/漏排, 走 citation_verify)")
uncited = sorted(ref_set - cited)
if uncited:
issues.append(f"uncited ref — 参考文献第 {uncited} 条正文从未引用 (删除或补引)")
dups = sorted({n for n in ref_nums if ref_nums.count(n) > 1})
if dups:
issues.append(f"参考文献编号重复: {dups}")
if ref_set:
gaps = sorted(set(range(1, max(ref_set) + 1)) - ref_set)
if gaps:
issues.append(f"参考文献编号不连续, 缺号: {gaps} (顺序编码制需 1..N 连续)")
if 1 not in ref_set:
issues.append("参考文献编号未从 [1] 起")
# web 来源只提示, 不判错(它们和学术引文分开计数)
if web_in_text and not web_refs:
issues.append(f"文中有 {web_in_text} 处 [W..] web 引用但参考文献无 [W..] 条目 — 补 web 来源(URL+日期)")
return issues
def main() -> None:
ap = argparse.ArgumentParser(description="科研方向简报质量检查")
ap.add_argument("sections_dir", type=Path)
ap.add_argument("--depth", required=True, choices=list(REQUIRED_SECTIONS.keys()))
ap.add_argument("--strict", action="store_true", help="严格模式: 任何问题退出 1")
args = ap.parse_args()
if not args.sections_dir.is_dir():
print(f"[ERR] {args.sections_dir} not a directory", file=sys.stderr)
sys.exit(2)
print(f"\n[简报质量检查] depth={args.depth}\n")
all_issues: list[str] = []
struct = check_structure(args.sections_dir, args.depth)
if struct:
print("[ERR] 结构问题:")
for s in struct:
print(f" - {s}")
all_issues.extend(struct)
else:
print("[OK] 结构完整")
cl = check_clusters(args.sections_dir, args.depth)
if cl:
print("\n[WARN] 热点簇数:")
for s in cl:
print(f" - {s}")
all_issues.extend(cl)
else:
print("[OK] 热点簇数在预算内")
files = sorted(args.sections_dir.glob("*.md"))
print(f"\n{len(files)} 个段落, 逐段扫描 (过度宣称 / 无源论断 / 占位符)...\n")
for f in files:
text = f.read_text(encoding="utf-8")
sub = (check_phrases(text, f.stem)
+ check_unsourced(text, f.stem)
+ check_placeholders(text, f.stem))
if sub:
print(f"[WARN] {f.stem}:")
for s in sub:
print(f" - {s.split('] ', 1)[1] if '] ' in s else s}")
all_issues.extend(sub)
cite_issues = check_citations(args.sections_dir)
if cite_issues:
print("\n[ERR] 引文交叉核对:")
for s in cite_issues:
print(f" - {s}")
all_issues.extend(cite_issues)
else:
print("\n[OK] 学术引文 [n] 与参考文献清单一致 (无 orphan / uncited, 编号连续)")
print("\n" + "=" * 60)
if all_issues:
print(f"[WARN] 共发现 {len(all_issues)} 个问题。")
print("\n建议:")
print(" - 过度宣称 -> 换成数据支撑的具体表述")
print(" - 无源论断 -> 挂 [n] 引文或删该句")
print(" - 占位符未替换 -> 走 citation_verify 把 [CITE-] 映射成真实引文")
print(" - orphan cite -> 大概率编造, 走 citation_verify 三角核验")
print(" - uncited ref -> 删条目或正文补引")
if args.strict:
sys.exit(1)
else:
print("[OK] 未发现问题。")
if __name__ == "__main__":
main()

View File

@ -2,8 +2,9 @@
相对 paper/render_docx.py 的简报专属增强:
- **商务红配色**(主色 #C00000):标题分级染色 + 标题下细色条;TL;DR / 「判断」行做浅红底纹 callout
- **引文上标 + 内部超链接**:正文 [1] / [W3] 上标红色,点击锚到文末参考文献对应条目
- **参考文献可点击**:DOI https://doi.org/... 蓝色超链接;web 条目里的域名/路径 https:// 超链接
- **引文上标 + 内部超链接**:正文 [1] / [W3] 上标红色,点击锚到重要论文列表 / 参考文献段对应条目
- **论文列表 / 参考文献可点击**:标题含论文列表 / 文献列表 / 参考文献的段,行首 [n] 条目作锚点;
条目内 DOI(整条是 DOI 或末尾 "DOI: 10.xxx") https://doi.org/... 蓝色超链接;web 条目里的域名/路径 https:// 超链接
- **化学式下标(白名单)**:CO2 / C3S2 / Na2O / SO4 ... 真实下标,**白名单精确匹配**,不误伤 LC3 / EN 197-5 / 8.5 Mt / 2026
字体规范同院内其它渲染:中文宋体小四 / 英文 Times New Roman 小四 / 行距 1.5 / 首行缩进 2 字符
@ -407,6 +408,7 @@ def add_page_footer(doc: Document, color: bool) -> None:
_REF_RE = re.compile(r"^\[(W?\d+)\]\s+(.+)$")
_DOI_RE = re.compile(r"^10\.\d{4,9}/\S+$")
_DOI_INLINE_RE = re.compile(r"10\.\d{4,9}/\S+") # 条目内 DOI 子串(论文列表条目末尾常带 "DOI: 10.xxx")
_URL_TOKEN_RE = re.compile(r"([a-z0-9][\w.\-]*\.[a-z]{2,}(?:/[^\s]+)?)", re.IGNORECASE)
@ -428,6 +430,18 @@ def add_reference_item(doc: Document, cid: str, value: str, bm_id: int, color: b
if _DOI_RE.match(value):
add_external_link(p, f"https://doi.org/{value}", value, size_pt=10.5)
return
# 论文列表条目:行内含 DOI(如 "<标题>. <作者>, <刊>, 2026-03. DOI: 10.1016/...")
# → 把 DOI 子串做成超链接,前后文正常
m_doi = _DOI_INLINE_RE.search(value)
if m_doi:
doi = m_doi.group(0).rstrip(".,;)")
pre, post = value[:m_doi.start()], value[m_doi.start() + len(doi):]
if pre:
_emit_plain_run(p, pre, size_pt=10.5, cn_font="宋体")
add_external_link(p, f"https://doi.org/{doi}", doi, size_pt=10.5)
if post:
_emit_plain_run(p, post, size_pt=10.5, cn_font="宋体")
return
# web 条目:把第一个像 URL 的 token 变成超链接
m = _URL_TOKEN_RE.search(value)
if m and ("/" in m.group(1) or m.group(1).count(".") >= 1) and " " not in m.group(1):
@ -604,7 +618,10 @@ def render_md_block(doc: Document, md_text: str, ctx: dict) -> None:
if m:
title = m.group(2).strip()
level = min(len(m.group(1)), 3)
in_refs = "参考文献" in title
# 只在 H1/H2 重判段类型 —— 让「重要论文列表」段下的 ### 期刊子标题不重置 in_refs,
# 子标题下的 [n] 条目才能继续按参考锚点渲染(带 DOI 超链接)
if level <= 2:
in_refs = ("参考文献" in title) or ("论文列表" in title) or ("文献列表" in title)
expect_meta = (level == 1)
if level <= 2:
in_tldr = ("要点" in title) or ("TL;DR" in title.upper())

View File

@ -1,60 +0,0 @@
# 简报骨架 + 篇幅预算
简报按深度分三档,骨架同构、详略不同。`sections/` 一节一文件,文件名见各段标注。
## 篇幅预算(按深度)
| 深度 | 页数 | 总字数(中) | 热点簇数 | 引文数(学术) | 机构-地理计量 |
|---|---|---|---|---|---|
| `flash` 快报 | 12 | 8001500 | 23 | 815 | 不做 |
| `standard` 标准 | 46 | 25004000 | 35 | 2040 | 可选(一句话点格局) |
| `deep` 深度 | 8+ | 6000+ | 57 | 4080 | 做(发文量趋势 / 国别机构格局) |
> 字数是预算不是硬指标;宁可短而准,不要灌水凑页。"重要性优先于完整性"。
## 骨架(各档同构)
### `00_tldr.md` — 一句话要点(TL;DR)
- 5 行内,**先给结论**:这个方向近期最值得知道的 35 件事,每行一句带判断
- 决策者只读这段也能拿到核心态势
- 例:`- LC3(石灰石煅烧黏土水泥)从中试走向标准化,近 1 年多国发布技术规程`
### `01_overview.md` — 方向概览与边界
- 这个方向**解决什么问题**(12 段)、本简报的**纳入/排除边界**(照搬 spec)
- 时间窗 + 数据源覆盖说明(收了哪几路、多少条),让读者知道简报的"视野范围"
### `02_clusters.md` — 研究热点聚类(主体)
按 spec 深度分 37 簇,每簇一个 `###` 小节:
```
### 簇N:<主题句,写判断不写关键词>
- 在做什么 / 解决什么:<12 >
- 代表性进展:<24 , [CITE-xx],各一句 takeaway + 关键数字>
- 新兴方法/技术:<若有>
- 争议/未解:<若有>
```
### `03_methods.md` — 新兴方法 / 技术(可并入 02,deep 单列)
- 跨簇出现的新表征 / 新建模(如 ML 配比优化)/ 新工艺,各带代表文献
### `04_progress.md` — 近期标志性进展
- 近 N 年**改变判断**的标志性成果(里程碑论文 / 中试 / 突破),38 条,带引文与数字
### `05_gaps.md` — 研究空白与争议
- 大家都没做的(空白)、还没共识的(争议)、方法学局限 —— 这段是简报"有判断"的体现
### `06_industry.md` — 产业 / 政策 / 标准动向(web,可选)
- 双碳政策 / 碳配额 / 新国标团标 / 行业会议 / 企业产线中试 —— **单列,标注来源为 web 资讯**
- 与学术引文分开计数;时效性内容注明日期
### `08_references.md` — 参考文献
- 仅 citation_verify 核验通过(verified / verified-revised / 用户确认)的进清单
- 学术引文按文中首次出现顺序编 `[1][2]...`,带 DOI;web 来源另起一段标 URL + 访问日期

View File

@ -1,54 +0,0 @@
# 简报 spec(定题对齐"宪法")
> 阶段一产物。写定后不再改,阶段二/三/四每阶段前都要 read。`<TODO>` 是占位符,需用户明确填值,不要硬编。
## 1. 方向 + 边界
- 研究方向(具体到子方向):`<TODO 低碳水泥的辅助胶凝材料(SCM)路线,不是泛泛的"水泥">`
- 纳入范围:`<TODO 粉煤灰/矿渣/煅烧黏土/石灰石粉等 SCM 替代熟料>`
- 排除范围:`<TODO 碱激发/地聚物单独成体系的不收;CCUS 仅在与 SCM 协同时提及>`
## 2. 时间窗
- 口径:`<TODO 1 / 2 / 3 (默认)>`
- 换算 `year_gte`:`<TODO 当前年减窗口, 近1年2025>`(当前年见 system prompt)
## 3. 受众
- `<TODO 院领导汇报 / 课题组内部 / 立项前调研 / 对外交流>`(决定语气与详略)
## 4. 深度
- `<TODO flash 快报(12页) / standard 标准(46页,默认) / deep 深度(8+页,含机构-地理计量)>`
- 对应字数预算 / 簇数 / 引文数见 brief_outline.md
## 5. 数据源开关(默认三路并用)
- documents(内部库,材料类首选):`<TODO /;胶凝材料库 classification_id=1>`
- research(补 DOI 与近期元数据):`<TODO />`
- web(政策·会议·标准·产业动向):`<TODO />`
## 6. 语言
- `<TODO 中文(默认) / 英文>`
## 7. 特殊关注点
> 用户特别想知道的,分析阶段重点回应。
- `<TODO 如 重点看 CCUS 与水泥协同 / 谁在做工业固废路线 / 关注新国标动向>`
## 检索词组(阶段二填,中→英)
> 中文方向转成的英文检索词,库里主语料英文。
```
<TODO 主词 + 同义/展开词,如:
supplementary cementitious materials | SCM | fly ash | GGBFS / ground granulated blast-furnace slag |
calcined clay | limestone calcined clay cement | LC3 | clinker substitution | low-carbon cement>
```
## 待用户提供 / TODO
- [ ] `<TODO 如 确认时间窗口是近1年还是近2年>`
- [ ] `<TODO 如 确认是否纳入碱激发体系>`