Community生產力與協作github.com

Belweave/belay

以小的驗證步驟逐步達成任何可用指令衡量的目標(修復所有失敗測試、完成稽核、加快速度、縮小體積、移植工具、優化 UI 或文本)。每次變更都由鎖定的檢查評分,若成功則提交,失敗則復原,可跨一個或多個儲存庫。當使用者說「belay」、「hill climb」、「climb this」或「keep going until it passes」,想要長時間無人值守地朝可測量目標前進,或要求恢復或報告一次攀登時使用。

belay 是什麼?

Belay 是一個 AI 代理技能,設計用來在開發者工具(如 Claude Code、Cursor、Codex)中,透過大量小型、自動驗證的步驟,自主地朝可測量的目標前進。它將目標抽象化為一個能輸出單一數值的指令:速度目標可能是時間或計數;稽核是失敗測試的數量;移植是相符輸出的數量。每次編輯後,系統會自動執行一個鎖定的檢查,若分數改善則提交變更,若分數退步則復原,由 `scripts/belay.py` 完全自動處理。此技能支援多個倉庫、守護檢查(guard)、保留資料集(holdout),並防止過擬合或作弊。攀登狀態儲存在 `.belay/<name>/` 目錄中,使其在崩潰或會話中斷後仍能恢復。使用者以「go」批准一個攀登卡(climb card)後,代理便進入一個長時間的無人值守循環,產生提交、記錄進度,並在達成目標、卡關或需要使用者協助時生成一份總結報告。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Belweave/belay/tree/HEAD/skills/belay

Installed? Explore more 生產力與協作 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

在你喜歡的 AI 中提問

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

說明文件

belay 是做什麼的?

你透過許多小步驟達成目標。一個檢查會為每一步評分,過程中無需人為介入。scripts/belay.py 負責記錄分數:你編輯,它執行檢查,若成功則提交,若失敗則復原,並寫入日誌。你永遠不需要自己記錄分數,也永遠不需要決定某一步是否「基本上」通過了。

每個目標最終都會轉化為同一種東西:一個輸出數字的指令。速度更快是時間或計數。稽核是失敗測試的數量,每個發現對應一個。移植是相符輸出的數量。UI 是評審的分數。

工作方式:

  • 使用者啟動一次攀登後便離開。 不要停下來提供更新。他們會閱讀三件事:卡片、只有他們能回答的問題,以及報告。如果工具有提問工具,請使用它來提問。
  • 狀態存在於磁碟上,而非對話中。 卡片、日誌、你的筆記以及最後一次的檢查輸出,都存放在 .belay/<name>/ 下。在壓縮或崩潰後,只需一次 status 呼叫就能恢復所有資訊。
  • 絕對不要使用 sleep 迴圈等待。 在背景執行長時間的指令,並在它們執行期間規劃下一步。
  • 下方的 BELAY 是此檔案旁 scripts/belay.py 的絕對路徑。 將完整路徑寫入每個指令。從目標儲存庫內部執行它。你傳遞的路徑和指令是相對於儲存庫根目錄的。
  • 攀登會擁有自己的分支 climb/<name>。 復原的步驟會重置樹狀狀態,並刪除 git 忽略規則未涵蓋的未追蹤檔案。如果其他人在此工作目錄中工作,請在單獨的工作樹(worktree)中進行攀登。如果你已經在為此工作建立的分支上,請傳遞 --here。

1. 開始前先恢復

執行 python3 "$BELAY" list。如果存在針對此目標的攀登,切換到它的分支,執行 status <name>,然後繼續執行步驟 4。在崩潰或新會話後「繼續」就是指這個意思。不要重新開始。

2. 建立檢查

攀登的品質取決於其檢查。一個衡量錯誤事物的檢查,會讓整個運行都在改善錯誤的事物。先讓一個粗略的檢查能運作,之後再用 relock 來改進它。

捫心自問:我會執行什麼指令來確認目標已達成?讓那個指令輸出一個數字。使用最合適、最嚴謹的形式:精確比對或測試計數,然後是工作量計數(查詢次數、往返次數、位元組數),然後是時鐘計時,最後,只有在沒有其他方式能判斷品味時,才使用模型評審。

目標分數
錯誤或功能根據規格(而非你的修正)所撰寫的失敗測試
稽核、穩定化、「讓 X 能運作」失敗測試,每個發現對應一個
速度或大小時間背後的工作量計數,或時間本身
移植或複製與真實工具相符的輸出
同時達成多個目標朝最差標準的進度
外觀、感受、文案帶有評分標準和良好範例的 judge.py

