Files
doc/skills/doc-funcs/SKILL.md
T

168 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: doc-funcs
description: 先判斷專案語言,再為每個 function 與每個指令檔(腳本/CI/部署設定檔)建立 .docs/ 草稿並補齊註解,並整理 `.gitea/workflows/readme.md` 的 workflow 說明、觸發條件與相關參數草稿;由使用者選擇實作方式後寫回原始碼/覆蓋指令檔/更新 workflow readme,接著保守優化被文件化原始碼的效能與排版,最後重建 README 專案列表、功能列表與使用範例。當使用者要補齊 function 文件、產生 XML doc、為每個 method 加 summary/param/remarks、為腳本或 CI/部署設定檔逐行加註解、整理 workflow README、建立 .docs 草稿,或提到 doc-funcs、function 文件化、指令檔註解、workflow 文件化、XML documentation comments 時使用此 skill。
---
# 補齊 function 與指令檔文件
你要替目前工作區內的專案補齊 function 文件、指令檔註解與 workflow README。所有草稿一律由 subagent 產生,草稿全部完成後再詢問使用者如何實作,實作完成後優化被文件化原始碼的效能與排版,最後重建 README。請依下列階段依序完成。
## 第 0 步:先判斷語言與生態
在產生任何草稿之前,必須先判斷目標 repo 的主要程式語言與生態,後續所有草稿的註解格式都以此為準:
- 檢查專案檔與設定檔(例如 `*.csproj`/`*.sln``package.json``pyproject.toml`/`requirements.txt``go.mod``pom.xml`/`build.gradle``Cargo.toml` 等)、主要副檔名分布與 README,推斷主要語言。
- 依語言決定 function 註解格式:C# 用 XML documentation comments`<summary>`/`<param>`/`<remarks>`);其他語言改用該語言慣用的文件註解格式(例如 JS/TS 用 JSDoc、Python 用 docstring、Go 用 doc comment、Java 用 Javadoc)。
-`.docs/doc-funcs-index.md` 開頭記錄判斷出的主要語言與將採用的註解格式,作為後續所有 subagent 的依據。
## 第 1 步:掃描 function 與指令檔
依第 0 步判斷的語言掃描兩類目標,皆排除 generated/bin/obj/.git/.docs 與第三方依賴:
1. **可文件化的 function/method**:以主要語言為準;若是 C#,包含 public/internal/protected/private method、constructor、extension method、operator。
2. **指令檔**:腳本與 CI/部署設定檔,包含但不限於:
- 腳本:`*.sh``*.bash``*.ps1``*.bat``*.cmd``Makefile`
- CI/部署設定檔:CI/CD workflow(例如 `.github/workflows/*.yml``.gitea/workflows/*.yaml`)、`Dockerfile``docker-compose*.yml`/`docker-compose*.yaml`
- 不確定是否屬於指令檔時,依第 0 步判斷的生態保守認定,並在索引標註。
## 第 2 步:建立 .docs/ 與索引
建立 .docs/ 目錄(若不存在)。產生總索引 `.docs/doc-funcs-index.md`,分三段列出:
- function 段:專案名稱、檔案、型別、可見性、簽名、是否已有文件、草稿檔路徑。
- 指令檔段:檔案路徑、檔案類型(腳本/CI/部署設定檔)、註解符號、草稿檔路徑。
- workflow 段:`.gitea/workflows/` 底下所有 workflow 檔案與 `.gitea/workflows/readme.md`,列出 workflow 名稱、觸發條件、相關參數、草稿檔路徑。
## 第 3 步:派 Sub Agent 產生草稿(三類,全部由 subagent 產生)
針對每一個 function 與每一個指令檔各派一個 subagent。subagent 只分析指定目標與必要上下文,**不直接改原始碼或原始指令檔**,只在 .docs/ 底下建立草稿。
### 3-1 function 註解草稿
草稿檔名需可追溯來源,例如 `.docs/doc-funcs/{relative-path}.{type}.{function}.md`。內容必須包含:
- 位置:檔案與行號
- 簽名:完整簽名
- 行為分析:方法實際做什麼、重要分支、副作用、例外/失敗行為
- 建議 `<summary>`(或該語言對應的摘要):根據功能產生,不要只改寫方法名稱
- 建議 `<param>`(或對應的參數說明):每個參數的用途、限制、null/empty 行為(能從 code 推論才寫;不能確定就標註需人工確認)
- 建議 `<remarks>`(或對應的使用情境說明):至少一個使用情境,描述何時呼叫、前置條件、結果或注意事項
- 內部呼叫:此 function 內直接呼叫的 internal/private/protected/private protected 方法;列出方法名稱、所屬型別、可見性與用途推論。若無呼叫則明確標註「無」。
### 3-2 指令檔草稿
對每個指令檔,subagent 要**複製原始指令檔的完整內容**到草稿,並補上註解,作為實作時直接覆蓋原檔的版本。草稿檔放在 `.docs/doc-funcs/commands/{relative-path}` (保留原副檔名,便於語法檢查)。草稿內容規則:
- 檔案開頭必須有一段註解區塊,且「該份指令檔的用途」與「更新日期」必須包在同一個區塊內,不得拆成兩個分開的註解區塊。更新日期使用台灣時區(Asia/Taipei)並固定輸出為 `yyyy/MM/dd HH:mm:ss`(可用 `TZ='Asia/Taipei' date +'%Y/%m/%d %H:%M:%S'` 取得)。標頭格式必須依本 skill 的範本 `templates/command-header.md` 產生:依檔案類型選用 `#``::`/`REM` 變體,並遵守範本的佔位符與放置規則(shebang/`@echo off` 之後、外框成對)。派 subagent 產生指令檔草稿時,必須把該範本內容一併提供給 subagent。
- 原指令檔的每一行有效指令之間必須換行,且每行都要有對應的註解說明,解釋這行在做什麼、為何需要、重要參數或副作用。
- 註解符號必須符合該檔案類型:`*.sh`/`*.bash`/`*.ps1`/Makefile/yaml/Dockerfile 用 `#``*.bat`/`*.cmd``REM``::`。若該行語法不允許行尾註解(例如某些 yaml 值),改用該行上方獨立一行註解。
- 必須保留原始指令的實際行為與順序,只新增註解與開頭用途/日期區塊,不得變更指令邏輯;若發現原指令可能有問題,於草稿中以註解標註「需人工確認」,不要逕自修改。
- 唯一例外是第 6 步定義的「輸出訊息格式/區塊階段命名/一行一則」正規化:可移除印出區塊橫幅的輸出指令、把區塊名稱併入該段每行訊息前綴、並統一訊息格式。此類調整只動「訊息呈現方式」,不得改變訊息反映的實際行為或判斷邏輯,且開頭用途/更新日期標頭必須保留。草稿即應呈現正規化後的最終樣貌。
### 3-3 workflow README 草稿
`.gitea/workflows/` 底下所有 workflow 檔案與 `.gitea/workflows/readme.md`subagent 要先彙整每個 workflow 的用途、觸發條件與相關參數,再產生可直接覆蓋的草稿。草稿檔放在 `.docs/doc-funcs/workflows/readme.md`,內容規則:
- 以繁體中文為主、英文為輔,先列出 workflow 總覽,再依 workflow 檔案逐一整理。
- 每個 workflow 至少包含:workflow 名稱、檔案位置、用途說明、觸發條件、主要輸入/環境參數、重要注意事項。
- 若 workflow 內容有不確定或推論成分,需明確標註「需人工確認」。
- 草稿內容不得變更任何 workflow 實際設定,只作為整理後的 README 草稿。
## 第 4 步:草稿品質檢查
在實作到原始碼之前,主 agent 必須檢查所有草稿:
- 內容以繁體中文為主、英文為輔,且沒有任何亂碼、編碼錯誤、不可讀字元或明顯破損文字。
- 指令檔草稿的指令本體與原檔一致、註解符號正確、每行皆有註解,且開頭標頭符合 `templates/command-header.md` 範本(用途與更新時間同一區塊、外框成對、位置正確)。
- workflow README 草稿需完整涵蓋 `.gitea/workflows/` 底下所有 workflow 檔案,且每個 workflow 都要有用途、觸發條件與相關參數說明。
- 若發現問題,先修正草稿並重新檢查,通過後才能進入下一步。
## 第 5 步:詢問使用者要如何實作
所有草稿完成且通過檢查後,主 agent 必須詢問使用者要如何實作(使用 AskUserQuestion),提供以下選項:
1. 全部一起實作。
2. 逐個草稿實作(每實作完一個草稿就回報,並讓使用者確認後再做下一個)。
3. 其他(由使用者輸入自訂方式)。
依使用者的選擇進行第 6 步。
## 第 6 步:依選擇實作草稿
主 agent 閱讀草稿並依使用者選擇的方式實作:
- function 草稿:依第 0 步判斷的語言把建議文件寫入原始碼(C# 用 XML documentation comments)。註解盡量使用繁體中文;保留既有正確文件,僅補齊缺漏或明顯不足處;此步驟不得為了文件改變 runtime 行為。
- 指令檔草稿:用草稿內容**覆蓋原始指令檔**(草稿已是含用途/日期/逐行註解的完整版本)。
- workflow README 草稿:用草稿內容**覆蓋 `.gitea/workflows/readme.md`**,保留 workflow 實際設定不變,僅整理成說明文件。
- 若選「逐個草稿實作」,每完成一個就回報並等待使用者確認。
- 若遇到大量目標,仍要分批持續處理,不要只做示範。若 token 或時間不足,先完成已列入 index 的批次,並在 `.docs/doc-funcs-index.md` 標記 pending。
- 輸出訊息格式:若該 function 或指令檔有輸出訊息(例如 log、console 輸出、echo、回傳給使用者的提示訊息),訊息格式必須統一為 `[{階段}?][{等級:INF/WRN/ERR/TRC/DBG}][{時間}]: {訊息}`。其中 `階段` 為選填(沿用該訊息所屬區塊的原始名稱、保留原文不翻譯,例如中文區塊名就用中文;無對應階段時省略整個 `[{階段}]` 區塊);`等級` 必須是 `INF`/`WRN`/`ERR`/`TRC`/`DBG` 其中之一;`時間` 使用台灣時區(Asia/Taipei)。調整輸出訊息格式僅限本次被文件化的原始碼或被覆蓋的指令檔,且不得改變訊息所反映的實際行為或判斷邏輯。
- 區塊內 log 的階段命名:若被調整格式的 log 被包在某個有名稱的區塊內,必須將該區塊名稱作為該 log 的 `階段` 名稱(沿用原始名稱、保留原文不翻譯),套用完成後移除標示該區塊的包裹/標題本身(僅移除標記與包裹,保留區塊內原有的指令與行為)。有名稱的區塊包含但不限於:
- 原始碼:`#region 名稱`/`#endregion`、或其他帶名稱的包裹結構。
- 指令檔:以「印出分隔線+區塊標題+分隔線」這種橫幅(banner)方式宣告的段落(例如先 echo `====`、再 echo 區塊名稱、再 echo `----`)。此時橫幅顯示的標題即為該段所有 log 的 `階段` 名稱,且必須移除這幾行印出橫幅的輸出指令,改成把 `階段` 名稱併進該段每一行訊息的前綴。
- 例外:指令檔開頭「用途/更新日期」的檔案說明標頭(含其外框分隔線)屬於檔案標頭、不是階段區塊,必須原樣保留,不可被移除或轉成 `階段` 前綴。
- 一行一則訊息:每一則輸出訊息(原始碼或指令檔皆適用)都必須是獨立的單行輸出指令,一則訊息對應一行;不得用任何區塊(例如多行字串、字串拼接累積成一坨、迴圈外層包住整段訊息的結構)把多則訊息包成一個輸出。原本被包成一坨輸出的多則訊息,必須拆成逐行、逐則的輸出,且每則仍套用上述統一訊息格式。
## 第 7 步:實作註解後,優化被文件化原始碼的效能與排版
完成註解實作後,對「本次被文件化的原始碼」做保守的效能與排版優化:
- 效能:在不改變對外行為與輸出的前提下,優化明顯可改善處(例如不必要的重複計算、可提前 return、低效集合操作)。任何不確定是否等價的改動一律不做,並以註解或回報標註建議人工評估。
- 排版:套用該語言/專案既有的格式化慣例(縮排、空白、括號風格、import/using 排序),不引入與專案風格衝突的格式。
- 每次優化後必須執行可用的格式化/建置/測試驗證行為未被破壞;若無法執行,明確說明原因並標註風險。優化僅限本次被文件化的檔案,不擴及無關檔案。
## 第 8 步:重建 README
補齊後,重建專案根目錄的 README.md。若根目錄已有 README.md,先刪除既有檔案,再產生新的 README.md;不要保留或合併舊內容。README 必須包含更新時間,更新時間必須使用台灣時區(Asia/Taipei)並固定輸出為 `yyyy/MM/dd HH:mm:ss` 格式,例如 `2026/06/22 18:30:05`;README 必須在功能列表前加入專案列表,並只列出所有專案內的公開方法(public method、public constructor、public extension method、public operator),但不得列出單元測試方法;若方法位於測試專案、測試檔案、測試型別,或帶有測試框架屬性/命名(例如 `Test``Fact``Theory``TestMethod``TestCase``SetUp``TearDown``Initialize``Cleanup`),即使是 public 也要排除。產生 README 前,必須先為每個公開方法決定「最終功能名稱」:
- 預設功能名稱為 `Type.Method`
- 若公開方法所在的型別簡名在不同專案或不同命名空間中重複,最終功能名稱不得只使用 `Type.Method`,必須在型別前加入可辨識的專案或模組前綴,格式為 `Module.Type.Method`。例如 `Hangfire.ServiceCollectionExtension.AddHangfireOptions``Hangfire.SqlServer.ServiceCollectionExtension.AddSqlServerHangfire``Swagger.ServiceCollectionExtension.AddSwagger``Swagger.ApplicationBuilderExtension.UseSwaggerUI`
- 模組前綴優先取專案名稱、套件名稱或命名空間中最短且能區分同名型別的一段或多段名稱;若專案名稱與命名空間都可用,優先選擇對使用者最能辨識功能所屬模組的名稱。不得只靠遞增數字、隱藏 suffix 或不可見字元處理重複名稱。
- 若同一個最終功能名稱仍因多載或同名方法重複,需在標題文字中加入可讀且語意明確的參數摘要,例如 `Module.Type.Method(string name, int count)`;同樣不得使用單純數字 suffix 當主要解法。
- 最終功能名稱、使用範例標題、功能描述與任何會輸出到 Markdown 表格、Markdown link text 或 heading 的文字,若包含 C# 泛型角括號,輸出前必須先做 Markdown/HTML 安全跳脫:`<` 轉為 `&lt;``>` 轉為 `&gt;`。例如 `ResponseModelExtension.WithData<TData>` 必須輸出為 `ResponseModelExtension.WithData&lt;TData&gt;``ResponseModelExtension.WithData(ResponseModel<object>)` 必須輸出為 `ResponseModelExtension.WithData(ResponseModel&lt;object&gt;)`。不得在表格、link text 或 heading 中輸出裸 `WithData<TData>``ResponseModel<object>``Dictionary<string, object>` 這類泛型片段。
- README 內部 anchor id 必須用未跳脫的最終功能名稱產生安全 slug,再移除或正規化泛型標點;anchor id 不使用 `&lt;``&gt;`。例如 `ResponseModelExtension.WithData<TData>` 的 anchor 可為 `responsemodelextensionwithdatatdata``ResponseModelExtension.WithData(ResponseModel<object>)` 的 anchor 可為 `responsemodelextensionwithdataresponsemodelobject`。同一個功能在功能列表與使用範例中必須共用同一個 anchor。
README 內容拆成三個主要區塊:
- 專案列表:必須放在功能列表前;依專案名稱列出每個非測試專案,並在此區塊內拆成三張 Markdown 表格:
- 專案描述表:欄位固定為「專案名稱」、「專案描述」。專案描述要根據該專案公開功能列表推測總結,不要只複製專案名稱;若專案沒有可列出的公開功能,保守描述為「此專案未公開可列入 README 的功能」。
- 參考專案表:欄位固定為「專案名稱」、「參考專案列表」。參考專案列表列出該專案的 ProjectReference,格式為 `名稱 版本`,版本優先讀取被參考專案檔中的 `Version``PackageVersion``AssemblyVersion`,都沒有時寫 `未指定`;沒有參考專案時寫 `無`。多個項目以 `<br>` 分隔。
- NuGet 套件表:欄位固定為「專案名稱」、「NuGet 套件列表」。NuGet 套件列表列出該專案的 PackageReference,格式為 `名稱 版本`,版本優先讀取 PackageReference 的 `Version` 屬性或子節點,其次讀取中央套件管理檔(例如 `Directory.Packages.props`)的對應版本,仍無法取得時寫 `未指定`;沒有 NuGet 套件時寫 `無`。多個項目以 `<br>` 分隔。
三張表中的「專案名稱」都必須做成 Markdown 連結,導向目標專案 git `origin` 遠端上的該專案資料夾;連結文字使用專案名稱,連結目標使用專案檔(例如 `.csproj`)相對於目標專案根目錄的所在資料夾。若專案檔位於 repo 根目錄,連到 repo 根目錄。Gitea 類網址使用 `/src/branch/<branch>/<project-directory>`GitHub 類網址使用 `/tree/<branch>/<project-directory>`;無法可靠判斷平台時,優先採 Gitea 格式。若無法可靠解析目標專案的 `origin` 遠端、目前分支或專案資料夾路徑,才退回純文字專案名稱。
- 功能列表:放在專案列表後並依專案名稱分組;每個專案使用一張 Markdown 表格呈現公開方法,欄位固定為「功能名稱」、「功能描述」。功能名稱顯示已跳脫的最終功能名稱,並需做成 Markdown 連結,導向目標專案 git `origin` 遠端上的對應檔案 function 起始行;功能描述使用已跳脫的簡單版描述,並做成 Markdown 連結,導向同一份 README 內「使用範例」區塊中該功能的標題錨點。
- 使用範例:每個功能各有一個標題,標題文字使用同一個已跳脫的最終功能名稱;標題前必須放置 `<a id="..."></a>``id` 必須由未跳脫的最終功能名稱產生安全 slug,且功能列表中功能描述連結的 `#anchor` 必須與對應使用範例標題前的 `<a id="anchor"></a>` 完全一致。完整版功能描述可依草稿的行為分析、`<summary>``<param>``<remarks>` 整理並完成必要跳脫;使用範例需展示典型呼叫方式、重要前置條件與預期結果。若無法可靠產生可執行範例,提供保守的情境式範例並標註需人工確認。
功能名稱連結必須以執行此 skill 的目標專案為準,先用 `git remote get-url origin` 取得遠端,再搭配目前分支、檔案相對於目標專案根目錄的路徑與 function 起始行號產生,不得使用本 skill repo、工作區外 repo 或硬編碼的外部 repo 座標。若 origin 是 SSH 格式(例如 `git@gitea.example.com:owner/repo.git`),需轉為對應 HTTPS 瀏覽 URL;若 origin 已是 HTTPS,沿用同一個 host 與 repo path,並移除尾端 `.git`。Gitea 類網址使用 `/src/branch/<branch>/<path>#L123`GitHub 類網址使用 `/blob/<branch>/<path>#L123`;無法可靠判斷平台時,優先採 Gitea 格式。若無法可靠解析目標專案的 `origin` 遠端、目前分支、檔案路徑或行號,才退回純文字功能名稱;README 不必列出內部呼叫方法。
## 第 9 步:README 錨點一致性檢查
README 重建完成後,必須自動檢查 README 內部錨點一致性;檢查未通過時要先修正 README 再清理草稿。至少確認:
- 專案列表必須存在於功能列表之前,且必須拆成三張表:欄位為「專案名稱」、「專案描述」的專案描述表;欄位為「專案名稱」、「參考專案列表」的參考專案表;欄位為「專案名稱」、「NuGet 套件列表」的 NuGet 套件表。若能解析遠端、分支與專案資料夾,三張表的專案名稱都必須是連到遠端專案資料夾的 Markdown 連結。
- 功能列表中的每個功能描述連結 `#anchor` 都存在完全相同的 `<a id="anchor"></a>`
- 使用範例區塊中沒有重複的 `<a id="..."></a>`
- 使用範例區塊中沒有未被功能列表引用的 anchor。
- 最後一個功能列表項目的功能描述連結能對應到最後一個使用範例 anchor。
- Markdown 表格的 link text 與使用範例 heading 中不得殘留裸泛型角括號模式,例如 `<TData>``<object>``<string, object>`;這些內容必須已轉為 `&lt;...&gt;`,但 `<a id="..."></a>` 錨點標籤本身不列為違規。
- 最後一個功能列表項目後面的章節標題不得被前一個 source link 包住;必須檢查最後一列 Markdown link 的 URL 括號已正確閉合,且後續 `##`/`###` heading 沒有落入任何未閉合的 link 文字或 URL 中。
- 若檢查發現同名型別造成 anchor 或標題語意不明,應回到最終功能名稱產生規則,優先補上專案/模組前綴後重新產生 README。
## 第 10 步:清理草稿
README 錨點檢查通過後,刪除本次產生的所有草稿與索引:`.docs/doc-funcs/`(含 `commands/` 指令檔草稿與 `workflows/` workflow 草稿)與 `.docs/doc-funcs-index.md`。若 `.docs/` 內已無其他內容,可一併移除空的 `.docs/` 目錄;不得刪除使用者既有的 `.docs/` 其他檔案。
## 第 11 步:格式化/建置驗證
完成後執行合適的格式化/建置或至少語法驗證(包含被覆蓋的指令檔語法);若無法執行,說明原因。
## 重要限制
- 不要修改 generated/bin/obj/.git/.docs 以外的非原始碼/非指令檔,除非是建立草稿、索引,依流程實作註解、依草稿覆蓋指令檔、優化本次被文件化原始碼,或刪除並重建根目錄 README.md。
- 不要新增與文件無關的 helper、測試或重構。
- 草稿是實作依據,不能跳過;所有草稿一律由 subagent 產生。
- function 註解步驟不得為了文件改變 runtime 行為;效能優化僅限第 7 步、僅限本次被文件化原始碼,且必須保持對外行為等價並驗證。
- 指令檔草稿只新增註解與開頭用途/日期區塊,不得變更指令邏輯;唯一例外是第 6 步的輸出訊息格式正規化(可移除區塊橫幅、把區塊名稱併入每行前綴、統一訊息格式),但不得改變訊息反映的實際行為,且開頭用途/更新日期標頭必須保留。指令檔開頭的用途與更新日期必須包在同一個註解區塊內,且格式依本 skill 的 `templates/command-header.md` 範本。
- function 或指令檔若有輸出訊息,訊息格式必須統一為 `[{階段}?][{等級:INF/WRN/ERR/TRC/DBG}][{時間}]: {訊息}``階段` 選填、沿用所屬區塊原始名稱並保留原文不翻譯、`等級``INF`/`WRN`/`ERR`/`TRC`/`DBG``時間` 用 Asia/Taipei 時區),且不得藉此改變訊息反映的實際行為。若該 log 被包在有名稱的區塊內(含指令檔以分隔線+標題+分隔線宣告的橫幅段落),須將區塊名稱當作 `階段` 名稱後移除該包裹/橫幅,且僅移除包裹、保留區塊內原有指令與行為;但開頭用途/更新日期標頭不算階段區塊,必須保留。每則訊息必須一行一則、各自為獨立的單行輸出指令,不得用區塊或字串拼接把多則訊息包成一坨輸出。
- 若 function 或指令行為無法可靠推論,文件中要保守描述並標註不確定點,不要編造。
- 原始碼註解與 README 盡量使用繁體中文;專有名詞、API 名稱、型別名稱與程式碼範例可保留英文。