thread-master/docs/product/scout-topic-quality/plan.md

14 KiB
Raw Blame History

Plan: 話題海巡品質、分數排序與批次分頁

Status: approved Source: docs/product/scout-topic-quality/spec.md Last updated: 2026-08-10

1. 交付策略

先以自動化案例鎖住現有的話題產詞、網址正規化與其他 Scout 模式,避免新工作覆蓋目前工作樹中的有效修正。接著遵守 Phase B → Phase C 順序,先讓前端與 mock 具備獨立 run、雙層分頁及貼文時間語意再由 goctl 產生後端契約,逐層完成 run persistence、搜尋管線與 worker 狀態。

後端不在原始候選階段截斷,而是每輪完成 canonical 去重、歷史去重與關聯性判定後才計算 target。完成結果以 run 為不可混同的邊界,由後端固定 score 排序並分頁;前端不再載入全量 posts 自行組批次。最後接上 live repository使用同一組 mock/live 契約案例、品質題組及全專案測試完成驗收。

實作期間保留目前未提交的 Scout 改動,不回復、不覆寫與本功能無關的使用者變更。所有後端 HTTP 變更一律先改 generate/api/*.api 再執行 make gen-api;生成的 handlerroutes 僅由 goctl 維護,業務實作只落在 internal/logic/**internal/module/**

2. 里程碑

M0 — 基線與可重現品質題組

  • **目標:**把目前已存在的產詞、關聯性與 shortcode 去重行為固定成回歸基線,並建立本次規格所需的代表題組與分頁 fixtures。

  • 完成定義:

    • 現有「鬼滅之刃」、「外包/後端工程師」與網址 alias 案例持續通過。
    • 加入至少 30 組人工標註題組的資料格式與首批固定 fixtures題組能標出必要概念群、直接相關與離題候選。
    • 建立 score同分時間排序 fixtures涵蓋已知時間、未知時間、相同時間與相同貼文網址別名。
    • 記錄開始實作前的 backend Scout 測試、web 單元測試與 build 結果;若既有失敗,與本工作造成的回歸分開列示。
  • 建議 task 區間: T001T004

  • 驗證:

    cd apps/backend
    go test ./internal/module/scout/... -count=1
    
    cd ../web
    npm test -- src/lib/threadsTerm.test.ts
    npm run build
    

M1 — Phase B前端 repository 契約、mock 與操作行為

  • **目標:**先在 mock 模式完成使用者能驗收的 run 清單、批次結果、時間顯示與獨立分頁,不依賴尚未存在的 live API。

  • 完成定義:

    • 前端 domain 定義 ScoutRun、不足原因與通用 page responseScoutPost 增加 run ID。
    • Scout repository 增加 listRunslistRunPostsremoveRunmock 與 live 介面形狀一致;舊 listPosts 暫時保留。
    • mock 每次執行建立新 run相同 theme 的兩次執行不合併、不搬動舊結果。
    • Scout 頁面先由新 repository 讀取批次與單批結果,不再使用全量 listPostsrunGroupspageSlice 作主路徑。
    • 批次 pager 預設 10、結果 pager 預設 8兩個頁碼獨立切換批次只重設結果頁。
    • 結果列與明細顯示貼文時間未知掃入時間另行標示score 主排序pending 不影響顯示順序。
    • 新批次完成只顯示提示,不自動切換目前選取或頁碼;刪除後頁碼收斂到有效頁。
  • 建議 task 區間: T010T018

  • 驗證:

    cd apps/web
    npm test -- src/pages/ScoutPage.test.tsx
    npm test -- src/data
    npm run lint
    npm run build
    

M2 — Phase C 契約地基goctl API 與 domain

  • **目標:**依已批准 Spec 建立 run、分頁結果與 scan response 契約,並產生可編譯的 go-zero 程式骨架。

  • 完成定義:

    • 在 Scout API 定義 ScoutRunPublic、run list、run posts page、run delete、pagination 與 run_id
    • scan response 同時含 job 與新建 run舊 posts/theme 端點保留相容。
    • domain 加入 Run、狀態、計數、不足原因與 guarded transition 所需輸入;所有時間為 UTC unix nanoseconds。
    • API 經 make gen-api 生成;不手寫 handler 或 routes。
    • 生成後 gateway、worker 及既有 Scout logic 可編譯,新增 logic 尚未實作時不得回成功空資料。
  • 建議 task 區間: T020T025

  • 驗證:

    cd apps/backend
    make gen-api
    go test ./internal/logic/scout/... ./internal/module/scout/... -count=1
    go build .
    go build ./cmd/worker
    

M3 — Run persistence、穩定查詢與 legacy 相容

  • **目標:**讓 memory 與 Mongo repository 都能保存獨立 run、穩定分頁結果及完整批次統計。

  • 完成定義:

    • repository 支援建立 run、guarded 更新狀態統計、owner-scoped run 分頁、單 run posts 分頁及終態 run 刪除。
    • run 排序固定為 created_at DESC, id DESC
    • run posts 依 score DESC;同分已知時間優先,再依 posted_at DESC, created_at DESC, id DESC
    • ownercanonical identity 維持唯一;新掃描遇到歷史貼文不覆寫其 run、時間或 outreach 狀態。
    • 批次 total、eligible 與 pending 從完整批次維護,不從目前頁推算。
    • legacy posts 以穩定 synthetic run 呈現、分頁及整組刪除;不虛構無法還原的多次執行。
    • Mongo 查詢具備符合 owner、run、時間與唯一性的索引memory 與 Mongo contract tests 使用相同案例。
  • 建議 task 區間: T030T037

  • 驗證:

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

M4 — 合格數驅動的搜尋、關聯性與原子發佈

  • **目標:**把「找得夠多」改成以合格結果計數,同時維持關聯性硬門檻與可診斷的不足原因。

  • 完成定義:

    • 候選管線拆成可測的 normalize → canonical dedupe → historical dedupe → relevance/classification → eligible 階段。
    • 話題簽章從原始 intent 與批准搜尋詞建立;泛用錨點不算主題證據,必要實體及多概念群不能被廣義詞繞過。
    • target 在每階段過濾後計算;不得在 raw hit 數達標時提前 cap。
    • 依 initial fan-out、同源加量、單一批准詞的有限 intent 擴展、既有次來源補量;達標立即停止,最多檢視 320 個原始候選。
    • 計算 searched、duplicate、irrelevant、eligible、shortfall 與原因;單一來源失敗可降級,全來源失敗則整批失敗。
    • 所有模式結果依 score 排序posted_at 僅作同分 tie-breaker軟時效只降分、不淘汰。
    • 結果先暫存為該 run 不可見集合,完整成功後才發佈;失敗 run 不暴露半套 results。
  • 建議 task 區間: T040T049

  • 驗證:

    cd apps/backend
    go test ./internal/module/scout/usecase/... -count=1
    go test ./internal/module/scout/... -run 'Target|Relevance|Dedupe|PostedAt|Run' -count=1
    

M4 補強 — 真實稽核後的召回與去重修正

首輪品質 gate 通過後,針對「實際結果仍偏少、單一核命中不夠貼題」再做一次資料流稽核:

  • 候選只有通過完整關聯性與分類門檻後才佔用 local identity低品質的先到摘要不會鎖死後續較完整摘要。
  • 自然語句意圖先抽出真正主題核,不把產生器的所有變體(外包/接案/徵人等)錯誤合併成同時必要條件。
  • activity 只有泛用錨點(例如「推薦」)時全部拒絕,不再把錨點當成主題證據。
  • 多概念批准詞的 token 不會被誤當成另一個核心的 alias只有單一批准詞才能明確授予短 alias。
  • API provider 沒有 offset 時,單一批准詞在同源加量仍重複,會依原始 intent 追加最多四組短查詢;每筆仍經同一個 topic signature gate。
  • 批次清單顯示 created_at,讓跨頁批次辨識不依賴狀態或結果數。

這些補強不降低關聯性門檻,只改善被錯誤去重與單一 query 第一頁限制造成的召回損失。

M5 — Jobworker 生命週期與進度

  • **目標:**讓 run 與 scout_scan job 一對一、狀態 guarded 且失敗可收斂。

  • 完成定義:

    • POST scan 先建立 run再排程 jobjob RefID 與 immutable payload 都帶同一 run ID。
    • 排程失敗時 run guarded 轉 failed不得留下永遠 queued 的批次。
    • worker 驗證 RefIDpayloadowner 一致後才執行,依序 guarded 更新 running、succeededfailedcancelled。
    • 進度摘要包含搜尋階段與目前 eligibletarget不記錄 token 或敏感 payload。
    • job 更新沿用既有 guarded 語意Redis lock value 維持 workerID。
    • retry 或重複 claim 不會重複發佈結果、搬動舊貼文或讓終態倒退。
  • 建議 task 區間: T050T055

  • 驗證:

    cd apps/backend
    go test ./internal/module/job/... ./internal/module/scout/... -count=1
    go test ./cmd/worker -count=1
    make test-integration
    

M6 — Live repository 串接與前後端整合

  • **目標:**讓 Phase B 已驗收的操作改用真 APImock 與 live 保持同一契約。

  • 完成定義:

    • live repository 正確送出 pagepageSize、run ID 與 filters映射 pagination、run counters、shortfall reasons、posted_at 與 created_at。
    • Scout 主頁只取得目前 run page 與目前 result page不再因 job revision 下載全部 posts。
    • 其他仍依賴舊 listPosts 的頁面維持相容並通過測試。
    • 401404409503 使用既有錯誤顯示,不將失敗轉成成功空列表。
    • live contract tests 驗證 URL、query、envelope mapping 與 unix ns 欄位;前端不以 JavaScript number 精度重新排序 ns 時間。
  • 建議 task 區間: T060T066

  • 驗證:

    cd apps/web
    npm test -- src/data/live/m5Repos.test.ts src/pages/ScoutPage.test.tsx
    npm run lint
    npm run build
    

M7 — 品質門檻、全域回歸與文件收尾

  • **目標:**以需求成功標準證明「相關、足量、按時間、可分頁、不重複」均成立。

  • 完成定義:

    • 30 組人工標註題組的 precision@10 平均至少 0.8;有足量合格候選的題組至少 90% 達成 target。
    • 規格中的 17 個 GivenWhenThen 場景都有自動化證據,或明確對應的人工驗收記錄。
    • backend 全測試、integration gate、web 全測試、lint 與 build 通過。
    • 檢查 goctl 生成差異,確認沒有手寫 handlerroutes也沒有改動 old/
    • 更新相關產品文件中的現況描述tasks INDEX 全部反映實際狀態;不把尚未達標項目標成 done。
  • 建議 task 區間: T070T075

  • 驗證:

    cd apps/backend
    make test
    make test-integration
    make build
    
    cd ../web
    npm test
    npm run lint
    npm run build
    
    cd ../..
    git diff --check
    git status --short
    

3. 依賴

M0 → M1 → M2 → M3 → M4 → M5 → M6 → M7
           └──────────────→ M6
  • M0 先建立保護網,所有後續里程碑都依賴它。
  • M1 先固定 Phase B 操作與 mock 契約M2 的 API 形狀必須與其一致。
  • M3 提供 M4 的歷史去重、暫存/發佈與分頁能力。
  • M4 完成後M5 才能正確把搜尋統計與終態寫回 run。
  • M6 同時依賴 M2 的 API 契約與 M5 的完整 live 行為。
  • M7 只能在所有前後端路徑接通後開始宣告成功標準。

4. 風險與緩解

風險 緩解
目前工作樹已有未提交的 Scout 修正,生成或重構時可能被覆蓋 M0 先記錄基線;每個 task 只碰輸出範圍,執行 goctl 後逐檔檢查差異,不回復使用者既有變更。
theme_key 曾同時扮演話題與批次,舊資料無法還原每次執行 新資料強制 run ID舊資料只建立一個穩定 synthetic run不虛構歷史。
ownercanonical identity 唯一規則可能與既有 permalink IDupsert 行為衝突 persistence contract tests 先覆蓋「新 run 不覆寫舊 post」在搜尋階段查 seen identity保存端再以唯一約束防競爭。
多文件結果寫入中途失敗會暴露半套批次 以 run 可見狀態隔離暫存結果;列表只讀成功發佈的 membership失敗路徑清理或保留不可見資料供重試。
offset pagination 遇到背景新增資料會漂移 完成 run 的 membership 與排序鍵固定;批次列表不自動刷新,提示使用者主動回到最新頁。
unix nanoseconds 超過 JavaScript safe integer前端重排可能不穩 score同分時間排序在後端完成使用唯一 ID 決勝;前端只格式化與顯示,不再按 ns 數值重排分頁結果。
高關聯門檻使窄題目無法湊足 target 三階段有限補量並呈現 shortfall品質門檻優先不降低核心概念要求。
人工題組過度貼合既有範例 30 組涵蓋不同領域並分離固定回歸 fixture 與驗收 fixture避免只對兩個已知查詢最佳化。
新 run API 破壞 Today 或其他舊呼叫者 保留舊 posts endpoint 與 repository 方法直到相依頁面另有批准的遷移計畫M6 明確跑全前端測試。
goctl 生成大量無關差異 固定使用專案內 goctl home 與 make target生成後只接受契約導致的差異業務不寫 handlerroutes。

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

  • 不改造 Radar 商機判定、CRM 狀態或 Radar 列表。
  • 不新增第三個外部搜尋/爬取來源。
  • 不降低主題關聯性門檻來湊 target也不做無限補抓。
  • 不自動發送 Threads 回覆。
  • 不刪除所有歷史 Mongo 重複資料;只確保讀取與新寫入不再重複呈現。
  • 不移除舊 GET /scout/posts 或強迫其他頁面同時遷移。
  • 不重新設計 Harbor Desk 全站視覺或導覽。
  • 不在本週期加入個人化學習、互動量趨勢或跨批次分析。

6. 全域驗證指令

cd apps/backend
make gen-api
make test
make test-integration
make build

cd ../web
npm test
npm run lint
npm run build

cd ../..
git diff --check
git status --short

需要 Mongo 行為的 repository contract 以可控 test database既有測試容器執行外部搜尋來源一律使用 fake provider不以真實 provider token 或不穩定網路作為 CI 成功條件。

7. 批准

  • Plan 已批准2026-08-09使用者