帶有摘錄的引用來源
概述
每個被引用的聲明都內嵌了其證據:逐字段落、一個跳轉到並高亮該段落的連結,以及選擇性的螢幕截圖。讀者無需點擊即可驗證;點擊後會精確落在該文字上。適用於 Markdown 檔案和聊天回覆。
每個引用都必須來自 snap.mjs 的輸出,絕不來自記憶、搜尋結果摘要或摘要型擷取工具。 搜尋摘要和 WebFetch 風格的工具會改寫頁面內容;只有這個腳本會檢查渲染後的逐字文字。
檢查聲明,而不只是引用。 一個匹配的引用證明該頁面說了那個,但對於該頁面沒說什麼則一無所知。有兩種聲明必須透過腳本作為各自的批次條目來處理,即使你只是在「驗證草稿」:
- 不存在 (Absence): 在撰寫某頁面「沒有說明、提及或要求」某事之前,請先加入如果該頁面有提及時會出現的句子(例如
Responses with the 429 status code MUST NOT be stored by a cache.)。只有match: none能支持「不存在」的聲明,然後寫「未在 上找到」,絕不能寫「該規格對 X 隻字未提」。 - 分歧 (Disagreement): 當記憶、搜尋摘要、你已撰寫的草稿或本技能的範例對某頁面的內容描述不一致時,請加入有爭議的句子。腳本的結果能解決爭議,無論它支持哪一方。(本技能範例中的每個引用都經過該腳本驗證。)
設定(每台機器一次)
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 應使用簡短的描述性英文 slug,而非數字。當同一個段落支持兩個聲明時,重用相同的
[^id]。 - 將截圖儲存到 Markdown 檔案旁的
refs/目錄;檔名使用註腳 slug。刪除已放棄引用的 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),絕不儲存到使用者的專案中。如果你的宿主環境有向使用者顯示檔案或圖片的工具,請用它來顯示每張截圖;否則,請在引用之後的獨立行中給出每張截圖的完整絕對路徑。 - 若未要求截圖,請在回覆結尾加上一行提議,例如:「想要這些段落的截圖嗎?」
兩者通用:
- 你自己的推理或建議不需引用;請說明這是你的(或團隊的)推理,而非來源的。關於外部世界(例如函式庫、瀏覽器或標準的行為)的事實性聲明需要引用,否則必須以期望的形式表述。
- 截圖是選擇性加入 (opt-in) 的:它們成本低廉(每頁約半秒),但會產生使用者需要保留或刪除的圖片檔案。僅在使用者要求截圖時,或者在 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 一樣改寫,且經常錯誤地歸屬哪個章節說了什麼。請將有爭議的句子交由腳本處理。
- 透過只檢查草稿中已有的引用來「驗證」草稿→ 其「不存在」聲明和有爭議的聲明未經測試,導致一個虛假的答案看起來完全被驗證。
