昨天,DevPulse 有了本機 CLI,只要輸入 devpulse run <filePath>,就能審查指定的檔案。
不過完整的「修復 → 驗收」流程,目前還是得手動一步步串起來:先在 Genkit Developer UI 對三個檔案各跑一次 patchFlow,再切換 DEVPULSE_SOURCE_DIR 跑測試,最後自己比對 diff。三個檔案、每個檔案好幾個步驟,全是重複操作。
今天不新增 AI 邏輯,而是把這些重複操作交給 Antigravity 的代理人。
今天要完成三件事:
devpulse fix 指令,讓 patchFlow 也能從終端機呼叫。AGENTS.md 替代理人訂好流程與界線。前面幾天,每一步都是「我下指令,我看結果」。代理人的差別在於:它會自己整理步驟、在終端機執行指令、讀取輸出,再決定下一步。
今天的流程剛好符合三個條件:步驟固定、每一步都有明確的結果(指令是否成功、測試是否通過)、最後可以由測試客觀驗收。
npm test(測試 samples/)→ 預期三個紅燈
↓
devpulse fix × 3 → 產生 fixed/ 修復檔
↓
npm run test:fixed → 看綠燈或紅燈
↓
代理人回報結果表
這裡的分工要先講清楚:
如果讓代理人自己動手改程式,就分不出綠燈是 DevPulse 的功勞,還是代理人偷偷修好的。所以今天它只當「操作員」。
devpulse fix目前 patchFlow 只能從 Developer UI 觸發,代理人在終端機裡沒有指令可以呼叫它。所以要先在 bin/devpulse.mjs 補上 fix,總共四處小改動。
1. 匯入 patchFlow(放在原本的 codeReviewFlow 匯入下面):
import { patchFlow } from "../src/patchFlow.mjs";
2. 說明頁加上兩行:
devpulse fix <filePath> 產生修復檔到 fixed/(不會改動原始檔)
devpulse fix samples/sql.cjs
3. 新增 runFix() 函式(放在 showHelp() 後面):
async function runFix(filePath) {
console.log(chalk.cyan.bold("\nDevPulse 產生修復檔"));
console.log(chalk.gray(`分析檔案:${filePath}`));
try {
const result = await patchFlow({ filePath });
console.log(chalk.green(`\n✓ 修復檔已寫入:${result.outputPath}`));
console.log(chalk.gray(`補丁數量:${result.patches.length}`));
for (const patch of result.patches) {
console.log(` 第 ${patch.startLine}-${patch.endLine} 行:${patch.reason}`);
}
console.log(
chalk.yellow("\n補丁已套用,但還沒有驗證。請執行:npm run test:fixed"),
);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.error(chalk.red.bold("\n產生修復檔失敗:"), message);
process.exitCode = 1;
}
}
4. 在 main() 裡讓 fix 通過指令檢查,並在算出 filePath 之後分流:
if (command !== "run" && command !== "fix") {
// ...原本的錯誤處理不變
}
const filePath = path.resolve(process.cwd(), targetPath);
if (command === "fix") {
await runFix(filePath);
return;
}
幾個設計重點:
fix 只會把結果寫進 fixed/,不會動 samples/,延續昨天「CLI 不擅自改動原始檔」的原則。process.exitCode = 1。對代理人來說,結束碼就是「這一步有沒有成功」最直接的訊號。patchFlow 寫入的是相對路徑 fixed/,所以要在 devpulse/ 專案根目錄執行。接著在 package.json 的 scripts 加上一行,保留原本的 test 不動:
npm install -D cross-env
"test:fixed": "cross-env DEVPULSE_SOURCE_DIR=fixed npm test"
Day 25 時,Windows PowerShell 與 macOS/Linux 設定環境變數的語法不一樣。cross-env 負責抹平這個差異,之後不管哪個系統,驗收 fixed/ 都只要一行 npm run test:fixed。對代理人來說,少一個需要臨場判斷的地方,就少一個出錯的機會。
交給代理人之前,先自己跑一次:
node ./bin/devpulse.mjs fix samples/sql.cjs
npm run test:fixed
指令本身有問題的話,代理人只會把錯誤放大。確認 fixed/sql.cjs 有出現,再往下走。
AGENTS.md:把規則寫給代理人Antigravity 會讀取專案根目錄的 AGENTS.md,把它當成長期規則(也支援 GEMINI.md 與 .agents/rules/;兩份同時存在時以 GEMINI.md 優先,所以今天只放一份就好)。
【發文前請確認】規則檔的讀取方式與檔名,請以你使用的 Antigravity 版本為準。
在 devpulse/ 根目錄建立 AGENTS.md:
# DevPulse 代理人守則
## 專案說明
DevPulse 是本機的程式碼診斷小幫手。
- `samples/`:三個刻意寫錯的範例(原始檔)
- `tests/`:驗收條件
- `fixed/`:DevPulse 產生的修復檔
## 可用指令(一律在專案根目錄執行)
- `npm test`:測試 `samples/` 原始檔。三個範例預期是紅燈,這是刻意的,不要去修。
- `node ./bin/devpulse.mjs fix <檔案>`:呼叫 Gemini 產生修復檔,寫入 `fixed/`。
- `npm run test:fixed`:用同一組測試驗收 `fixed/`。
## 工作流程
1. 先執行 `npm test`,記錄原始檔的測試結果。
2. 對 `samples/` 裡的每個 `.cjs` 檔,各執行一次 `fix`。
3. 執行 `npm run test:fixed`。
4. 如果有檔案失敗:記下 Jest 的 Expected 與 Received,再用
`git diff --no-index samples/<檔名> fixed/<檔名>` 找出補丁問題。
對失敗的檔案最多重跑一次 `fix`,然後再測一次。
## 不可以做的事
- 不修改 `tests/` 與 `samples/` 裡的任何檔案。
- 不手動編輯 `fixed/` 裡的檔案,它必須是 DevPulse 的產出。
- 不讀取、不印出 `.env`,也不把金鑰寫進任何檔案或回報。
- 不執行 `git commit`、`git push`,不安裝或升級套件。
## 回報格式
用一張表回報:檔案|原始測試|修復後測試|備註。
附上實際的測試結果,不要只寫「已完成」。
這份守則有幾個刻意的寫法:
npm test 失敗,很可能會想「幫你修好」。fixed/,綠燈就不再代表 DevPulse 的補丁有效,Day 25 的驗收也就失去意義。node ./bin/devpulse.mjs,而不是 devpulse。 這樣不依賴 npm link 的全域指令,避免代理人的終端機找不到它。.env。 .gitignore 只是叫 git 不要追蹤這個檔案,並不保證代理人讀不到它。要特別注意:AGENTS.md 是「請代理人遵守」的規則,不是技術上的限制。真正的限制要靠下一段的權限設定。
用 Antigravity 開啟 devpulse/ 資料夾,在 Agent 面板貼上今天的提示詞:
請依照 AGENTS.md 的流程,替 DevPulse 做一次完整驗收:
1. 先執行 npm test,確認 samples/ 的三個範例目前是紅燈。
2. 對 samples/ 裡的每個 .cjs 檔各執行一次 fix。
3. 執行 npm run test:fixed。
4. 用表格回報每個檔案在修復前後的測試結果。
如果修復後仍有測試失敗,請只回報原因,最多重跑一次 fix。
不要修改測試,也不要手動編輯 fixed/ 裡的檔案。
長期規則放在 AGENTS.md,這次任務放在提示詞,所以提示詞可以很短。
接著是權限。第一次執行終端機指令時,請讓 Antigravity 先詢問你,不要一開始就全部自動放行,並且只允許這幾種指令:
node ./bin/devpulse.mjs fix ...
npm test、npm run test:fixed
git diff
其他指令一律拒絕。如果你的版本有 Strict Mode,可以先打開,由它搭配權限設定限制代理人能讀寫哪些檔案。
另外,任務範圍刻意收得很小:三個檔案、失敗最多重試一次。免費方案的代理人額度有限,不要讓它在失敗時無限重試。
送出提示詞後,可以觀察代理人是否照 AGENTS.md 的順序走:先跑 npm test 確認紅燈、對三個檔案各執行 fix、再跑 npm run test:fixed,最後回報。
【發文前請替換】貼上 Antigravity 面板截圖:任務步驟、授權詢問、最終回報表。
如果三個補丁都符合測試契約,最後的回報大致會像這樣(以下是輸出示意,實際內容以你的執行結果為準):
| 檔案 | 原始測試 | 修復後測試 | 備註 |
|---|---|---|---|
async-await.cjs |
FAIL | PASS | 改用 for...of 搭配 await |
sql.cjs |
FAIL | PASS | 改用 ? 佔位符並傳入參數陣列 |
boundary.cjs |
FAIL | PASS | 缺少 profile 時回傳 Unknown |
如果其中有一個檔案仍然是 FAIL,那反而是今天最值得記錄的結果。請看代理人是否依守則「只回報原因」、最多重試一次,而不是偷偷改測試或手動編輯 fixed/。
不要只相信代理人的回報。 跑完後,自己再驗收一次:
npm run test:fixed
git status --short samples tests
第一行確認測試結果和代理人回報的一致;第二行確認 samples/ 與 tests/ 沒有被動過,應該沒有任何輸出。
devpulse fix,讓 patchFlow 可以從終端機呼叫test:fixed 指令,用 cross-env 統一各系統的驗收方式AGENTS.md,替代理人訂好流程與界線下一篇 Day 28:代理人會讀程式碼,也會執行指令。如果程式碼的註解裡藏著一句「忽略以上規則」,會發生什麼事?明天來實測 Prompt Injection,看看 DevPulse 會不會被帶偏。