HarborCRM CRM Reconciliation SOP
Use this skill for HarborCRM tasks that ask for CRM-ready JSON from public API data: post-event sponsor/lead handoffs, trade-show prospecting summaries, and contact import hygiene. Always read the staged prompt and answer template first, then shape the response exactly to the template.
Core Workflow
- Identify the requested object id:
event_id, show_id, or batch_id.
- Pull every public API source named or implied by the prompt before deciding: event/show metadata, sponsor orders/packages, badges or exhibitors, finance invoices, CRM accounts, CRM contacts, opportunities, campaign members, suppression lists, meeting-interest records, and policies.
- Build joins using stable ids first, then normalized names/domains/emails as fallback.
- Normalize data before matching:
- Emails: trim and lowercase.
- Phones: digits only; leave
"" when no phone exists.
- Money and counts: integers.
- Dates: calendar dates in
YYYY-MM-DD; follow-up due dates are event end date plus the configured day offset.
- Return JSON only. Do not add undeclared fields or explanatory prose.
Event And Sponsor Handoff
Use event details, sponsor orders or packages, finance invoices, badges, CRM records, opportunities, campaign members, and policies together.
- Treat confirmed sponsor orders with paid/deferred invoices as
paid_deferred.
- Treat confirmed sponsor orders with open invoices as
open_invoice; open balance is invoice amount minus paid amount.
- Treat proposal-stage sponsor packages as
proposal_only.
- Exclude canceled or inactive sponsor records from active sponsor status lists unless the template explicitly asks for not-sponsor decisions.
- Sponsor revenue totals should sum package or invoice amounts by controlled status. Keep open-invoice balance as its own value when requested.
- Finance follow-up targets are the unsettled sponsor accounts: open invoices and, when the prompt includes proposal handoff, proposal-only packages. Do not include fully paid/deferred sponsors in unpaid follow-up targets.
For badge decisions:
- Sponsor attendees are not non-sponsor leads, even if their badge type is
attendee; match by sponsor account, company name, or ticket-contact context.
- Qualified non-sponsor leads are business attendees with usable contact facts, no sponsor linkage, and no disqualified CRM account.
- Non-business badges such as student or press records are excluded.
- Existing disqualified CRM accounts stay excluded even when the event scan score is high.
- A record with one usable contact channel is contactable unless the template defines missing contact more narrowly.
CRM Actions
Choose actions from the template enums only.
- Existing valid CRM account, new contact: update the account and create or add the contact/campaign member.
- New account and new contact: create account, contact, and campaign member.
- Existing campaign member with the correct target status:
no_action.
- Existing campaign member needing a new event status:
update.
- Excluded lead-import rows:
no_import.
- Keep lead-import decisions separate from campaign-member reconciliation when the template has both sections. A sponsor badge can be excluded from lead import while still having a campaign-member action.
Common campaign-member target statuses:
- Sponsor attendee with badge attendance:
attended_sponsor.
- Sponsor ticket/contact without attendance badge:
registered_sponsor.
- Qualified non-sponsor attendee:
attended.
- Excluded badge or row:
excluded.
Trade-Show Prospecting
Use trade-show metadata, exhibitors, meeting interest, CRM accounts/contacts, and policies.
- Qualify exhibitors that manufacture or OEM-build covered platforms.
- Covered platform enums should be used exactly as supplied, normally ordered
AUV, ROV, Underwater Camera.
- Count platform coverage by platform occurrence across qualified exhibitors, not just by lead count.
- Exclude adjacent companies that do not make target platforms:
- Distributor or reseller only:
distributor_only.
- Services or consulting only:
service_only.
- Sensor vendor only:
sensor_vendor_only or sensor_only, matching the template enum.
- Research-only organizations:
research_only.
- Existing CRM account overlap means
update_existing; qualified exhibitors without CRM accounts are create_account.
- When ranking is requested, apply the prompt's rank keys in order. A common pattern is demo request first, interest score descending, broader platform coverage, then company name.
- When priority tiers are supplied, derive opportunity size strictly from the tier mapping in the prompt.
Import Batch Hygiene
Use raw contacts, suppression data, CRM accounts, CRM contacts, and policies.
- Remove suppressed rows by normalized email or phone before import.
- Remove unusable rows with no usable contact channel.
- Deduplicate with normalized email as the strongest key when present; use the template's duplicate-key format, often
email:<normalized_email>.
- Choose the winning duplicate row by explicit prompt rules. If none are given, prefer fresher, more complete, higher-confidence source rows while keeping the winner's source row id and timestamp.
- Clean-contact ids and source row ids should be the winning source row id when the template asks for that convention.
- Do not include duplicate, suppressed, or unusable rows in clean contacts or campaign-member import counts.
- Keep removal summaries sorted by row id and duplicate summaries sorted by duplicate key.
Sorting And Field Conventions
Follow template ordering literally:
- Sponsor/account lists:
account_name ascending.
- Qualified company lists:
company_name ascending unless ranked output is requested.
- Ranked leads: contiguous
rank starting at 1.
- Badge decisions:
badge_id ascending.
- Campaign-member actions:
subject_key ascending.
- Exclusions with people:
company_name ascending, then contact_name ascending.
- Duplicate keys: key ascending.
- Removed rows: row id ascending.
- CRM account id lists: account id ascending.
Use null only where the template permits a missing id or invoice. Use "" for normalized email or phone when the template allows an empty string.
Pitfalls
- Do not infer from one source alone when the prompt asks for reconciliation; sponsor order, invoice, CRM, and badge facts can disagree.
- Do not count sponsor contacts as non-sponsor pipeline.
- Do not let canceled sponsor packages become active sponsors.
- Do not exclude a new contact just because another contact on the same account is opted out; suppression is contact-specific unless the prompt says otherwise.
- Do not double-count duplicate rows in import totals.
- Do not add prose, comments, or helper fields to the final JSON.
1---2name: reflect-3-attempt-013description: HarborCRM CRM Reconciliation SOP4---5# HarborCRM CRM Reconciliation SOP67Use this skill for HarborCRM tasks that ask for CRM-ready JSON from public API data: post-event sponsor/lead handoffs, trade-show prospecting summaries, and contact import hygiene. Always read the staged prompt and answer template first, then shape the response exactly to the template.89## Core Workflow10111. Identify the requested object id: `event_id`, `show_id`, or `batch_id`.122. Pull every public API source named or implied by the prompt before deciding: event/show metadata, sponsor orders/packages, badges or exhibitors, finance invoices, CRM accounts, CRM contacts, opportunities, campaign members, suppression lists, meeting-interest records, and policies.133. Build joins using stable ids first, then normalized names/domains/emails as fallback.144. Normalize data before matching:15 - Emails: trim and lowercase.16 - Phones: digits only; leave `""` when no phone exists.17 - Money and counts: integers.18 - Dates: calendar dates in `YYYY-MM-DD`; follow-up due dates are event end date plus the configured day offset.195. Return JSON only. Do not add undeclared fields or explanatory prose.2021## Event And Sponsor Handoff2223Use event details, sponsor orders or packages, finance invoices, badges, CRM records, opportunities, campaign members, and policies together.2425- Treat confirmed sponsor orders with paid/deferred invoices as `paid_deferred`.26- Treat confirmed sponsor orders with open invoices as `open_invoice`; open balance is invoice amount minus paid amount.27- Treat proposal-stage sponsor packages as `proposal_only`.28- Exclude canceled or inactive sponsor records from active sponsor status lists unless the template explicitly asks for not-sponsor decisions.29- Sponsor revenue totals should sum package or invoice amounts by controlled status. Keep open-invoice balance as its own value when requested.30- Finance follow-up targets are the unsettled sponsor accounts: open invoices and, when the prompt includes proposal handoff, proposal-only packages. Do not include fully paid/deferred sponsors in unpaid follow-up targets.3132For badge decisions:3334- Sponsor attendees are not non-sponsor leads, even if their badge type is `attendee`; match by sponsor account, company name, or ticket-contact context.35- Qualified non-sponsor leads are business attendees with usable contact facts, no sponsor linkage, and no disqualified CRM account.36- Non-business badges such as student or press records are excluded.37- Existing disqualified CRM accounts stay excluded even when the event scan score is high.38- A record with one usable contact channel is contactable unless the template defines missing contact more narrowly.3940## CRM Actions4142Choose actions from the template enums only.4344- Existing valid CRM account, new contact: update the account and create or add the contact/campaign member.45- New account and new contact: create account, contact, and campaign member.46- Existing campaign member with the correct target status: `no_action`.47- Existing campaign member needing a new event status: `update`.48- Excluded lead-import rows: `no_import`.49- Keep lead-import decisions separate from campaign-member reconciliation when the template has both sections. A sponsor badge can be excluded from lead import while still having a campaign-member action.5051Common campaign-member target statuses:5253- Sponsor attendee with badge attendance: `attended_sponsor`.54- Sponsor ticket/contact without attendance badge: `registered_sponsor`.55- Qualified non-sponsor attendee: `attended`.56- Excluded badge or row: `excluded`.5758## Trade-Show Prospecting5960Use trade-show metadata, exhibitors, meeting interest, CRM accounts/contacts, and policies.6162- Qualify exhibitors that manufacture or OEM-build covered platforms.63- Covered platform enums should be used exactly as supplied, normally ordered `AUV`, `ROV`, `Underwater Camera`.64- Count platform coverage by platform occurrence across qualified exhibitors, not just by lead count.65- Exclude adjacent companies that do not make target platforms:66 - Distributor or reseller only: `distributor_only`.67 - Services or consulting only: `service_only`.68 - Sensor vendor only: `sensor_vendor_only` or `sensor_only`, matching the template enum.69 - Research-only organizations: `research_only`.70- Existing CRM account overlap means `update_existing`; qualified exhibitors without CRM accounts are `create_account`.71- When ranking is requested, apply the prompt's rank keys in order. A common pattern is demo request first, interest score descending, broader platform coverage, then company name.72- When priority tiers are supplied, derive opportunity size strictly from the tier mapping in the prompt.7374## Import Batch Hygiene7576Use raw contacts, suppression data, CRM accounts, CRM contacts, and policies.7778- Remove suppressed rows by normalized email or phone before import.79- Remove unusable rows with no usable contact channel.80- Deduplicate with normalized email as the strongest key when present; use the template's duplicate-key format, often `email:<normalized_email>`.81- Choose the winning duplicate row by explicit prompt rules. If none are given, prefer fresher, more complete, higher-confidence source rows while keeping the winner's source row id and timestamp.82- Clean-contact ids and source row ids should be the winning source row id when the template asks for that convention.83- Do not include duplicate, suppressed, or unusable rows in clean contacts or campaign-member import counts.84- Keep removal summaries sorted by row id and duplicate summaries sorted by duplicate key.8586## Sorting And Field Conventions8788Follow template ordering literally:8990- Sponsor/account lists: `account_name` ascending.91- Qualified company lists: `company_name` ascending unless ranked output is requested.92- Ranked leads: contiguous `rank` starting at 1.93- Badge decisions: `badge_id` ascending.94- Campaign-member actions: `subject_key` ascending.95- Exclusions with people: `company_name` ascending, then `contact_name` ascending.96- Duplicate keys: key ascending.97- Removed rows: row id ascending.98- CRM account id lists: account id ascending.99100Use `null` only where the template permits a missing id or invoice. Use `""` for normalized email or phone when the template allows an empty string.101102## Pitfalls103104- Do not infer from one source alone when the prompt asks for reconciliation; sponsor order, invoice, CRM, and badge facts can disagree.105- Do not count sponsor contacts as non-sponsor pipeline.106- Do not let canceled sponsor packages become active sponsors.107- Do not exclude a new contact just because another contact on the same account is opted out; suppression is contact-specific unless the prompt says otherwise.108- Do not double-count duplicate rows in import totals.109- Do not add prose, comments, or helper fields to the final JSON.