Communitygithub.com

robcsaszar/tend

針對 SvelteKit + TypeScript 專案提供的本機、隨需維護技能,涵蓋安全性、效能、重構、無障礙與測試覆蓋率。

tend 是什麼?

`robcsaszar/tend` 是一款專為 SvelteKit 與 TypeScript 專案設計的本機、隨需 AI 代理技能,可協助開發者識別並修復最高優先級的無障礙 (A11y)、使用者體驗 (UX) 或文案語氣問題。此技能的核心運作模式為每次執行僅處理一個問題,透過嚴格的優先級掃描(從使用原始 HTML 而非元件庫、缺少 accessible name 的互動元素、到文案語氣違規等)來確保改進的準確性與可審查性。它支援多種平台,包括 Claude Code、Cursor 等,並透過 `.claude/tend/config.yaml` 進行設定,可自訂排除路徑與元件庫規則。技能會自動學習專案中既有的元件庫慣例,避免自行發明不一致的原始 HTML 修復。完成修復後,它會執行 lint/typecheck 驗證,並僅顯示 diff 供開發者審閱,絕不自動提交或建立 PR,確保人類保留最終的程式碼審查權。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add robcsaszar/tend

在你喜歡的 AI 中提問

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

說明文件

Tend A11y — 先行者(The Herald)

在此儲存庫的標記碼中找到單一最高優先級的無障礙、使用者體驗或文案語氣問題,以最小改動修復它,進行驗證,然後將差異(diff)交給開發者審閱。每次執行只處理一個問題。

0. 載入設定

  • 讀取 .claude/tend/config.yaml。使用 skills.a11y(禁止修改的 glob 清單、注意事項 notes)。此技能沒有模組功能(capability modules)——完全跳過模組門控步驟,此處沒有 modules: 門控步驟。
  • 沒有設定檔? 以 核心層級(core tier) 執行:採用預設的 SvelteKit + TypeScript 假設,使用保守的內建防護規則(絕對不碰鎖定檔、CI、.env、設定檔)。發出一次訊息:「run tend-onboard to sharpen.」然後繼續。

1. 分類

必須閱讀 references/scan-core.md。

  • 建立禁止修改的集合:設定檔中的 skills.a11y.off-limits 加上內建的防護規則(絕對不碰鎖定檔、CI 設定、.env、專案設定檔,或後端/API 路由邏輯——此技能僅限於呈現層)。
  • 建立進入點:此儲存庫的標記碼檔案——.svelte 元件、+page.svelte / +layout.svelte 路由,或該技術棧實際使用的任何模板檔案。檢查 skills.a11y.notes 中有無指定的元件庫目錄(例如 src/lib/components/ui)——如果有的話,其匯出項目就是第 2 階段「應使用此替代原始 HTML」的目標清單。
  • 在掃描之前,先閱讀 1–2 個現有元件以了解此儲存庫實際的元件庫與狀態/載入慣例——你需要先掌握實際的模式,才能將偏離它的情況視為違規。

完成標準:已知禁止修改的集合、已識別元件庫慣例(如果有的話)、已識別進入點的 glob 模式。

2. 掃描——按優先級順序,在遇到第一個真正的命中點時停止

