# FR-114 自動跑第二輪：卡住的地方與下一輪怎麼更穩

- 執行日：2026-09-22 12:02～16:57，13 張全走完（26 支 agent，4.9 小時，subagent 共 406 萬 token）
- Run ID：`wf_678e8f3b-69f`；腳本 `night-run/workflow.js`；清單 `night-run/cards.json`（13 張）
- 寫這份的目的：把這一輪「哪裡卡、為什麼卡、要不要人介入」記下來，下一輪開跑前先把能避免的先避掉。

## 一句話結論

沒有任何一張需要人介入，也沒有需裁的卡。卡住的都是機器自己撞到的三種坑：
① 大卡 runner 跑太久被中斷、由 harness 自動重啟兩次才過；
② 兩張程式全對但「順手重 build 資安報告」做壞而被判不過；
③ 一顆早就紅的既有測試每張卡都要驗證 agent 再確認一次「與本卡無關」。

## 進度與耗時（到 16:35 為止）

| 順序 | 卡 | 做卡 model | 做卡＋驗證耗時 | 結果 |
|---|---|---|---|---|
| 1 | CM-2044 拆三組零呼叫功能 | sonnet | 12 分 | 過 |
| 2 | CM-2045 刪小工具＋死開關 | sonnet | 8 分 | 不過（報告表格多一欄） |
| 3 | CM-2046 刪成員名冊入口 | sonnet | 27 分 | 過 |
| 4 | CM-2043 快取連線改套件版 | sonnet | 16 分 | 過 |
| 5 | CM-2050 掃描不多存明文帳密 | sonnet | 6 分 | 過 |
| 6 | CM-2021 稽核守門嚴格版 | opus | 18 分 | 過 |
| 7 | CM-2022 弱點檢測改嚴格守門 | sonnet | 27 分 | 過 |
| 8 | CM-2027 公告發送範圍 migration | sonnet | 6 分 | 不過（報告頁 build 壞） |
| 9 | CM-2026 公告發送範圍套件側 | opus／high | 82 分 | 過 |
| 10 | CM-2030 意見回饋端點補權限 | opus／high | 131 分（三次嘗試） | 過 |

前九張平均 22 分一張。兩張 opus／high 的大卡吃掉一半以上時間。

## 坑一：大卡 runner 被中斷兩次，第三次才過（CM-2030）

**發生什麼**：第一次嘗試跑了 43 分鐘、第二次 30 分鐘，兩次 transcript 都以「Request interrupted by user」收場，harness 立刻自動重啟一支新的 runner 從頭做。第三次 39 分鐘做完並驗證通過。

**中斷當下 runner 在做什麼**：兩次都還在「讀」的階段，一行程式都沒改。第一次 63 步、第二次 49 步全是讀卡、讀套件原始碼、查 DEV 資料庫、甚至去翻 FE 的頁面程式碼確認參數名。沒有任何工具錯誤、沒有 API 錯誤。

**為什麼被中斷（已查明）**：Bifrost gateway 的 Stream Idle Timeout 180 秒。兩次被切的時間點都是「最後一筆事件之後整整 192 秒」（07:21:10→07:24:22、07:51:02→07:54:14），與 180 秒加誤差吻合。與 2026-09-19 資安掃描被切是**同一個機制、不同觸發原因**：掃描那次是 context 破百萬觸發自動壓縮、壓縮跑超過 3 分鐘；這次 context 只有 20 萬，是 opus／high 單回合思考太久——每回合吐 1 萬到 1 萬 3 千 token、加 20 萬 context，單回合常跑 150～190 秒，前兩次嘗試各有 4 次和 2 次超過 150 秒，最後一次越過 180 就被切。其他 26 支 agent（sonnet、或 context 較小）幾乎沒有超過 150 秒的回合。第三次同樣 opus／high，運氣好沒越線。

**代價**：白燒 73 分鐘 opus／high，且第三次是從零開始（前兩次讀過的東西全丟）。

**下一輪怎麼避**（治本在第一條，其餘減少觸發機率）：
- **把 Bifrost 的 Stream Idle Timeout 從 180 拉到 600 秒**。一次改好，壓縮與長思考兩種觸發原因都蓋到。設定位置見記憶檔 `reference_bifrost_gateway_disk_full_500`。
- 大卡 effort 從 high 降 medium，單回合思考量少一半以上。
- 這種「10 個入口、跨套件＋BE＋要看 FE」的卡太大，拆成兩張（守門＋作者比對一張、查看範圍參數一張）。
- 卡上「在哪裡」段已經把 file:line 列好了，runner 還是去讀了大量週邊程式碼。prompt 可以加一句「卡上列的入口就是全部，不要為了確認去讀 FE 或其他套件」。
- 如果決定不拆卡，至少把大卡排在清單最前面，晚上人還在時跑，被中斷能看到原因。

