Community程式設計與開發github.com

JoshuaKGoldberg/lint-rule-review-skill

以經驗豐富的 ESLint、typescript-eslint 和 Flint 維護者的方式審查自訂 lint 規則,透過突變規則並執行對抗性測試案例來證明錯誤。當使用者要求審查、稽核、批評或檢查 lint 規則、規則的修復器、其測試或文件,或是新增或變更規則的 PR 或分支時使用,即使他們只說「看看這個規則」或提供 linter 或外掛儲存庫中的 PR 編號。請勿用於在專案中配置 lint 規則或修復應用程式程式碼中的 lint 錯誤。

lint-rule-review-skill 是什麼?

此技能模擬一位擁有數千條審查意見經驗的 ESLint 維護者,對自訂 lint 規則進行深入審查。它的核心方法是以實證為基礎:不會僅閱讀規則,而是會嘗試破壞它,例如刪除條件並觀察測試是否失敗,或發想從未被想到的語法。該技能支援審查 PR、分支或規則檔案,並會讀取規則的測試、文件、PR 說明及相關問題,以判斷規則是否符合其設計目的。 審查過程包含五個步驟:理解變更、檢查規則設計、逐行閱讀新增程式碼、嘗試破壞規則(包含突變條件、比較版本與執行對抗性測試),以及篩選與整理發現。突變腳本會自動刪除條件並執行測試,以找出測試未涵蓋的倖存突變體,並支援比較 head 和 base 版本以發現回歸問題。最終的發現會以結構化標記檔案輸出,並區分阻塞與非阻塞意見,且會優先報告回歸問題。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/JoshuaKGoldberg/lint-rule-review-skill/tree/HEAD/skills/lint-rule-review-skill

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

ESLint 規則審查技能

以一位擁有數千條過去審查意見的維護者的方式,來審查 lint 規則。 那位維護者的標誌性習慣是實證主義:他們不只是在閱讀規則,他們試圖破壞它。 他們會刪除一個條件,看看測試是否失敗,並且他們會發想沒人想到過的語法。 在此遵循這個習慣。 一個有失敗測試或倖存突變體佐證的發現,遠比聽起來合理的發現更有價值,而聽起來合理的噪音正是讓自動化審查被忽略的原因。

發現結果會交給使用者,由使用者決定如何處理。 將審查結果寫入本地檔案是全部的工作:發佈到 GitHub 或推送任何內容,只有在使用者另外要求時才會發生。

1. 瞭解變更

弄清楚正在審查的內容:一個 PR、一個分支或一個規則檔案。 對於 PR,如果可能,請檢出它的 head commit,因為後續步驟會執行程式碼。

在形成意見之前,請先閱讀以下內容:

  • 規則、其測試及其文件頁面
  • PR 說明與關聯的問題,因為規則是根據其目的來評判,而不是根據其自身的演算法
  • 同一儲存庫中的兩到三個同類規則,以及 CONTRIBUTING 文件

注意作者在說明中提出的任何問題。 審查應該回答這些問題。

儲存庫慣例優先於此技能的參考資料。 這些參考資料來自數個專案,因此如果某個模式與儲存庫明顯的做法相衝突,請遵循儲存庫的做法。

參考資料很大,所以不要從頭到尾閱讀。 從 references/index.md 開始,它列出了每個模式,並只提取適合此變更的部分。 也請閱讀 references/extra-checks.md,它很短,涵蓋了工具陷阱以及對修復器、匯入規則和 Flint 的檢查。

2. 檢查規則的設計

根據變更的類型,從索引中的 design.md 列表中挑選:

  • 新規則: 它是否歸屬於此、其範圍、與其他規則的重疊、類型資訊、選項以及預設集放置位置。
  • 對既有規則的變更: semver 影響、需要相同變更的同類規則,以及該變更是否服務於該問題。 跳過其餘部分。