按價值從高到低排序(對使用者影響最隱蔽的優先)——在第一個有真實、有證據支持的命中點時停止:

  1. 存在可用的元件庫等價物,卻使用原始互動式 HTML——在儲存庫其他位置有 Button/Link/Input 匯出的情況下,卻使用原始 <button>/<a>/<input>。
  2. 僅含圖示或以圖示為主的互動元素缺少可存取名稱——沒有 aria-label、沒有視覺隱藏文字、沒有 title 後備方案。
  3. <img> 缺少 alt 屬性——缺少屬性是違規;但在裝飾性圖片上有意設為空的 alt="" 則不算。
  4. 表單輸入缺少關聯的標籤——沒有 label for=、aria-label 或元件庫的標籤 prop。審計的是執行時期渲染的數量,而不只是模板:在迴圈({#each} 或等價物)內部產生的輸入會在執行時期產生 N 個無名稱的控制項。
  5. role="button"(或在非互動元素上使用裸 onclick)缺少對應的鍵盤處理器——需要 onkeydown 來處理 Enter + Space。原生 <button> 已自動具備此功能;此規則只針對使用原始元素的逸出路徑。
  6. 非同步的成功/錯誤/載入回饋被渲染成一個純文字、未被宣告的元素——沒有 role="alert"/role="status"、沒有 aria-live,且儲存庫其他地方也未使用現有的元件庫橫幅/快顯提示元件(banner/toast primitive)。
  7. 破壞性操作(刪除/移除/重置)在生效前沒有確認步驟。
  8. 文案語氣違規,根據設定驅動的允許/禁止清單(skills.a11y.notes,或其所指向的專案語氣文件)進行檢查。如果沒有儲存庫特定的清單,則回退到通用預設值:在驗證/錯誤指示中使用強制性緩和詞如「請」(「請輸入名稱」 vs. 「輸入名稱」),或在常規確認/指示性文案中出現不必要的驚嘆號。同時掃描渲染後的標記文字和 <script> 區塊內的字串常值——指派給變數、傳遞給 toast/alert 呼叫、或透過 .textContent/.innerText 設定的文案都存在於 script 區塊中,而非僅在標記碼裡;僅掃描標記碼會遺漏真正的驗證字串。

3. 修復——一個原子性的改動

編輯前,請回答:

  1. 這對真實使用者(使用螢幕閱讀器、僅使用鍵盤、或注意文案語氣的人)來說,是否確實不明確或無法存取——而非我個人的風格偏好?
  2. 修復是否僅限於呈現層/文案——不涉及邏輯、後端或新的依賴項?
  3. 此模式是否已經存在元件庫等價物?如果是,則使用它,而不是自行撰寫原始 HTML 修復(如果儲存庫已經有攜帶 role="alert" 的狀態/橫幅元件,就不要把 role="alert" 硬加在一個原始的 <div> 上)。

基準驗證:在編輯前執行儲存庫的 lint/typecheck(如果速度快,也執行測試套件)——記錄任何預先存在的失敗,以免日後錯誤歸因。

大小預算:標記碼/結構性修復最多 50 行程式碼變更;純文案修復最多 10 行;每次執行只處理一個元件或頁面。

絕對不碰禁止修改的路徑。如果實際修復需要觸及其中一個路徑,則停止並報告原因,而不是強行在其他地方繞過。

4. 驗證並呈現

重新執行 lint/typecheck(以及你在步驟 3 中曾執行的測試)——僅當你的變更引入了新的失敗時才中止;預先存在的失敗並非你的責任來修復。顯示 diff。停止——不要提交,不要開啟 PR。

絕對禁止

  • 絕對不要在一次執行中標記或修復超過一個問題 改為: 在第一個真正的命中點處停止掃描,修復它,然後呈現。 原因: 批次處理的無障礙/文案差異(diffs)難以單獨審閱,並且會隱藏哪個特定修復導致了回歸。

  • 絕對不要在有元件庫等價物存在時自行撰寫原始 HTML 修復 改為: 使用儲存庫自己的 Button/Input/Link/狀態橫幅元件。 原因: 平行的自製修復會創造出第二個不一致的模式,而不是收斂到儲存庫其他部分已依賴的模式——下一次稽核會再次將其標記為偏移(drift)。

  • 絕對不要發明一個不受 skills.a11y.notes 或通用、清楚標示的預設值支持的文案語氣規則 改為: 使用設定驅動的允許/禁止清單,或明確說明你正在回退到通用預設模式。 原因: 當場發明的規則在下一次執行時無法重複使用或稽核,且可能與儲存庫實際的內部風格相矛盾。

  • 絕對不要只掃描標記碼而跳過 <script> 區塊中的文案字串 改為: 也要在 <script> 區塊內搜尋字串常值——驗證和回饋文案經常在那裡被指派,而不是直接寫在模板中。 原因: 真正面向使用者的字串通常是插入模板的變數;僅掃描標記碼會匹配到插入點,而不是實際的違規文字,並且報告不出任何可修復的內容。

  • 絕對不要觸碰禁止修改的路徑或提交/開啟 PR 改為: 尊重 skills.a11y.off-limits 以及內建的防護規則;在呈現 diff 後停止。 原因: 此技能的工作止於「已驗證的 diff,準備好交給人類審閱」——提交或觸碰排除的路徑會移除整個工作流程所依賴的審閱關卡。

檔案

  • references/scan-core.md——核心檢查(在第 1 階段載入)
  • evals/——ai-forge-eval 斷言

相關技能