1---2name: reflect-3-attempt-03-303description: HarborCRM Task Solving Skill4---5# HarborCRM Task Solving Skill67## 1. Preparation8- Read `MANIFEST.md`, `environment_access.md`, and the staged train prompt/answer template.9- **Do not assume train tasks share the same schema.** Each train task may use a different event/show/batch and a different JSON template.10- The remote base URL is `http://34.46.77.124:8001`. Do not use localhost unless explicitly overridden.1112## 2. Data Fetching Rules13- Query **only** the endpoint paths and entity IDs explicitly named in the prompt.14- Do **not** call global list/index endpoints to discover unrelated IDs (e.g., do not scan `/api/tradeshows` to find test shows).15- For each task, fetch **all** explicitly listed endpoints before building the answer.1617## 3. Event / Trade-Show Handoff Tasks (e.g., neuralops_2026, edgeai_field_2026)1819### 3.1 Sponsors20- Use **orders** and **sponsor_packages** to identify sponsors.21- Use **invoices** to determine finance state.22- Map invoice `status` to controlled enum values:23 - `paid_deferred` — invoice status is `"paid_deferred"`.24 - `open_invoice` — invoice status is `"open"`.25 - `proposal_only` — no invoice exists and order status is `"proposal_sent"`.26 - Exclude canceled/inactive sponsors from `sponsor_statuses`.27- `open_balance` for an open invoice = `amount - paid_amount`.28- `sponsor_revenue_totals` group by the same status enum.29- `sponsor_finance_accounts` should list only sponsors needing follow-up (open_invoice and proposal_only), sorted ascending.3031### 3.2 Badges (Leads)32- Iterate every badge.33- Exclude:34 - **sponsor contacts** (any badge from a sponsor company),35 - **non-business badges** (`student`, `press`, etc.),36 - **contacts whose CRM account is disqualified**,37 - **inactive/canceled sponsor records**.38- Qualified non-sponsor leads are the remaining business attendees.39- Use the event’s `lead_opportunity_amount` for each qualified lead.4041### 3.3 Normalization42- **Email**: lowercase, trim whitespace.43- **Phone**: strip **all** non-digit characters. Then ensure the country code is present:44 - If the badge/record `country` is `"United States"` (or inferred US) and the stripped string does **not** start with `1`, prepend `1`.45 - If the badge already supplies a leading `1` (e.g., `"+1 206 555 0177"`), keep it.46 - Examples:47 - `"(415) 555-0188"` → `"14155550188"`48 - `"+1 907 555 0108"` → `"19075550108"`49 - `"+1 (206) 555-0150"` → `"12065550150"`5051### 3.4 Campaign Members52- Reconcile existing `campaign_members` with badges.53- If a sponsor has a campaign member but no badge scan for the contact, still update the member to `attended_sponsor` when the event is completed and the sponsor is active.54- Sort `campaign_member_actions` by `subject_key` ascending using standard string ordering.5556### 3.5 Follow-up Dates57- `lead_due_date` = `end_date + followup_days_after_end`58- `sponsor_finance_due_date` = `end_date + sponsor_followup_days_after_end`5960## 4. Prospecting Tasks (e.g., aquafarm_robotics_2026, marinesense_2026)6162### 4.1 Qualification63- Read the exhibitor `description` and classify:64 - **Qualified**: makes or OEM-builds robotics or underwater-camera platforms.65 - **Excluded**: distributors, service-only, sensor-only, research-only.66- Assign platforms from the enum `["AUV", "ROV", "Underwater Camera"]` based on explicit description text.67 - If a company builds ROVs **with camera arrays**, include **both** `ROV` and `Underwater Camera` when the camera is called out as a built-in/integrated platform.6869### 4.2 Ranking & Tiers70- Sort qualified leads by:71 1. `requested_demo` (true first)72 2. `interest_score` descending73 3. Broader platform coverage (more platforms first)74 4. `company_name` ascending75- Priority tiers:76 - **A** ($120,000): demo requested + score ≥ 9077 - **B** ($90,000): demo requested + score ≥ 8078 - **C** ($50,000): all other qualified leads7980### 4.3 CRM Action81- `update_existing` if `crm_account_id` is present in exhibitor data.82- `create_account` if absent.8384### 4.4 Excluded Exhibitors85- Populate `relationship_type` and `exclusion_reason` from controlled enums.86- Sort by `company_name` ascending.8788## 5. Batch Import Tasks (e.g., fall_webinar_import)8990### 5.1 Deduplication91- Normalize email (lowercase, trim) and use it as the duplicate key.92- When multiple rows share the same normalized email, choose a **winner**:93 - Prefer the row with the **earlier** `captured_at` or the **lower** `row_id` when timestamps tie.94- The `removal_summary.removed_rows` **must include every removed row**: duplicates, suppressed, and missing-contact rows.9596### 5.2 Suppression97- Match raw contacts against the suppression list by **normalized email** or **normalized phone**.98- Remove matches with reason `"suppressed"`.99100### 5.3 Missing Contact Removal101- Remove rows where **both** email and phone are blank/empty after normalization.102- Reason: `"missing_contact"`.103104### 5.4 Clean Contacts105- For each surviving row, set:106 - `clean_contact_id` = winning `row_id`107 - `existing_account_id` = matching CRM account ID (by company name/domain), or `null`108 - `existing_contact_id` = matching CRM contact ID **only if the contact name/email actually matches**; otherwise `null`109 - `crm_action`:110 - `update_existing` when the account exists111 - `create_account` when no account matches112113### 5.5 Counts114- `import_action_totals` reflect the `crm_action` values of the surviving clean contacts.115- `campaign_member_import_count` = number of surviving clean contacts.116117## 6. Sorting & Ordering118- Adhere strictly to every `ordering` rule in the answer template.119- Common sorts:120 - `company_name` / `account_name` ascending121 - `rank` ascending (1-based contiguous)122 - `badge_id` ascending123 - `subject_key` ascending (standard string order)124 - `row_id` ascending125- Sorting errors are a frequent cause of partial credit.126127## 7. Test-Specific Rules128- Do **not** query or inspect entity IDs that are not explicitly named in the current staged prompt.129- Do **not** call global list/index endpoints to discover other events, shows, batches, tasks, or IDs.130- Query **only** endpoint paths and entity IDs explicitly named in the staged prompt.131132## 8. Common Pitfalls133- **Do not mix up tasks.** Each train task uses a different event/show/batch ID and schema. Verify the ID in the prompt before querying.134- **Do not omit removed rows.** `removed_rows`, `excluded_records`, etc. must be exhaustive.135- **Do not forget country-code normalization for US phone numbers.** The CRM stores digits-only phones with country codes.136- **Do not set `existing_contact_id` unless the contact truly matches.** An existing account does not imply an existing contact.137- **Do not include sponsor contacts in qualified leads.** Any badge from a sponsor company is excluded.138- **Do not update campaign members for excluded/disqualified accounts** unless the template explicitly requires it.