---
active: false
description: "Reconcile newly-extracted playbooks against existing storage. Decides per-candidate whether each one is a duplicate, supersedes / is superseded by an existing row, should differentiate (refine both triggers), or is independent."
changelog: "v1.1.0: rendered NEW/EXISTING rows now include `Trigger` and `Rationale` alongside `Content` so the model can compare the fields it is asked to refine (differentiate, same-trigger contradictions, trigger refinements). No variable changes."
variables:
  - new_playbook_count
  - new_playbooks
  - existing_playbooks
---
You are reconciling a set of newly-extracted playbooks (each with a `polarity` of `"positive"` or `"negative"`) against the related existing playbook rows already in storage. For each new candidate, decide its relationship to the existing rows.

Each rendered row carries `Content`, `Trigger`, `Rationale`, `Polarity`, `Name`, `Source`, and `Last Modified`. Use `Trigger` and `Polarity` (not content framing) as the primary keys for comparison.

[New playbooks (count: {new_playbook_count})]
{new_playbooks}

[Existing related playbooks]
{existing_playbooks}

# Decision kinds

Emit exactly one decision per `(new, related-existing)` consideration. Each decision is one of:

- **duplicate** — same intent across NEW + one-or-more EXISTING (same trigger, same polarity, semantically the same rule). Set `kind: "duplicate"`, list all `item_ids`, write `merged_content` / `merged_trigger` / `merged_rationale`, and set `merged_polarity` to the polarity all members share. All members MUST share polarity.

- **prefer_new** — NEW wins; archive the existing row and insert NEW. Choose when:
  - NEW contradicts EXISTING (opposite polarity) and NEW's evidence is stronger, OR
  - NEW is broader and correctly subsumes EXISTING's narrower case.

- **prefer_existing** — EXISTING wins; drop NEW. Choose when:
  - EXISTING contradicts NEW (opposite polarity) and EXISTING's evidence is stronger, OR
  - EXISTING is broader and already subsumes NEW's narrower case, OR
  - NEW is a weaker / stale restatement of EXISTING.

- **differentiate** — both valid in distinct contexts (typically same trigger, opposite polarity, where the contexts differ). Set `refined_new_trigger` and `refined_existing_trigger` to be strictly narrower than the originals AND mutually exclusive.

- **independent** — different topic or trigger from any existing row. Insert NEW with no archive.

# Hard constraints

- A pair with the same trigger and opposite polarity MUST resolve to `prefer_new`, `prefer_existing`, or `differentiate`. NEVER `duplicate` (different intent). NEVER `independent` (same trigger).
- Polarity comes from each playbook's `polarity` field — do not infer it from content framing.
- `differentiate.refined_new_trigger` and `refined_existing_trigger` MUST be non-empty and strictly narrower than the originals.
- When in doubt about a same-trigger opposite-polarity stalemate, default to `prefer_existing`. Storage stability wins ties.

Output strictly conforming to the `PlaybookConsolidationOutput` schema (a JSON object with a single key `decisions` whose entries each carry a `kind` discriminator).
