compound 是做什麼的?
將最近解決的問題或已推出的功能記錄下來,以累積專案的知識。每個記錄下來的解決方案都能讓未來的規劃與實作更快——代理在執行 /research 和 /write-a-prd 時會查閱 docs/solutions/,因此今天學到的教訓可以避免明天犯錯。
如果工作中出現了規劃或估算上的意外,也請一併記錄下來。McConnell 風格的校準只有當實際工作回饋到未來的規劃中時才可能發生。
調用位置
這是一個主要管線技能,用來閉合知識累積循環。它位於預設交付路徑的尾段,在 /pre-merge 建立 PR 之後執行。
預設——在 PR 中記錄經驗,合併前完成。 當在 PR 階段已經知道可複用的經驗時,在開放 PR 的分支上執行 /compound,讓 docs/solutions/ 的條目與教導該經驗的程式碼在同一 PR 中——在同一次審查中審查,並以原子方式合併。這將 /compound 放在 /pre-merge 和 /closeout 之間,並透過 /pre-merge 回傳一次:
… → /pre-merge → /compound (在 PR 中,當有經驗存在時) → /pre-merge (重新執行:compound 提交是後戳記增量;重新蓋章) → /closeout (合併 + 清理) → cleanup
回傳環節並非裝飾。在分支上提交會將頭指標移到 /pre-merge Phase 4 寫入的戳記之後,而 /pre-merge 是戳記唯一的寫入者——因此如果不重新執行,條目會與程式碼一起合併但無人閱讀,這正是選擇「在 PR 中」預設路徑所要避免的情況。Phase 5 說明了這個交接;這就是它存在的原因。
備用——合併後記錄經驗。 有些經驗只在合併期間或之後才浮現:整合中的意外、QA 發現、上線後才看到的行為。對於這些情況,在 /closeout 合併之後執行 /compound。這是備用路徑,而非預設路徑。
無論哪種方式,/compound 都不會執行合併或工作樹清理——那是 /closeout 的職責——也不會寫入審查貨幣戳記,那是 /pre-merge 專屬的。在 PR 中記錄經驗意味著在開放 PR 的分支上提交並交回以進行涵蓋它的審查;它不代表合併。
請勿將其用於瑣碎編輯,或用於完全適合更高保真度工件(如測試、Linter 規則或程式碼註解)且沒有持久專案級學習價值的經驗。無論是在 PR 中還是合併後,下方「何時不使用」的防護條件仍然適用——大多數 PR 都不包含可複用的經驗,也沒有每個 PR 都必須填寫的 docs/solutions/ 欄位。
為什麼存在
如果沒有這個步驟,你只是在用 AI 輔助進行傳統工程。工作流程的前三個步驟(規劃、工作、審查)產生一個功能。這個第四步驟產生一個系統,讓每一次建立功能都變得更好。
何時使用
- 當一個功能的 PR 準備好,並且它提供了可複用的經驗時——在合併前將其記錄到 PR 上(快樂路徑)
- 上線後,當一個經驗只有在合併期間或之後才變得清晰時(合併後備用路徑)
- 修復了一個棘手的錯誤,且根本原因不明顯時
- QA 週期揭示了本可以更早發現的問題時
- 做出了具有重大取捨的架構決策時
- 發現了一個應該被重複使用的模式時
何時不使用
- 對於瑣碎的修正(打字錯誤修正、簡單的配置變更)
- 當解決方案已經在官方函式庫文件中完整記載時
- 當經驗是專案特定的,但你即將棄用那段程式碼時
- 當工作是預先規劃好的乾淨執行——沒有意外、沒有重做、沒有不明顯的決策。問題正文和 PR 描述已經包含了這些記錄;一個沒有可複用經驗的
docs/solutions/條目會訓練未來的讀者跳過它 - 當不確定時——跳過沒有任何成本,因為問題和 PR 仍然存在於 GitHub 中。記錄一個低價值的經驗會消耗未來規劃者每次查閱
docs/solutions/時的注意力
執行流程
Phase 1:識別要記錄的內容
在 PR 內預設路徑下,正在審查的工作是開放的 PR 分支,因此下面的指令直接讀取它——對分支及其要合併的基底分支執行 git log 和 git diff,在尚未合併時進行。在合併後備用路徑下,在一個仍然能看到合併功能歷史的會話中執行它們——一旦 /closeout 清理了分支並拉取了基底,該 diff 就會是空的,你必須改用 gh pr diff <n> 來讀取 PR diff。無論哪種方式,請檢閱近期的工作。
首先解析基底。不要硬編碼 main——這個 repo 本身就使用了 prod,而且一個名稱不是一個引用:在工作樹工作流程中,沒有人會檢出基底分支,因此本地分支凍結在檢出時的狀態,而 origin/<base> 則會繼續前進。詢問 sidecar.sh base-ref;不要自行推斷基底。
SC="<此技能的目錄>/references/sidecar.sh"
BASE_REF="$(bash "$SC" base-ref)" || { echo "base-ref 失敗:不猜測基底" >&2; exit 1; }
git log --oneline "$BASE_REF..HEAD"
git diff --stat "$BASE_REF...HEAD"
檢查:
-
Git 日誌 — 進行了哪些提交?更改了什麼?基於基底,而不是
-20:固定的計數會將基底的歷史讀取為「正在審查的工作」,如果分支更短的話。這裡的兩個點是正確的——這些是這個分支上而非基底上的提交。(git diff使用三個點是基於對稱的原因:它從合併基礎進行比較,而不是減去基底側的工作。)在合併後備用路徑下,分支已消失,因此如上所述使用gh pr diff <n>。 -
問題討論串 — 原始問題是什麼?討論了什麼?
-
差異 — 哪些檔案更改了?出現了哪些模式?
詢問使用者:「你在這個功能中學到的最重要的事情或最棘手的部分是什麼?」他們的回答通常會揭示最有價值的經驗。
在撰寫之前,將經驗分類到正確的層級:
- 事件 — 一次性的事件或可見的失敗
- 模式 — 跨功能、錯誤或交接重複發生的事情
- 結構 — 程式碼庫、工作流程、激勵機制或決策過程中反覆出現的條件,不斷產生該模式
優先記錄你能夠提供證據支援的最高層級。如果經驗是結構性的,請指出使得該結果成為可能的回饋迴路、缺失的回饋或延遲效應。
在繼續之前,回答四個問題:
- 這是否真正新穎? 檢查官方函式庫文件和 Phase 4 的重疊搜尋涵蓋的存儲。如果經驗已經在別處有詳細記錄,請跳過或連結到現有來源。
- 三個月後這是否仍然準確? 如果經驗與某個依賴版本或臨時解決方案緊密耦合,請註明——這會影響下面的
volatility分類。 - 能否以更接近原始碼的形式捕捉? 行為不變性最好作為測試。約定最好作為 Linter 規則。「為什麼」的解釋最好作為與決策共置的程式碼註解——僅限於當前的為什麼,讀者需要理解現有程式碼的原因。發現該事件的事件屬於提交訊息和 PR 正文,讀者重建歷史時已經會查看那裡;
/execute步驟 3 在撰寫註解時指出了該路由,而這個問題是對它的回顧檢查。如果經驗可以以更高保真度的工件記錄,請這樣做,而不是撰寫散文。這是關於承載經驗——Phase 4 的聚類檢查問了一個不同的問題,即一個機制是否應該捕捉下一個實例,而一個重複發生的情況可能需要一個機制,即使經驗本身需要散文。 - 流程是否已修正?(僅限錯誤修復的經驗記錄。)修復是修正(移除了缺陷)還是變通方案(抑制了失敗)?程式碼庫中其他地方是否存在結構上相似的模式,並已找到並解決?什麼流程更改可以防止此類缺陷再次進入程式碼庫——更強的測試、Linter 規則、斷言、規劃檢查清單項目,或是在
chrislacey89/skills中提交的問題(請參閱下面的針對技能包提出問題)?如果答案是「沒有」,那麼產生此缺陷的機制仍然活躍。
針對技能包提出問題——第五個機制
本小節不限於錯誤修復。 上面的 Q4(其標題如此),但 Q4 和 Phase 4 的提升為機制的規則都引用了下面的規則,而 Phase 4 不受錯誤修復限制。這個機制存在的案例是一個功能的經驗記錄。一個只能從其自身案例未走的路徑到達的程序,正是正在修復的缺陷,低一層——因此規則在此處一次性宣告,兩個階段都指向它們。
第五個名稱的範圍由所有權決定,而非難度。 前四個是這個程式碼庫的工件;第五個存在是因為某些預防性更改不是——它們是對 chrislacey89/skills 中某個技能的散文、閘門、交接或合約測試的更改,而這些是任何下游工件都無法承載的。僅此一種情況,第五個名稱才符合條件。它不符合條件是因為前四個在此處難以實現、成本高昂或不明確:這就是 chrislacey89/skills#257 故意保持關閉的合規出口,而「我無法構建一個」仍然按照一貫的方式解決——在條目中說明四個中哪一個最接近,以及是什麼阻止了它。
提交者閘門(務必確認——在撰寫任何外送內容之前檢查)
提交會將文字從你所在的儲存庫移到一個公開儲存庫中。 這與清單中的其他所有機制(測試、Linter 規則、斷言和檢查清單項目都留在原地)是不同的行為。因此,在撰寫正文之前,請確認當前儲存庫的所有者是允許你從中提交的:
git remote get-url origin | sed -E 's#(git@[^:]+:|https://[^/]+/)([^/]+)/.*#\2#'
將其與下面的允許清單進行比較。**允許清單就是整個閘門——不在允許清單上的所有者是不允許的,包括你不認識的所有者。**不要將其反轉為「封鎖我知道是工作的所有者」:上週才入職的客戶組織還不在任何人的清單上,因此封鎖清單恰恰會允許保密姿態最不明確的儲存庫。對未知情況採取失敗關閉。
chrislacey89
該柵欄周圍的標記是關鍵的:本小節包含幾個柵欄區塊,因此「清單是下面的程式碼區塊」對於機械讀取來說是模糊的——猜錯的讀者會提取散文,然後每個所有者都會檢查失敗。匹配標記,而不是位置。
只有在經過深思熟慮的審查編輯後,才能將所有者添加到該清單中——一行,離線,可 grep。你貢獻的公開儲存庫一旦你命名它就符合條件;它不僅僅因為是公開的就符合條件。可見性是一個可變的遠端屬性,一個公開的分支可以隱藏一個私有的父倉庫,而且——這才是這裡重要的原因——被提交的是關於工作的敘述,而不是儲存庫的程式碼。公開的原始碼和圍繞它的機密約定是一個普遍的組合,而「我們在為 Y 構建 X 時遇到了這個」會泄露關係,即使每一行程式碼都是世界可讀的。
當所有者不在允許清單上時,第五個名稱不可用。 回退到此機制之前的行為:將處方記錄在條目的 Prevention → Process-level 插槽中,建議 /improve-pipeline,然後讓人類將其傳遞過去。經驗不會丟失;它只是不會自動傳播。
撰寫和提交
當所有權防護和提交者閘門都通過時,提交就是機制,而 /compound 會執行提交——到達此儲存庫的處方是工件,而不是建議別人將其帶到那裡的一句話。首先檢查重疊情況並在現有問題上發表評論,而不是提交一個新的問題;一個新的外送通道進入待辦事項清單只有在不充滿重複陳述時才有價值。
gh issue list -R chrislacey89/skills --state all --search "<管線區域> <失敗模式關鍵字>"
gh issue create -R chrislacey89/skills --title "[improve-pipeline] <管線區域> — <處方>" --body-file <file>
--title 和 --body* 是必須的,而非風格選擇:在非互動式執行器下,gh issue create 如果兩者都沒有會報錯,而此機制旨在所有 AFK 路徑中存活。
將正文匿名化,並將其視為合約的一部分,而非禮貌。 上面的閘門決定是否你可以提交;這決定什麼可以跨越。描述案例的形狀,而不是它的主題:
- 命名要更改的技能包檔案、遺漏它的管線步驟,以及它本應改做什麼。
- 不要命名下游儲存庫、其所有者、其客戶、其路徑、其標識符或其問題和 PR 編號。用特徵描述它——「一個下游 TypeScript 網頁/頁面分析儲存庫」——如同
chrislacey89/skills#266所做的那樣,這是一個實例:它打開Triggering repo: anonymized並記錄了來源是刻意刪除了標識符。 - 不要引用此條目的路徑作為證據。
docs/solutions/…路徑是一個讀者可能沒有存取權限的儲存庫中的檔案名稱,因此對他們沒有任何證明作用,卻會向其他人識別出該工作。請將推理過程傳遞過去;條目留在家裡。
技能包檔案和失敗模式是什麼讓一個提案在此處具有可操作性。匿名化規則剝離的所有細節都是只有在來源儲存庫中才可讀的細節。
保持簡短。這是一個提案草稿,不是一個完整的提案——/improve-pipeline 是用來發展它的,而本階段中後續的 /improve-pipeline 建議仍然有效:建議它,但不要調用它。在條目中引用 issue 編號。 一個未引用的提交就只是散文:條目命名 #N,否則就沒有使用第五個名稱。
Rabbit Hole 審查。
...(此處為截斷內容)