## 坑二：程式全對、報告重 build 做壞而被判不過（CM-2045、CM-2027）

兩張的程式改動驗證 agent 都親自核過是對的（含連 DEV 查 migration 有沒有真的套上），不過的原因都出在「順手更新資安報告」這一步：

- **CM-2045**：`M04-common.md` 那張表只有五欄，runner 照別張六欄表的習慣多塞一格「✅ 已修」，render 出來的 HTML 直接把多的格子丟掉，決策者打開看到的還是「已裁定刪除」。
- **CM-2027**：runner 重 build 那一頁時用錯 script，產出的 HTML 樣式路徑指到站外（`../specs/_shared/`）、側欄與上下頁導覽全沒了。整站其他 32 頁都正常，只壞這一頁。

**共同原因**：runner prompt 說「回寫報告與重 build」但沒說用哪支指令、表格有幾欄。每張卡的 runner 都是新的、不共享記憶，靠猜就會有人猜錯。

**下一輪怎麼避（二選一）**：
- **A. 把指令寫死**：runner prompt 明寫「重 build 一律 `python scripts/deliverables/render_index.py docs/security-report/`」、「改狀態只改該列最後一欄，不新增欄位，改完 `grep -c '|'` 確認欄數沒變」。
- **B. 報告不交給 runner**：runner 只改程式與 Notion，報告狀態由首腦跑完後一次批次更新、一次 build。一支手做，變異最小。**建議 B**，報告是給決策者看的整站，分十三個人各改一頁本來就容易長歪。

兩張補救都是一支 commit 的事（CM-2045 併回那一格重 build；CM-2027 用對的 script 重 build 一次），不用重做程式。

## 坑三：一顆既有紅燈每張卡都要再確認一次

`test/test_grc_error_code_values_match_frozen_baseline` 一直是紅的，缺的是 FR-112 加的 `GRC_TASK_FORCE_START_*` 兩個 error code 沒登記進基準表。CM-2045、CM-2030 的驗證 agent 都撞到，各自單獨重跑、翻 commit 確認「本卡沒碰 error code 檔」才敢寫「與本卡無關」。

**下一輪怎麼避**：開跑前先把那兩個 code 補進基準表（一支小 commit），或在 verifier prompt 列「已知紅燈清單，看到直接略過」。前者乾淨。

## 其他觀察（沒出事，但值得知道）

- **BE 工作區一直有未 commit 的 `pyproject.toml`／`poetry.lock`**（jedi-iam、jedi-detection 的 path 覆寫，第一輪留下的）。每張卡的 runner 都要自己認出「這不是我的、不要 add」。這一輪 13 張沒人夾帶進去，但這是靠每個 runner 都守紀律；下一輪可以在開跑前先 `git stash` 或明寫進 prompt 的禁區清單。
- **caffeinate 不是腳本管的**：開跑時機器上只有三支 5 分鐘的 caffeinate，我另掛了一支 12 小時的。下一輪的派工 prompt 或腳本第一步應該自己起 `caffeinate -i -t 43200`，不要靠人記得。
- **harness 的自動重啟救了 CM-2030**：腳本自己寫的是「runner 回 null 就整批停」，但 harness 在底層先重試了兩次，腳本層完全沒感覺到。這是好事，但也代表「被中斷幾次」腳本不知道、results 裡看不到，要從 journal 才挖得出來。
- **驗證 agent 做得很實**：三張抽看的驗證報告都有自己重跑測試、自己連 DEV 查、自己開檔核欄位，不是聽 runner 自報。這層可以信。

## 最終結果

過 10（CM-2044／2046／2043／2050／2021／2022／2026／2030／2029／2028）、不過 2（CM-2045、CM-2027，都只差報告重 build）、需裁 1（CM-2047，task-setup.json 有 101/144 個 key 被四支活頁面共用，整支刪會打壞四頁，runner 建議 i18n 檔保留不動）、剩 0。全程不需人介入。完整白話總結已 append 母卡 CM-2019。
