# MGID Moderation Recovery

Turns a pile of rejected teasers into a short, grouped work list: how many, for
which reasons, which campaigns are starved by it, and what has to change per
group. Read-only by default.

Tools: [../_shared/ads-mcp-tools.md](../_shared/ads-mcp-tools.md)

---

## Why this exists

Rejection reasons already ship in the v1 teaser payload — `status.code` and
`status.reason_if_drop_karantin` — but nothing groups them. Buyers see one
rejection at a time in the UI and fix them one at a time; the same reason usually
covers dozens of creatives at once.

---

## Required inputs

| Input | Required | Default |
|---|---|---|
| Scope | No | all campaigns with rejected teasers |
| Fix mode | No | report only; ask before any write |

---

## MCP tools

| Tool | Purpose |
|---|---|
| `list_campaigns` | Campaign names, `type`, status |
| `list_teasers` | Teaser status + `status.reason_if_drop_karantin` — the whole input to this skill |
| `get_teaser` | Full config for a teaser being fixed |
| `get_portfolio_statistics` | Spend of the affected campaigns, to rank the work |
| `update_teaser` | ⚠️ Fix a teaser — **full replace**, see guardrails |
| `create_teaser` | ⚠️ Resubmit as a new creative when editing is not enough |

There is no `send_to_moderation` tool: a created or edited teaser re-enters
moderation by itself. The verdict comes back through `list_teasers`.

---

## Workflow

### Phase 1 — Collect

`list_teasers` per campaign in scope (no metrics needed). Partition by status:

| Bucket | Meaning | Action |
|---|---|---|
| Rejected | Declined with a reason | The work list |
| Pending | Awaiting a verdict | Report age; nothing to do |
| Active | Serving | Ignore |
| Blocked by client | Paused by us, not by moderation | Ignore — do not confuse the two |

### Phase 2 — Group by reason

Cluster rejected teasers on the **normalised** reason text — trim, lowercase, and
merge reasons that differ only by a quoted word or an id. Report the raw text of
one representative per group verbatim; never paraphrase a moderator's wording
into your own.

For each group: count, affected campaigns, and the campaigns' 7-day spend from
`get_portfolio_statistics`. Rank groups by **teasers × campaign spend** — the
reason blocking the most money comes first.

### Phase 3 — Classify the fix

Per group, decide what kind of change the reason demands:

| Fix class | Meaning | Who does it |
|---|---|---|
| Copy | Wording of title/text must change | **MGID creative generation**, not the agent |
| Image | Creative asset must change | MGID Media Gallery |
| Landing page | Destination violates policy | Advertiser |
| Compliance | Vertical/claim not allowed for this geo or category | Advertiser, possibly unfixable |
| Metadata | Category, price flags, call-to-action wrong | Fixable directly via `update_teaser` |
| Unclear | Reason text does not say | Escalate to the MGID manager |

Only the **metadata** class is safely fixable through this skill. Say so plainly
instead of implying everything can be automated.

### Phase 4 — Report, then optionally apply

---

## Output

**Chat:**

1. Totals: rejected / pending / active, and the spend of campaigns held back.
2. Grouped table: reason (verbatim), count, campaigns, fix class, and whether it
   is agent-fixable.
3. **Campaigns with zero active teasers** — flagged first, whatever their rank.
   A campaign that cannot serve at all is a different severity from one that
   lost three of twenty creatives.
4. Suggested order of work, with the unfixable groups named as such.

**Return:** `Recommendation[]` of `fix_teaser_metadata` / `escalate_moderation` /
`replace_creative`.

---

## Guardrails

- **Never rewrite ad copy.** MGID's creative generation owns headlines and
  images; this skill names what must change and hands off. Suggesting a rewritten
  headline here bypasses tuned prompts and brand rules.
- `update_teaser` is a **full replace** (v1 PUT). Always `get_teaser` first and
  resend every field you intend to keep, or unrelated fields reset to defaults.
- Never resubmit an unchanged teaser hoping for a different verdict.
- Never resubmit a compliance-class rejection without an explicit human decision
  — repeated resubmission of policy-violating creatives is an account risk.
- One teaser at a time on the first fix of a group; confirm the verdict before
  applying the same edit to the rest.
- Write scope required for Phase 4; without it, stop after the report.
