# CRM Sync Review Proof Runbook

Purpose: prove a CRM sync review path before touching live CRM records, client data, credentials, phone calls, messages, payment actions, or connected CRM accounts.

First paid slice:

- Source: one redacted CRM, appointment, form, email, phone, or activity export.
- Transformation: normalize identity fields, compare against the contact map, classify accepted rows, conflicts, and hard errors, and preserve reviewer evidence.
- Destination: sync ledger, conflict queue, error log, first-slice map, and written handoff.
- Useful sample: one clean mapped row, one identity conflict, one unmapped or missing-identity row, and the fields that must never be overwritten.

## Inputs

- `contact-map.csv`: current known mapping between Close contacts, GHL contacts, emails, and phones.
- `close-appointments.csv`: mock appointment events from Close.
- `ghl-contact-changes.csv`: mock contact-field changes from GHL.
- `activity-events.csv`: mock Gmail and OpenPhone activity events for the GHL review path.
- `first-slice-map.csv`: how the same guardrail maps to Copper duplicate cleanup, Gmail/OpenPhone-to-GHL sync, and two-way CRM drift.

## Command

```bash
python3 demo/crm-sync/process_crm_sync_demo.py
```

## Outputs

- `sync-ledger.csv`: rows that are safe for a reviewer to approve for sync.
- `conflict-queue.csv`: business conflicts that need a human decision before any write happens.
- `error-log.csv`: malformed or missing-identity rows that are blocked immediately.

## Acceptance Checks

- A valid Close appointment for a mapped contact lands in the sync ledger.
- A valid GHL contact change for a mapped contact lands in the sync ledger.
- A valid Gmail or OpenPhone activity for a mapped contact lands in the sync ledger for review.
- A Copper or GHL first slice can be scoped to one trigger/activity, one match policy, and one review queue before live writes.
- A Close appointment whose email belongs to a different Close contact is blocked.
- An unmapped Close appointment becomes a conflict, not a blind contact create.
- A GHL change whose identifiers disagree with the contact map is blocked.
- A Gmail/OpenPhone activity whose email and phone map to different contacts is blocked.
- A row with no usable identity is written to the error log.

## Non-Goals

- No CRM write is executed.
- No contact is created automatically.
- No phone, SMS, email, or payment action is triggered.
- No promise is made about Copper, Close, GHL, or any third-party API availability.
