thread-master/docs/product/brand-product-radar/plan.md

18 KiB
Raw Permalink Blame History

Plan: 品牌 × 產品商機雷達

Status: approved
Status note: 使用者 2026-08-10「批准」
Source: docs/product/brand-product-radar/spec.mdapproved 2026-08-10
Requirements: docs/product/brand-product-radar/requirements.mdapproved 2026-08-10
Parent capability: docs/product/demand-radar/58/58 tasks 已完成)
Last updated: 2026-08-10

1. 交付策略

  1. 先保住既有雷達。 新欄位與新行為全部向後相容;舊 RadarWatch 讀作 generic、舊 Opportunity 顯示未指定產品。P0 不做猜測回填,也不先改掉既有去重唯一性。
  2. 嚴格遵守 A → B → C → D。 Phase A 只鋪契約、索引與相容測試Phase B 先以 mock 把選產品、證據、多產品去重、全部結果與主推產品操作走通mock 驗收通過後才寫 Phase C 真 API 業務Phase D 再把產品歸屬帶進回覆、CRM、成交與品質校準。
  3. 先驗證互動,再擴後端。 多產品合併後的卡片資訊量最大,也是最容易做錯的地方。前端必須先證明使用者能回答「這個人適合哪個產品、為什麼、是否值得現在聯絡」。
  4. 擴充既有實體,不平行建系統。 RadarWatch、Opportunity、RadarSweep、Contact、OutcomeEvent 都原地擴充;同 ownerexternal identity 的 Opportunity 唯一語意不變。
  5. 判定與持久化分層。 先完成可純測試的產品適配規則,再接 AIAI 不可用時仍須輸出完整四維理由,否則整筆 match 失敗,不回空成功。
  6. 準確度是上線閘門。 P0 live 串接後,以代表性真實樣本檢查前十筆至少八筆同時具備需求與產品適配證據;未達標只回到召回/判定調校,不先擴 P1。

所有 task 預估以 100200 行生產碼變更為主;較大能力在 tasks 階段再拆,避免一題同時跨契約、後端、前端與測試。

2. 里程碑

