# Tasks INDEX — demand-radar

> Plan：`../plan.md`（**approved** 2026-07-31）  
> Spec：`../spec.md` §9（SP／RW／SW／OP／TD／RP／CR／FU／ST／QT／PR／RG）  
> 後端根：`apps/backend`（goctl）· 前端根：`apps/web`  
> Status：**approved**（2026-07-31 使用者「好」）· phase=`ready-to-implement`  
> Updated：2026-07-31 · 58/58 done（M0–M6 完成）

## 範圍硬規則

| 規則 | 內容 |
|------|------|
| 加值層 | 既有海巡三模式／抓取雙路徑／Outbox／付費流程**原樣保留**；新 group、新 collection 並存 |
| 橋接單向 | scout → opportunity 只做**複製＋反向連結**，狀態機不共用 |
| 不新增 meter | 沿用四個既有 meter＋`radar.*` source 標籤（RG-04） |
| 成交 | 只有人可回報；寫既有 `growth_outcomes`（`source_type=radar_opportunity`），不另建帳 |
| 送出 | 公開留言必經既有 AccountHealth 送出閘；私訊 P0 只能複製，UI 不得宣稱自動送出 |
| 判定契約 | `reasons[]` 五條齊全否則不入庫；band 門檻 80／50 鎖定，只調權重與 prompt |
| 配額 | `max_active_watches`／`max_daily_opportunities`；達上限為**截斷非錯誤** |
| 命名紅線 | 全域禁用 `lead` 指稱銷售線索（RG-05） |
| 樣式 | 新頁樣式只進 `src/styles/radar.css`，`npm run check:tokens` 為必跑閘 |
| 契約 | goctl `.api` → `make gen-api`；業務只寫 `internal/logic/**`、`internal/module/**`；envelope 102000；時間 ns UTC；**禁止未實作回空成功** |

## INDEX

| ID | Title | M | Kind | Status | Est |
|----|-------|---|------|--------|-----|
| T500 | api shells radar crm goctl | M0 | feat | done | ~180 |
| T501 | mongo indexes radar crm | M0 | feat | done | ~120 |
| T502 | fe domain types and repo interfaces | M0 | feat | done | ~180 |
| T503 | fe radar css shell token guard | M0 | chore | done | ~60 |
| T510 | service profile model repository | M1 | feat | done | ~170 |
| T511 | service profile api get put | M1 | feat | done | ~160 |
| T512 | radar watch model repository | M1 | feat | done | ~180 |
| T513 | radar watch api crud quota gate | M1 | feat | done | ~200 |
| T514 | watch keyword suggest ai | M1 | feat | done | ~160 |
| T515 | fe service profile tab brands | M1 | feat | done | ~180 |
| T516 | fe radar watches page | M1 | feat | done | ~200 |
| T517 | test m1 profile watch quota | M1 | test | done | ~180 |
| T525 | opportunity model repository | M2 | feat | done | ~190 |
| T526 | radar sweep model repository | M2 | feat | done | ~140 |
| T527 | job radar sweep template daily schedule | M2 | feat | done | ~190 |
| T528 | sweep fetch reuse dual path | M2 | feat | done | ~170 |
| T529 | five question judge scorer | M2 | feat | done | ~200 |
| T530 | judge persist reject reasons dedupe | M2 | feat | done | ~170 |
| T531 | daily quota truncation and metering | M2 | feat | done | ~160 |
| T532 | sweep failure notify and resume | M2 | feat | done | ~160 |
| T533 | sweeps list and manual trigger api | M2 | feat | done | ~150 |
| T534 | test m2 sweep judge integration | M2 | test | done | ~200 |
| T535 | judge accuracy sampling gate | M2 | docs | done | ~120 |
| T545 | today api stats and empty reasons | M3 | feat | done | ~180 |
| T546 | opportunities list detail api | M3 | feat | done | ~170 |
| T547 | opportunity accept dismiss override api | M3 | feat | done | ~160 |
| T548 | reply variant model repository | M3 | feat | done | ~130 |
| T549 | reply generation forbidden filter | M3 | feat | done | ~200 |
| T550 | reply send outbox health gate | M3 | feat | done | ~180 |
| T551 | fe radar today page | M3 | feat | done | ~200 |
| T552 | fe opportunity actions and reply panel | M3 | feat | done | ~200 |
| T553 | fe sidebar ia and today summary | M3 | feat | done | ~150 |
| T554 | test m3 today reply integration | M3 | test | done | ~200 |
| T565 | contact model repository unique key | M4 | feat | done | ~180 |
| T566 | contact touch model timeline repo | M4 | feat | done | ~140 |
| T567 | accept binds or creates contact | M4 | feat | done | ~150 |
| T568 | contact stage transition engine | M4 | feat | done | ~170 |
| T569 | contacts list api filters sort | M4 | feat | done | ~160 |
| T570 | contact detail notes followup flag api | M4 | feat | done | ~170 |
| T571 | contact merge unmerge owner guard | M4 | feat | done | ~180 |
| T572 | conversion report writes growth outcomes | M4 | feat | done | ~180 |
| T573 | conversion amend delete audit | M4 | feat | done | ~150 |
| T574 | fe crm contact work list | M4 | feat | done | ~200 |
| T575 | fe contact detail timeline conversion | M4 | feat | done | ~200 |
| T576 | test m4 crm conversion integration | M4 | test | done | ~200 |
| T585 | followup model repository and hooks | M5 | feat | done | ~170 |
| T586 | job radar followup scan and notify | M5 | feat | done | ~180 |
| T587 | followup api list done snooze escalate | M5 | feat | done | ~170 |
| T588 | ai followup message generation | M5 | feat | done | ~140 |
| T589 | crm stats api three dimensions | M5 | feat | done | ~200 |
| T590 | usage radar source aggregation | M5 | feat | done | ~140 |
| T591 | fe followup inbox and stats | M5 | feat | done | ~200 |
| T592 | test m5 followup stats integration | M5 | test | done | ~180 |
| T600 | scout promote to opportunity | M6 | feat | done | ~170 |
| T601 | fe scout promote action | M6 | feat | done | ~100 |
| T602 | integration test matrix spec9 | M6 | test | done | ~200 |
| T603 | regression scout outbox outcomes naming | M6 | test | done | ~180 |
| T604 | docs testing and gaps | M6 | docs | done | ~120 |

