SR Search Record · 综述文章的检索与筛选记录
把综述文章的检索环节做成可复现、数字能对账、且一口气跑得完的流水线。Snyder 三型共用这一套(历史原因名字里带 sr,不只服务 systematic review)。AI 干 80%(设计检索式、多轮校准、全量抓取、排序截断、摘要筛选建议、记账出表),剩下 20%(最终纳入裁决、边界记录、学科术语补漏)交给人。
产出不是"搜到的一堆文献",是论文方法节能直接贴的三张表 + 一个 60–100 篇的纳入集。
摘要层定稿模式(本 skill 的核心设定)
判定只有一层:题名 / 摘要。ai_decision 就是纳入决定,没有全文筛选层。
- 筛选阶段不获取全文。全文在 ③ 成文阶段(
review-synthesis/review-draft)best-effort 获取,拿不到不改变纳入集,只影响evidence_level。 ft_decision/ft_reason两列已退休。台账里不再有它们。- 这是明示的方法学让步,不是无损优化,三型都适用:
- 摘要经常不写清关键闸门(样本、设计、是否报告了某类结果),只靠摘要判会同时放进假阳性、漏掉假阴性。
- PRISMA 要求全文评估。systematic 型用本模式,产出里必须写明这条偏离,投稿时大概率被要求补做。
- RAMESES(半系统)与 Torraco(整合式)不强制全文评估层,与本模式不冲突。
- 产出里一律如实写:"筛选在题名/摘要层完成,未进行全文合格性评估"。不得把流程图标成完整 PRISMA,systematic 型的流程图要标注该偏离。
规模链(三个数必须一致,流程才闭得上)
| 环节 | 目标 | 谁保证 |
|---|---|---|
| 检索式校准后命中 | 300–2,000 | 第 2 步,种子召回 + 精度守卫 |
| 排序截断后候选集 | 300 条(可扩到 600 / 900) | 第 4 步 rank --shortlist |
| 摘要筛选后 include | 60–100 | 第 4 步收敛闭环 |
实测参考(在一个 7,660 条的真实语料库上验证):截断线 300 时候选集里 include 密度约 23–25%,预计产出 70–80 篇,落在目标带内。
截断线是预算,不是相关性悬崖。实测 301–600 名这一段的 include 密度与前 300 名相当(都是 25% 上下)——词面排序的区分力到几百名就饱和了。所以线外那批不是"不相关",是"这次没预算看",措辞必须如实,不得暗示它们已被评估过。
调用约定(独立运行)
- 定型(第一件事):读
RV_综述/01_选题/选题.md机器锚块的review_type(systematic / semi-systematic / integrative),写进检索配置.json——它决定报告规范与出表形状(检索与筛选内核三型完全一致)。锚块缺失就问用户,不要默认 systematic。这是本 skill 唯一的硬停点。 - 输入:优先读
RV_综述/01_选题/选题.md(综述规格、RQ、纳入排除标准、近邻综述)。有这个文件就直接开跑,不要回头确认概念块;只有在没有该文件、纳入标准只能从口述推断时,才在拆完概念块后确认一次。 - 输出:默认落项目根下的
RV_综述/02_检索筛选/;调用方给了路径以调用方为准。RV_综述/是综述文章在项目里的独立子树(01_选题/02_检索筛选/03_综合成文),与实证论文那条线彻底隔离。不要把综述的产出写进实证论文的目录(尤其04_数据/研究发现.md:两条线同名不同义)。 - 检索引擎:本 skill 目录下的
scripts/oa_search.py(OpenAlex 开放 API + Europe PMC)。必须调用这个脚本,不要临时自己写检索代码——脚本保证检索记录格式一致、命中数可复跑、截断与收敛规则统一。运行前设export OPENALEX_MAILTO=<用户邮箱>进礼貌池。 - 质量标准:对齐已发表综述的主流做法(2 个以上信息源 + 概念块布尔式 + 限制器 + 纳入文献参考文献回溯)。不追求 Cochrane 级的双人独立筛选、MeSH 逐行检索与全文合格性评估——这三条必须由人完成,本 skill 只做到可交接。
- 调用方覆盖约定:调用方显式给出的参数、路径与工具选择,一律覆盖本 skill 的默认;但本 skill 的方法步骤、硬约束与降级规则不可被省略或稀释。
全局硬约束
- 不编造文献。 所有条目必须来自脚本实际返回的记录,带 DOI 或 OpenAlex ID。不得凭印象补充"应该还有一篇…"。
- AI 不是第二评审。 AI 的判断写在
ai_decision列,reviewer_1/reviewer_2/final_decision一律留空给人填。不得声称完成了双人独立筛选。 - unclear 一律保留。 摘要缺失、信息不足、边界模糊的记录标
unclear进候选池,不得为了缩短清单自动排除。摘要层定稿模式下 unclear 尤其重要——它们正是本该靠全文判、而本流程放弃了的那批。 - 数字必须对账。 选择流程里每个数字都要能从
records.csv/筛选决定.csv反算出来;对不上就报错,不许四舍五入或估算。 - 检索源如实报告。 方法节必须写明"检索源为 OpenAlex(+ 补充源)",不得表述成 Scopus / Web of Science。局限节要写明未使用受控词表与商业库、未检索中文数据库、以及未做全文合格性评估。
- 区分"改标准"与"修词"。
- 禁止:为了让数字好看而提高纳入门槛、删种子、砍掉合法的检索维度。任何标准改动写进"协议偏离"。
- 必须做:修掉伤精度的泛词(单块命中 > 100 万时
probe会点名)。合法性判据:改动前后recall的种子召回率不下降。 守住这条就是纯赚精度,与本条前半句不冲突。
- 截断 ≠ 排除。 截断线外的记录标
not-screened-lowrank,在选择流程说明里单列一行,措辞为"未进入筛选(相关性排序预算外)"。不得计入排除数,也不得说成"已评估后排除"。 - 规模不达标不是失败。 include 落不进 60–100 时按第 4 步的收敛闭环处置,最多调 2 次;两次后接受当前数字并如实汇报。硬凑一个漂亮数字才是错。
- 不中途讨许可,遇阻就降级。 每一步都设计成一口气跑完。唯一合法硬停点 =
选题.md缺失或读不出review_type(定不了型就定不了报告规范,无法降级)。其余任何失败都走下面的降级阶梯:记账 → 降级 → 继续,跑完一次性汇报。上下文预算将尽是软停:先写盘、报出续跑位置再停。"数量大、要花时间"不是停点。
降级阶梯("不卡住"的实现)
| 卡点 | 降级动作 | 停? |
|---|---|---|
| OpenAlex 429 / 超时 | 脚本已内置指数退避 5 次;仍失败 → 把 filters.publication_year 拆成几段分批抓 → 再失败用已抓部分,覆盖缺口写进降级记录 |
否 |
| 种子 DOI 不在 OpenAlex | 记录该事实,保留种子,继续(不为它无限加词) | 否 |
| 校准 5 轮不收敛 | 接受当前检索式,交给第 4 步排序截断;迭代史写进检索记录 | 否 |
| 命中 > 本型过宽阈值 | 先按硬约束 6 修泛词;修完仍过宽 → 截断照跑,把过宽事实写进局限 | 否 |
| 命中 < 30 | 依次放宽:去限制器 → 降为 2 块 AND;每次放宽记协议偏离 | 否 |
| include 偏离目标带 | expand 扩线 / 核心闸门复筛,最多 2 次 |
否 |
| 引文追踪 API 失败 | 跳过补漏,在选择流程说明里写"未执行引文追踪"及原因 | 否 |
| Zotero 写入失败 | 降级为导出 RIS / BibTeX 落盘 + 报告写明,流程继续 | 否 |
| 上下文将尽 | merge 写盘 + 报续跑位置 |
软停 |
选题.md 缺失 / 无 review_type |
无法降级 | 是 |
每触发一次降级,追加一行到 RV_综述/02_检索筛选/降级记录.md(时间、卡点、降级动作、对结果的影响)。收尾汇报必须把这个文件的内容摊开讲,不许埋在文件里。
步骤
第 1 步 · 拆概念块,出配置
读 选题.md(或用户口述)→ 把研究问题拆成 2–4 个概念块(PICO / PECO / SPIDER / 自定义均可)。
- 每块列全同义词:全称与缩写、英美拼写、旧称、近义表达。块内 OR,块间 AND。
- 警惕单词级泛词。
verification/accountability/autonomy/responsibility/subjectivity/adoption/performance这类各学科通用词,会把块撑到百万量级并淹掉整个语料库。要表达这些概念,用精确短语(epistemic responsibility而不是responsibility)。 - 不要把 outcome、研究设计、过窄情境塞进检索式,除非纳入标准明确要求——那会牺牲召回。
- 限制器(年份 / 语言 / 文献类型)只在纳入标准有学术理由时才加,理由要写下来。
写成 RV_综述/02_检索筛选/检索配置.json:
{
"field": "title_and_abstract",
"blocks": [
{"name": "AI", "terms": ["artificial intelligence", "machine learning", "ChatGPT"]},
{"name": "采纳", "terms": ["technology adoption", "implementation intention"]},
{"name": "中小企业", "terms": ["SME", "small and medium enterprises"]}
],
"filters": {"publication_year": "2015-2026", "type": "article", "language": "en"},
"sentinels": ["10.xxxx/yyyy"],
"review_type": "systematic"
}
种子文献(sentinels)不问用户要,按序自动获得:① 选题.md 里的近邻综述 / 关键文献的 DOI;② 不够 3 篇时,用最宽的一两个块跑一次 probe+fetch --cap 40,按被引数排序,AI 从题摘里挑出明显合格的 3–5 篇当种子。用户主动给了就优先用用户给的。
第 2 步 · 检索式自动校准(循环,AI 自己跑,不问用户)
每轮执行:
python3 <skill>/scripts/oa_search.py probe -c RV_综述/02_检索筛选/检索配置.json
python3 <skill>/scripts/oa_search.py recall -c RV_综述/02_检索筛选/检索配置.json
看三个指标改式子:
- 精度守卫:
probe会点名单块命中 > 100 万的块并列出块内的单词级词条。这类块必须收紧(换精确短语 / 删通用词),改完重跑recall确认种子召回没掉。这是硬约束 6 明确要求做的事。 - 种子召回 < 100% →
recall会指出是哪个块(或哪个限制器)把它挡掉了。给那个块补精确短语(不要图省事补单词);若是限制器挡的,判断该限制器是否真有学术理由,没有就删掉。 - 命中数 → 目标 300–2,000。<30 一律是偏窄,给命中最少的块补同义词。
收敛条件(三条同时满足,可机器判定):种子召回 100% && 命中落 300–2,000 && 本轮相对上一轮无改动。
上限 5 轮。 5 轮仍不收敛时不要停下来让用户选方案:接受当前检索式继续往下跑,把"未收敛 + 原因 + 每轮迭代史"写进检索记录的协议偏离节,收尾汇报时一并告知。命中超过本型过宽阈值时也一样继续——截断线本来就是为这种情况准备的——但要把过宽事实写进局限。
种子召回不了且诊断为不可修复时(概念只出现在全文、题摘完全不提,或该 DOI 在 OpenAlex 无记录),记录该事实并继续,不要删掉这个种子。
每轮都追加记录到 RV_综述/02_检索筛选/检索记录.md,保留全部历史版本(这就是"检索式如何迭代"的证据)。
第 3 步 · 全量抓取
python3 <skill>/scripts/oa_search.py fetch -c RV_综述/02_检索筛选/检索配置.json -o RV_综述/02_检索筛选/records
得到 records.csv / .jsonl(含 DOI、题名、年份、期刊、作者、被引数、摘要、命中了哪几个块)。记下三个数:原始命中数、去重后待选数、摘要覆盖率——直接抄脚本打印的 PRISMA · Identification 那行,不要自己相减。
数字必须来自不带 --cap 的完整抓取。 --cap 是试跑用的,脚本会明确打印"被截断、没抓完",那种结果只能当样本看。另外 OpenAlex 的 meta.count 是估算值,与翻页实际遍历数可能差几条,以遍历数为准并在方法节说明。
学科对口时补跑一个信息源,让"信息源 ≥2"成立:
- 医学 / 健康 / 护理:Europe PMC(支持 MeSH)
oa_search.py epmc -q '(MESH:"Artificial Intelligence") AND (MESH:"Education, Nursing")' -o RV_综述/02_检索筛选/epmc - 中文文献:本 skill 的自动检索不覆盖中文核心期刊。OpenAlex 的覆盖来自 Crossref DOI,而 CNKI 系核心刊基本不注册 DOI——实测《中国电化教育》在 OpenAlex 只有 915 条、AI 主题命中 10 条,《电化教育研究》8 条,且多无 DOI、无摘要。要做中文综述,须另行人工检索 CNKI / 万方 / 维普并如实写进方法节(导出的题录用
add子命令并进台账,found_via=cnki:<检索式>,选择流程里单列为一个信息源)。 - 灰色文献 / 政策报告:WebSearch,单列来源,不与数据库检索混算
第 4 步 · 排序截断 + 摘要筛选(连续跑,AI 出建议)
先把纳入 / 排除标准写成可判定的条目表(对齐 选题.md;每条都要能对一篇摘要回答 yes/no),落 RV_综述/02_检索筛选/纳入排除标准.md。
注意:标准表里凡是"只能读全文才判得了"的条目(如是否报告了某种分层结果、样本量细节),在摘要层判不了。这类条目标注为「全文层标准 · 本流程未执行」,写进局限,不要在摘要层硬判。
4.1 建台账 + 截断
python3 <skill>/scripts/oa_search.py rank -i RV_综述/02_检索筛选/records.csv \
-c RV_综述/02_检索筛选/检索配置.json -o RV_综述/02_检索筛选/筛选决定.csv --shortlist 300
排序键:Σ_块(题名最佳词权 × 2 + 摘要最佳词权) → 命中块数 → 有无摘要 → 被引数,其中精确短语 3 分、单词 1 分(这是压制泛词噪音最直接的杠杆)。
前 300 条进入筛选;其余自动标 pass1 = not-screened-lowrank。必须给 -c,不给就退化成弱排序。
台账已存在且已有判定时不要跑 rank(会清空判定,脚本本身也会拒绝执行)——那是续跑,直接跳到 4.2 从第一条空判定接着筛。
4.2 连续筛(分批是内部颗粒度,不是汇报节奏)
只筛 pass1 不是 not-screened-lowrank 的记录,按 seq 顺序,每次在脑子里处理约 40 条:
ai_decision ∈ {include, exclude, unclear} + ai_reason(排除必须对应标准表里的某一条,每篇只记一个首要排除理由)
- 无摘要(
has_abstract=N)→ 一律unclear,不得据题名排除。 - 判不准 →
unclear。宁可多留——摘要层定稿模式下没有第二道关了。 - 量大时先过一遍题名(只排明显的人群/场景不符,绝不用需要读摘要才能判的标准),再对推进的读摘要;两遍连着跑完,中间不汇报。用
pass1列记进度(exclude/advance/pass2-done/locked-noabs)。
每处理完一批,写一个分片 RV_综述/02_检索筛选/筛选决定-partNNN.csv(列只需 uid, pass1, ai_decision, ai_reason),然后立刻继续下一批(硬约束 9)。
分片只给真正逐条判定的记录用。 not-screened-lowrank 由 rank 一次性写进台账,绝不为它们写分片——那会产出几百个空壳文件。merge 成功后分片自动归档进 _parts/。
4.3 合并 + 收敛检查
python3 <skill>/scripts/oa_search.py merge -b RV_综述/02_检索筛选/筛选决定.csv -p RV_综述/02_检索筛选/筛选决定-part*.csv
merge 把判定写回台账、拒绝 AI 填写人工列、报进度,并做收敛检查:
| include 数 | 动作 |
|---|---|
| 60–100 | 达标 → 第 5 步 |
| < 60 | expand -b 筛选决定.csv -n 600 扩线,只筛新增的那批,重跑 merge。扩到 900 仍不足 → 接受,记账 |
| > 100 | 不扩线、不改标准:对 include 集按标准表里最核心的 1–2 条闸门再过一遍,边缘的降为 unclear(进候选池,不是 exclude),重跑 merge |
最多调 2 次,两次后接受当前数字并如实汇报(硬约束 8)。每次调整都要写进 检索记录.md:调整前的 include 数、动作、理由。不得事后按结果反推标准。
跑不完怎么办:上下文预算将尽时先跑 4.3 写盘再停,汇报里写清 已筛 X / N,续跑从 seq=Y 起。
台账列固定为:
seq, uid, doi, title, year, journal, has_abstract, n_blocks_hit, found_via, oa_url, rank_score, pass1, ai_decision, ai_reason, pdf_status, evidence_level, reviewer_1, reviewer_2, final_decision, note
AI 可写 pass1 / ai_decision / ai_reason(本步)与 pdf_status / evidence_level(③ 成文阶段回填);
reviewer_1 / reviewer_2 / final_decision / note 永远留空给人填,merge 会拒绝 AI 写入。
4.4 手工补充(书 / 书章 / 库外经典)
OpenAlex 对专著与书章的覆盖弱于期刊论文,整合式综述尤其容易漏掉最重要的一批:
python3 <skill>/scripts/oa_search.py add -b RV_综述/02_检索筛选/筛选决定.csv \
--dois 10.xxxx/yyy --csv 手工题录.csv --reason "概念奠基专著"
补进来的记录 found_via = manual:<理由>,走同样的筛选流程,选择流程说明里单列为「其他方法识别的记录」,不得混进数据库检索命中数。
第 5 步 · 引文追踪补漏(一轮,自动)
前提:第 4 步已筛完候选集(merge 报「候选集全部筛完」)。
对 include 的记录做双向追踪(对齐已发表综述"翻纳入文献参考文献"这一步):
python3 <skill>/scripts/oa_search.py cite -c RV_综述/02_检索筛选/检索配置.json \
--dois-file RV_综述/02_检索筛选/included_dois.txt --known-csv RV_综述/02_检索筛选/records.csv \
-o RV_综述/02_检索筛选/补漏 --min-blocks 2
补漏集走同样的第 4 步筛选(rank -i 补漏.csv --shortlist 0 建自己的台账——补漏集通常本来就不大,不必再截断),found_via 保留为 citation:backward / citation:forward,选择流程里单列成"其他方法识别的记录"。只做一轮,不递归。
补漏筛完后把 include 数合并计算,再对总数做一次第 4.3 的收敛检查。
第 6 步 · 入 Zotero + 出表 + 复核清单
6.1 入 Zotero:调 lit-pdf-zotero,明确 override:
- 不建金字塔——
Classic / Key Texts / Supporting-P/X/Y/V是 PXYV 那套,综述文章不用。也不出金字塔分布图与 PXYV 罗盘图。 - 只建一个 Collection:
review-<项目名>,不下设子集合。 - 只入
ai_decision = include的文献——Zotero 里这个集合就等于本综述的纳入集。unclear的留在台账里交人复核,人确认后再手工加进来。 - 本步不做专门的 PDF 获取(那是 ③ 的事)。
zotero_add_by_doi的attach_mode="auto"顺手抓到 OA PDF 就抓到,抓不到不重试、不换渠道、不记账、不报告。 ⚠️ 已知故障:zotero-mcp 的attach_mode="auto"在上传失败时仍会返回「PDF attached」(_download_and_attach_pdf不检查attachment_both的返回值直接return True)。不得把接口提示当作附件已挂的证据;要报告附件状态就必须用子项接口复查。 ⚠️ 禁止用zotero_add_from_file挂 PDF——它没有 parent 参数,永远新建父条目,只会造重复题录。 - 标签用
sr-included+ 项目 slug;extra写study_id、found_via、doi。 - Zotero 写入失败不阻塞:降级为导出 RIS / BibTeX 落
RV_综述/02_检索筛选/,写进降级记录,流程继续。 - 人之后手工改了
final_decision,以台账为准;不要自作主张改 Zotero 集合成员。
纳入集只在这一步之后才成立,交给 lit-verify 做一次 DOI / 题录验真,再进入 ③(review-synthesis)。
6.2 出表(一趟出全,不再分两趟):
- 检索记录表 →
RV_综述/02_检索筛选/检索记录.md| # | 概念块 / 步骤 | 内容 | 命中数 |的 S1–Sn 表(probe直接给),加上:检索日期、检索源、完整可复跑检索式、限制器及理由、迭代过程(第 2 步每轮)、截断规则与扩线记录、协议偏离。 - 纳入 / 排除标准表 →
RV_综述/02_检索筛选/纳入排除标准.md| 维度 | 纳入 | 排除 |,维度如可得性、样本、学科、研究设计、文献类型、语言、年份。"全文层标准 · 本流程未执行"的条目单独标出。 - 选择流程数字 →
RV_综述/02_检索筛选/选择流程.md识别(各源命中数)→ 去重删除数 → 去重后总数 → 未进入筛选(相关性排序预算外) → 进入摘要筛选数 → 摘要排除数(按理由分组)→ include → unclear → 纳入集。 每个数字标出从哪张表哪一列反算得来;对不上就停下报错。- systematic 型:可画 PRISMA 式流程图,但必须在图注写明"未进行全文合格性评估,本流程在题摘层定稿"。
- semi-systematic:加一张传统 / 主题覆盖表。
- integrative:加一张概念覆盖矩阵(概念 × 文献,标出空格)。
- 全文获取率一栏留空标「待 ③ 回写」——那是成文阶段的数字。
- 待人工复核清单 →
RV_综述/02_检索筛选/待复核.md列ai_decision = include与unclear(各带 AI 理由),加一节「需要你确认的三件事」——① 概念块是否漏了本学科行话;② 是否需要去 Scopus / WoS 复核一次纳入集(投保守期刊时);③ 边界记录的裁决。 这份清单不是停点:默认直接往下走 ③,用户想看随时能看。
筛选未跑完时:三张表照出,但每一份产出的开头必须放醒目警告——已筛 X/N、剩余 Z 条未筛、排除数与纳入数都是部分值、不得据此绘制流程图或撰写方法节,并写清续跑位置。不得把部分结果呈现成最终结果。
最后给会话内小结:规模链各步数字、降级记录逐条摊开、协议偏离、以及"人接下来要做什么"。
与其他 skill 的边界
- 纳入集验真 →
lit-verify(第 6 步之后跑一次)。 - 全文获取 → ③ 成文阶段(
review-synthesis起手做,best-effort,调lit-pdf-zotero/scansci-pdf)。本 skill 不取全文。 - 下游综合 →
review-synthesis(三型三方法)。不要走data-analysis-round/analyze-quantitative-data——那是实证论文的单研究数据分析,不含效应量合成。 - 综述文章的三型都走本 skill。
literature-search(PXYV 金字塔)是给实证论文定位理论坐标用的,对综述文章是错的产出形状——审稿人问的是"你怎么选的文献",金字塔答不了。 - 成文 →
review-draft(按 PRISMA / RAMESES / Torraco 报告规范,局限节必须写摘要层定稿这一条)。