---
active: false
description: "Reconcile newly-extracted playbooks against existing storage. Decides per-candidate whether each one unifies with one-or-more existing rows, is rejected as redundant against an existing row, should differentiate (refine both triggers), or is independent."
changelog: "v2.2.0: `unify` re-synthesizes leaner, more general content (MDL / simplify-in-place) instead of concatenating — fewest, most general rules that still cover all inputs; drop redundant/subsumed wording. Asymmetric fidelity: compress/generalize success guidance, but preserve every distinct avoidance/failure detail verbatim — never soften a named pitfall into a vague platitude. Prefer `differentiate` over `unify` when merging would force an over-long, low-cohesion rule. v2.1.0: `unify` no longer emits a `polarity` field — the unified row's orientation is derived from its wording (recommendation vs avoidance) by the apply-path polarity validator. Same-trigger opposite-orientation rules still must not unify; express orientation through the rule wording. v2.0.0: collapsed 5-kind union → 4-kind. `unify` subsumes `duplicate`+`prefer_new`; `reject_new` replaces `prefer_existing`. Output schema is structurally incompatible with v1.x."
variables:
  - new_playbook_count
  - new_playbooks
  - existing_playbooks
---
You are reconciling a set of newly-extracted playbooks 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`. The `Polarity` label (`positive` = a recommendation / do-this, `negative` = an avoidance / don't-do-this) is derived from the rule's wording. Use `Trigger` and `Polarity` 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 candidate. Each decision is one of:

- **unify** — the NEW is the same rule as one or more EXISTING rows (after merge), OR the NEW supersedes one EXISTING (stronger / broader / more specific evidence). Provide the final `content`, `trigger`, and `rationale`. List which EXISTING ids you're archiving in `archive_existing_ids` (use an empty list when no EXISTING rows are absorbed). The unified row carries a single orientation: word its `content` and `rationale` so they consistently recommend OR consistently warn against the behavior — never blend both. Every archived EXISTING must share that orientation; the apply-path polarity validator (which derives orientation from wording) will reject a mixed-orientation unify.

- **reject_new** — an EXISTING row already covers NEW or makes NEW redundant. Name the EXISTING id that wins via `superseded_by_existing_id`. Storage-stability tie-break: when same-trigger opposite-orientation evidence is balanced, default here.

- **differentiate** — both valid in distinct contexts (typically same trigger, opposite orientation, 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.

# How to write a unified row (re-synthesis, not concatenation)

When you `unify`, re-synthesize a single leaner rule. Do not stitch the inputs together.

- Produce the **fewest, most general rules that still cover all the inputs**. Generalize the shared behavior into one clear statement; drop wording that is redundant with or subsumed by another input.
- **Preserve every distinct avoidance/failure detail with high fidelity.** This is asymmetric: compress and generalize the success guidance, but keep each specific failure intact. Never collapse a named pitfall, concrete error, or specific anti-pattern into a vague platitude — carry it forward in its specific form.
- Prefer **`differentiate` over `unify`** when merging the inputs would force an over-long, low-cohesion rule. Two focused rules that each read cleanly beat one bloated rule that tries to say everything. If you cannot state the merged rule concisely without losing distinct failure detail, that is a signal to `differentiate` (or keep NEW `independent`) rather than `unify`.

# Hard constraints

- A NEW + EXISTING pair with the same trigger and opposite orientation MUST route to `unify` (only if you can pick one shared orientation backed by evidence and word the unified row accordingly — the polarity validator will reject a mixed-orientation unify), `reject_new`, or `differentiate`. Never `independent`.
- Orientation is read from each row's wording (the derived `Polarity` label). A unified row's orientation follows the words you choose for its `content` and `rationale`.
- `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-orientation stalemate, default to `reject_new`. 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).
