# Detection pipeline

Field names and enums are defined in [data-model.md](data-model.md).

## Principle
A score is a reason for a human to look. It is never a reason for the system to act.
No notice is drafted, approved, or sent from a score, a match_type, or a derivation flag alone.
Every step before human triage is read-only with respect to the outside world.

## Stages

### 1. Discover
Inputs: a performer's verified reels and handles.
Sources: platform search and hashtag feeds, audio-reuse lists where platforms expose them, performer or fan reports, re-check of URLs from open cases.
Output: candidate with `status: discovered`, `url`, `platform_id`, `found_at`. Nothing else is filled yet.
Rate-limit per platform and respect robots and terms; discovery that needs a logged-in account uses the performer's own consented handle.

### 2. Capture evidence first
Before any scoring, archive the candidate: page snapshot, media file, visible metadata (uploader, upload date, view count, caption), capture time, and a content hash of the archive.
Store under `evidence_ref`. A candidate with `evidence_ref: null` cannot be scored or escalated.
Reason: copies get edited or deleted once attention arrives; the notice must cite what existed at capture time, not what a detector saw in memory.

### 3. Fingerprint and match
Compute fingerprints on the captured media and compare against the performer's reels.
| detector | writes to signals | supports match_type |
|---|---|---|
| video_phash (frame hashes, transform-tolerant) | phash_full, phash_segment | exact_reupload, clip_lift, re_edit |
| audio_chroma (tempo-tolerant) | chroma_full, chroma_segment | exact_reupload, audio_lift, re_edit |
| transcript similarity | transcript_sim | ai_imitation |
| pose / choreography similarity | pose_sim | ai_imitation |
| voice embedding | voice_sim | voice_clone (only if `likeness_opt_in`) |
| face / style embedding | face_sim | lookalike (only if `likeness_opt_in`) |

Output: `match_type` (the strongest supported type), `score`, `signals`, `segments`, `status: scored`.
The score is the detector's confidence in that match_type given the signals. It is not a probability of infringement.

### 4. Derivation signals (AI-made content)
Separately from matching, check for signs the candidate was machine-generated: C2PA or provider watermarks, generator metadata, synthetic-voice classifier output, face-swap artefacts.
Write to `derivation_flags`. These are **weak evidence** and are treated as such:
- They never raise `score`.
- They never set `match_type` on their own. "This looks AI-made" is not "this copies performer X".
- Watermark absence proves nothing; most generators strip or lack them.
- Synthetic-voice classifiers have high false-positive rates on compressed, filtered, or autotuned real voices.
Their only effect is to surface the candidate to triage sooner and to be mentioned, with their limits, in a notice if a human chooses to include them.

### 5. Human triage
A reviewer sees: both videos side by side with `segments` highlighted, the signals table, derivation flags with their caveats, evidence capture details, and any earlier dismissals of the same uploader.
Reviewer sets status to one of `confirmed`, `dismissed`, `needs_more_evidence`, with `triage_note`, `reviewed_by`, `reviewed_at`.
Required checks before `confirmed`:
- Is the source actually the performer's work and not something they also lifted?
- Is the candidate the performer's own cross-post or an authorised repost?
- Is it commentary, parody, reaction, or duet that the platform and law may permit?
- For likeness types: does the performer have `likeness_opt_in`, and is this an impersonation or just resemblance?

### 6. Case routing
A confirmed candidate is attached to a new or existing case (same uploader, same performer). A named person records `standing` (see legal-support-flow.md for who may act) and sets `route`:
- `takedown` — clear copy, performer or rights holder has standing.
- `licensing` — copy with reach the performer may prefer to monetise.
- `monitor_only` — lookalike or weak evidence; set `recheck_at`, no contact.
- `no_action` — permitted use or not worth pursuing; record why.
- `refer_counsel` — likeness, voice clone, cross-border, or disputed standing.
Notices are created only inside a case, and move `draft → approved` only when `approved_by` is a named human.

### 7. Re-check
On `recheck_at` and after every response: re-fetch each candidate URL, re-capture, and diff against the stored evidence. Record `removed`, `unchanged`, `edited`, or `reuploaded_elsewhere` (which starts a new candidate back at stage 1, linked to the case).

## What counts as a copy
In scope: exact re-uploads; lifted segments; re-edits that preserve the performance; original audio over new video; generated content that reproduces the performer's specific performance, script, or voice.
Out of scope by default (route `no_action` or `monitor_only` unless a human judges otherwise): duets and stitches using platform features; reaction and commentary with substantial added content; parody; dance trends and formats the performer did not originate; resemblance of style, genre, or look without reuse.
Match types are ordered in data-model.md from strongest to weakest evidence; the weaker the type, the higher the bar at triage.

## Failure modes
- **False positives.** Shared stock music, trending sounds, and platform templates match on audio_chroma; cross-posts by the performer match on everything. Mitigation: own-handle allow-list, trending-sound suppression list, mandatory triage.
- **False negatives.** Heavy re-edits, mirrored and cropped video, pitch-shifted audio, or short lifts under a few seconds fall below detector thresholds. Mitigation: performer and fan reports feed discovery; do not present the system as exhaustive.
- **Detector overconfidence.** A 0.98 score on a dismissed cross-post looks the same as a 0.98 on a real copy. Mitigation: score shown with signals and never as a verdict; UI shows the dismissed-cross-post example in seed data; no automatic actions.
- **Derivation-flag overreach.** Treating "AI-made" as "infringing" would target legitimate creators and fail on real recordings misclassified as synthetic. Mitigation: weak-evidence rule above.
- **Likeness and voice matching without consent.** Building face or voice embeddings of a performer without their opt-in, or matching against uploaders who merely resemble them, is a privacy harm to both. Mitigation: `likeness_opt_in` gate; lookalike defaults to monitor_only; embeddings of candidates are not retained after scoring.
- **Evidence loss.** Scoring before capture leaves a notice with nothing to cite. Mitigation: hard rule in stage 2.
- **Privacy of uploaders.** Candidates may be ordinary users. Store only public metadata, keep dismissed candidates minimal (URL, reason, date), and do not profile uploaders across performers.
- **Chilling effect and misuse.** The tool could be pointed at critics or competitors. Mitigation: standing check by a named person, audit event for every transition, route and reason required on every case.
- **Wrong source.** The "original" reel may itself be lifted. Triage check 1 exists for this.
- **Platform drift.** Scraping breaks and takedown channels change. Mitigation: platform record carries `takedown_channel`; discovery failures are logged as audit events, not silently skipped.
