
昨天,我和 Claude 把通知失敗查到有依據的位置,也留下哪些事情還沒完成。
但那次查核能往下走,是因為對話裡已經交代了程式版本、通知 ID,以及為什麼 API 回 200 還不能收工。
如果關掉這段對話,重新開一個 session,Claude 還能照同一套方法查嗎?
我把反覆提醒的查核要求整理成 Skill,先用完整與缺件的封存資料試跑,再接上本機 Log server,確認 Claude 能不能自己查,也試一次查詢失敗。今天先確認一件事:查法離開原來的對話後,能不能被重新使用。這也是第三幕的起點:從一個人查得動,走到團隊接得住。
Day 4 已經把查證要求整理成共用方法。今天繼續往下問:當這套方法離開原來的對話,它還知道需要什麼資料、哪些結論不能直接下嗎?
最容易的做法,是把昨天那串提示與回答貼進 SKILL.md。但這樣可能連「重試四次、接收端回 503」都留下來。下次若第一次就送達,它還拿昨天的答案解釋今天的問題,就麻煩了。
我把兩種東西分開:
| 留在方法裡 | 每次事件重新提供 |
|---|---|
| 先對程式與部署版本 | 本次版本與對應程式 |
| 用訂單、通知 ID 串紀錄 | 這次要查的 ID 與紀錄範圍 |
| 分開看 API、發送端與接收端 | 本次請求、Log 與接收端紀錄 |
| 結論要有出處,缺件就留下未知 | 本次實際查到的內容 |
| 不自行補送或宣告結案 | 這次誰能接受結果、授權到哪裡 |
留下的是怎麼查;查到什麼,要重新從這次的資料回答。
Claude Code 的 Skill,是把可重複使用的工作方法,整理成可以按需載入的操作說明。 核心是 SKILL.md,寫清楚何時使用、需要哪些資料、怎麼查、最後交出什麼;需要時也能附上參考文件與執行腳本。
一般提示交代這次怎麼做;Skill 保存共同要求,下次呼叫時再提供事件資料。
Claude 依這份查法選工具:先對照程式,再用通知 ID 查 Log,工具結果回到同一個 LLM 比對,決定下一步查哪裡。已有 Log server 就使用它的查詢入口,不必另外寫一套收集程式。Skill 本身不會增加查詢權限。
方法入口是 .claude/skills/trace-notification/SKILL.md。以下節錄查核迴圈的第 4、5 步與輸出契約:
## 查核迴圈
4. 分開 API 結果、發送端觀察與接收端佐證。notify_sent 不自動等於接收端已核對。
5. 區分查詢成功但無符合資料、缺來源、格式錯誤、權限不足與工具失敗。
查不到或查詢失敗不能寫成一定未送達;缺證據標 unknown。
## 輸出
逐項附查詢依據與來源位置。最後加 JSON:order_id、sender_status、
receiver_status(confirmed/unknown/not_confirmed)、missing_sources、next_action。
接收端 confirmed 須有對應來源,不能由發送端推得。
整份還包含輸入與工具、其餘查核步驟與離線模式,也能附帶腳本與參考檔案隨 repo 分享;但存進去只是有了共同版本,還不是證明每個人都會用。官方 Skills 說明
第 4 步是全篇的樞紐,其餘要求都圍繞它:先核對資料身分、對照當時程式、每項觀察附來源;缺資料時報告已知部分,不順手補送或替人結案。
把這份 SKILL.md 放進專案後,使用前先確認 Claude 能讀到指定版本的程式,也有該 Log 平台的查詢入口與權限;工具尚未接上時,先回報缺少的入口。
接著在 Claude Code 呼叫以下指令,將括號內資訊換成這次事件的實際值:
/trace-notification
環境與服務:<測試環境、訂單服務>
時間範圍:<起訖時間與時區>
事件:<訂單 ID 或通知 ID>
部署版本:<commit 或發布版本>
Log 工具與資料來源:<已授權的工具、資料來源>
程式與設計:<repo 或本機路徑、設計文件>
請先核對資料是否足夠,再沿 API 與背景通知查核。
只查詢與分析;需要額外權限或處置時,列出原因與下一步。
這段的關鍵是最後兩行:先要它核對資料是否足夠、缺件就報缺,而不是把找不到當成零筆結果。假設目前只有訂單 ID,Claude 應先找對應的通知 ID,再用通知 ID 追背景工作;如果查到多個版本或不同環境的同名事件,先釐清範圍,不能混成同一次請求。
沒有 Log server 也能先用封存資料練習;離線演練附件見文末,正文不把它當成使用 Skill 的必要步驟。
檔案放進 repo,只代表方法留了下來。所以我另開一個沒有原對話的新 session,讓 Claude 只帶這份 Skill(唯讀,工具只開 Read、Grep、Glob、Skill)查一筆缺收據的事件。它把接收端標 unknown、列出 missing_sources,沒有把查不到寫成未送達。
但這裡我原本的推論錯了。 我以為是 Skill 讓它守住這一格,所以又跑了一次對照:同一筆事件,不給 Skill,只用一句外行提問「這筆通知到底有沒有送到」。結果它照樣沒有誇大,自己看出「只有發送端記錄成功、沒有接收端證據」,還主動指出收據缺失(US$0.064)。
不帶 Skill 的對照也保留了未知,所以謹慎不能歸功於 Skill。 那 Skill 留下了什麼?差別在輸出形式:
帶 Skill(固定契約):
{"receiver_status": "unknown",
"missing_sources": ["receipts.json"],
"next_action": "向服務 Owner 補查接收端收據"}
不帶 Skill(一段散文):
「只能證明發送端送出、收到成功回應,
沒有接收端自己的證據,不能斷言已送達。」
兩段皆節錄自實跑原始輸出;每組各一次,不代表普遍效果。
帶 Skill 的版本依約定留下狀態、缺件與下一步,接手者能逐欄核對、程式也能讀取欄位;不帶 Skill 的散文版同樣沒誇大,但要讀完整段才拼得出來。
這次實跑也暴露了查法之外的問題:Claude 自己指出設計文件的行號過期(設計寫 69、79、84、88、89,現行程式是 64 到 93),改以現行程式為準;這是 Day 16 撞到的同一件事,換個 session 又出現一次。
但這幾次讀的仍是本機封存資料。檔案少一份,與 Log server 回傳零筆或連線失敗,是不同的問題。我接著把工具接起來,再查一次。
一般團隊會把應用程式 Log 送到集中平台,不會每次先請人整理一份檔案。所以我用 Docker 架起 Grafana、Loki 與 Alloy:Alloy 收集教學服務的 Log,Loki 保存紀錄,Grafana 提供資料來源,Claude Code 透過 Grafana MCP 查詢。
Skill 留下查法,MCP 提供工具,查詢結果回到 Claude 比對,再決定下一步。 程式與設計仍從本機讀取,這輪沒有接 repo MCP,也沒有使用公司資料。
這次沿用 Day 16 的 r2 發布包,重新建立與取消三筆教學訂單,產生新的 API 與接收端 Log。不是把昨天四次 503 的紀錄重新倒進平台。每次只提供指定資料來源、事件、時間窗與對應程式,不把測試答案交給 Claude。
完整案例的查法有兩步。第一步從訂單找通知 ID:
{lab_case="complete", service_name="order-api"} |= "live-20261001-02-complete"
lab_case 隔開本次情境,service_name 限定發送端,後面那串是訂單 ID。查到 notify_sent 後,Claude 取出紀錄裡的 notification_id,再查接收端:
{lab_case="complete", service_name="notification-receiver"} |= "3b30d36ba5a64e7c9ea01ea02cc61074"
兩次查詢都帶任務指定的時間範圍。第二次實際查到 notification_received,ID 也對得上,才有依據填接收端 confirmed。這裡確認的是接收端收到通知,沒有延伸宣稱退款或其他後續工作完成。
接入過程沒有一次成功:最初 MCP 的傳輸設定不合,Skill 也沒有成功載入。我修正連線與明確載入方式後,才取得真正的查詢紀錄。第一次接通的完整案例又省略了獨立的接收端查詢,所以我把這一步寫進 Skill,再用相同情境重跑;失敗與修正前的結果都保留在附件。
重跑缺件情境時,Claude 先用了 service 標籤,得到零筆。但平台實際的標籤叫 service_name。它查詢標籤名稱、修正條件後,才找回兩筆 API 紀錄,接著用通知 ID 查接收端,這次才是真的零筆。
零筆結果,可能是沒蒐集到,也可能是查錯了。先確認怎麼查,再解釋查到什麼。 這就是只讀一份整理好的檔案,還看不到的問題。
| 我準備的情境 | 工具實際回傳 | Claude 最後的判斷 |
|---|---|---|
| 完整:兩端都送進 Loki | 兩筆 API 紀錄、一筆相同通知 ID 的接收紀錄 | 發送端與接收端皆 confirmed |
| 缺接收端:刻意不蒐集接收端 Log | API 有資料;修正查詢後,接收端仍為零筆 | 發送端 confirmed,接收端 unknown,要求補查來源 |
| 查詢失敗:指定不可連線的資料來源 | Grafana 查詢回 502 | 兩端都 unknown,保留錯誤與下一步,不偷偷換來源 |
缺接收端那一組,測試端其實收到通知,只是沒有把接收紀錄送進 Loki。這份對照答案沒有放進 Claude 的工作目錄。因此 unknown 是正確邊界,不能寫成「一定沒送到」。查詢失敗則連資料都沒取得,也不能混成「查過了,零筆」。
三個新 session 都成功載入修訂後的 Skill,實際呼叫 MCP(完整 12 回合/30 秒/US$0.105、缺件 13 回合/37 秒/US$0.122、查詢失敗 11 回合/26 秒/US$0.093),工作目錄前後雜湊沒有變動。逐項檢查載入、查詢範圍、事件關聯、狀態與缺件輸出,共 36 項檢查通過;我也逐份核對回答與工具回傳。這是三個情境的檢查結果,不是 36 次獨立實驗,也不是準確率。
讀者可以從文末操作附件啟動相同環境,再用自己的新 run 名稱重做。方法的價值,在這裡變得具體:換成真正的查詢工具後,仍有一套可以核對的步驟與交付格式。
這次留下了查核順序、判斷條件與交付格式。換個 session,Claude 能照著使用;從封存資料到 Log server,這次都能核對它如何查;至於是不是更準、更省力,這些有限情境還不能回答。
但它也指出,設計文件裡的行號已經過期。查法可以留下來,查法依賴的系統知識,又該怎麼保持正確?
參考資料:
days/day17/lab-method-pack/ 的 runs/ 保留原三次離線對照。新增 log-server-lab/ 含 Docker 設定、Skill、啟動與驗證程式;runs/live-20261001-02/ 保存新的請求與工具紀錄,model/r2/ 是修正後三種情境,verification-r2.json 為 36 項檢查結果。操作附件分開列出 Log server 實跑與離線練習。r2-healthy-01 的封存資料;新增實跑沿用 r2 發布包,產生新訂單與 Log,兩者沒有混成同一次事件。新一輪使用 Claude Code 2.1.285、Sonnet 5.5,各情境每版一次;失敗接入與修正前紀錄也保留。本機教學環境沒有驗公司權限不足或逾時情境,不代表 Production、真人團隊採用或人工減載。36 項驗證與離線整理器的七項檢查不同,也不能替代對每句推論的核對。