**合計：58 tasks**（feat 48 · test 7 · docs 2 · chore 1）

## 建議實作順序

```text
T500 → T501 → T502 → T503
  → T510 → T511 → T512 → T513 → T514 → T515 → T516 → T517
  → T525 → T526 → T527 → T528 → T529 → T530 → T531 → T532 → T533 → T534 → T535
  ──【判定準確度閘門：T535 結論為「可進 M3」才往下】
  → T545 → T546 → T547 → T548 → T549 → T550 → T551 → T552 → T553 → T554
  → T565 → T566 → T567 → T568 → T569 → T570 → T571 → T572 → T573 → T574 → T575 → T576
  → T585 → T586 → T587 → T588 → T589 → T590 → T591 → T592
  → T600 → T601 → T602 → T603 → T604
```

可並行的組合（同 M 內無互相依賴）：

| 組合 | 說明 |
|------|------|
| T501 ‖ T500 ‖ T503 | M0 三條互不相依 |
| T510＋T511 ‖ T512 | 服務檔案與 watch 模型可並行，到 T513 收斂 |
| T526 ‖ T525 | sweep 與 opportunity 模型可並行 |
| T548 ‖ T545／T546 | 回覆模型與今日頁 API 可並行 |
| T565＋T566 ‖ T569 | Contact 模型與列表查詢可並行 |
| T515 ‖ T516 | 前端兩頁可分頭做（皆需 T502／T503） |

## spec §9 覆蓋對照

| 群組 | 覆蓋 task |
|------|-----------|
| SP-01～02 | T511、T513、T517 |
| RW-01～04 | T513、T514、T516、T517 |
| SW-01～06 | T527、T528、T530、T531、T532、T534 |
| OP-01～07 | T525、T529、T530、T547、T534 |
| TD-01～02 | T545、T551、T554 |
| RP-01～05 | T548、T549、T550、T552、T554 |
| CR-01～09 | T565～T573、T575、T576 |
| FU-01～04 | T585、T586、T587、T588、T592 |
| ST-01～03 | T589、T591、T592 |
| QT-01～03 | T531、T590、T534、T592 |
| PR-01～02 | T600、T601 |
| RG-01～05 | T528、T550、T572、T590、T603 |

## 里程碑結案

### M0（地基）— 2026-07-31

`.api` 殼＋mongo 索引＋前端型別／repo 介面／`radar.css`。未實作能力一律回 `501010`，前端 live 直接把它丟成 `ApiError`，不做空清單降級。

### M1（服務檔案與雷達訂閱）— 2026-07-31

- 後端：`ServiceProfile`（每會員一份，`exists` 區分「沒建」與「建了空的」）、`RadarWatch` 狀態機（active／paused／archived，archived 為終點）、配額閘（`max_active_watches`，既有超額者不強制降級）、AI 關鍵字建議（`ai_copy`／`radar.suggest`，失敗退點）。
- 前端：`/app/policy` 獨立服務 Policy（由原品牌頁分頁遷出）、`/app/radar/watches` 訂閱管理＋建議面板。
- 驗收：SP-01、SP-02、RW-01～RW-04 各一個具名 case（`internal/logic/radar/m1_integration_test.go`），已納入 `make test-integration`。
- 跑過：`go test ./... -count=1`、`make test-integration`、`cd apps/web && npm run build && npm run check:tokens && npm run test && npm run lint`。

M1 沒有做（依 plan 排在後面）：sweep／判定／商機／回覆／CRM，以及手動觸發即時巡的 UI（T533／T552）。

### M2–M6 — completed 2026-07-31

- T525：`Opportunity` domain＋memory／mongo repo；`UpsertByExternalID` 去重併 term；`reasons[]` 五維度契約；band 80／50。
- T526：`RadarSweep` domain＋memory／mongo repo；計數累加、`judged_external_ids` 去重、GetByJobID。
- T527：`TemplateRadarSweep`、UTC 22:00 每日排程、worker maintenance lock 下建 Job、執行殼層（抓取待 T528）。
- 下一個：T528 抓取雙路徑複用。

## 閘門

- [x] tasks 批准（2026-07-31）→ phase=`ready-to-implement`
- 實作時**指定 T###** 才寫碼；一次一題（建議從 **T500** 起）
- **M2 → M3 硬閘門**：T535 抽驗報告結論須為「可進 M3」，否則回 T529 調權重／prompt 後重測