M0 — Phase A契約、相容與資料地基

  • 目標: 先讓跨層型別、API 契約、索引方向與舊資料讀法固定,尚未完成的業務明確回未就緒,不產生成功空資料。
  • 完成定義:
    • generate/api/*.api 原地擴充 RadarWatch、Opportunity、ProductMatch、Sweep counters、產品篩選與主推產品操作再執行 make gen-api;不手寫 handlerroutes。
    • 新增 BrandProduct 關聯與 ProductMatch 查詢所需 migration保留 ownerexternal identity 唯一索引,先以測試資料確認多產品不會產生第二筆 Opportunity。
    • 前端 domain types、Radar repository 介面與錯誤型別對齊 specmocklive 共用同一介面。
    • 建立舊 watch舊 opportunity 相容 fixture缺新欄位時分別讀為 generic未指定產品。
    • 新 API 尚未實作時回既有明確 not-ready error不得讓 goctl 產生的空 logic 回 102000。
  • 建議 task 區間: T700T706
  • 驗證: make gen-api、後端 compile、前端 type/buildspec 驗收 #1、#10、#13 的契約層案例。

M1 — Phase B產品型雷達設定frontend + mock

  • 目標: 不接真 API先完成「選 Brand → 選 Product → 看資料完整度 → 取得需求詞 → 建立產品型 watch」操作。
  • 完成定義:
    • 新增具狀態的 mock Radar repository可建立 productgeneric watch、一次性補綁、pauseresumearchive並模擬 ownership、關聯錯誤與 product unavailable。
    • /app/radar/watches 加 BrandProduct 串接選擇、產品內容完整度、includeexclude 建議依據、短詞驗證與名稱快照。
    • 新 UI 不提供 generic 新建入口;既有 generic 卡片顯示「補上產品」,補綁後不可更換。
    • product watch 不被 ServiceProfile 必填卡住generic watch 維持原門檻。
    • /app/brands 刪 Product 前,顯示受影響 watch 數量與「將暫停、不刪歷史」的結果。
    • mock contract test 與頁面互動測試覆蓋成功、空品牌、錯誤品牌關係、產品失效及舊資料。
  • 建議 task 區間: T710T718
  • 驗證: spec 驗收 #1、#7、#9、#10、#13 的 mock 場景;前端 buildtestlinttoken check。

M2 — Phase B商機證據、去重與全部結果frontend + mock

  • 目標: 用足量 mock 資料確認「一張商機卡+多個產品匹配+一個主推產品」真的看得懂,並容納較舊與低適配結果。
  • 完成定義:
    • /app/radar/today 加 BrandProductfit band 篩選;卡片顯示主推產品、商機分、產品適配分、需求證據、風險與其他匹配數。
    • 四維 ProductFitReason 可展開;產品篩選時優先展示該產品證據,但不暗中改 PrimaryProduct。
    • 支援自動主推與人工主推 mock人工指定後新出現的更高分 match 不覆蓋。
    • 新增 /app/radar/opportunities 全部結果:可看 staleweakexcluded未指定產品預設分數排序。
    • Exploremanual import 面板先選 BrandProductmock 統計分清新商機、合併 match 與截斷。
    • CRM 卡片/時間軸與商機回覆面板能顯示產品歸屬;尚不改真 CRM 行為。
    • 至少準備同貼文雙產品、20 天舊文、高分但 excluded、無品牌名但痛點吻合、純產品名命中、舊 generic 六組 fixture。
  • 建議 task 區間: T720T729
  • 驗證: spec 驗收 #2#6、#8、#11、#14 的 mock 場景;人工 UX 走查可在三分鐘內回答產品與證據。
  • 硬閘門: M2 未經使用者確認操作與資訊密度前,不得進 M3 大寫業務後端

M3 — Phase C後端領域與持久化

  • 目標: 建立 product watch、ProductMatch、PrimaryProduct 與舊資料相容的可信領域模型及 repository 行為。
  • 完成定義:
    • RadarWatch 加 context mode、BrandProduct IDs、名稱快照、綁定時間與 pause reason驗證 genericproduct 不變量。
    • Opportunity 加 ProductMatch 集合、PrimaryProduct 與人工 overridematched_service 保留給 generic舊資料。
    • memoryMongo repository 支援產品篩選、穩定排序、同 ProductMatch 合併 watchterm以及主推產品 guarded 更新。
    • 既有 ownerexternal identity 唯一鍵保留;同 ProductMatch 在競態下不得重複。
    • BrandProduct owner 與父子關係由後端重新驗證,不信任 request IDs。
    • 舊文件不需批次回填即可正常 listdetailCRM 使用。
  • 建議 task 區間: T730T739
  • 驗證: domainrepository 單元測試spec 驗收 #1、#4#7、#10、#12、#13。

M4 — Phase C產品上下文、適配判定與原子去重

  • 目標: 把 BrandProduct 真相接入建議詞與判定,並在多 watch多 worker 下正確合併 ProductMatch。
  • 完成定義:
    • 共用產品上下文讀取器產 snapshot來源無效時回明確原因不跨 owner、不自動改綁。
    • 關鍵字建議以品牌受眾、產品痛點、情境、標籤、能力與排除詞產生,回 basis仍通過 Threads 短詞規則。
    • 產品適配判定完整輸出 pain 35scenario 25audience 20capability 20、四維理由、公開 excerpt、product basis、risks 與 exclude reason。
    • eligiblestrongpossibleweak 規則與主推產品自動選擇固定;人工 override 後不自動換主推。
    • 新貼文建立 OpportunityProductMatch既有貼文新產品只新增 match同產品再命中只合併來源且不重複計費。
    • stale 仍保存產品證據但不進今日;產品名單純命中不可成為 eligible。
    • AI 不可用時的規則降級仍需四維完整;不完整結果不持久化並記失敗。
  • 建議 task 區間: T740T749
  • 驗證: scorer table tests、AI structured-output tests、repository concurrency testsspec 驗收 #2#8、#12。

M5 — Phase C每日立即巡、查詢與產品生命週期 API

  • 目標: 將 M3M4 接回每日巡、立即探索、手動匯入、today全部結果與 Product 刪除,形成完整真 API。
  • 完成定義:
    • radar_sweep 每次重新驗證 BrandProduct無效時 guarded 暫停 watch、通知並記原因不建立成功空 Sweep。
    • 每日、首巡、立即探索、手動匯入共用同一 ProductMatch merge只有新 Opportunity 占每日筆數,新增 match 不被配額誤算成新卡。
    • today 支援 BrandProductfit band全部結果支援 staleweakexcludedgeneric 與指定排序filtered product 使用自己的 match 作展示/次排序。
    • 主推產品 API 驗證 match、eligibleoverride reason、owner 並留 audit。
    • Sweep 回報 match evaluatedmergedfit rejectedExplore 回報 createdmergedtruncated數量語意不混淆。
    • 刪 Product 前冪等暫停相關 active watch任何步驟失敗不得回刪除成功歷史保留。
    • product_unavailable watch 不可直接 resume可複製設定建立新產品 watch。
  • 建議 task 區間: T750T759
  • 驗證: radarscout logic integration testsspec 驗收 #4、#8#13失敗路徑確認非 102000 空資料。

M6 — Phase Clive repository 接線與 P0 真實閉環

  • 目標: 用 live repository 替換 Phase B mock 資料,保持畫面與錯誤行為一致,完成可操作的 P0。
  • 完成定義:
    • Radar live mapper 支援所有新增欄位、filters、assign product、primary product、exploreimport counters缺選用欄位不丟失舊資料。
    • M1M2 頁面切到 live 後操作與 mock 一致loading、not-ready、forbidden、product unavailable、no eligible match 狀態均有明確 UI。
    • /app/radar/opportunities 與 today 的 URL filter返回狀態穩定重新整理不改查詢意圖。
    • Product 刪除後 watch 頁立即反映 pause reason舊 Opportunity 仍顯示快照名稱。
    • 完成跨層 integration建產品 watch → 巡邏 → 同貼文合併兩 ProductMatch → 改主推 → today全部結果正確。
  • 建議 task 區間: T760T769
  • 驗證: backend integrationfrontend repository contractpage testsspec §9 #1#13 全路徑,前後端 build 綠。

M7 — Phase D回覆CRM 歸屬、品質閘與回歸

  • 目標: 把產品上下文帶完整個成交閉環,驗證準確度、併發、成本與既有功能沒有退化。
  • 完成定義:
    • 新回覆使用 PrimaryProduct snapshot正確 Brand選用 ServiceProfile 限制;已送出回覆不隨主推產品修改。
    • ContactTouch 保存接觸當下 BrandProduct同一 Contact 可有不同產品;舊 touch 相容。
    • 成交 OutcomeEvent 保存成交當下 product_id舊 outcome 可空;不新增成交帳與自動成交判定。
    • 建立代表性人工樣本集,記錄需求證據、產品適配與誤判原因;高排名前十至少八筆合格才通過。
    • 多 worker重試測試證明單 Opportunity、單 ProductMatch、不重複 AI 計費Sweep counters 可對帳。
    • 回歸 generic radar、Scout 三模式、Outbox、AccountHealth、CRM、成果歸因、方案配額與舊資料。
    • 更新 testinggaps 文件,明列 P1 回饋學習、產品轉換統計與 P2 多產品 watch 未做。
  • 建議 task 區間: T770T779
  • 驗證: spec 驗收 #4、#12、#14成功標準全表全 repo backendfrontend tests、build、lint、token check。

3. 依賴與硬閘門

M0 Phase A 契約地基
 └─► M1 Phase B watch mock
      └─► M2 Phase B results mock ──【使用者 UX 批准】
           └─► M3 Phase C domain/repository
                └─► M4 Phase C product fit/merge
                     └─► M5 Phase C pipeline/API
                          └─► M6 Phase C live UI ──【P0 live 驗收】
                               └─► M7 Phase D CRM/品質/回歸
關係 原因
M0 → M1 mock 必須依批准後的共用型別與錯誤契約,不自行發明另一套 shape
M1 → M2 結果 fixture 必須來自可選定的 BrandProduct 與 watch 上下文
M2 → M3 硬性: 前端mock 操作未通過,不大寫業務後端
M3 → M4 適配判定需要可原子保存、合併與查詢的 ProductMatch 模型
M4 → M5 每日/立即巡必須共用已驗證的 fit 與 merge不在 handler 重寫判定
M5 → M6 live 前端需有完整 todaylistprimarylifecycle API
M6 → M7 CRM 與回覆深化建立在已可操作的 P0 商機閉環上
M5 → Product CRUD 刪 Product 的 watch 暫停副作用需要 RadarWatch repository 能力
M7 → 既有 OutcomeEvent 只加產品歸屬,不新增成交資料來源

4. 風險與緩解

風險 緩解
多產品卡片資訊過載 M2 先以 mock 驗證;卡片只露一段主要證據,四維與其他產品按需展開;未通過 UX 閘不進後端
同貼文競態產生重複 ProductMatch 保留 Opportunity 唯一鍵M3 repository 定義原子 merge 與 guarded primaryM4M7 加多 worker 測試
ProductMatch 陣列查詢/排序變慢 M0 先驗證索引與代表性資料 explain列表只回分頁必要的主要產品欄位獨立保存不在 request 逐筆掃全品牌
Product 更新後歷史漂移 match 保存名稱與版本快照;舊 match 不重算;新 Opportunity 才讀最新版
Product 刪除只做一半 採可重試的「先暫停 watch再刪 Product」部分失敗不回成功重試不重複副作用
跨 owner ID 洩漏 每個入口都從 JWT owner 重查 BrandProduct錯誤不回對方名稱M3/M5 有越權 integration test
AI 用關鍵字腦補成受眾 正分必須有公開 excerpt 與 product basis未知受眾給 0禁止敏感屬性推測
搜尋量變多但品質變差 搜尋詞只負責召回eligible 必須有痛點情境證據M7 用前十至少八筆的人工樣本閘門
stale 全被丟掉又「完全找不到」 stale 保存並進全部結果,今日頁維持及時性;空狀態連到全部結果
每日上限導致既有貼文無法補 ProductMatch 配額只限制新 Opportunity既有卡片新增 match 仍可處理AI 點數 gate 另算
goctl 產出空 logic 被誤當成功 M0 每個新增能力先回明確 not-ready業務只落 internal/logic/**internal/module/**,不手寫 handlerroutes
Phase B mock 與 live 漂移 同一 repository interfacecontract testsM6 同一組 fixture 對 mocklive mapper 驗證

5. 刻意不做(本 plan 週期內)

  • Requirements P1用適合不適合、CRM 行為自動調整產品詞權重。
  • Requirements P1產品維度漏斗、成交率金額比較與自動調校建議。
  • Requirements P2一個 watch 同時服務多個產品、產品專屬理想使用者欄位、跨來源擴張。
  • 批次猜測舊 watchopportunity 的 BrandProduct 關聯。
  • 因 Product 更新而批次重算舊商機。
  • 自動留言、私訊、自動改主推產品的人工 override、自動成交。
  • 重做 BrandProduct 編輯器、Radar 排程、Threads 抓取、CRM 狀態機、計費或 AI provider 抽象。
  • 新增 usage meter產品適配沿用 ai_researchsource=radar.product_fit

6. 驗證策略與指令

6.1 每個 milestone 都要跑

cd apps/backend
go test ./internal/module/radar/... ./internal/module/scout/... ./internal/logic/radar/ -count=1

cd apps/web
npm run test
npm run build
npm run lint
npm run check:tokens

6.2 契約或 API 變更後

cd apps/backend
make gen-api
go test ./... -count=1
make build

6.3 Phase CD 整合閘

cd apps/backend
make test-integration
go test ./internal/module/radar/... -race -count=1

cd apps/web
npm run test -- RadarWatchesPage RadarTodayPage

6.4 Migration 驗證

只對獨立測試資料庫執行,不使用預設開發資料庫:

cd apps/backend
RADAR_TEST_MONGO_URL=mongodb://127.0.0.1:27017/thread_master_brand_product_test
MONGO_URL="$RADAR_TEST_MONGO_URL" make migrate-up
MONGO_URL="$RADAR_TEST_MONGO_URL" make init

6.5 里程碑驗收摘要

M 額外驗收
M0 舊 fixture 無新欄位仍可解碼;新增未實作 API 不回 102000 空資料migration 可重複初始化
M1 product watch 不需 ServiceProfilegeneric 仍維持舊門檻;錯誤產品關係在 mock 明確失敗
M2 同貼文雙產品只一張卡filter 展示指定產品但不改 primarystale 可在全部結果找到;完成 UX 批准
M3 memoryMongo 行為相同;競態只有一筆 Opportunity 與一個同產品 match舊資料不回填也可用
M4 四維理由完整;純產品名命中不 eligible同產品重命中不重判重計費
M5 每日exploreimport 數量可對帳Product 刪除暫停 watch失敗不空成功
M6 mock 與 live 主要行為一致;跨層 P0 流程可展示spec #1#13 全過
M7 前十至少八筆合格回覆ContactTouchOutcomeEvent 產品歸屬正確;全回歸綠

7. Task 號段總表(供下一階段拆 task

區間 Phase / Milestone 內容
T700T706 A / M0 goctl 契約、migration索引、FE typesrepo、舊資料 fixture、not-ready guard
T710T718 B / M1 mock Radar repo、BrandProduct 選擇、完整度、建議詞、generic 補綁、刪除影響 UI
T720T729 B / M2 today 產品卡、四維證據、多產品primary、全部結果、exploreimport、CRM 標示、UX tests
T730T739 C / M3 WatchOpportunityProductMatch domain、memoryMongo repository、ownership、相容讀取
T740T749 C / M4 context snapshot、建議詞、fit scorer、AIfallback、atomic merge、primary arbitration、stale
T750T759 C / M5 sweepexploreimport、todaylist filters、primary API、counters、Product delete pause
T760T769 C / M6 live repositorymapper、頁面接線、錯誤狀態、跨層 integration、P0 live 驗收
T770T779 D / M7 reply、ContactTouch、OutcomeEvent 產品歸屬、準確度、race成本、回歸與缺口文件

正式拆 tasks 時,每一題都必須包含 Goal、Depends on、Inputs、Outputs實際路徑行為、Out of scope、Acceptance commands、對應 spec 驗收編號;不得把整個 milestone 塞成一題。

8. 批准

  • Plan 已批准2026-08-10使用者「批准」