il-marketplace-pull skill (v2 — consolidated 2026-04-28)

Role: IL-specific data adapter feeding the centralized acquisition_deals table. Adds wholesaler company-level enrichment that the base IL pipeline doesn’t cover.

v2 change vs v1: Five scripts that duplicated existing workspace code have been retired. v2 keeps only the genuinely-new pieces.

⚡ Execution-mode model routing (G-MODEL-ROUTING-AT-EXEC)

This skill is execution-mode by definition. Per CLAUDE.md “MANDATORY: Execution-Mode Model Routing” + feedback_model_routing_at_exec.md:

Step 1 of every invocation: decompose the work and dispatch via the Agent tool with model: "sonnet" using the 8-element prompt contract (task goal, evidence, tool to use, test requirements, acceptance criteria, rollback command, rule constraints, output format).

Opus (main conversation) role = dispatcher + verifier + Henry-gate. Direct Opus script invocation / code edits = governance violation unless the work fails the Sonnet rubric (novel architecture, rule arbitration, Henry decision gate, first instance of a new pattern). Verify each subagent report against acceptance criteria before marking complete.

Architecture (where this skill sits)

IL list/detail API
        │
        ▼
[workspace/scripts/sync-il-api-to-supabase.js]   ← list pull (existing, NOT in this skill)
[workspace/scripts/enrich-il-deals-detail-api.js] ← detail + description regex mining (existing)
        │
        ▼
acquisition_deals (CCP — universal source-agnostic table)
        │
        ▼
[acquisitions-outreach skill] ──→ HubSpot via [hubspot-deal-ingest skill]
        │
        ▼ (parallel branch — what THIS skill adds)
[il-marketplace-pull/scripts/enrich-contacts.js] → wholesaler_contacts (Apollo + Hunter)
[il-marketplace-pull/scripts/account-rollup.js]  → analytics (no DB write)

What this skill provides (only the net-new)

1. enrich-contacts.js — wholesaler company-level enrichment

For each unique account_id in acquisition_deals (one wholesaler can have 50+ deals), find the wholesaler’s company domain via Apollo and the dispositions manager’s email via Hunter. Writes to wholesaler_contacts table (source-agnostic — works for any source, not just IL).

node ~/.claude/skills/il-marketplace-pull/scripts/enrich-contacts.js \
  [--top=50]             # top-N accounts by deal count
  [--account-id=N]       # specific account
  [--budget=50]          # max Hunter credits per run (free tier = 50/mo)
  [--dry-run]

Pipeline per account: Apollo /v1/organizations/enrich (free) → Hunter /v2/email-finder (1 credit/match).

2. account-rollup.js — wholesaler analytics

Group by account_id, surface top wholesalers by deal volume. Read-only — no DB writes.

node ~/.claude/skills/il-marketplace-pull/scripts/account-rollup.js \
  [--top=25]
  [--from-list=/tmp/il-list.json]   # offline mode, no DB needed
  [--from-db]                        # query acquisition_deals
  [--with-managers]                  # include manager names

Output: account_id, total deals, active/pending/sold split, top 3 states, avg price, top wholesalers.

bash ~/.claude/skills/il-marketplace-pull/scripts/cookie-status.sh

Returns OK (live) or STALE (refresh needed). Auto-SSHes to Mac if run from VPS.

What this skill does NOT do anymore (use existing workspace scripts)

TaskUse thisNot the v1 script
Pull IL list, upsert to Supabaseworkspace/scripts/sync-il-api-to-supabase.jsscripts/upsert-list.js (retired)
Detail enrichment + description miningworkspace/scripts/enrich-il-deals-detail-api.jsscripts/enrich-detail.js + scripts/mine-descriptions.js (retired — both functions already in the workspace script)
Daily sync orchestrationworkspace/scripts/investorlift-daily-sync.shscripts/pull-list.sh (retired)
Cookie refreshworkspace/scripts/investorlift-refresh-cookies.js (Playwright auto-refresh on Mac)scripts/cookie-refresh.sh (retired runbook)
HubSpot synchubspot-deal-ingest skill (calls workspace/scripts/hubspot-deal-creator.js)

Centralized schema (READ FIRST)

Per project_acquisition_deals_centralized_schema.md (2026-04-28):

  • All deal data → acquisition_deals (CCP svueekfvfrvhylxygktb, ~70 columns including meta JSONB)
  • All wholesaler company-level data → wholesaler_contacts (renamed from data_il_marketplace_contacts)
  • NEVER create per-source data_<source>_* tables again (this skill v1 made that mistake)

Triggers

User says any of:

  • “enrich IL wholesaler contacts” / “find IL wholesaler emails”
  • “rollup IL accounts” / “top IL wholesalers”
  • “check IL cookies” / “are IL cookies stale”

For “pull IL deals” / “scrape investorlift” → DO NOT route here. Route to workspace/scripts/investorlift-daily-sync.sh (the existing pipeline).

Capabilities matrix

CapabilityWhere it livesCost
List pull (54K rows)workspace/scripts (NOT this skill)Free
Detail enrichment (60+ fields, regex-mined phones/emails)workspace/scripts (NOT this skill)Free, ~22h sequential
Wholesaler domain + LinkedIn (Apollo)this skill — enrich-contacts.jsFree
Wholesaler manager email (Hunter)this skill — enrich-contacts.js1 credit/match, 50/mo free
Account-level analyticsthis skill — account-rollup.jsFree, query only
Cookie freshness probethis skill — cookie-status.shFree

Failure modes

SymptomCauseRecovery
relation "wholesaler_contacts" does not existSchema migration not yet appliedRun schema migration (see HANDOFF-FOR-KIMI Phase 0)
relation "acquisition_deals" does not existWrong Supabase projectConfirm SUPABASE_URL points to CCP svueekfvfrvhylxygktb
Hunter 429Rate limitSleep 60s, retry; consider --budget
Apollo returns nothingWholesaler too small for Apollo’s indexSkill falls back to heuristic domain (lowercase company.com)
Cookie status STALEIL cookies expiredRun workspace/scripts/investorlift-refresh-cookies.js on Mac (NOT this skill)

Memory cross-references

v1 → v2 retirement summary (audit by Kimi)

Five scripts retired because they duplicate live workspace code:

v1 retiredReasonReplacement
scripts/upsert-list.jsDuplicates sync-il-api-to-supabase.js (writes to acquisition_deals, not data_il_marketplace)workspace/scripts/sync-il-api-to-supabase.js
scripts/enrich-detail.jsDuplicates enrich-il-deals-detail-api.jsworkspace/scripts/enrich-il-deals-detail-api.js
scripts/mine-descriptions.jsAlready inside enrich-il-deals-detail-api.js (lines 113-118 of that file)(same)
scripts/pull-list.shDuplicates investorlift-daily-sync.sh orchestrationworkspace/scripts/investorlift-daily-sync.sh
scripts/cookie-refresh.shManual runbook duplicates auto Playwright refresh on Macworkspace/scripts/investorlift-refresh-cookies.js

Retirement happens after Kimi confirms the workspace replacements work end-to-end. Until then v1 scripts remain in place but documented as deprecated.