如果 PR 很粗糙,例如還沒有測試或設計需要重新思考,請停在高層級審查並說明原因,並跳過突變,因為沒有測試,突變無法告訴你任何資訊。 仍然嘗試在幾個案例上執行規則,因為在任何階段報告一個真實的錯誤都是有價值的。 對即將變更的程式碼進行詳細評論會浪費每個人的時間。

3. 閱讀每一行新增的程式碼

使用索引來提取與變更內容相符的章節:

變更的內容請查看
規則邏輯bugs.md、simplification.md、performance.md
修復器或建議fixes.md
訊息messages.md
測試test-method.md
文件頁面docs.md
新的名稱、選項或規則naming.md

在嘗試破壞任何東西之前執行此操作,因為錯誤搜尋一旦開始就會佔據主導地位。 隨著進度記錄筆記,並在第 5 步中對它們進行分類。

逐行瀏覽差異中的每一行新增程式碼,並對每一行提出以下問題:

  • 名稱: 你能在不進一步閱讀的情況下知道這個識別碼持有什麼或做什麼嗎? 注意那些描述類型而非目的的名稱,以及聲稱錯誤動作的名稱。 如果需要再讀一遍才能理解,請說出來並建議一個更好的名稱。
  • 區域變數: 這個變數是否只使用一次,並且在設定之後立即使用? 建議將其內聯。
  • 條件: 它是否可以折疊?!x || x.kind !== y 變成 x?.kind !== y。 巢狀或相鄰的 if 通常可以合併,而布林值的 if 通常可以直接回傳。
  • 守衛: 給定 AST 和上面的程式碼,這種狀態真的可能發生嗎?
  • 重用: 是否已經有一個共享的實用工具可以做到這一點? 在接受任何輔助函式之前先檢查。 如果一個輔助函式放在 create 內部,它需要的參數會不會更少?
  • 長度: 有沒有更少的程式碼可以做到相同的事情? 簡化是過去審查中最大的類別。
  • 值得做嗎: 這段程式碼或 TODO 是否在為沒人需要的東西做規劃? 說它可以刪除。

如果程式碼看起來是 AI 輔助的,請用更挑剔的眼光閱讀它,因為那裡往往是冗餘程式碼的聚集地。

**掃過每一條註解和每一句文件。**錯誤搜尋會排擠這個,然而它卻是真實審查意見的常規來源,所以將它作為一個單獨的步驟,對每一條新增的註解和每一行新增的文件進行審查。 不要問它是否正確,而是問它是否應該按照寫好的樣子存在:

  • 這條註解會過時嗎? 關於測試覆蓋率、歷史或測試涵蓋內容的註解會過時,所以建議刪除它們。
  • 它是否在重複程式碼? 建議刪除它。
  • 它是一個重要的已知捷徑嗎,例如上游程式碼的一個分支? 要求一個 TODO,如果有的話附上問題連結,並建議精確的註解文字。
  • 最終使用者會關心這個文件句子嗎? 實作細節不應該出現在頁面上。
  • 這個文件範例是否包含了它不需要的程式碼? 建議刪除任何超出展示行為所需的內容。
  • 句子是否精確? 注意那些聽起來很通用或總是正確但實際上並非如此的措辭,並建議重寫。

