thread-master/docs/product/opportunity-inbox/plan.md

283 lines
22 KiB
Markdown
Raw Normal View History

2026-08-13 02:22:24 +00:00
# Plan: 商機工作收件匣與產品需求搜尋
> Status: `approved`
> Status note: 使用者 2026-08-11「請幫我做」視為批准 plan 並要求進入實作拆解
> Source: `docs/product/opportunity-inbox/spec.md`approved 2026-08-11
> Requirements: `docs/product/opportunity-inbox/requirements.md`approved 2026-08-11
> Baseline: `docs/product/brand-product-radar/` T700T762 done
> Last updated: `2026-08-11`
## 1. 交付策略
1. **保留已完成的產品雷達底座。** Opportunity、ProductMatch、主推產品、owner來源去重、每日巡邏、mocklive repository 均原地擴充,不另建一套商機或抓取系統。
2. **先簡化操作,再擴大後端。** Phase A 只固定新增資料語意、跨層契約與舊資料映射Phase B 先用 mock 驗證單一收件匣、完成移除復原、時間排序、DemandMap 與成本確認。使用者未確認這套操作前,不進入 Phase C 大量業務後端。
3. **先把免費流程做實,再接付費判定。** ReviewState、tombstone、DemandMap baseline、前處理與輕量排序先獨立可測搜尋與 AI 深判最後才接入 CostPreview、CreditCeiling、有效判定快取及既有 usage meter。
4. **分數不互相偷換。** 既有 `intent_score``product_fit_score` 保留,新 `priority_score` 專門服務推薦排序;所有分頁排序由後端穩定執行,前端不只重排當頁。
5. **用漏斗與點數對帳驗收。** 每次巡邏必須能對上 hit → dedupe → prefilter → cache → judge → createdmergedtombstonedeferred以及 searchjudge 實際點數;部分完成不能顯示完整成功。
6. **準確度與成本同時是上線閘門。** 前十至少八筆具有真實需求與產品適配證據,且同候選同版本重試不重扣;任一未達標,先修召回、前處理、排序或冪等,不擴 P1 自動學習。
正式 tasks 每題預估約 100200 行 production change測試或文件可較小但不得把 API、repository、worker、頁面與品質閘塞成單一大題。
## 2. 里程碑
### M0 — Phase A契約、相容與測試地基
- **目標:** 固定 ReviewState、DemandMap、CostPreview、PriorityScore、Sweep funnel 的跨層 shape 與舊資料讀法;尚未完成的能力明確回 not-ready不回成功空資料。
- **完成定義:**
- 盤點並鎖定現有 OpportunityStatus、acceptdismiss、todayopportunities、ProductMatch、Sweep 與 usage 行為,建立不可退化的 baseline tests。
- 只從 `generate/api/radar.api` 擴充 review state、需求地圖、cost preview、列表 query、priorityevidence 與 Sweep funnel 契約,再執行 `make gen-api`;不手寫 handlerroutes。
- goctl 產生的新 logic 在業務尚未完成前回明確 not-ready不得回 `102000` 空物件或空陣列。
- 前端 domain types 與 RadarRepo 加入同一契約mocklive 的方法簽名一致。
- 建立舊資料 fixtureaccepted→completed、dismissed→removed(legacy_unknown)、其他→pending`sort=score|posted` 映射新排序。
- 定義 ownersourceproductinput/map versionjudge kind 的判定冪等測試鍵,但此里程碑不實作深判業務。
- **建議 task 區間:** **T800T806**
- **驗證:** spec 驗收 #1、#11、#12、#24 的契約fixture 層generated code 無手改;前後端 compilebuild。
### M1 — Phase B單一商機收件匣frontend + mock
- **目標:** 先讓第一次使用者只在一個頁面完成「看證據 → 完成或移除 → 查看/復原」;不接真 API。
- **完成定義:**
- `/app/radar/opportunities` 成為唯一商機入口,預設 pendingtodayrecommended`/app/radar/today` redirect 並保留可理解的 query。
- 導覽移除第二個商機結果入口today7dall 只作為同頁時間範圍。
- 卡片首層只顯示問題、主推產品、一段最強證據、分數時間、原文、完成、移除回覆、CRM、其他產品與完整理由放詳情層。
- mock RadarRepo 支援 pendingcompletedremoved、移除原因、復原前狀態、legacy mapping、tombstone 再命中。
- 支援 recommendednewestoldestproduct_fitdemand_intent 與穩定分頁;未知 posted_at 在 newestoldest 均置底。
- filter、sort、time scope、page 寫 URLloading、error、各種 empty reason、操作失敗 rollback 均有明確狀態。
- 完成、移除、復原的 mock 用量保持 0加入 CRM 成功後自動 completed但單純完成不建 Contact。
- **建議 task 區間:** **T810T819**
- **驗證:** spec 驗收 #1#5、#11、#12、#24頁面 keyboardmobile 走查;前端 testbuildlinttoken check。
### M2 — Phase B需求地圖、探索成本與巡邏漏斗frontend + mock
- **目標:** 在任何付費後端開發前,驗證使用者能看懂「系統準備找什麼、可能花幾點、結果為何被排除或延後」。
- **完成定義:**
- `/app/radar/watches` 或其產品詳情提供 DemandMap 五類內容、來源 basis、完整度、AIuserproduct origin 與 stale待確認狀態。
- 免費 baseline、人工新增啟停 phrase 與版本衝突用 mock 完整走通;產品只有名稱時明確 incomplete 並阻擋新巡邏。
- QueryPlan 摘要顯示 16 組使用者語言;純品牌/產品名不能單獨成查詢組。
- AI enrichment、手動 sweepexplore 與回覆按鈕在需要的位置顯示固定點數或範圍;變動成本先開 CostPreview 確認。
- mock CostPreview 覆蓋 platformBYOK、過期、版本變動、餘額不足與 ceiling 小於固定成本。
- mock Sweep 結果顯示 hit、dedupe、prefilter passreviewreject、cache、judge、createdmergedtombstone、deferred 與 credit breakdown。
- `complete / partial_budget / blocked_budget / failed` 的文案與下一步可辨識,不用成功空畫面代替。
- **建議 task 區間:** **T820T829**
- **驗證:** spec 驗收 #6、#7、#13#15、#19、#20、#22人工走查能在執行前回答最多花幾點完成後回答點數花在哪裡。
- **硬閘門:** M1M2 未取得使用者 UX 批准前,不得開始 M3M6 的業務後端。
### M3 — Phase CReviewState、軟移除與穩定列表
- **目標:** 把 Phase B 已批准的收件匣工作狀態接到可信 domain、repository 與 live API保持既有業務狀態相容。
- **完成定義:**
- Opportunity domain 加 ReviewState、previous state、移除欄位與 review auditOpportunityStatus 保留原語意。
- memoryMongo repository 實作 idempotent 狀態更新、append-only audit、duplicate target owner 驗證與 tombstone merge。
- 缺 review 欄位的舊文件讀時映射,不要求全庫回填;首次更新才持久化。
- accept 在 Contact binding 與 completed 之間維持一致成功邊界;舊 dismiss 保存 reason 或 legacy_unknown。
- list 支援 review state、time scopefrom-to、新五種 sort、priority band 與 server-side 穩定 pagination未知時間置底。
- `/today` 使用新列表語意提供相容結果;新 UI 不再依賴 today 專屬商業邏輯。
- migration索引只加入必要查詢與 audit 支援,保留 owner來源唯一性。
- **建議 task 區間:** **T830T839**
- **驗證:** domainmemoryMongo parity、owner isolation、race 與 API integrationspec 驗收 #1#5、#11、#12、#24。
### M4 — Phase CDemandMap、版本與 CostPreview
- **目標:** 以產品真相建立可追溯需求地圖,並在 provider 執行前完成成本預估、版本確認與 ceiling gate。
- **完成定義:**
- DemandMap domain 定義五類 phrase、basis、origin、enabled、inputmap version、readyincompletestale 不變量。
- baseline 只讀 BrandProduct 受眾、痛點、情境、能力、匹配與排除內容,免費建立;不得因開頁或排程自動呼叫 AI。
- input version 只對實質搜尋內容變更名稱圖片等顯示修改不改版。產品內容變更後AI phrases 失效、user phrases 標待確認。
- memoryMongo repository 支援 current map、舊版本解釋、optimistic version conflict 與 owner 隔離。
- QueryPlan 產生 16 組合法短詞與排除訊號,保存使用版本與摘要。
- CostPreview 對 enrichment、manual sweepexplore、批次判定與回覆回固定範圍、key mode、餘額、期限及依據取得 preview 不扣點。
- preview 使用時驗證 owner、action、context version、expiry、remaining credits 與 ceiling不合格時 provider 不被呼叫。
- AI enrichment 走既有 meter 與新 `radar.demand_map` source結構basis 驗證成功才切 current map 並 commit失敗保留舊 map 且不重複扣。
- **建議 task 區間:** **T840T849**
- **驗證:** spec 驗收 #6、#7、#13、#17、#20#22usage event 可與 action 對帳BYOK credits=0。
### M5 — Phase C候選前處理、推薦排序與判定快取
- **目標:** 把昂貴 AI 判定縮到真正高價值或不確定候選,並讓推薦排序比產品名/關鍵字命中更貼近產品痛點。
- **完成定義:**
- 建立可純測試的 candidate preprocessing來源正規化去重、基本有效性、產品排除、provider廣告公告雜訊、DemandEvidence 抽取、產品證據與 passreviewreject。
- 每個 rejectreview 保存 machine reason 與 Sweep counterreject 不進 AI不建立高低商機。
- 輕量 ranking 在 provider 呼叫前排序review 只可低順位或在 ceiling 內抽樣深判,不能直接進 high。
- AI judge 輸出可驗證原文 excerpt、DemandMap產品 basis、風險與 priority factors缺欄位、找不到引文或 basis 不存在即失敗。
- `priority_score=45 pain fit + 25 demand intent + 15 evidence quality + 15 freshness`,並落實 high hard gates。
- JudgmentResult 以 ownersourceproductinput/map versionkind 唯一;有效 acceptedrejected 都可復用,失敗不進快取。
- 逐筆 usage commit 與結果保存具冪等關聯;同候選跨 watchquery、HTTP 重試或 worker 重跑不重扣。
- 建立口語改寫、純名稱、同業銷售、公告、泛討論、未知時間、重複來源與真正求助的固定 fixture。
- **建議 task 區間:** **T850T859**
- **驗證:** tablefixtureAI structured outputconcurrency testsspec 驗收 #8#12、#15#18、#21、#23。
### M6 — Phase C巡邏整合、續跑、live UI 與完整點數對帳
- **目標:** 把 DemandMap、前處理、快取、深判與新收件匣接回每日手動巡邏完成真實可操作的 P0。
- **完成定義:**
- `radar_sweep` 保存 system preview、DemandMapQueryPlan 版本按搜尋→前處理→cache→judge→persist 執行。
- API search 成功 0 hit 仍按既有規則計 search前處理 reject 不計 AI有效 rejected judge 正常計 AI無效 AI 結果走失敗退點語意。
- 每完成一筆保存 guarded checkpoint中斷後只續未完成唯一鍵。Redis lock value 保持 workerID晚到 worker 不覆寫終態。
- CreditCeiling方案額度用完後停止新 provider 呼叫,保留已完成結果並寫 deferredwatch 不刪除、不封存。
- removed tombstone 再命中只合併來源Sweep 增加 tombstone count不新建、不恢復、不重判。
- Sweep API 與 UI 可對帳所有 funnel counts、status、faileddeferred reason 與 searchdemand mapjudgereply credits。
- Phase B 頁面切 live repositorymocklive contract tests 使用同一組 fixturesloading、not-ready、conflict、quota、partial、empty reason 行為一致。
- 完成跨層流程:產品資料 → DemandMap → previewceiling → sweep → prefilterjudge → 收件匣排序 → 完成/移除/復原 → usage 對帳。
- **建議 task 區間:** **T860T869**
- **驗證:** spec 驗收 #1#22、#24 的 live pathintegration、race、restart tests前後端全套 buildtest。
### M7 — Phase D品質閘、成本回歸與安全上線
- **目標:** 以代表性資料證明搜尋更貼近產品且成本可控,再收斂相容路徑、文件與既有回歸。
- **完成定義:**
- 建立人工標註集與可重跑 evaluation有效需求、口語同義、產品不適合、provider、廣告、公告、泛討論、stale、unknown time、duplicate。
- recommended 前十至少八筆同時具備 DemandEvidence 與產品證據provider公告純名稱命中不得為 high。
- 比較 baseline 關鍵字排序與新 pipeline 的 precision@10、AI judged ratio、每筆有效商機平均 credits未達品質或成本閘不宣告完成。
- 多 worker、provider retry、HTTP retry、跨 watchquery、產品僅改名與產品實質改版的防重扣回歸全部通過。
- 回歸 generic radar、ProductMatch、主推產品、回覆、CRM、Scout、Outbox、usage soft caps、BYOK、通知與舊 Opportunity。
- `/today` redirect 與舊 API 相容性保留一個版本週期;文件記錄移除條件,不在本周期直接刪 API。
- 更新 testinggaps操作說明明列 P1批次操作、每產品 ceiling、移除原因調校、產品成本報表。
-`brand-product-radar` T773T775 共用 accuracyraceregression 驗收資產tasks 階段交叉引用一次實作,不複製兩套 fixture 與指令。
- **建議 task 區間:** **T870T879**
- **驗證:** spec 驗收 #16#23、requirements 成功標準全表;全 repo testbuildlinttoken check 綠。
## 3. 依賴與硬閘門
```text
brand-product-radar T700T762已完成底座
└─► M0 Phase A 契約/相容
└─► M1 Phase B 收件匣 mock
└─► M2 Phase B DemandMap成本 mock ──【使用者 UX 批准】
├─► M3 Phase C ReviewState列表
└─► M4 Phase C DemandMapCostPreview
M3 ─┐
M4 ─┴─► M5 Phase C 前處理/排名/快取
└─► M6 Phase C sweeplive ──【P0 live 驗收】
└─► M7 Phase D 品質/成本/回歸
```
| 關係 | 原因 |
|------|------|
| baseline → M0 | 新能力沿用現有 ProductMatch、主推產品、去重與 usage不重做底座 |
| M0 → M1M2 | mock 與 UI 必須使用批准後的共用 shape、legacy mapping 與錯誤語意 |
| M1M2 → M3M6 | **硬性:** 前端mock 操作未批准,不大寫業務後端 |
| M3 ↔ M4 | 可在 UX gate 後分開進行;兩者只透過已凍結契約相遇,不互相直接依賴 repository |
| M3M4 → M5 | 前處理結果需保存到商機/判定快取,且需要 DemandMap 版本與 basis |
| M5 → M6 | worker 不可自己重寫另一套前處理、排序或計費判斷 |
| M6 → M7 | accuracy 與成本只能用真 pipeline、真 funnel 語意驗證 |
| T773T775 ↔ M7 | 舊待辦與本計畫最後閘門範圍重疊;正式 tasks 只建立一次共用輸出並同步兩邊狀態 |
## 4. 風險與緩解
| 風險 | 緩解 |
|------|------|
| ReviewState 與既有 accepteddismissed 混義 | M0 鎖 legacy mappingM1 先驗證用語M3 保持兩個狀態機獨立accept 只做明確同步 |
| 合併頁面反而塞更多資訊 | M1 首層固定七項資訊,其餘進詳情;以第一次使用者走查作 Phase B 硬閘 |
| removed 後相同貼文再次出現 | M3 tombstone 沿用 owner來源唯一鍵M6 sweep 專測再命中只 merge |
| 移除一次就污染後續搜尋 | P0 只保存原因,不立即 AI 調校P1 批次建議仍需人工確認 |
| DemandMap 成為第二份產品真相 | phrase 必須有 basisbaseline 由 Product 建立AIuser 只作可辨識擴充;產品實質變更會改版 |
| 產品改名造成重判重扣 | DemandInputVersion 排除顯示欄位M4M7 專測名稱修改不改版 |
| 廣召回造成 AI 成本暴增 | M5 先免費前處理與 cache再在 ceiling 內 shortlistM7 比較 judged ratio 與每筆有效商機成本 |
| 前處理過嚴造成完全找不到 | reject 與 review 分開review 可低順位保留或抽樣深判Sweep 保存每階段原因供抽查 |
| CostPreview 顯示假精準 | 固定成本顯示確值,候選未知顯示 min/max 與依據;版本或餘額變動即失效重估 |
| provider 成功但後續中斷造成雙扣 | M5 有效判定唯一鍵usage 關聯M6 逐筆 checkpoint重跑只續未完成鍵 |
| ceiling 競態被多 watch 突破 | owner 當日額度在 provider 前 guarded 檢查M6M7 多 worker race 測試 |
| server 與前端排序不一致 | M0 共用 enumM3 server-side stable sortmocklive contract 使用相同 fixture |
| goctl 產生空 logic 被當成功 | M0 每個新 logic 先明確 not-ready只改 `.api` 後 gen業務只在 logicmodule |
| 舊工作樹已有相關修改 | tasks 實作前逐檔比對現況,保留使用者變更;禁止用 resetcheckout 覆蓋,重疊無法安全拆分時停下回報 |
## 5. 刻意不做(本 plan 週期內)
- 不實作 P1 的批次完成/移除、每產品 CreditCeiling、移除原因自動調校與產品成本儀表板。
- 不因每次完成或移除即時呼叫 AI也不自動修改 Product、Brand 或 DemandMap。
- 不提供 Opportunity 不可逆硬刪除,不封鎖作者,不刪除來源內容。
- 不新增 usage meter、不修改 FreeStarterPro 售價,不重做 StripeBYOKprovider 抽象。
- 不重做 Threads APIcrawler、排程器、CRM、Outbox、通知或成果歸因。
- 不用 priority score 取代既有 intentproduct fit 歷史欄位。
- 不保證公開發文者有預算、身分真實或一定購買;只判斷公開需求與產品證據。
- 不在本週期移除舊 `/api/v1/radar/today` 或 dismiss API只提供相容映射與 UI redirect。
## 6. 驗證策略與指令
### 6.1 前端里程碑
```bash
cd apps/web
npm run test
npm run build
npm run lint
npm run check:tokens
```
### 6.2 API 契約或 generated code 變更
```bash
cd apps/backend
make gen-api
go test ./internal/logic/radar/... ./internal/module/radar/... -count=1
make build
```
### 6.3 Phase C 整合與競態
```bash
cd apps/backend
make test-integration
go test ./internal/module/radar/... -race -count=1
go test ./... -count=1
```
### 6.4 Migration 驗證
只使用明確的獨立測試資料庫,不對預設開發資料庫執行:
```bash
cd apps/backend
RADAR_INBOX_TEST_MONGO_URL=mongodb://127.0.0.1:27017/thread_master_opportunity_inbox_test
MONGO_URL="$RADAR_INBOX_TEST_MONGO_URL" make migrate-up
MONGO_URL="$RADAR_INBOX_TEST_MONGO_URL" make init
```
### 6.5 品質與成本閘
正式 task 需提供固定 evaluation 指令,至少輸出:
```text
precision_at_10
high_without_required_evidence
provider_or_announcement_in_high
ai_judged_ratio
credits_per_valid_opportunity
duplicate_judgment_or_charge_count
```
通過條件:`precision_at_10 >= 0.8`、兩種 high 違規數皆為 0、重複判定扣點數為 0AI judged ratio 與每筆有效商機 credits 先記 baseline再由實際成本資料決定 P1 預算優化目標,不在 P0 捏造門檻。
### 6.6 里程碑驗收摘要
| M | 額外驗收 |
|---|----------|
| M0 | 舊 fixture 可讀;新 logic 未完成不回成功空資料goctl 產出乾淨 |
| M1 | 一個頁面完成處理流程today redirect五種排序與 URL 狀態正確;操作不扣點 |
| M2 | DemandMap 與 QueryPlan 看得懂執行前知道成本範圍partialblocked 不裝完整成功;取得 UX 批准 |
| M3 | reviewbusiness state 不混tombstone 不重建memoryMongoAPI 行為一致 |
| M4 | inputmap version 正確preview 免費且會過期provider 前 ceiling gateenrichment 失敗不覆蓋 |
| M5 | provider公告純名稱不進 highreject 不問 AI有效 acceptedrejected 都能防重復用 |
| M6 | 中斷可續、budget partial 可對帳mocklive 行為一致;完整 P0 流程可展示 |
| M7 | precision@10 過 0.8high 違規 0duplicate charge 0全 repo 回歸綠 |
## 7. Task 號段總表(供下一階段拆 task
| 區間 | Phase / Milestone | 內容 |
|------|-------------------|------|
| T800T806 | A / M0 | baseline tests、goctl 契約、not-ready、FE typesrepo、legacysort fixtures、冪等鍵契約 |
| T810T819 | B / M1 | 單一入口、收件匣 layout、review mock、完成移除復原、時間排序、URLemptymobile tests |
| T820T829 | B / M2 | DemandMap mock、phrase editor、QueryPlan、CostPreview、付費確認、Sweep funnel點數、UX gate tests |
| T830T839 | C / M3 | review domainaudit、memoryMongo、migration、tombstone、acceptdismiss 相容、列表 API排序 |
| T840T849 | C / M4 | DemandMap domainrepo、版本、baselineQueryPlan、CostPreview、enrichment、meterBYOK |
| T850T859 | C / M5 | preprocessor、evidence、disposition、priority scorer、AI judge、JudgmentResult cache、冪等計點、fixtures |
| T860T869 | C / M6 | sweep pipeline、checkpointresume、budget partial、counters、live repopages、跨層 P0 integration |
| T870T879 | D / M7 | 標註集、precision成本 evaluation、raceretry、相容與全回歸、文件rollout |
正式拆 tasks 時,每題必須包含 Goal、Depends on、Inputs、Outputs實際路徑行為、Out of scope、Acceptance commands、對應 spec 驗收編號。M1M2 tasks 只能做 frontendmockM3 之後才可寫業務後端。與 `brand-product-radar` T773T775 重疊的測試輸出只能建立一份並由兩邊索引交叉引用。
## 8. 批准
- [x] Plan 已批准2026-08-11使用者
- 批准後下一步:建立 `tasks/INDEX.md` 與各 T8xx task 文件;不在同一輪開始實作。