# RETRACTION_SCREEN_PROTOCOL.md

**Owner:** Source Integrity Screen (RAM S2)
**Type:** Tool (operational protocol)
**Scope:** Authoritative procedure for the retraction phase.

## 1. Data Sources

- **Retraction Watch Database (RWDB)** -- acquired by Crossref September 2023; license CC-BY 4.0. Full CSV mirror: `https://gitlab.com/crossref/retraction-watch-data`. Daily refresh. Approximately 50K retracted papers in the combined Crossref + RWDB set.
- **Crossref REST API** -- returns `update-to[]` on per-DOI `works` lookup. Each entry: `DOI`, `type`, `label`, `updated`, `source` (`publisher` or `retraction-watch`).
- **PubPeer** -- adjacent post-publication-comment feed. Not a retraction source. Attach as `retraction.pubpeer_concerns_count` only.

## 2. Lookup Order

1. DOI present -> query local RWDB CSV cache first.
2. Cache hit -> parse `RetractionNature`, `Reason`, `RetractionDate`. Set `retraction.status` to `retraction` | `expression-of-concern` | `withdrawal` | `clean`.
3. Cache miss with DOI -> Crossref polite-pool call (Section 3).
4. No DOI -> `retraction.status = unverifiable`, `retraction.note = no-doi`. NEVER silently re-code to `clean`.

## 3. Crossref API

**Primary:**
```
GET https://api.crossref.org/works/{doi}?mailto=ram-agent@futureclientsnow.com
```

**Sweep (daily refresh only):**
```
GET https://api.crossref.org/works?filter=update-type:retraction,from-update-date:YYYY-MM-DD
```

**Bulk seed (daily pull):**
```
git clone https://gitlab.com/crossref/retraction-watch-data
```

**Polite-pool quotas (effective 1 Dec 2025):** 10 req/s single-DOI, 3 req/s list, 3 concurrent. The `mailto=` parameter is the admission token -- without it you fall to public-pool (5 / 1 / 1) and risk throttling.

**Parse rule.** Walk `message.update-to[]`; filter `type` in `{retraction, expression-of-concern, withdrawal}`. Map each matched type into `retraction.status`. Ignore `correction`.

**Backoff.** Exponential on HTTP 429, max 3 retries. On final failure: `retraction.status = deferred`, `retraction.reason = api_unavailable`. Continue the run; Fitness Adjudicator decides weighting.

## 4. Cache Policy

- Local CSV cache TTL: 24 hours.
- Per-DOI response cache: 24 hours, keyed on normalized DOI.
- Append-only for positives; negatives refresh per TTL. A once-retracted paper never silently reverts to `clean`.

## 5. Coverage Gaps

- **Non-English / non-DOI retractions** -- tag `unverifiable`, note `non-doi-venue`.
- **Paper-mill backlog** -- roughly 7.3K of 44K RWDB entries tagged paper-mill as of mid-2024; tighten monitoring for post-2018 papers.
- **Publisher-lag** -- some publishers omit machine-readable Crossref retraction metadata; consult both sources.
- **Paywalled retraction notices** -- RWDB `Paywalled` field surfaces this; carry as `retraction.note = paywalled-notice`.
- **PubPeer concerns without formal retraction** -- not retraction; separate `pubpeer_concerns_count`.
- **No webhook / push** -- pull-only; daily cache refresh is the saturation mechanism.

## 6. Output Contract

Populate the `retraction` block of the Integrity Verdict: `status`, `source`, `reason` (if retracted), `retraction_date`, `pubpeer_concerns_count`, `note`. Every phase transition writes a Ledger entry via the Public-RAM write contract.

## 7. Anti-Patterns

- Treating `unverifiable` as `clean`.
- Skipping `mailto=`.
- Running the sweep endpoint per-source (daily-refresh only).
- Treating PubPeer comments as retraction evidence.
- Ignoring `expression-of-concern` -- it is a load-bearing intermediate state.