以 ```suggestion 程式碼區塊的形式給出這些建議。 它們對作者來說很容易接受。

**注意做得好的地方。**指出任何幫助你審查或處理了棘手問題的內容,並在審查主體或以 [Praise] 註解的形式具體提及。

4. 嘗試破壞它

這個步驟產生最有價值的發現,所以不要跳過它。 首先讓規則的現有測試通過,這樣你就有一個可以執行此規則測試的工作指令。

**突變條件。**從儲存庫根目錄執行捆綁的腳本。 它需要 Node 22.18 或更新版本,這可能與儲存庫鎖定的版本不同。 每個突變體是一次測試運行,所以請在背景執行它。 它會原地編輯規則,因此在此期間執行的任何其他操作都必須使用以臨時名稱儲存的規則副本:

node <skill-dir>/scripts/mutate-conditions.ts --file <rule> --test "<test command>" --base <base ref>

--base 將突變限制在 PR 變更的行,而 --diff <file> 則從差異中執行相同操作。 省略兩者以突變一個全新的規則。 突變體按原始碼順序執行,最多 --max 個,預設為 60,所以如果摘要顯示有任何未測試的,請提高它。 如果測試是從套件資料夾執行的,請從那裡執行腳本。--out <file> 儲存完整結果,並且一個簡短的倖存者列表總是會最後列印出來。 它首先檢查當規則拋出時測試是否失敗,如果沒有則停止,因為這表示它們沒有在測試規則。 腳本在完成或停止時會還原檔案。 如果它被直接殺死,下一次執行將拒絕啟動並列印原始檔案的儲存位置,所以請在更改規則之前比較兩者,因為你可能已經編輯過它。 如果測試指令會建構規則,請在建構後重新執行,因為建構輸出仍然包含最後一個突變體。 它使用儲存庫的 typescript 進行解析,並且在 TypeScript 7 或更新版本上,它會列印如何使用 --typescript 傳遞一個較舊的副本。

測試沒有注意到的突變體就是倖存者:每一個都表示缺少測試或程式碼是無效的,你應該弄清楚是哪一種。 刪除該條件並思考什麼輸入會需要它。 如果你無法建構一個,建議刪除該程式碼。 如果你可以,將它添加到下一步。 標記為 likelyTypeOnly 的倖存者是通常僅為了編譯器而存在的純空值檢查出口,所以最後再檢查它們,但請確認該分支並非只是未經測試。 如果測試執行器進行類型檢查,一個突變體也可能因為無法編譯而「失敗」,所以請盡可能使用僅轉譯的指令。

該腳本僅涵蓋常見的突變。 也要手動嘗試任何它無法觸及但 PR 依賴的內容,例如將一個參數與作用域中已有的類似變數交換。

**比較 head 和 base。**對於對既有規則的變更,這是最重要的檢查。 過去有效程式碼中的回歸問題遠比已經存在的差距重要得多,而且如果不執行兩個版本,你無法區分它們。 將 base 版本儲存在規則旁邊,例如使用 git show <base>:./<rule> > <rule-dir>/<name>.base-tmp.ts,或透過反向應用差異。 然後將 assets/compare-rule.test.ts 複製到規則的測試旁邊,並調整其標記的行。 它透過比較報告數量來對每個案例進行排序,並且它還會記錄每個 fixture 中的訊息、範圍、修復輸出、建議、崩潰和編譯錯誤。 自己閱讀 CHANGED OUTPUT 結果,因為變更的訊息或修復可能是錯誤,並忽略任何具有 fixtureErrors 的案例,直到其 fixture 可以編譯。 對於新增修復器的 PR,修復和建議輸出是主要需要閱讀的內容,因此在這些案例上設定 expectedOutput。 如果 PR 新增了一個選項,請設定 baseOptions,以便 base 版本的模式接受該案例。 沒有它,該案例僅根據 head 版本進行評判。

對於一個新規則,將其同時匯入為 head 和 base,以便測試框架報告 ok 或 WRONG,而不是比較版本。 如果測試框架不適合該外掛,請改用儲存庫自己的測試框架中的一個臨時測試檔案。

**編寫對抗性案例。**從 references/test-cases.md 中挑選適合此規則所處理的語法和類型的類別,並編寫字面案例。 在執行每個案例之前決定正確的行為,因為這可以防止你合理化回傳的任何內容。 同時列印訊息資料和報告數量,因為訊息中的錯誤類型名稱也是一個錯誤。 將一個使用新語法的案例與一個使用舊語法的對照組配對,例如一個符號鍵與使用字串鍵的相同案例。 尋找:

  • 崩潰
  • 誤報,即有效程式碼被報告
  • 漏報,即無效程式碼未被報告
  • 產生無效程式碼、改變行為或遺漏註解的修復
  • 比違規程式碼範圍更廣的報告範圍

保留那些暴露了問題的案例,以便它們可以作為字面測試案例放入審查中。 字面案例很重要:這個維護者要求手寫案例,並反對 .map、工廠方法以及生成的測試。

**證明重大建議。**如果你認為重新設計可以消除多個錯誤,請建立原型並執行現有測試。「268 個測試中有 267 個通過,以下是另一個失敗的原因」遠比一個直覺有用得多。

**清理。**在繼續之前執行 git status 並刪除所有暫存檔案,以便儲存庫恢復到原本的狀態。

5. 篩選發現

在寫任何東西之前,請逐一檢查每個發現:

  • 錯誤: 包含案例和實際發生的情況。 如果你無法重現它,請刪除它,或者如果你仍然有具體理由懷疑它,則將其降級為 [Question]。
  • 順序: 回歸問題優先,然後是新程式碼中的錯誤,最後是 PR 觸及的現有錯誤。
  • 單一根因: 如果一次重新設計可以修復多個錯誤,請將其作為一條註解並在其中列出這些案例。 只有在一個錯誤無論如何都需要自己的修復時(例如回歸問題),才保留單獨的註解。
  • 有爭議的立場: 將這些視為非阻塞問題:對節點的 in 檢查、esquery 使用、選項結構形狀以及 import ts 風格。 其他維護者對它們有合理的不同意見。
  • 擴大或推遲: 如果一個差距與規則的概念相同,並且真實使用者會遇到它,請在此 PR 中要求修復它。 否則建議建立一個後續問題。
  • 新增或刪除選項: 僅在規則會因此禁止有效程式碼,或是有真實使用者要求時,才要求新增一個選項。
  • 既有程式碼: 除非問題很嚴重,否則忽略 PR 未觸及的既有程式碼中的問題,並將它們標記為 [Non-Actionable]。
  • 重複項: 將重複的內容合併為一條註解,並寫「此處及其他地方」。

雜訊的成本比遺漏更高:一個作者如果略過了三條弱勢的評論,他們也會略過真正重要的那條。 阻塞性評論應該只包含在合併前必須更改的內容。 最多保留大約八條非阻塞性評論,選擇那些最能改進程式碼的評論,並在每條要求變更的評論旁邊附上一個可直接套用的建議。 優先刪除這些:

  • 品味問題,沒有真正提高清晰度,例如改寫一條訊息或折疊一個讀起來還不錯的條件
  • 說明中說是有意為之的任何內容,例如為計劃中的工作提供的架構
  • 你嘗試過但找不到真實案例的錯誤,並且沒有具體理由懷疑它們
  • 空白和引號風格
  • 不會增加任何價值的流程請求,例如為每個小的 TODO 建立一個追蹤問題

沒有什麼可報告也是一個好結果,所以不要為了看起來全面而捏造發現。

使最終結論與阻塞性評論相符。 如果沒有阻塞性內容,請批准並將其餘內容作為建議留下。 這位維護者對可靠的 PR 的許多審查都是一個溫和的批准,帶有一兩個小請求。

6. 撰寫審查

閱讀 references/review-voice.md,然後在當前目錄中撰寫 lint-rule-review-skill-<pr-or-rule>.md,不進行提交。 將審查主體保持在一兩句話,只有在回答作者的問題或解釋設計決策時才寫得更長。 使用此結構:

# Review of <PR or rule>

**Verdict:** approve | request changes | high-level only

<Review body, following the order in review-voice.md>

## Inline comments

### `path/to/file.ts:42` · blocking

[Bug] <Comment as it would be posted>

```ts
<Literal failing case or suggestion>
```

Evidence: <What you ran and what happened, or "not reproduced">

## Not checked

<Anything you couldn't run or verify, and why>

將每條評論標記為 blocking 或 non-blocking,阻塞性評論優先排序。「Evidence」是給使用者看的,不會被發佈。(此處原文有截斷,但翻譯已包含主要結構指引)

相關技能