每種目標的具體做法都放在 references/checks.md 中。在撰寫檢查之前,請閱讀符合你目標的部分。

使用儲存庫現有的資源。--score '<regex>' 從任何測試執行器的輸出中讀取分數,例如 --score '(\d+) failed'。它會取最後一行符合的內容,並累加其捕獲的數字。一個通過且無符合項目的執行,其分數為 0。如果沒有 --score,檢查標準輸出的最後一行必須是純粹的數字。重複使用 --check 可同時執行多個指令;它們的分數會相加。對攀登會編輯的每個其他工作目錄,使用 --repo <path>。這樣,步驟會在所有這些儲存庫中同時被保留或復原。

在信任檢查之前,先證明它:

  • 它能失敗。 故意破壞程式碼,觀察分數變差。使用 git checkout -- <file> 還原。
  • 它能看見成功。 一個微小的真實改進必須能改變分數。
  • 它很穩定。 執行它 3 次。如果分數在沒有程式碼變更的情況下飄移,請用計數取代時鐘計時,或使用 --runs 3、高於飄移量的 --min-gain(當分數會大幅縮小時,使用百分比,如 3%),以及 --paired。
  • 它無法被欺騙。 每次執行時改變輸入,並與參考資料比較。手動嘗試一種作弊方式,例如寫死答案,並確認檢查或某個守護檢查能抓到它。
  • 它很快。 每次步驟都需要花費檢查的時間。設法讓一個步驟在 2 分鐘內完成:對樣本或每次步驟的計數進行評分,並將完整的測試套件或計時運行保留作為守護檢查或保留資料集。
  • 標準是可達到的。 找出當前設計能做到的最佳結果。如果標準超出此範圍,請在卡片上說明,並提出一個你可達到的標準。

保護所有分數未衡量的項目:

  • 守護檢查(--guard,透過結束代碼 0 通過)。列出你將要修改的程式碼所影響的範圍:呼叫者、其他平台、儲存的資料、公開 API。每個都需要一個守護檢查:今日能通過的測試、型別檢查、lint、建置。當分數是失敗計數時,將那些通過的測試放在它們自己的檔案中作為守護檢查,這樣崩潰就不會偽裝成「更少的失敗」。
  • 鎖定(--lock)檢查、測試、固定裝置和保留資料集。當鎖定檔案發生差異時,try 會拒絕評分。在 --lock 路徑下的新檔案會成為攀登分支上的第一個提交。任何其他未提交的變更都會阻止 init。
  • 保留資料集(--holdout),當檢查使用樣本、基準測試或評審時:攀登從未訓練過的案例,保存在 .belay/<name>/holdout/ 下。不要再打開它們。如果分數上升但保留資料集沒有,表示攀登過度擬合。停止並說明原因。

稽核和開放式目標。 將目標涵蓋的範圍作為檢查清單,列在 .belay/<name>/notes.md 中。逐區尋找錯誤。根據規格或錯誤報告,為每一個真正的發現撰寫一個失敗測試。當後續步驟發現一個新的錯誤時,加入其測試並執行 relock --why "found <bug>"。分數會因正當理由而上升,且日誌會顯示原因。需要使用者決定的發現應寫入筆記和報告,而不是分數中。

3. 卡片,然後 init

僅傳送一條包含卡片的訊息來決定,不要有其他內容:

攀登卡片:build-speed

目標: 冷建置快 2 倍,輸出相同

分數中位數建置秒數,越低越好:現在 47.0,標準 23.5
檢查./scripts/bench-build.sh,3 次運行,配對比較,最小增益 3%
守護檢查npm test、npm run typecheck
保留資料集12 個範例應用中的 3 個
鎖定scripts/bench-build.sh、test/、samples/
限制無(每次步驟約 2 分鐘)

需要你的回答: 無

回覆 go,或更改其中一行。

填寫每一行,使用你最佳的選擇。如果使用者給了一個沒有標準的目標,提出一個有野心且可檢查的標準,例如「快 2 倍」或「每個範例都相符」。等待「go」,這表示批准了卡片、分支及其提交。當使用者已經要求直接執行而不詢問,或者目標很小且標準無庸置疑時,則跳過等待,並將卡片放在報告的頂部。在那之後,除了你能自行查詢或決定的事情之外,不要詢問任何事。

