From escc
Detect and merge duplicate CRM records — contacts, companies, deals — with a survivor recommendation. Trigger: 'merge duplicates', 'dedupe', 'two records for the same company'.
How this skill is triggered — by the user, by Claude, or both
Slash command
/escc:dedupe-mergeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The canonical owner of survivorship rules and association-preservation logic for
The canonical owner of survivorship rules and association-preservation logic for ESCC. Every merge of duplicate CRM records — contacts, companies, deals — runs through this skill. Other skills that encounter a duplicate situation cite this skill and defer; they do not define their own survivorship logic.
This skill OWNS survivorship and association-preservation rules. Other skills cite these by name and point here. Do not define a competing merge model elsewhere.
Governing rules (DEFER for policy; this skill owns the merge mechanics):
rules/common/crm-hygiene.md— CRM data standards; dedupe-first is a hygiene rule enforced here.rules/lifecycle-stages.md— a disqualify/recycle is a status + reason, NEVER a delete. No record is removed from HubSpot as a byproduct of a merge.All merges are crm-operator writes requiring explicit approval. A merge is proposed as a review-pack (survivor + losing record + field/association resolution);
crm-operatorapplies it only after the approval is confirmed. No merge is applied speculatively or in bulk without a review-pack.
Activate this skill when:
rules/common/crm-hygiene.md).Do not activate for routing a clean (non-duplicate) lead (that is lead-routing),
for disqualifying or recycling a valid record (that is rules/lifecycle-stages.md),
or for bulk data imports where deduplication is an ETL concern upstream of ESCC.
When two records represent the same real-world entity, one becomes the survivor (retained, enriched) and the other becomes the loser (merged in, then archived). Apply these rules in order; the first match determines the survivor.
rules/common/crm-hygiene.md
that are populated; the record with more populated required fields is the survivor.Losing records carry history and relationships that must not be discarded. Every merge must preserve:
Association preservation is non-negotiable. A merge that orphans a deal, drops activity history, or loses a contact association is worse than leaving the duplicate in place.
Every merge is proposed as a review-pack before crm-operator applies it.
No merge happens without an explicit approval of the review-pack.
MERGE REVIEW-PACK: <object type> merge
APPROVAL REQUIRED before apply.
Survivor: <record name> (HubSpot ID: <id>)
Created: <date> | Associations: <n contacts, n deals, n activities>
Required fields populated: <list>
Losing record: <record name> (HubSpot ID: <id>)
Created: <date> | Associations: <n contacts, n deals, n activities>
Required fields populated: <list>
Survivorship rule applied: <rule name and rationale>
Field conflicts (both records have a value — survivor value kept unless noted):
field_name: survivor value "<X>" vs losing value "<Y>" -> KEEPING: <which>
[repeat for each conflict]
Associations being re-associated to survivor:
- <contact name> (currently on losing record) -> survivor
- <deal name> (currently on losing record) -> survivor
- [etc.]
Activity history: <n> activities from losing record will merge into survivor timeline.
Ownership: survivor is currently owned by <rep name>.
[If losing record has a different owner: flag for routing review post-merge.]
Post-merge: losing record archived, not deleted.
APPLY ONLY AFTER EXPLICIT APPROVAL.
rules/common/crm-hygiene.md:
search by company name, domain, email, and phone before creating. If a match is
found, this workflow begins.crm-operator (read). Capture all fields,
association counts, and activity history for each.lead-routing after the merge — do not silently adopt the survivor's owner
without flagging it.merge_approval_requested via crm-operator / governance-capture
against the record.crm-operator checks that the merge approval is
on-record before applying any write. Approval must be explicit — a verbal
acknowledgement is not sufficient.crm-operator writes to the activity log:
lead-routing using the correct assignment rule (named-account /
territory / round-robin from rules/routing-rules.md).Pre-creation dedup: company match found
Rep attempts to create "Example Co Corp" (acme.example).
crm-hygiene check: search by domain acme.example.
Found: existing company "Example Co Corporation" (ID: 11111), created 2025-03-01,
3 contacts, 1 open deal, 12 activities.
Rep's new record would be: "Example Co Corp", no associations yet.
Survivorship rule: existing record has more associations -> existing is survivor.
Action: do not create a new record. Use existing "Example Co Corporation" (ID: 11111).
Rep's new contact is associated to the existing company.
No merge write required — creation was blocked. crm-operator logs the dedup event.
Full merge: two company records, different owners
Found: GlobalBank (ID: 22222, owner: Jordan) and Global Bank Inc (ID: 33333, owner: Dana).
ID 22222: created 2024-11-01, 5 contacts, 2 deals, 40 activities.
ID 33333: created 2025-01-15, 2 contacts, 0 deals, 8 activities.
Survivorship rule 1 (more associations): ID 22222 wins.
Survivor: GlobalBank (ID: 22222). Losing record: Global Bank Inc (ID: 33333).
Field conflicts:
phone: 22222 has "+1 212 555 0100" vs 33333 has "+1 212 555 0199" -> keeping 22222 value.
[33333 value noted in log for manual review.]
industry: 22222 has "Financial Services" vs 33333 has "Banking" -> keeping 22222 value.
Associations from ID 33333 to re-associate:
- Contact: Dana's champion (contact ID 44444) -> GlobalBank (ID 22222)
- Activity: 8 call logs -> merged into GlobalBank timeline
Ownership conflict: ID 22222 owned by Jordan; ID 33333 owned by Dana.
Post-merge ownership must be resolved via lead-routing.
REVIEW-PACK submitted. [Manager approves.]
crm-operator applies:
1. Re-associate contact 44444 to ID 22222.
2. Merge 8 activities into ID 22222 timeline.
3. Resolve field conflicts per pack.
4. Archive ID 33333 (not deleted). Log: archived ID 33333 merged into 22222.
5. Read back ID 22222 — 7 contacts, 2 deals, 48 activities confirmed.
6. Ownership conflict flagged to lead-routing for territory-rule resolution.
Rejected merge: deal-quarter conflict
Found: two deal records for Initech — "Initech Q2 Expansion" (stage: Proposal,
close: 2026-06-30) and "Initech New Logo" (stage: Discovery, close: 2026-09-30).
Survivorship check: different close-date quarters.
Rule: do not merge deals across different close-date quarters without explicit approval.
Output: these may be two genuinely separate opportunities (expansion and new logo).
Flagging for rep and manager review — not merging without explicit approval.
[If manager confirms they are the same deal: re-submit with manual override noted.]
rules/lifecycle-stages.md
prohibits deletion as a cleanup action.lead-routing, pipeline-hygiene,
and crm-hygiene SKILL (when built) should cite this skill and defer. A competing
rule set creates drift and inconsistent merge decisions.rules/lifecycle-stages.md,
not a merge. Merges are for genuine duplicates of the same real-world entity.ESCC_BULK_SEND_MAX batch discipline as any bulk crm-operator
write. Above the cap, split into approved batches.rules/common/crm-hygiene.md.rules/lifecycle-stages.md.crm-operator (sole write path;
review-pack required; explicit approval before apply).lead-routing.pre:crm-write-guard (also checks stage exit criteria).lead-routing.governance-capture.npx claudepluginhub aura-farming/escc --plugin esccGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.