Skip to content
Back to skills

Failure Handling

ASecurity

This skill should be used when handling failures in go-class command flows — Soyo blocking with NEEDS_CHANGES / BLOCKED, Taki test failures, subagent infrastructure overload / unavailability (e.g. 529), mid-task usage/session-limit interruption of a running subagent, and infinite-loop protection for repeated same must-fix or same test ID. Applies to /maigo:go, /maigo:quick, /maigo:team, and /maigo:address-comments step 5.

  • 14 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
ai-agentsgobashnodegitapi

Works with

  • claude code
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add Lee-W/maigo --skill failure-handling --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Failure Handling?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Failure Handling
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lee-w-failure-handling/badge)](https://www.skillsdirectory.com/skills/lee-w-failure-handling)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: failure-handling
description: This skill should be used when handling failures in go-class command flows — Soyo blocking with NEEDS_CHANGES / BLOCKED, Taki test failures, subagent infrastructure overload / unavailability (e.g. 529), mid-task usage/session-limit interruption of a running subagent, and infinite-loop protection for repeated same must-fix or same test ID. Applies to /maigo:go, /maigo:quick, /maigo:team, and /maigo:address-comments step 5.
---

<!-- mkdocs-include-start -->

# Failure Handling

**Consumers**: [`/maigo:go`](https://github.com/Lee-W/maigo/blob/main/commands/go.md) 失敗處理段、[`/maigo:quick`](https://github.com/Lee-W/maigo/blob/main/commands/quick.md) 同段、[`/maigo:team`](https://github.com/Lee-W/maigo/blob/main/commands/team.md) 同段、[`/maigo:address-comments`](https://github.com/Lee-W/maigo/blob/main/commands/address-comments.md) step 5 都引用本 skill。

### 爽世擋下(NEEDS_CHANGES / BLOCKED)

1. **完整把爽世 (Soyo) 的輸出傳給愛音 (Anon)**——must-fix 清單 + evidence 待補 + 具體改法
2. 愛音修完後,**必須附上每條 must-fix 的對應 diff 與 evidence**(不接受「都改好了」這種模糊回報)
3. 重新請爽世 review。爽世會逐條對照——任何一條沒清就維持 BLOCKED

### 修正輪閉環

套用任何 review 修正後,一律**送回同一位 reviewer** 複驗——同一個 context 才抓得到這輪
修正本身引入的新矛盾;換一個沒看過前情的 reviewer,等於失去對照歷史的能力。

1. **修到 PASS 為止**——每一輪修正都可能引入新缺陷,改完就收工等於沒驗;verdict 未達
   對應 command 的通過門檻前,流程不算完成。
2. **reviewer 無法續用**(原 agent session 已結束、必須開新 agent)時,**視同重新審查**:
   附上完整前情——原始 diff、前幾輪 must-fix 清單、目前已套用的修正——不能只給「這是修正
   後的版本」讓新 reviewer 從零判斷。

### 立希驗證紅

1. 把 failure 完整貼給愛音 (Anon)(command + exit code + output)
2. 🎀 愛音修完後,若程式碼、測試或其他受審內容有變,先送回 🟡 爽世複審,再讓 🟣 立希重跑;team 可依原本規則並行兩者。**不接受口頭說「修好了」,也不沿用修改前的 APPROVED。**
3. 只有修復環境且受審內容完全沒變,才能沿用 review、只重跑驗證。
4. 🟡 爽世 APPROVED 與 🟣 立希 PASS 必須對應同一份變更快照才算過。交辦與回報保留 HEAD、tracked diff 與 untracked 檔內容的識別/雜湊;僅 HEAD 相同不足以證明內容未變。修復改了內容,舊 review 與驗證結果都失效。

### 環境造成的假紅

測試紅燈被診斷為**環境造成的假紅**(Node/OS/工具版本行為差異,不是程式碼缺陷)時,
判準:乾淨環境會綠、紅的成因指向 Node/OS/工具版本而非被測程式碼本身。

優先順序:

1. **改環境設定讓它真的綠**(例如 `.claude/settings.local.json` 的 `env`、正確的 flag、
   對版本的工具)
2. 治本的 repo 改動(測試 setup 層的隔離),範圍合理時另開 PR
3. **最後才是遮蔽**(本 repo 的 known-test-failures 機制)

**Why**:遮蔽名單是全檔粒度,遮掉噪音的同時把該檔案未來的**真回歸**一起遮掉;環境修法
沒有這個代價,還會讓別的 session 也直接受益。

**不要把「加進 known-test-failures」當預設收尾動作**——寫之前先問使用者,並在選項裡說明
代價;修完環境要回報「修掉幾個 / 還剩幾個」,剩下的說清楚為什麼修不掉。

### Subagent 過載 / 不可用(如 529 Overloaded)

某個 agent 的 Task 因基礎設施問題(伺服器 529 Overloaded、逾時、暫時不可用)反覆啟動失敗,與該 agent 的工作品質無關時:

1. **有限次重試**——重試 **2-3 次**。每次重試成本不低(subagent 啟動到報錯可能耗數分鐘),不要無聲地一直重撞。
2. 仍失敗 → **把選項攤給使用者**,不自行決定:
   - 等久一點再試(短間隔重試只是重複燒時間;建議擱 20-30 分鐘讓尖峰過)
   - **orchestrator 主線代打**該 stage——繞過過載點立即解卡
   - 暫停,等基礎設施恢復後再接續
3. 使用者授權主線代打時:
   - **明示這違反該 command 的分工守則**(orchestrator 本不該自己 review / 實作),且**獨立性較弱**(等於審 / 改自己流程的產出)
   - **嚴格度不打折**——照對應 skill(如 `strict-review` 9 項)硬走,以 `git diff` / 實測為憑,不因「我自己跑」放水
   - review 類代打要實際構造場景驗證(不只讀 code 說 OK);驗證類代打要貼真實 exit code
4. **infra 恢復後,讓真人 agent 補跑一次複核**——代打有真實盲點(代打者對該 repo 的慣例未必熟,且審/驗自己的產出獨立性弱)。基礎設施恢復可 spawn 時,對代打過的 stage 補跑真正的 agent 一輪;真人 agent 揪出代打漏掉的問題是常態,不是例外。

**不能做**:因 subagent 撞 529 就**跳過**該 stage(跳過 review / 跳過驗證)。過載是基礎設施問題,不是放行理由——要嘛代打、要嘛等,不能省。

### Subagent 中途被切斷(`stalled`/睡眠/連線中斷)

與 529 不同:529 是啟動失敗,這是**跑到一半沒了**,而且回傳往往只有一句 harness 訊息,看不出真因。

**`Agent stalled: no progress for 600s` 不等於基礎設施過載。** 同樣的訊息也會由
**本機電腦進入睡眠**產生(訊息可能到下一次才變成 `Your computer went to sleep
mid-response`)。差別很重要:過載該退避重試,睡眠退避無效——所以**不要**因為連續幾次
`stalled` 就把 prompt 拆得越來越小,那治不到真因,只是把同一份工作重跑好幾遍。
判準:`ListAgents` 顯示其他 agent 同時段也一起停、或多次中斷落在同一段掛機時間 → 懷疑睡眠。

**唯一可靠的緩解是把「落檔」寫進回報合約**,而不是縮小任務:

> 報告檔路徑:`<scratchpad>/<agent>-<task>.md`
> **每答完一條就立刻追加寫入,不要累積到最後才寫。** 若你中途被切斷,落檔的部分就是有效交付。

被切斷後的復原順序:

1. **先看落檔**(`ls` scratchpad、讀那個報告檔)——已答完的部分可能已經在裡面
2. **不要開新 agent 從頭重做**——用 `SendMessage` 續跑同一個 agent,transcript context 還在
3. 續跑指令要求**先盤點再續作**:讀既有報告檔 + `git status` + 檢視目標檔,逐項判斷做到哪,**只補缺的**
4. 明確告知「哪幾項已確認完成、不用重做」——orchestrator 自己先盤點過,能省掉一整輪

**第二個成因:單一前景指令長時間無輸出。** 睡眠之外,`stalled` 也常停在一個逼近 Bash
10 分鐘上限、期間不吐任何輸出的前景指令上(整包 pytest、`pnpm install`、mkdocs build)。
這是相關性觀察加合理機制(watchdog 只看得到「600 秒沒進度」),不是已證明的因果;但緩解
成本低,所以**交辦文一律附防停滯條款**——這也不是「拆小 prompt」,任務範圍不變:

> 任何可能超過 2 分鐘的指令一律背景執行、輸出導檔,用 `tail` 短指令輪詢;每條指令加
> `timeout`;每完成一步就把結論追加進 progress 檔。

續跑的上限與接手:

- 同一個 agent 經 `SendMessage` 續跑後**再次** `stalled` → 不要第三次續跑同一個
  transcript。改開新 agent,輸入=progress 檔+既有 scratchpad 產物+完整失敗軌跡
  (原交辦文、兩次停在哪個指令);要不要換模型依
  [`model-dispatch`](https://github.com/Lee-W/maigo/blob/main/skills/model-dispatch/SKILL.md)
  「模型選擇與重試」(只換已授權的替代模型,換了也計入兩輪重試預算)。這不違反上面
  第 2 點:新 agent 是接手續作,不是從頭重做。
- 被切斷的 agent 若正在做**變異驗證**,worktree 可能殘留被改壞的檔案——續跑或接手的
  第一件事是 `git status --short` 加 sha 對帳並還原,再做別的。

> 案例(2026-10):兩個 sonnet review agent 各 `stalled` 兩次,每次都停在整包 pytest 的變異驗證或
> `pnpm install` 上,其中一個 worktree 殘留了 M5 變異,靠接手者先對帳才發現;之後約 14 個
> 交辦加上防停滯條款,含 35 分鐘、165 次工具呼叫的審查,零次 `stalled`。

### Subagent 中途撞 usage / session limit

與 529 不同:529 是啟動失敗,這是**跑到一半被切斷**——subagent 可能已完成部分工作(working tree 留有半成品),回傳卻只有一句 limit 訊息(含重置時間)。

1. **不要開新 agent 從頭重做**——半成品會跟新一輪工作糾纏,已完成的部分也白費。
2. Limit 重置後,**用 SendMessage 續跑同一個 agent**——transcript context 還在,任務背景不用重講。
3. 續跑指令必須要求**先盤點再續作**:`git status` + 檢視目標檔案,逐項判斷任務做到哪,只補缺的。盤點常發現工作其實已全部完成(切斷發生在回報前)——此時直接進驗證,避免重工。
4. 盤點與續作完成後照常走原流程——review / 驗證不因中斷打折。

### task-notification 標記 `status: failed`,不代表工作沒做完

跟 529(啟動失敗)、usage/session limit(有明確 limit 訊息)都不同:這是第三種訊號——subagent
在收尾寫最終報告時遭遇 API 連線中斷,task-notification 的 `status` 欄位字面上顯示
`failed`,`summary`/`result` 只留下被截斷的半句話(例:"Exit 0, passed. Let's verify final
git state is clean...")。**這個 `failed` 字面上看起來像整個任務失敗,但實際常常是:實質工作
(含 commit)早就做完,中斷只發生在自我確認 / 收尾報告階段。**

1. **先查實際狀態,不要照 `status: failed` 字面重派**——去該 agent 實際操作的目錄/repo 跑
   `git log --oneline` + `git status --porcelain` + `git diff --stat <base>...HEAD`,對照原始
   交辦的驗收條件逐項核對,而不是看到 `failed` 就假設一切從零開始。
2. 若 git 狀態顯示工作(含 commit)已完整——**不要重派 agent 從頭做**,直接把這個結果送進
   下一階段(review / 驗證),比照「Subagent 中途撞 usage / session limit」第 3-4 點的做法;
   被截斷的只是它自己的收尾敘述,不是它的產出。
3. 若 git 狀態顯示工作明顯未完成或矛盾——才視同「跑到一半被切斷」,比照上面 usage/session
   limit 小節處理(SendMessage 續跑同一 agent,要求先盤點再續作)。

### Handback 送達但內容遺失

`<task-notification>` 正常到達且 `status: completed`,`<result>` 寫著報告已用訊息送達,
但那則訊息從未出現——這是內容遺失,不是任務失敗。**不要**重派新 agent 重做同一輪工作、
不要自己代跑它該做的檢查、不要假設遺失的結論是 PASS。三步處置(先自己看現場 →
`SendMessage` 同一 agent 要求只重貼不重跑 → 採用重貼內容)與案例,見
[`references/handback-content-missing.md`](https://github.com/Lee-W/maigo/blob/main/skills/failure-handling/references/handback-content-missing.md)。

**附帶**:這也代表**不能用「收到 handback」當 agent 已停止的訊號**——handback 只是那一輪
的輸出,agent 可能仍在跑、仍在改共用 worktree;生命週期一律用 `ListAgents` 查。

### 等待自己開的背景 agent

用 Agent tool 開的背景 agent 完成時會自動發 task-notification 把 orchestrator 叫回來,**不需要
排 ScheduleWakeup 去輪詢**。ScheduleWakeup 是 `/loop` dynamic mode 專用工具,不是等待自己 spawn
的背景任務的機制——同一條教訓在不同 `/maigo:address-comments` 場次重複違反過,根因是
orchestrator 自己跑 `/maigo:*` 流程前沒有主動查一次 memory(見
[`skills/memory-loading`](https://github.com/Lee-W/maigo/blob/main/skills/memory-loading/SKILL.md)
consumer 清單已補上 orchestrator)。

背景 subagent 若寫了一個等待「從未被建立過的哨兵檔案」的假迴圈(例如輪詢一個不存在的 flag
檔案直到自己的 Bash timeout 打斷它),**不要重新 spawn 這個 agent**——用 SendMessage 直接告訴它
(1) 那個假旗標檔案不會被任何東西建立,停掉那個迴圈;(2) 明確給出它自己啟動的背景任務的真實
output 檔案路徑或 task id,叫它直接讀那個檔案或用 TaskOutput 查真實狀態。

同理,也**不要為了「等待」而 spawn 一隻 placeholder / fork agent**——harness 會在背景 agent
結束時自動發 task-notification,不需要任何 tool call 觸發。想等待時直接結束當前 turn(回一句
短訊息告訴使用者正在等什麼)即可。實例:一次為了等 review 完成而 spawn 的「placeholder to
force wait」agent 燒掉約 28 萬 subagent token 卻什麼都沒做。

### Subagent 拒絕 relay 而卡死

Orchestrator 用 `SendMessage` 把 Soyo 的 must-fix 轉給一個正在跑的 Anon 時,Anon 可能把這個
relay 當成「沒有使用者直接授權的 coordinator 訊息」而拒絕執行,即使 orchestrator 事後確認授權
也持續卡住。

**How to apply**:對於一個一行、完整指定的簡單修正(import 移動、rename、單行邏輯),
orchestrator 直接 inline 套用,不要再 relay 一次。真的需要委派時,開一個**全新**的 Agent()
(乾淨 context、無 relay 框架),不要對已卡死的 agent 再 SendMessage——同類任務由全新 agent
執行通常不會被拒絕。

### 先定位層級再修,不要直接 patch 工具原始碼

當某個 maigo / hook / 共用工具在**特定 repo** 表現異常時,先追高層再考慮改工具本身:

1. 這個 repo 是否已有對應的 `repo-aware` skill(如 `airflow-aware`、`commitizen-aware`)在處理這類摩擦?有 → 修法大概率在該 skill 或它引用的 seed。
2. maigo 的 `SessionStart` `repo_detect` hook 是否已經替這個 repo seed 了對應的 `.claude/<config>`?檢查 `hooks/repo_detect.py` 的 `REPO_RULES` → `claude_config_seeds`;若有,可能只是這個 worktree 建立在該功能之前,手動補寫一次 seed 檔即可。
3. 這個工具是否已支援 opt-in / opt-out 設定檔(如 `skip-test-verification`、`test-command`、`known-test-failures`)?有就用它。

三層都確認缺席後才考慮動工具原始碼——patch 共用工具的 blast radius 是跨 repo 的,一個為
某 repo 環境限制調校的「修法」會改變所有沒有那個限制的其他 repo 的行為。

### Stop hook 假陽性迴圈

當 Stop-hook 的 test verifier 因為**環境 / collection 層**問題(不是變更本身壞掉)逐輪重新觸發:

1. **先確認一次成因**——是 host 環境結構性壞掉(bootstrap / install-time 失敗),還是單純
   monorepo scope 抓錯 test 指令。前者才適用「寫 skip 檔」;後者且變更有真正新行為要覆蓋時,
   應該修對應的 `.claude/test-command` 成正確 scoped 指令、寫一個真的 test 去測,不要圖方便
   直接跳過驗證。
2. 環境結構性壞掉、且已經用該 repo 的真實 runner 確認過一次是綠的 → 立刻寫
   `.claude/skip-test-verification`(帶非空、非註解的原因說明)disarm 該 worktree 的 verifier,
   不要每輪重新解釋同一個假陽性——任何一次回覆都會重新觸發 Stop hook,逐輪重複解釋等於空轉。
3. 使用者明確說「忽略這個 hook」時,**輸出零字元**——連 `.`、`[ignored]`、空白都不行。任何輸出
   都會結束該輪、讓 harness 重跑 Stop hook、hook 再次擋下,形成迴圈。等使用者修 hook 設定 /
   中斷 session / 送新任務,不要逐次確認每次觸發。
4. **受限權限模式下,第 1、2 點的寫檔動作本身可能被擋。** `.claude/` 是 harness 的設定目錄,
   權限 classifier 會把寫入判成 self-modification / safety bypass(實例 2026-09-17,Claude Code
   auto mode:Bash heredoc 回 `[Self-Modification]`、Write 工具回 `[Safety Bypass Flag]`,同一個
   檔案兩條路都不通,hook 連擋五輪)。這道防護的用意是對的——不該讓模型自己關掉測試驗證——
   所以**不要繞**,也**不要換工具重試**(換工具做同一個動作,仍是同一個動作)。第一次被擋就
   停手交給使用者,並給**可直接執行的一行**,而不是「請你去寫個檔案」:

   ```text
   ! printf '%s\n' "<scoped test command>" > .claude/test-command
   ```

   `!` 前綴讓使用者在自己的 session 裡跑,輸出直接進對話。使用者授權後再由模型寫入亦可。

### 無限迴圈防護

計數只屬於同一個邏輯任務/執行批次,不帶入其他 work item 或舊 session 的歷史總數。
`verify_task.py` 首次回傳 run/task ID,重試須沿用;SubagentStop 只能辨識同一 agent 的續跑,
Stop 沒有可靠的 task ID。換 agent、沒有 hook 或缺識別碼時,由 orchestrator 保存本任務預算,
不能因 runtime 無法聚合就無限重試。doctor 的歷史次數不是這個連續計數。

- 爽世連續擋 **2 次**同一條 must-fix → 停下,請使用者介入(可能是計畫本身有問題)
- 立希連續紅 **2 次**同一個 test → 停下,請使用者介入(可能 test 本身需要更新)

「同一條 must-fix」判準:Soyo 輸出的 must-fix 條目**指向同一個檔案 + 同一個函式 / 區段 + 同一類問題描述**(不要求 wording 完全相同,但語意相同算同條)。Anon 改 wording、換實作方式但問題本質沒解掉 → 仍算同條。

「同一個 test」判準:test runner 報出的**同一個 test ID**(pytest 的 `path::TestClass::test_method[param]`、其他 framework 的等價 identifier)。**錯誤訊息字串變化不算「不同 test」**——ID 相同就是同一條。一次 run 裡多個 test ID 同時紅 → 各自獨立計次,不互相抵消。

Files in this skill

  • SKILL.md18.1 KB
  • references/handback-content-missing.md2.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.