python3 "$BELAY" init build-speed --goal "cold build 2x faster" \
  --check ./scripts/bench-build.sh --direction min --target 2x \
  --runs 3 --paired --min-gain 3% --guard "npm test" --guard "npm run typecheck" \
  --holdout ./scripts/bench-holdout.sh --lock scripts --lock test \
  --lock .belay/build-speed/holdout

一個涵蓋後端和前端稽核的範例:

python3 "$BELAY" init billing-audit --goal "every billing finding fixed" \
  --check "pytest tests/billing -q" --check "cd ../web && npx vitest run billing" \
  --score '(\d+) failed' --direction min --target 0 --repo ../web \
  --guard "pytest tests/legacy -q" --guard "cd ../web && npx tsc --noEmit" \
  --lock tests/billing --lock ../web/src/billing/__tests__

init 會建立分支、測量基準值,並在任何守護檢查已失敗時拒絕開始。在第一步之前,修正它所警告的內容。僅在使用者指定限制時,才設定 --max-hours 或 --max-steps。若無限制,攀登會持續進行,直到滿足標準或卡關為止。

4. 攀登

每一步就是一個想法、一個變更、一次 try:

  1. 選擇想法。除非你能說明這次有何不同,否則不要重試日誌中已復原的想法。如果使用了評審,請閱讀 .belay/judge-notes.md。
  2. 為一個原因做一個變更,並猜測其影響。將猜測寫入想法中:例如 "cache the parser (expect -10%)"。當猜測與實際結果相差甚遠時,表示你對程式碼的理解有誤。在下一步之前進行效能分析。
  3. python3 "$BELAY" try "<idea>"。它會提交成功或重設樹狀狀態。無論如何,繼續前進。該步驟的完整檢查輸出在 .belay/<name>/last.txt,最佳步驟的輸出在 best.txt。請閱讀這些檔案,而不要再次執行檢查。
  4. 當檢查執行時,不要編輯樹狀狀態。同時只有一個會改變攀登狀態的 belay.py 指令在執行。如果它顯示另一個指令仍在執行,請等待它。
  5. 每 5 個步驟,用幾行文字更新 .belay/<name>/notes.md:說明哪些有效、哪些無效、下一步該嘗試什麼。下一次會話將從此處繼續。

如果你相信一個被檢查復原兩次的想法,表示這個檢查無法看到它的價值。讓檢查更精細並執行 relock。永遠不要為了讓步驟通過而編輯鎖定的檔案。

永遠不要欺騙檢查

以下每一項都會提高分數,但會使工作成果更糟。即使 try 保留了它們,每一項都是一次失敗的攀登:

  • 針對檢查使用的輸入編寫特殊案例,或寫死/快取預期輸出。
  • 跳過、削弱或刪除測試,或捕捉並隱藏錯誤。
  • 讓基準測試做更少的工作,而不是讓程式碼更快。
  • 使用 relock 來移除或放寬困難的案例,以便達到標準。Relock 只應讓檢查更正確。如果標準無法達成,請報告你所測量到的極限。
  • 讀取保留資料集。

一個真正的成功,是讓同樣的程式碼在檢查從未見過的輸入上表現得更好。如果前進的唯一方法是上述之一,那麼檢查有問題。請說明情況。

持續重新評估

分數只是使用者真實需求的代理。請持續檢查它是否仍然代表這個需求:

  • 每 10 個保留的步驟,以及達到標準時: 親自檢查真實的結果。打開應用程式、讀取輸出、檢視螢幕截圖。執行完整的測試套件和 holdout。如果分數和真實結果之間出現了偏差,修正檢查並執行 relock --why "..."。
  • 某個東西壞了,但沒有任何守護檢查抓到: 使用 git bisect run <failing command> 找出是哪個步驟造成的,然後用 try --fix "<what broke>" 來修復它,這會保留一個能維持住分數的變更。如果唯一的修復方式必須放棄該步驟的成果,則使用 git revert 復原該步驟,並執行 relock --why "reverted step N: broke X"。加入缺失的守護檢查。
  • 在提出報告之前: 將 git diff <start>..HEAD 視為一個整體變更來審查,用全新的眼光。尋找被移除的測試、被吞沒的錯誤、被關閉的功能、被改變的預設值,以及資料或 API 的變更。使用 try --fix 修復,然後再執行一次檢查和 holdout --why final,以便報告引用測量到的數字。

5. 當它卡關時

