diff --git a/docs/TODO.md b/docs/TODO.md index ede4fd2..98585fe 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -485,11 +485,91 @@ admin 端 `grep -i rating` 零命中,營運方對爛司機完全無感。 --- +## 🧹 清開發殘留 worktree/舊分支(維護項 5,2026-07-28 完成) + +> 三個 repo 累積的殘留:**76 條本地分支、18 個 worktree**。 +> 這項的重點不是刪,而是**刪之前逐條證明內容真的在 main**—— +> 前兩批「救回」(app PR #48、dispatch PR #49)就是因為有人把未合併的分支當成已合併。 + +**判定方法**(不靠 commit message、不靠「PR 看起來合併了」): +1. `git merge-base --is-ancestor main` → 是 ancestor 就安全。 +2. 非 ancestor 者查對應 PR,**MERGED 還要再比對 `headRefOid`**—— + squash merge 後本地 tip 可能又有新 commit,PR 頁面不會告訴你。 + 全 40 條 MERGED 分支的本地 tip **都等於合併時的 tip**(無漏網)。 +3. 剩下的例外逐條看 diff:**只有 4 條**不是「已合併且 tip 相同」。 + +**4 條例外的判定**: + +| 分支 | 判定 | 依據 | +|---|---|---| +| app `claude/todo-review-priority-54ffe7`(PR #40 CLOSED) | 已救回 | 整合測試+`tool/watch_driver_location.sh` 在 PR #48、功能碼在 PR #41 | +| app `claude/project-planning-docs-803c8e`(PR #37 CLOSED) | 已被取代 | 純文件;T1 車資預估已完成、T2/T3 仍列在下方、T5-2 評分已上線 | +| dispatch `claude/driver-phone-profile`(PR #42 CLOSED) | 已被取代 | 那份 service 測試的每一條都被 main 的 `handler/driver_profile_test.go`(真 DB)覆蓋,含「改電話不重置 O5 審核」;且**「空字串=清除電話」在 main 已改成 400 拒絕**,原測拿到 main 反而會 FAIL | +| dispatch `claude/determined-shannon-17f4ac`(**從未開 PR**) | 🐛 有漏 → 已救回 | 功能碼(`PickUpResult`/`dropoff_lat`/tracking ETA)都在 main,但帶著一份 main 沒有的 `ride_dropoff_integration_test.go` | + +- [x] **救回 dropoff repository 測試**(dispatch PR #50):原檔測的 `GetDropoffCoords` + 在 main 已不存在,故改寫成對現有 API(`Create` → `GetByID`)的等價覆蓋。 + 關鍵是**「未指定目的地 → `DropoffPoint` 必須是 nil」這條 main 完全沒有**—— + 守的是踩過的 `GeoPoint.Scan` 坑:NULL 被當成掃描成功而留下 `(0,0)`, + 導航與計費會把幾內亞灣外海當真目的地且**不報錯**。 + 負向斷言的取值路徑由同檔正向案例校準(同一個 `GetByID → DropoffPoint`), + 不會永遠 PASS。真 PostGIS(testcontainers)實跑 **2/2 PASS**、gofmt/go vet 乾淨。 +- [x] **清除**(三端數字皆為實測 `git worktree list`/`git branch -a`): + 本地分支 **76 → 5**(app 55→2、admin 2→1、dispatch 19→2)、 + worktree **18 → 3**(僅留兩個進行中的工作區)、 + remote 舊分支 **17 → 0**(app 7、dispatch 10;使用者 2026-07-28 同意含 4 條未合併的一併刪, + GitHub 的 PR 頁面仍看得到 diff)。admin 端本來就乾淨。 + +--- + +## 🗄️ 清 dev DB 測試殘留(維護項 6,2026-07-28 完成) + +> ⚠️ **先更正原本這條待辦寫錯的機制**:舊敘述說「十幾個殘留的『線上』司機**擋在派單佇列前**」。 +> 讀 `dispatchRound` → `Store.NearbyDriverIDs` 後確認**跨 session 不成立**: +> 派單候選**只從 Redis 的 `drivers:geo` 取**,且每個候選還要 `driver::loc` +> 的 `updated_at` 在心跳鮮度內才算數。compose 的 redis **沒有掛 volume**, +> `docker compose down` 之後派單池是空的(實測 `dbsize` 0、`zcard drivers:geo` 0)。 +> 所以 Postgres 裡的 `status=1` 殘留**本身不會**吃掉派單輪次; +> 2026-07-27 那次白跑,是**同一個 session 內**那些司機還在送位置心跳造成的。 + +**盤點到的真正的坑**(這個才會咬下一次的自己): +`GoOnline` 對 `status=OnTrip` 的司機**直接 return、不改狀態**,`GoOffline` 則回 +`ErrDriverOnTrip`。上次留下 **3 個卡在「載客中」的司機**(id 4 `o5-driver`、11、13)—— +下次重用這些帳號時,**App 會顯示上線成功,但派單要求 `Idle` 所以永遠收不到單,也無法離線**, +沒有任何錯誤訊息。另有 **4 張未結案訂單**(#7 已派單但無司機、#11/#14/#16 已接單) +讓 customer 3/6/9/11 一律拿到「已有進行中訂單」。 + +**清理前的盤點**(只讀):drivers 24(19 待命/3 卡載客中/2 離線)、customers 20、 +rides 27(13 完成/10 取消/**4 未結案**)、ride_events 108、ride_stops 12、 +ride_ratings 2、ride_messages 1、daily_driver_earnings 11、device_tokens 1。 + +- [x] **做法:整個砍掉重練**(使用者 2026-07-28 拍板;`ask-before-db-writes` 已遵守, + 盤點先只讀、把選項與代價列出後才動手)。`docker compose down -v` 刪掉 + `line-fleet-dispatch_postgis_data`。**動手前先核對過不會損失任何設定**: + `fleet_settings` 的每個值都等於 migration 預設(8500/2000/8500/1500/300000/ + lost_item_fee_bps 1000/pet_cleaning_fee_bps 0),admin 帳號由 app 啟動時重種。 +- [x] **驗證重建後仍是可用的 dev DB**(不只是刪掉):`docker compose up -d` → + migration 自動跑到 **000023**、admins 重種 1 筆(`admin`/superadmin)、 + `fleet_settings` 1 筆回到預設值,其餘業務表**全部 0 筆**; + `POST /api/admin/login`(admin/admin)**200 並取得 token**、 + 未帶 token 的 `GET /api/customer/fees` 正確回 **401**。 +- [x] **順手清掉兩個孤兒 volume**(使用者同意):`customer-ride-stops_postgis_data`/ + `driver-phone_postgis_data`,各 114MB、`LINKS=0`,是維護項 5 刪掉的 worktree 留下的。 + 共釋出 **228MB**。 + +**下次做 E2E 前的提醒**:這個 DB 現在是全新的,所以**沒有任何測試帳號**—— +司機/乘客都要重新註冊,司機還要走 O5 車輛審核(admin 核准)才能接單。 +若又要收尾,離開前把 `status=OnTrip` 的司機與未結案訂單處理掉, +否則下一次又會踩上面那個「上線成功卻收不到單」的無聲坑。 + +--- + ## 下次任務 -> **✅ B5 評分的模擬器實跑 E2E 已完成(2026-07-27)**,詳見上方「⭐ 乘客評分司機」。 -> 實跑抓到一個後端文案 bug(評分被拒時講遺失物協尋),已修(dispatch PR #46)—— -> 又一次印證「單元測試綠 ≠ 使用者看到的東西是對的」。 +> **✅ 維護項 5「清開發殘留」已完成(2026-07-28)**,詳見上方。 +> 清理過程又撈到一份未合併的測試(dispatch PR #50)—— +> **「從未開過 PR」的分支是最危險的一種殘留**:它不在任何 PR 列表裡, +> 只有逐條比對 diff 才看得到。 > > **➡️ 下次任務:剩下的都被外部資源卡住**,開工前先確認前置條件到位: > 1. **A2 真裝置推播**——需要你先建 Firebase 專案並提供 `google-services.json`(後端 FCM 已上線)。 @@ -499,16 +579,18 @@ admin 端 `grep -i rating` 零命中,營運方對爛司機完全無感。 > 4. **車種供給為零時的選項處理**——等產品拍板要停用、隱藏、還是照選但提示。 > > **不需前置條件、隨時可做的維護項**(2026-07-27 盤點新增): -> 5. **清開發殘留**:三個 repo 累積了十幾個**已合併卻沒刪的 worktree 與舊分支** -> (`git worktree list` 看得到)。它們會讓 `git branch -a` 難讀, -> 也讓下次開 worktree 時撞名。**條件**:純維護,不動產品程式碼。 -> 6. **清 dev DB 測試殘留**:本機 docker compose 的 DB 堆了大量前幾次 session 的 -> 測試司機與訂單——2026-07-27 的 B5 實跑就因為十幾個殘留的「線上」司機擋在派單佇列前, -> 白跑了一輪派單逾時才輪到目標司機。**條件**:會寫 DB,動手前要先問過。 +> 5. ~~**清開發殘留 worktree/舊分支**~~ ✅ **已完成(2026-07-28)**,見上方專段。 +> 6. ~~**清 dev DB 測試殘留**~~ ✅ **已完成(2026-07-28)**,見上方專段 +> (**原本寫的機制是錯的**,一併更正)。 > 7. **評分的營運動作**(B5 下游):三端現在都只「看得到」評分, > **沒有低分司機的處理流程**(通知/停權/申訴)。 > **條件**:等實際累積評分、營運說得出要對低分司機做什麼再開—— > 做在前面只會做出沒人用的流程。 +> +> **🎯 下次開工第一件事**:**維護項已經清空了**(5、6 都完成,7 要等營運需求)。 +> 第 1–4 項全部需要你提供外部資源或拍板,**沒有前置條件就不要硬找事做**—— +> 開工前先確認:Firebase 專案(A2)/iPhone+Xcode Personal Team(A5 階段 5)/ +> 金流方案(付款)/車種供給為零的產品方向。四者皆無時,正確答案是「這輪沒有可做的事」。 > **🎨 App icon(叫車系統圖示)✅ 已完成(2026-07-15,PR #15)**:品牌綠 LINE green #06C755 + 白色計程車, > 以 `flutter_launcher_icons` 產生 Android(含 adaptive icon)與 iOS 各尺寸,driver/customer 兩 flavor 共用。