# T042 — 歷史 identity 去重

> Status: `done`
> Milestone: `M4`
> Est. change: `~140 lines`

## Goal

完成後，新 run 遇到同一使用者已保留的 Threads 貼文時會計入 duplicate 並繼續找，不覆寫舊 run。

## Depends on

- T030、T041

## Inputs

- 讀取 / 依賴：
  - 檔案：`apps/backend/internal/module/scout/usecase/candidate.go`、domain repository
  - 既有能力 / API：canonicalPostIdentity、seen identity query
  - Spec 段落：§4 流程 B #3、§8.1、§9 #5/#6

## Outputs

### 程式變更（預期路徑）

| 路徑 | 動作 | 說明 |
|------|------|------|
| `apps/backend/internal/module/scout/usecase/candidate.go` | edit | 注入歷史 seen set，區分批內／歷史 duplicate。 |
| `apps/backend/internal/module/scout/usecase/historical_dedupe_test.go` | add | 驗證 alias、跨 run、舊狀態不覆寫與 current-run staging。 |

### 行為變更

- 已見貼文不算 eligible；duplicate_count 增加，target 缺口保留。

### API / 契約（若有）

- owner-wide 去重；查詢不得跨 owner，current run retry 的 staging 不視為外部歷史。

## Out of scope

- 不刪除歷史資料，不合併不同實際 shortcode。

## Acceptance

- [x] 新 run 不會改變舊 post 的 run_id、posted_at 或 outreach_status。
- [x] 指令：

```bash
cd apps/backend && go test ./internal/module/scout/usecase -run HistoricalDedupe -count=1
```

驗收結果：CandidateEvaluator 支援 owner-scoped historical identity lookup，canonical shortcode alias 會計入 duplicate；跨 owner 不共享 seen set，既有 post 不被覆寫。

## Notes

唯一索引是競爭防線，usecase seen query 則用來主動補找。
