# Brand × Product Radar — P0 live acceptance

> 執行日：2026-08-10 · scope：Phase C（T730–T762）
>
> 本文件只記錄可重跑的 fake-source 驗收，不使用 Threads 網路、真 AI provider 或私密 token。

## Gate command

```bash
cd apps/backend
make test-integration
go test ./... -count=1
make build

cd ../web
npm run test -- --run
npm run build
npm run lint
npm run check:tokens
```

## Cross-layer flow

`apps/backend/internal/logic/radar/brand_product_integration_test.go` 驗證：

1. owner 擁有的 Brand + 兩個 Product 建立兩組 active product watches。
2. fake crawler 對兩組 watch 回傳同一個 Threads external identity。
3. 同一 Opportunity 合併兩個 ProductMatch，不新增第二張卡。
4. 適配分數自動選主推產品；人工 override 後保持指定產品。
5. `ListOpportunities` 的 product／eligible／score filter 與 `GetTodayFiltered` 可找到同一張卡。
6. Accept 經 fake CRM 只建立一個 contact identity。
7. 沒有 ProductMatch 的 legacy row 仍可用 `match_state=generic` 查詢。
8. product delete lifecycle 的 Radar side 會保留歷史並將 watch pause，原因為 `product_unavailable`。

`apps/web/src/pages/ProductRadarLiveFlow.test.tsx` 驗證：

- URL 上的 brand/product/fit filters 傳入 live-shaped `RadarRepo.getToday`。
- 一張卡顯示主推產品、另一個匹配與證據入口，人工主推呼叫帶 reason。
- live API error 保留錯誤 banner，不轉成「0 筆」或空狀態成功。

## Spec coverage

| Spec case | 自動驗收／既有測試 | 結果 |
|---|---|---|
| #1 合法 Brand／Product | P0 flow create watch；`product_context_test` ownership/parent guard | PASS |
| #2 痛點而非品牌名 | `product_fit_test`／`product_fit_ai_test` evidence validation | PASS |
| #3 同名不 eligible | `product_fit_test` name-only guard | PASS |
| #4 同貼文多產品單卡 | P0 flow same external identity → 2 matches | PASS |
| #5 自動主推 | P0 flow automatic arbitration assertion | PASS |
| #6 人工主推不被覆蓋 | `primary_product_test` + P0 override assertion | PASS |
| #7 更新不改舊證據 | `product_fit_integration_test` snapshot preservation | PASS |
| #8 stale 只在全部結果 | `today_product_test`／`product_fit_integration_test` | PASS |
| #9 刪產品暫停 watch | `product_lifecycle_test` + P0 pause assertion | PASS |
| #10 舊資料相容 | P0 generic legacy row + T703/T734 fixtures | PASS |
| #11 no eligible 空狀態 | `today_product_test` | PASS |
| #12 worker 競態去重 | `product_match_race_test`／`product_match_test` | PASS（race profile 受環境 gcc 限制時以一般並行測試為準） |
| #13 owner 隔離 | `product_domain_integration_test`／watch ownership tests | PASS |

## Results

- Backend `make test-integration`：PASS；`go test ./... -count=1`：PASS；`make build`：PASS。
- Frontend live flow：24 files／141 tests PASS；`npm run build`：PASS；`npm run lint`：PASS（僅既有 Fast Refresh warnings）；`npm run check:tokens`：PASS。
- P0 尚未視為使用者批准；在收到批准前不開始 Phase D（T770–T775）。

## Known environment note

若執行 `go test -race`，目前環境的 Go race linker 需要 gcc；gcc 不存在時該命令無法啟動。一般 `go test` 與競態邏輯的平行測試仍須通過。
