GitHub Extract 是做什麼的?
這個技能要解決的問題
使用者丟來一個 GitHub 連結,通常不是想要一堆檔案內容,而是想弄明白三件事:
- 這個項目到底是幹嘛的?
- 這次改動想解決什麼問題?
- 為什麼用這種做法?
檔案、diff、元數據只是證據。把證據當結論交出去,等於沒提取——讀者得到了一堆表,卻說不出這個倉庫存在的理由。
完成標準(一句話):一個從沒聽過這個倉庫的人,讀完前 300 字,能用自己的話複述「它解決什麼問題、這次改了什麼、為什麼這麼改」。做不到,就還沒提取完。
第 0 步:先讀「項目」,再讀「頁面」
在抓 PR / issue 之前,先搞清楚載體本身。跳過這步,後面寫得再全也是懸空的。
| 要回答的問題 | 從哪裡讀 |
|---|---|
| 這是什麼項目 | repo 的 description、topics、README 開頭 |
| 它補上了什麼缺口 / 替代了什麼 | README 裡每個套件的 "Why" 列 |
| 誰在什麼場景下用 | README 的 Install / Usage / Develop |
| 這次改動處在什麼位置 | PR 的 base 分支、被改的套件在清單裡的角色 |
monorepo / 插件集合尤其不能跳:必須先列出「套件名 → 一句話職責」的對照,否則讀者無法定位這次改動。若 README 用了大量行話(如 "lifecycle hooks"、"ctx.web seam"),先用一句人話翻譯,再進入正文。
第 1 步:識別 URL 類型
| URL 形狀 | 類型 | 主數據源 |
|---|---|---|
github.com/{o}/{r} | repo | /readme + git/trees?recursive=1 |
…/issues/{n} | issue | issues/{n} |
…/pull/{n} | PR | pulls/{n} + pulls/{n}/files + pull/{n}.diff |
…/commit/{sha} | commit | commits/{sha} |
…/blob/{ref}/{path} | file | contents/{path}?ref={ref}(base64) |
#1 是 fragment,不是路徑。issue 與 PR 共用一個編號空間:/issues/1 若 302 到 /pull/1,那它就是 PR,必須明說。
第 2 步:從 API 取全文,不要跟 HTML 較勁
- 頁面 HTML 只給導航欄和截斷的正文,正文一律走
api.github.com。 - 補丁走
patch-diff.githubusercontent.com/raw/{o}/{r}/pull/{n}.diff(github.com/.../pull/n.diff會跨域重定向,必須直連最終地址)。 raw.githubusercontent.com常不可用,改用contents的 base64 本地解碼。- 本機
git/curl報 TLSSEC_E_NO_CREDENTIALS時不要去修 shell,換 harness 的web_fetch;不要把「clone 失敗」當成任務受阻。
第 3 步:交叉校驗
additions/deletions/changed_files ↔ files 列表 ↔ .diff 的 hunk;PR 的 head SHA ↔ 補丁 ref;merged 不能只看 state=closed。不一致就繼續查(多半是分頁或舊補丁),不要寫一份自相矛盾的產物。
第 4 步:組織成「能讀懂」的產物
順序是硬性的:解釋在前,證據在後。讀者不該翻過 200 行表格才明白這是什麼。
- 它是什麼(150–300 字,白話) — 項目存在的理由、補的是什麼缺口。專有名詞第一次出現必須一句話解釋:
hookkit = 把「寫插件才能掛生命週期鉤子」變成「寫一段 YAML」。 - 這次改動想解決什麼 — 用「原來會怎樣 → 現在怎樣」的對比寫,不要用檔案清單代替。
- 為什麼是這個做法 — 從 PR 描述 / commit message 裡提煉取捨與因果鏈(為什麼不選 push 觸發、為什麼把 registry 當狀態)。
- 改動清單 — 表格:檔案 / 狀態 / 增刪 / 一句話作用。
- 原文 — PR 描述、commit message 逐字引用,不改寫。
- 完整內容 — 每個檔案全文,不寫 "……其餘省略"。
- 可遷移的做法 — 只留讀者下次真能用上的。
- 驗證與覆蓋 — 放最後當附錄:
git apply --check結果、blob SHA 比對、哪些沒抓到。
寫作規則
- 結論先行:每段第一句就是結論,後面才是依據。
- 表格不承擔解釋責任。凡是「這是什麼」「為什麼」,必須用完整句子寫。
- 不許用檔名代替功能描述:「改了 publish.yml」❌;「新增手動發佈工作流,按按鈕才發佈,預設只演練」✅。
- 數字要能追溯來源,但別把校驗日誌放在開頭。
- 使用者用什麼語言就用什麼語言寫。
- 反模式:大表格堆砌、把逐檔案 diff 當正文、開篇就是元數據、術語不解釋。
第 5 步:自檢
- 只看前 300 字(不含標題表),能否答出「幹什麼 / 改了什麼 / 為什麼這樣改」?不能就重寫。
- 有沒有沒解釋過的術語?
- 是不是把「檔案 A、B、C 有變化」當成了改動說明?
- 補丁是否
git apply --check通過?沒跑就明確寫「未驗證」。
失敗模式
| 症狀 | 原因 | 處理 |
|---|---|---|
| 正文寫到一半斷掉 | 抓了 HTML | 改用 API |
404 on raw.githubusercontent | 網路白名單 | 解碼 contents base64 |
403 rate limit | 未認證循環 | 批次、放慢、如實報告缺口 |
cross-origin redirect not followed | .diff 跳轉 | 直連 patch-diff… |
檔案數與 changed_files 不符 | 分頁 | ?per_page=100 重取 |
| 讀者回饋「沒看懂」 | 只給了證據,沒給解釋 | 回到第 4 步第 1–3 節重寫 |
邊界
優先級:使用者顯式指令 > 本節約束 > 預設保守。
預設只提取內容,不順手 clone / build / install / 跑測試。私有倉庫要使用者提供 token,不要編造;倉庫已歸檔要說明——內容仍可提取,但狀態影響解讀。
必須停下來問(而不是自行擴權)的情形
- 使用者說「裝一下 / 跑一下」,但物件是別人的倉庫,或會寫入全域環境:先確認範圍與回滾方式。
- 指令本身有歧義(「處理這個倉庫」):給一行預設方案 + 一句確認,不要猜著做。
- 動作不可逆或會改變使用者環境(
pnpm install、全域套件、改 profile、提 PR、push、刪檔案):一律先問。 - 需要憑證(私有倉庫、token、SSH key):問一次;拿到就用,拿不到就只輸出公開可驗證的部分,並註明缺了什麼。
可以自行放寬的情形
- 使用者自己的倉庫,且明確說過「隨便改 / 直接裝 / 不用問」;
- 或在臨時目錄內完成、不觸碰原倉庫與全域狀態(此時放寬的只是「寫」,不是「執行不可信程式碼」)。
放寬時在產物末尾寫一句「已按你的授權執行了 X」,讓越界可見、可撤銷。