带原文摘录的引用来源
概述
每一个被引用的声明都附有内联证明:原文逐字摘录、可跳转到该段落并高亮的链接,以及可选的屏幕截图。读者无需点击即可验证;点击则精确定位到文本所在位置。适用于 Markdown 文件和聊天回答中的答案。
每条引文必须来自 snap.mjs 脚本的输出,绝不能凭记忆、搜索结果摘要或任何网页抓取工具的总结来提供。 搜索结果摘要和类 WebFetch 工具会对页面内容进行转述;只有该脚本才会逐字检查页面的实际渲染文本。
不仅要验证引文,还要验证声明。 一个匹配的引文只能证明页面 说了 那句话。它无法证明页面没有说什么。以下两类声明必须分别作为独立的批次条目放入脚本中处理,即使你只是“审核一份草稿”:
- 缺失声明: 在断言某页面没有提及、说明或要求某个内容之前,应先把“如果它包含了”会出现的句子放入脚本(例如
Responses with the 429 status code MUST NOT be stored by a cache.)。只有match: none结果支持“缺失”声明,然后写作“未在 上找到”,绝对不要写“该规范对 X 只字未提”。 - 争议声明: 当你的记忆、某个搜索摘要、你已写的草稿或本技能中的示例对页面内容说法不一时,应将有争议的句子放入脚本。无论脚本结果支持哪一方,它都将作为最终裁定。(本技能示例中的每条引文都经过了脚本验证。)
设置(每台机器仅需一次)
npm install --prefix <skill-dir>/scripts && npx --prefix <skill-dir>/scripts playwright install chromium
<skill-dir> 是包含此 SKILL.md 文件的目录。
脚本
先起草文档或答案,收集所有待引用内容,然后 一次性批量验证:
node <skill-dir>/scripts/snap.mjs --batch - <<'EOF'
[
{"url": "https://www.rfc-editor.org/rfc/rfc6585.html", "quote": "Responses with the 429 status code MUST NOT be stored by a cache."},
{"url": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After", "quote": "A non-negative decimal integer", "out": "/abs/path/docs/refs/delay.png"}
]
EOF
一次浏览器会话完成整个批次;相同 URL 上的引文共享一次页面加载。out 字段必须使用绝对路径。输入也可以是 {"defaults": {...}, "cites": [...]} 的格式,以便为所有条目应用相同的截图选项。批次输出是一个 JSON 数组,顺序与输入顺序一致(单条模式 snap.mjs "<url>" --quote "..." 会打印一个对象)。每个条目的字段如下:
| 字段 | 用途 |
|---|---|
ok / match | exact/loose 表示逐字匹配。fuzzy 表示你的引文有误;应使用 quote_on_page 替换你的引文,并重新检查声明是否仍成立。none 表示页面上未找到。 |
quote_on_page | 应放入引用块中的文本。永远不要使用你最初输入的 --quote。 |
fragment_url | 应使用的链接(包含 #:~:text=,在 Chrome/Safari/Firefox 中可高亮跳转)。 |
excerpt | 引文所在的段落上下文,用于检查否定、限定条件、例外等。若想引用更多内容,请将更长的段落作为 --quote 重新运行脚本,以确保链接和截图匹配。 |
title, section, retrieved | 归属行:[<title> — <section>](fragment_url) · retrieved <date>,或当 section 不存在时为 [<title>](fragment_url)。请使用这些字段;不要凭记忆添加章节编号。 |
occurrences / occurrence | 当引文在页面上出现多次时出现。请检查 excerpt 是否是你想要的那一处;若不是,请使用 prefix/suffix 字段(页面上紧邻引文前后的词语)重新运行。 |
hidden | 引文位于页面隐藏的内容中(例如非活动标签页):已验证,但无截图。 |
note | 其他任何值得注意的信息(模糊匹配、展开的折叠区域、回退框架等)。请仔细阅读。 |
internal | 页面位于内部网络中。其内容可能为机密信息;不要引用超出声明所需的部分。 |
退出码:0 表示全部找到,1 表示部分未找到,2 表示部分出错(PDF、4xx、登录墙、机器人验证、超时)。预期需要进行一次后续批次处理:将所有需要再次验证的条目(失败的、模糊匹配的、选错出现位置的、或需要更长段落的)一起放入该批次。
截图选项
任何条目(或在 defaults 中)都可以包含以下可选字段。根据用户的表述来映射;若无相关表述,则省略该字段。
| 用户说 | 字段 |
|---|---|
| "紧截图", "只截引文" | "frame": "quote"(默认为 paragraph) |
| "显示整个章节" | "frame": "section"(高度上限自动提升至 1200) |
| "全屏", "显示页面周围内容" | "frame": "viewport" |
| "截取周围几行" | "context": 2(引文上下的完整文本行数) |
| "手机大小" | "width": 390(默认为 1100) |
| "短一点" | "max_height": 150(默认为 500;裁剪以引文为中心) |
| "黄色高亮", "不高亮" | "highlight": "#fff3a0" / "none" |
| "深色模式" | "theme": "dark"(仅适用于有深色主题的站点;否则 note 字段会提示) |
| "更小的图片" | "scale": 1(默认为 2) |
这些选项仅影响截图。如果用户要求的是文本本身的上下文(或不截图),请引用 excerpt 中的更长段落,并在后续批次中重新运行。对于表格单元格中的引文,脚本会自动将截图框选至包含表头行的整行。所有选项及其对应的截图示例,请参阅仓库中的 examples/README.md。
输出格式
根据文本所在位置选择格式。
Markdown 文件: 声明放在正文中,脚注放置证明:
客户端不应缓存速率限制响应。[^429-cache]
[^429-cache]: > Responses with the 429 status code MUST NOT be stored by a cache.
>
> — [Additional HTTP Status Codes — 4. 429 Too Many Requests](https://www.rfc-editor.org/rfc/rfc6585.html#:~:text=Responses%20with%20the%20429%20status%20code%20MUST%20NOT%20be%20stored%20by%20a%20cache.) · retrieved 2026-11-08
>
> 
- 脚注 ID 应使用简短描述性标识,而不是数字。当同一段引文支持多个声明时,重复使用同一个
[^id]。 - 截图保存到 Markdown 文件旁边的
refs/目录;文件名 = 脚注标识。删除已弃用引文的 PNG 文件。
聊天回答: 不使用脚注(终端中会显示为纯文本)。直接将证明放在所支持的声明下方:
客户端不应缓存速率限制响应:
> Responses with the 429 status code MUST NOT be stored by a cache.
> — [Additional HTTP Status Codes — 4. 429 Too Many Requests](https://www.rfc-editor.org/rfc/rfc6585.html#:~:text=Responses%20with%20the%20429%20status%20code%20MUST%20NOT%20be%20stored%20by%20a%20cache.)
- 不需要
retrieved日期(答案本身就是一次检索)。 - 聊天中的截图保存在系统临时目录下(例如
$TMPDIR/receipts/<slug>.png),绝不能保存到用户的项目中。如果你所在的主机具有向用户展示文件或图片的工具,请使用该工具展示每张截图;否则,在引文之后的新一行上给出每张截图的完整绝对路径。 - 如果未请求截图,则在答案末尾添加一句简短的提议,例如“需要这些段落的截图吗?”
两者通用:
- 你自己的推理或建议不应使用引文;应说明这是你(或团队)的推理,而非来源的声明。关于外部世界(如库、浏览器或标准的行为)的事实性声明需要引用,否则必须以“期望”的口吻表述。
- 截图是 可选功能:它们成本低廉(每个页面约半秒),但会生成用户需要保留或删除的图片文件。仅当用户明确要求截图时,或对于 Markdown 文件中证据是视觉内容(表格、图示、代码布局)而纯文本会丢失含义时,才添加
"out"字段。仅当结果中包含screenshot字段的条目才添加图片或路径。 - 引用最能支持声明的、最简短的那段原文(一句话是典型情况)。
当脚本失败时
| 结果 | 处理方式 |
|---|---|
match: fuzzy | 使用 quote_on_page 替换(截图已高亮该部分)。如果它不再支持你的声明,请修改声明。 |
match: none | 换一种方式搜索页面(不同的段落、不同的章节 URL)。仍然未找到 → 放弃该声明或将其标记为 **UNVERIFIED:** 并附带普通链接。绝不要将未经验证的引文呈现为引用块。 |
ok: false + 错误信息(PDF、登录墙、机器人验证、403) | 普通链接 + **UNVERIFIED (could not load: <error>)**。不要凭记忆或 WebFetch 捏造引文。 |
occurrences > 1 且 excerpt 指向错误位置 | 使用 "prefix" 或 "suffix" 字段设置为你所指位置周围的词语,重新运行。 |
常见错误
- 引用页面“大致说了什么” → 引用块仅接受逐字原文;转述内容应放在正文中。
- 使用章节锚点(
#section-4)代替fragment_url→ 读者仍需手动搜索。 - 引用某段引文,但其
excerpt与声明矛盾(例如下一句话是“这不适用于…”)。 - 使用 WebFetch 来“验证” → 它只做总结;无法确认逐字文本。请使用脚本。
- 相信搜索工具提供的关于页面内容或缺失内容的回答摘要 → 它像 WebFetch 一样进行转述,且经常搞错哪个章节说了什么。应将有争议的句子通过脚本验证。
- 仅验证草稿中已存在的引文来完成“审核” → 缺失声明和争议声明未经检验,使得一个错误的答案看起来像是完全验证过的。
