---
name: verify-deploy
description: PR merge 後由 AI 查核合併、驗收與部署證據,更新適用文件並自審,交人審閱未完成事項。
---
# Post-Merge Wrap-up
AI 完成適用的證據查核、文件修訂與自審,人審核結果及尚待決策事項。合併、部署與功能可用是不同事實,不能互相替代。
## 1. 確認合併與範圍
- 使用 `gh pr view` 或實際可用的 GitHub MCP 查 PR state、mergedAt、merge commit、base 與相關 Issue。Claude/Codex 依 callable inventory 使用等效工具,不依賴特定 hooks 或提問工具。
- 使用者說已 merged 可作為查核線索;無法讀遠端時標示「使用者回報,未遠端驗證」,先整理本機候選修訂,不宣稱已驗證合併或進行不可逆收尾。
- 未 merged 就不執行 merge 收尾;可回報目前證據與待完成項目。
- 讀取目前工作樹狀態及此次 PR 的實際 diff,保留他人修改;需要合併後程式時用唯讀 ref 或隔離 checkout,不強制切換/重設共享工作樹。
## 2. AI 核對需求與證據
- 從 PR/Issue 連結找已確認 PRD、既有 FRD、開發計畫與驗收紀錄,保留原 FR/TP/AC ID。
- 核對此次合併涵蓋哪些需求、哪些仍未完成。依目前 commit 分列程式實作、測試、部署、目標環境操作證據;未執行就記未驗證。
- 自動部署 workflow 成功只能支持該工作實際完成的步驟;確認環境與 revision 後才能更新部署狀態。功能可用仍需相應驗收證據。
- 部分完成、驗收失敗或缺少環境證據,不勾選整份需求完成,也不直接把中央 Issue 標 Done。中央 Issue 的 Done 只由 PM 驗收通過(關 issue)產生;唯一例外是掛 `acceptance:engineering` 的工程驗收卡,冒煙全部 ✅ 時由本 skill 關 issue(見 §2.5 第 5 步)。
## 2.5 目標環境冒煙(寫入或讀取權限變更必做)
合併與部署都不證明使用者能完成任務:#179 是 server 合併後 dev DB 缺欄位,任何建立場次都 500,由使用者在 dev 撞到。這一步用 PR 自己承諾的核心旅程,在部署後的環境再走一次。
1. **取得矩陣**:從 PR body「## 驗證證據」或 task.md「### 核心旅程矩陣」取全部旅程列(格式見 develop 的 [journey-matrix.md](../develop/references/journey-matrix.md))。讀取權限適用時一併取 [角色與資料矩陣](../develop/references/read-access-verification.md),不可因沒有寫入或新增端點而跳過。PR 寫 `核心旅程不適用` 時先核對 diff 與讀取權限不適用理由;兩類行為都不涉及才記原因後跳過。
2. **確認部署 revision**:查該 repo CD run 是否已部署合併後 commit(run URL、環境、revision);跨 repo 依實際依賴(通常 storage → server/AI backend → f2e)逐一記錄環境、revision 與成功 run,全部到位才算環境就緒;不能漏掉列表/搜尋實際呼叫的 AI 服務。未到位就停在「已合併,待部署」,不冒煙、不回報可用。
3. **重跑旅程**:在部署後環境(dev 前端 + server-dev,或 PR 標明的目標環境)用瀏覽器或 curl 重跑**全部正常列 + 至少一列錯誤路徑**;bug 卡另外照 task.md 的 `REPRO-01` 重跑原本的通報路徑,攔 response 記狀態碼;登入與工具選擇沿用 develop 的 [browser-verify.md](../develop/references/browser-verify.md)。
- **讀取權限旅程**:沿用同一組 fixture,核對目前登入的實際使用者 ID/角色與 membership,從使用者入口一路走到詳情、打卡/留言等受影響下游。依矩陣重驗本人、同範圍、範圍外、退出/移除及未登入;不適用角色保留具體理由。檢查原始回應的私人內容排除,不只看 200/403。快取適用時先成功讀取、確認命中,再撤權後重讀;期限適用時驗臨界當日與隔日。無法在 dev 安全造出時間邊界時,附真實 DB 邊界測試證據並明列部署後未重做項目,不假稱全旅程通過。
- **原生 App 才適用**:核對可安裝 preview build/安裝連結、測試裝置與實際版本;OTA success/Expo web 僅是各自證據。
- **2026-10-29 起 App 暫不由 PM 驗收**(沒有可安裝測試版,避免卡片一直卡在 Acceptance):只改 App 的卡改走工程驗收——補掛 `acceptance:engineering`,冒煙(Expo web 或模擬器)全部 ✅ 就依第 5 步留「工程驗收通過」留言並關 issue,不進 Acceptance。網頁+App 混合的卡照常交 PM,但交接留言的 PM 步驟只寫網頁,App 步驟放「已知限制/這次沒做的」並註明「App 暫不驗收」。規則見 move-board-card「誰驗收」。
- **測試帳號 email 只能用使用者指定的 QA 信箱**(`~/.claude/projects/-Users-xiaoxu-Projects-daodao/qa-email.txt`,plus 別名 `+qa@`)。dev 走真 SMTP,自己編的地址會把退信灌進維運信箱(#218 實例見 browser-verify.md §3a)。能用 `dev-login mode=user` 登既有帳號就別建新帳號。
- **冒煙完清理測試資料**:本次新建的 QA 帳號先退訂 `PUT /users/me isSubscribeEmail=false`,再停用 `PUT /admin/users//status {"isActive":false}`;沿用共用 fixture/既有帳號時不停用或重設他人資料。刪掉本次建立的實踐等排程來源並回讀;清不掉的用明顯測試命名並在 comment 標明。
- **改到共用資料要還原**:冒煙時改了共用的場次、模板、組織或 fixture(改名稱、加項目、改設定),先記下原值,測完改回並回讀;改不回去就在 comment 寫明改了什麼、原值是什麼。共用 dev 資料被改名或多出東西,是 PM 驗收受阻的第二大原因(#344 場次被改名、#216 多出模板、#332 fixture 少了第 5 天的資源)。
- **每一筆都記進冒煙留言的「測試資料」表**(第 4 步):建立了什麼、改了什麼、怎麼處理、回讀結果。沒建立也沒改就寫一行「未建立或改動資料」,不能空著。
4. **回寫**:在對應 issue comment 追加「dev 冒煙」表:
```markdown
## 🔥 dev 冒煙(<環境>,revision ,<日期>)
| ID | 旅程 | 類型 | 實際 | 證據 |
|---|---|---|---|---|
| J-01 | 建立場次 | 正常 | ✅ 201 | <截圖/curl 輸出連結> |
| J-03 | 建立場次 | 錯誤路徑 | ✅ 409 訊息可見 | ... |
### 測試資料
| 資料 | ID/網址 | 建立或改動 | 處理 | 回讀 |
|---|---|---|---|---|
| 實踐 | | 建立 | 刪除 | ✅ 404 |
| 場次 900001 名稱 | <網址> | 改動(原值「驗收共同挑戰」) | 改回原值 | ✅ 名稱已還原 |
```
全部 ✅ 只代表 AI 冒煙通過,docs/product 標「dev 冒煙通過,待 PM 驗收」;PM 驗收通過後才標「已驗收」(見 §2.6)。任一 ❌ → 走 `report-bug` 開卡、comment 標「已合併,dev 冒煙未過」,中央 Issue 不標 Done。僅工具、登入、環境或 installer 前提不足時記「未冒煙/受阻:<原因>」,不算行為 FAIL 或可用:初次交驗前留 Review 並列出待排除前提;已在 Acceptance 則依 §2.6 留 Acceptance、掛 `acceptance:blocked`。
4a. **交接可執行性檢查(移 Acceptance 前必做)**:工程冒煙通過後,把即將發布的請驗收留言另存檔,從其中的網址開始,使用**指定 PM 測試帳號、相同角色、相同資料**逐步實跑全部網頁步驟,確認每個預期結果都能看見。不得以工程帳號、其他 fixture 或 API 成功代替;不碰 PM 的 Google 憑證,工程可用 `dev-login mode=user` 查核同一既有帳號,但記明登入方式,這不等於正式 PM 驗收。
- 先列每條 AC 的資料前提:資料 ID/直接連結、擁有者、所需 membership/權限、可修改或鎖定狀態、必要欄位值與數量,以及保存/重設方式。只看名稱或沿用舊冒煙資料不算確認;例如 #332 需要真正未鎖定的第 2/5 天資源,名稱含「第5天」不算。
- 有既有讀取端點可判定的前提,執行唯讀檢查並保存時間、契約與逐項結果。實踐資源使用 [acceptance-preflight](references/acceptance-preflight.md);其他資料沿用對應檢查腳本,尚無腳本則保存即時讀取證據與人工檢查表,不填假的 PASS。`acceptance-lint` 仍只檢查文字,不能證明 fixture 或網頁旅程可用。
- 瀏覽器確認實際登入帳號,照留言順序實跑,保存各步驟輸入與終態證據。做不到就列「交接受阻」與缺少的前提;初次交驗留 Review,不先把問題丟給 PM。
- 實跑後還原用過的 fixture,再檢查初始資料,**保留至 PM 驗完**;不要按一般冒煙清理規則刪掉交接指定資料。若會到期、被 reset 或排程修改,寫出有效期限與可執行的重設方式;依賴尚未開發的設定入口不算準備方式。無法維持前提時不要交驗。
- 工程證據附「驗收前置檢查」:檢查時間、指定帳號/角色、資料連結與必要值、唯讀報告、同帳號逐步實跑證據、還原後檢查與保留/到期規則。沒有特殊 fixture 仍須說明如何從指定入口建立;不能以 none 跳過步驟實跑。
5. **回寫 Planning board 並交給 PM**(中央卡在 board 上時必做,這是卡片離開 `Review` 的唯一路徑):
```bash
# 全部 ✅ 且卡片沒有 `acceptance:engineering`:移 Acceptance,並自動 assign PM(PM_LOGIN)+回讀;不移 Done、不關 issue
pnpm -s tsx bin/pipeline/board.ts set accept
# 全部 ✅ 且卡片有 `acceptance:engineering`:不進 Acceptance。先發冒煙結果留言(標題「工程驗收通過」,附冒煙表與驗證報告),再關 issue,內建 workflow 會移 Done
gh issue close --repo daodaoedu/daodao --reason completed
# 實際操作已觀察到違反 AC 的 ❌:退回;僅環境/installer 前提受阻不執行此行
pnpm -s tsx bin/pipeline/board.ts set needfix
```
移 Acceptance 後**立刻**在中央 issue 發交接留言([issue-status-comment.md](../../templates/issue-status-comment.md) 的「交給 PM 驗收」段):第一行隱藏標記 ``(PM 的 [test-acceptance](../test-acceptance/SKILL.md) 靠它找規格)、`@peggy1213-create`、測試網址(直接點進對應頁面)、白話驗收步驟、對照的 AC、工程證據、驗證報告連結、已知限制、驗完收尾(驗收建立的資料怎麼處理),以及「通過請關 issue;退回請留言哪條 AC 沒過並移 Need Fix」。沒發交接留言等於 PM 不知道輪到他。
**驗收步驟只寫 PM 在畫面上做得到、看得到的操作與預期**。冒煙表裡的 API 送出內容/回讀、regression test、CI、log 改寫成「工程證據(已驗,PM 不需重做)」區塊並附連結,不要搬進 PM 步驟;只能用 API 或測試驗的 AC 標工程驗收項,不列入 PM 步驟。驗收契約「必須證據」欄寫了 API 回讀或測試時,「對照的 AC」要寫明由工程提供、PM 依畫面判定(#370、#358 的 PM 照契約去要 PUT body、GET 回讀與 regression test 輸出,判 BLOCKED 退回)。留言先寫成檔案,發布前必跑:
```bash
# 在 daodao root 執行;留言檔放 repo 外的暫存位置
pnpm -s tsx bin/pipeline/acceptance-lint.ts <留言檔>.md # 有 error 就改到通過再發;warn 是引用的文案在 locale 找不到,逐一確認
gh issue comment --repo daodaoedu/daodao --body-file <留言檔>.md
```
`Need Fix` 的卡由下一次 `/develop` start 移回 `In Progress`。跨 repo 中央卡只有在**所有** repo 的 PR 都 merged 且冒煙通過時才移 Acceptance;部分 merged 留 Review 並在 comment 寫明剩哪些。
**母卡**(有 GitHub sub-issues):子卡還有沒關的(含 bug 子卡),母卡冒煙通過也**留在 Review**,comment 寫明等哪幾張子卡;子卡全關後再跑一次本步驟交 PM,交接留言的驗收步驟寫「整體走一遍」而不是重驗各子卡 AC。規則見 [move-board-card](../move-board-card/SKILL.md) 的「母卡與子卡」。
## 2.6 PM 驗收之後
- **通過**:PM 關 issue → 內建 `Item closed → Done` 自動移卡。之後收尾:拔 `human-driving`(`board.ts audit` 會列「Done 仍掛 human-driving」提醒)、docs/product 狀態改「已驗收」並附 PM 關 issue 的記錄。
- **退回**:PM 留言哪條 AC 沒過並移 `Need Fix`(或請工程師代移 `set needfix`)。退回理由對應不到任何 AC 時,代表 AC 寫得不清楚:先跟 PM 補齊 AC,再修。
- **受阻/新增要求不是退回**:PM 測不了 → 卡留 Acceptance、掛 `acceptance:blocked`,工程排除後拔 label 並 @PM 重驗;驗收當下的新要求或通過後改文案 → 另開卡(相關:#n),原卡依原 AC 判定。分流表見 [move-board-card「Need Fix 只收 AC 失敗」](../move-board-card/SKILL.md)。
- **處理 BLOCKED 先查證,再重跑**:逐項記錄 PM 所述前提、目前資料/權限/網頁的實際觀察與時間。任一必要前提不滿足就足以受阻,不因其他描述不準確而否定 BLOCKED;目前狀態不能證明歷史狀態。先分出資料不足、角色/權限不足、環境問題與已觀察到的 AC 失敗,再修正對應原因。補好資料或 API PASS 只能寫「前置資料已補齊」;必須用同一 PM 帳號、指定資料重跑原受阻步驟及依賴步驟,還原後再次驗前置條件,才能寫「阻擋已排除」、依既有授權移除 blocked 標籤並重新請驗收。不能重跑時保留受阻,不要求 PM 反覆代查。
## 3. 更新適用文件與歸檔
1. 在可存取的 daodao `docs/product` 找對應需求與 roadmap,按證據更新「已合併/已測試/已部署/已驗收」等適用狀態,附日期與 PR/run/驗收來源;沒有部署證據不寫已上線。
2. OpenSpec 已於 2026-09-20 退役(舊 change 封存於 `docs/archive/openspec/`,不再歸檔);用現有開發文件與 Issue 驗收契約記錄完成與剩餘事項。
3. 結構、入口或 build 流程有變更時更新適用 codebase-map;服務依賴/schema 流程有變更時,先查 canonical system-map 與實際同步機制,再同步可確認的副本,不假定固定有六份。
4. 相關 repo/文件不可存取時留下具體路徑、建議修訂與限制;不宣稱跨 repo 已同步。不相關項目標為不適用。
## 3.5 這次該被擋卻沒擋的(符合條件才做)
只在以下情況做:dev 冒煙有 ❌、verify 同一項失敗兩次以上、PM 退回,或這張卡本身是漏到 dev/prod 的 bug。要在 develop cleanup 刪掉任務資料夾**之前**做,task.md 的失敗紀錄是唯一素材。
每條教訓分到三類之一:
1. **能用腳本、lint 或閘門抓到**:寫成 issue 草稿(`notes/issue-drafts/`),標「閘門候選」,指出最適合掛的位置(pre-pr-gate、check-pr-evidence、acceptance-lint 等)。新閘門要先在事故修正前的版本跑出 ❌、修正後 ✅。
2. **需要判斷、寫不成檢查**:提議一條 develop `gotchas.md` 的「症狀 → 做法(#n)」。
3. **一次性的**:丟掉,寫一行理由。
清單交人核准後,才開卡或修改 skill;不自動改。§4 報告加一行「經驗整理:閘門候選 N/gotchas N/丟棄 N」,沒觸發就寫「未觸發」。
## 4. AI 自審後交人審閱
- 檢查文件間狀態一致性、來源連結、FR/TP 對應、未完成項目及 diff;按變更執行適用文件檢查。
- 報告每項「已完成/未驗證/待決策/不適用」、實際修改文件及證據。人只需審閱修訂與產品/發布決策,不必重新手動搜尋合併證據。
- 報告第一行寫明「已合併/已部署/dev 冒煙通過」三個事實各自的狀態;三者不齊不寫「功能完成」。
- 本機文件修訂不等於 commit、push、部署或關閉 Issue。這些動作依既有明確授權及目標 repo 流程進行;不因 PR merged 自動發布或 merge 其他 PR。Board 回寫與交接留言(§2.5 第 5 步)是本 skill 的標準輸出,不另外要授權,但只依冒煙結果移卡;本 skill 不移 Done,也不關中央 issue(那是 PM 驗收通過的動作);例外是 `acceptance:engineering` 的卡冒煙全部 ✅ 時,依 §2.5 第 5 步留證據後關 issue。
- 遠端動作如已授權,執行後讀回確認;部分失敗保留成功項目與待處理項目,避免重複操作。