在連續 5 個步驟沒有進展後,try 和 status 會顯示 PLATEAU。停止嘗試想法,找出阻礙。在猜測之前先進行測量:

  • 時間或錯誤計數實際上從哪裡來?進行效能分析。
  • 檢查是否不穩定、太粗糙以至於無法看到小的成功,或者對問題視而不見?
  • 是否存在一個更大的想法,是小的步驟無法達成的?
  • 什麼工具、存取權限、資料或運算資源可以改變接下來的十個步驟?

使用 python3 "$BELAY" review "<what you found>" 記錄下來,這會讓 PLATEAU 狀態靜默 5 個步驟。修復你能修復的部分:更快的檢查、更細緻的指標、不同的方法。只有在所有其他想法都嘗試過之後,才向使用者請求只有他們能提供的東西,例如存取權限或資金。

6. 停止並報告

當以下任一情況發生時停止:

  • try 顯示 BAR REACHED。它會自動為你執行保留資料集。一個可見的成功但保留資料集沒有變化的情況,並非真正的成功。
  • status 顯示 STUCK:兩次阻礙審查之間沒有任何進展。
  • try 拒絕並顯示「Budget used」。
  • 保留資料集與分數不一致。
  • 下一步需要只有使用者能提供的東西。

然後執行上述的最終審查,刪除 .belay/<name>/data/,並傳送報告。讓報告能在十秒內讀完:

攀登 build-speed:已達標準

47.1 秒 → 18.7 秒,快 2.5 倍(標準 23.5 秒,在第 41 步達成)

保留資料集51.0 秒 → 20.2 秒,與分數同步變化
步驟52 步中保留了 19 步
安全性每個保留的步驟都通過了守護檢查。完整套件和最終審查乾淨
分支climb/build-speed,19 個提交

有效的嘗試

  • 增量型別快取:−12 秒

嘗試過但已復原

  • swc 交換:破壞了 3 個守護檢查

你的下一步

  • 審查:git log --oneline 1a2b3c4..climb/build-speed

標題是以下之一:已達標準、卡關、預算用盡、保留資料集不一致、需要你。引用腳本測量到的數字,絕不使用估計值。如果你在中途更改了檢查或標準,請在標題中說明。最大的成果優先。每個區塊最多 3 個項目符號。跳過空白區塊。

如果使用者之後想要更多,使用 raise 2x --why "..." 為同一個聲明設定更嚴格的標準,並繼續攀登。永遠不要切換到一個新的目標。

子代理

如果工具能啟動子代理,可以在設定階段用它們進行並行閱讀,並在阻礙審查和最終審查時提供新的觀點。要求結論,而不是檔案傾印。只有你可以在攀登樹狀狀態中寫入,因為 try 會重設它。一個輔助代理負責閱讀,或在自己的工作樹中起草一個修補程式,再由你套用並執行 try。如果沒有子代理,則內聯處理。

指令

指令功能
init <name> --goal "..." --check "..." --direction min|max基準值、分支、鎖定。選項:--check(可重複)、--score '<regex>'、--target(數字或 2x)、--guard(可重複)、--lock(可重複)、--holdout、--repo(可重複)、--runs、--paired、--min-gain、--timeout、--max-hours、--max-steps、--here
try "<idea>" [--fix]為編輯評分,然後保留或復原它。--fix 會保留一個能維持分數的修復
status [name]分數、最近步驟、筆記、PLATEAU 或 STUCK
relock --why "..."接受已更改的檢查並重新測量
holdout --why "..."立即執行保留資料集
review "<found>"記錄一次阻礙審查
raise <bar> --why "..."在達成當前標準後設定一個更嚴格的標準
budget [--hours N] [--steps N]為攀登設定或檢視預算。若無引數則顯示當前預算
list列出此工作目錄中的所有攀登
log [name]以可讀格式顯示攀登日誌
export [name]匯出攀登結果為 JSON

環境

  • BELAY_PATH:scripts/belay.py 的路徑。若未設定,則使用 scripts/belay.py 相對於此 SKILL.md 檔案的路徑。
  • BELAY_BACKEND:要使用的 LLM 後端(例如 claude、openai、gemini)。預設為系統預設值。
  • BELAY_DEBUG:設定為 1 以啟用除錯輸出。
  • HOME、USER:用於識別使用者和個人配置目錄。
  • SHELL:用於執行指令的 shell。
  • GIT_*:所有標準的 git 環境變數都受尊重。
  • PATH:應包含所有必要的工具(git、python3、node、npm、pytest、npx 等)。

相關技能