Portfolio/Michael G Attias — CaterzenMonday, June 29 at 8:18 AM EST
⌘KNotifications
Cy
MG
Consulting· started 2026-04-10· $2.0k/mo

Michael G Attias — CaterzenPAYING

Michael G Attias <michael@caterzen.com>, also Avi (engineering collaborator) · Last touched 1mo ago
North starMichael successfully runs the catering vertical playbook himself — closes BBQ + corporate caterer customers using the systems we built. Validates the "build-once-hand-off" pricing model.

Timeline

28 events · newest first
May 2026
May 26EVENT
AgentMail pod migration: shared "Cold Outreach" pod → dedicated "Caterzen" pod

Ricki created a dedicated AgentMail pod (pod_id 2af90166-…, same org as the main Cynthia pod) so CaterZen's per-client Hermes agent on cynthia-caterzen (5.78.209.54) can talk to AgentMail with a pod-scoped key that sees only CaterZen inboxes — no leakage of (or from) the other 40+ inboxes in the main pod. AgentMail offers no cross-pod transfer endpoint (verified against docs.agentmail.to/documentation/core-concepts/pods and probed live: PATCH /domains/{id} silently ignores pod_id; POST /domains to a second pod returns AlreadyExistsError). Only path = destroy + recreate. Executed:

  1. Snapshotted both the 11-inbox roster and all 3 domains' DNS records to data/agentmail-pod-migration-2026-05-26/ (recovery reference).
  2. DELETE /inboxes × 11 (all 11 — Michael×3, Ricki, Avi, Casey/Taylor/Morgan/Skyler/Harper/Riley) and DELETE /domains × 3 (mail./team./hello.).
  3. POST /domains × 3 against the new pod's API key. Diffed records: only the DKIM TXT changed per subdomain — MX, SPF, DMARC values are pod-agnostic and stayed identical.
  4. Updated Namecheap zone for caterzenteam.com via setHosts (full-zone replace) using data/agentmail-pod-migration-2026-05-26/update-namecheap-dkim.py. AgentMail re-poll via POST /domains/<id>/verify.
  5. Recreated the inboxes in the new pod. 8 of 11 live: michael×2 (mail./team.) + casey/taylor/morgan (mail.) + skyler/harper/riley (team.). 3 missing on hello.caterzenteam.com: avi/ricki/michael — that domain has all 5 records reading VALID per AgentMail and DNS confirmed byte-exact on Google/Cloudflare/OpenDNS, but the top-level status field is stuck at VERIFYING for 1+ hour while mail+team flipped to VERIFIED in ~5-10 min. Pure AgentMail backend lag with this specific domain object. Email AgentMail support to unstick if needed; otherwise wait and recreate the 3 hello.* inboxes later (they're duplicate identities — michael covered by mail./team., avi/ricki not actively sending). Cost of the migration: lost all inbox content + 10 days of mutual warmup conversation. The new pod has no peer inbox pool, so warmup needs to bootstrap from scratch. Outreach to the 160 ezCater OO prospects remains gated until persona inboxes hit warmup_day ≥ 21 in the new pod AND Michael confirms go.
May 26EVENT
Custom `email/caterzen` skill written for the CaterZen Hermes agent (NOT a clone of main agentmail skill)

Per Ricki's call — don't duplicate the main Cynthia email/agentmail skill on the per-client box; the multi-tenant guidance and 50+-inbox roster is wrong for a single-client agent. Wrote a fresh, focused skill scoped to CaterZen alone:

  • Path on box: ~/.hermes/skills/email/caterzen/
  • Source of truth in vault: hermes-skill/ (this folder is the editable copy; scp deploys to box)
  • SKILL.md — CaterZen-tailored: 11-inbox table grouped by real-name vs persona, decision matrix for which inbox to send from, brand voice per sender (Michael/Ricki/Avi/personas), hard rules ("never sign as AI", "cold outreach gated until warmup_day ≥ 21 + Michael go", "key stays in env never echo")
  • scripts/inbox.py — fresh 250-line Python script with 10 commands (list / recent / thread / read / search / send / reply / mark-read / label / counts). Cleaner subset than the main agentmail.py (480 lines) since this script only needs to cover what a single-client operator does. Reads pod-scoped key from ~/credentials/agentmail.env automatically.
  • references/cold-email-playbook.md — the ezCater OO wedge (7% + CC fees pain), the 160-prospect file path, the 5-8-line copy frame, 3-touch cadence, reply-classification table, things NOT to do (no screenshots, no "AI" mention, no feature pitch). Tested live: python3 ~/.hermes/skills/email/caterzen/scripts/inbox.py list on the box returns the 8 inboxes currently created in the new pod (the 3 hello.* will appear once that domain finishes verifying).
May 26EVENT
AgentMail API key saved on caterzen box at `~/credentials/agentmail.env`

Pod-scoped key for the "Caterzen" pod (am_us_pod_1a83d4449651…) saved on the box, perms 600, verified live (returns the Caterzen pod via /v0/pods). The script reads from this path automatically. Memory entries: [[caterzen-hermes-agent]] + [[agentmail-pod-migration-caterzen]].

May 16EVENT
caterzenteam.com AgentMail pool stood up + warmup started (11 inboxes)

Ricki connected caterzenteam.com to AgentMail yesterday (3 verified subdomains: mail., team., hello.) and provisioned 6 persona inboxes (casey/taylor/morgan on mail., skyler/harper/riley on team.). They sat un-warmed because nothing registered them in cold_email_inbox_settings — that table is what cold-email-warmup.js (PM2 #76) reads. Today (09:04 EDT): provisioned the 5 remaining inboxes Ricki asked for and registered all 11 into the warmup pool under tenant user_12166447650 (the existing Cynthia outbound tenant — joins the 35-inbox warmup pool so pairing has scale). New inboxes:

  • michael@mail.caterzenteam.com / michael@team.caterzenteam.com / michael@hello.caterzenteam.com — display "Michael Attias"
  • ricki@hello.caterzenteam.com — display "Ricki Bodner"
  • avi@hello.caterzenteam.com — display "Avi" Existing inboxes registered for warmup:
  • mail.caterzenteam.com: casey, taylor, morgan
  • team.caterzenteam.com: skyler, harper, riley All 11 set: warmup_enabled=true, active=true, warmup_day=0, daily_send_limit=30, tenant_id=user_12166447650. Round-trip delivery test passed: michael@mail.caterzenteam.comricki@hello.caterzenteam.com, message_id 0100019e30e45bed-61ee5d27...@email.amazonses.com, thread 1ba7a44e-2490, landed in ~3 seconds. Warmup PM2 service restarted to pick up the new rows. Ramp: 2 sends/day → 5 → 10 → 20 → 30 → 40 across 28 days. Graduation to cold-email-ready requires warmup_day ≥ 21 AND warmup_health ≥ 80. So earliest send-ready date for these inboxes: 2026-06-06. Script: ~/scripts/provision-caterzenteam-inboxes.js (idempotent — safe to re-run). OPEN: (1) decide whether catering cold-send should use Cynthia inboxes (per 2026-05-05-cynthia-sender-cold-email-framework.md) or these caterzenteam personas (strategy shift). (2) personas have no playbook/role_description tuned for catering yet — currently using a generic CaterZen description. (3) booking_link is unset on all 11 — needs Michael's Calendly. (4) These 11 inboxes are in the same warmup pool as Cynthia's other 35+ inboxes — fine for warmup (more pairing diversity) but means cold-email-sender will need a filter to only pick caterzenteam inboxes for CaterZen sends.

May 11EVENT
Ricki caught the quality gap — verified down to 109 actually-active OO restaurants

After publishing the 835 to analysis.cynthiaconcierge.com/caterzen-oo-list, Ricki pointed out the right thing: yesterday's 8 link-back-confirmed sites had a clean "Order Catering" nav button pointing to ezCater. The 835 didn't have that gold-standard verification — Wayback's archive only proves "someone, somewhere linked to /brand/pvt/{slug} at some point" not "this restaurant currently has the button on their homepage." Pulled the page, ran new script 21 (21-verify-ezcater-link-on-homepage.js) which is a CSV-driven port of script 06's link-back detector: for each row, fetch the homepage + /catering, /order, /menu, /order-online, /catering-menu subpages, grep for ezcater.com hrefs, score by context (nav/header + "order catering" CTA + /pvt/ URL = HIGH; only /pvt/ link present = MEDIUM; footer-only = LOW). Result on 835 inputs in 3 min @ concurrency 20:

  • 109 verified active OO (69 HIGH + 40 MEDIUM, 13% pass rate)
  • 5 LOW (weak signal, kept in deliverable)
  • 356 NONE — site reachable but no current ezCater link (42%)
  • 365 UNREACHABLE — Hetzner outbound flap, sites not responding (43%) The 109 HIGH+MEDIUM is the honest deliverable. Each one has a confirmed live link from their nav/header/catering-menu to ezcater.com/brand/pvt/{slug} — same gold-standard as yesterday's 8. Sample passes: 1492 New World Latin Cuisine, 7th Street Burger, 5th Street Pub, Acropolis Greek Taverna, Acropolis Cuisine, Another Broken Egg, Annapurna San Diego, Atria's Restaurant. Files:
  • data/ezcater-oo-VERIFIED-DELIVERABLE.csv — 109+5=114 with link-back proof (the clean deliverable, mirrored to analysis.cynthiaconcierge.com/caterzen-oo-list.csv)
  • data/ezcater-oo-VERIFIED.csv — full 835 with all statuses (audit trail)
  • data/ezcater-oo-VERIFY-unreachable-for-retry.txt — 365 slugs for tomorrow's retry via Apify proxy (should recover another 80-200 confirmed hits) Republished analysis.cynthiaconcierge.com/caterzen-oo-list with the honest 109 number + explanation of the 3-stage filter (Wayback → website resolution → homepage link verification). No more "candidates dressed as confirmations" risk for Michael.
May 11MILESTONE
835 confirmed OO restaurant websites delivered — Wayback Machine bypassed every dead end

After Ricki pushed back on the "we have 87, hit a wall" framing, found the actual unlock: Wayback Machine CDX API. ezCater's /brand/pvt/{slug} pages are noindex so Google has crawled few, but Wayback Machine has archived them over the years because restaurant sites link to them. CDX prefix query returned the full archived universe in seconds, free:

  • 2,918 unique /brand/pvt/{slug} slugs (brand-level OO pages, 5sec query)
  • 45,230 unique /catering/pvt/{slug} slugs (per-location OO pages, 43sec query) — but Subway alone is 13,091 of those; after chain-prefix filter → 23,088 indie locations remain Then ran parallel SerpAPI per-slug website resolver (script 20) against the 2,918 brand slugs to convert slugs → real restaurant websites in one pass. Got through 2,918 in 35 min before hitting SerpAPI's 1,000 searches/hour soft cap mid-run — last ~1,400 queries returned empty. Deliverable saved at data/ezcater-oo-CONFIRMED-WEBSITES.csv: 835 confirmed-OO restaurants with verified clean websites. Spans every state, mix of indie + multi-loc, every cuisine. This is 10× the 87 we had at start of day. Tomorrow's pickup: 2,062 remaining slugs need SerpAPI retry — saved as data/ezcater-oo-wayback-unresolved-for-retry.txt. After SerpAPI 1k/hr cap resets (rolls hourly), re-run: IN_FILE=~/vault/clients/michael-attias/data/ezcater-oo-wayback-unresolved-for-retry.txt OUT_BASE=~/vault/clients/michael-attias/data/ezcater-oo-wayback-resolved-retry CONCURRENCY=3 node ~/reach/scripts/b2b/20-resolve-wayback-slugs-parallel.js — concurrency=3 keeps us under cap (~0.6 req/s = 2,160/hr). Expect another ~1,200-1,500 clean restaurant websites = total ~2,000-2,300 confirmed OO universe. ~$10 SerpAPI spend. After that, the 45k /catering/pvt/ per-location universe is also available if Michael wants per-store granularity (separate run, slugs at data/ezcater-oo-wayback-catering-slugs.txt + filtered indie set at data/ezcater-oo-wayback-catering-slugs-indie.txt).
May 11ANALYSIS
Mapped the limits of every "find OO customers" approach — gold standard remains restaurant-side link-back

Worked through Michael's bigger-than-87 ask. Resumed last night's SerpAPI state-query scrape that completed all 50 states overnight to 87 unique /brand/pvt/{slug} slugs (Google-indexed Online Ordering pages). Resolved 75/87 to clean restaurant websites via SerpAPI per-slug lookup (script 15). Files: data/ezcater-oo-slugs-resolved.csv + .json. Then attempted Phase 2 universe expansion via two failed paths: Path A — ezCater sitemap pull. Yesterday's "Cloudflare blocked us" diagnosis was wrong — the 7 sitemap URLs at www.ezcater.com 303-redirect to static.cdn-ezcater.com which is not CF-protected. Pulled all 7 cleanly: 30,082 unique marketplace brand slugs. Saved to data/ezcater-marketplace-brand-slugs.txt. But — every marketplace brand also has a /brand/pvt/{slug} page auto-generated. So the sitemap gives us all marketplace brands, not all OO users. Different bucket. Path B — /brand/pvt/{slug} existence probe. Built script 16 to probe every marketplace slug. After 523/30,082 done (alphabetic A's), Cloudflare rate-limited us — 263 consecutive 403s. But more importantly, every probe returned 200 with isPrivateStore: true. Finding: the /brand/pvt/ page exists for every marketplace brand whether they actively use OO or not. The probe doesn't filter. Partial results saved to data/ezcater-oo-probe-partial-* for future cross-reference. Gold standard signal stays unchanged from 2026-05-01: the only reliable "this restaurant actively uses ezCater OO" indicator is an outbound link from the restaurant's own homepage to ezcater.com/brand/pvt/{slug}. Script 06 already detects this. The 31 hits on the 2,615-caterer cohort (May 1) is the existence proof. Real expansion path = bigger restaurant universe + script-06 link-back scan, NOT ezCater-side enumeration. Best routes:

  • Run [MA-WK19-02] Apify Maps universe expansion ($200-400, ~50-80k restaurants, expect ~600-1k OO confirmations at 1.2% historical rate)
  • Backlink crawl via Ahrefs/SEMrush API ($50/mo, direct backlinks to ezcater.com/brand/pvt/* from across the web — purest signal)
  • Bing SerpAPI mirror of the state-query scrape (different index, may pick up brands Google missed) Net deliverable from today: 87 confirmed OO slugs with 75 clean restaurant websites in data/ezcater-oo-slugs-resolved.csv. Smaller than the original 5,000+ hope, but high-confidence (every slug is Google-indexed, every website is direct restaurant site after manual noise filter).

May 5EVENT
Michael's response to form + leads tool — addressed all 4 points

Michael emailed back on the audit form + leads tool we shipped earlier today. Four points: (1) Form was hard to complete — couldn't pinpoint exactly where it hung. Decision: he and Avi will host the form on their own domain and feed it into HubSpot + their audit model. (2) Leads tool false positives — Chicken Salad Chick (uses OLO, not ezCater) and The Flying Biscuit Cafe (already a Caterzen customer per restaurantcateringsystems.com/tfbcafeatlanta/) were appearing in the prospect list. He spot-checked and lost trust in the data. (3) Don't single ezCater out by name — he's integrating with them. New phrasing: "stop paying 5-10% of catering sales to use 3rd party online ordering software for your catering that does not provide a full catering software suite." (4) Instantly visibility — wanted access to "our Instantly" to see messaging + dedupe vs his consultant. We don't use Instantly (AgentMail). His consultant runs Instantly for him, grocery-store-only. Addressed all 4 in one pass:

  • Hand-off package at data/avi-handoff/ (and zipped at data/avi-handoff.zip): audit-form.html + scoring.js + backend-handler.js + schema.sql + README.md with HubSpot mapping example. Self-contained drop-in.
  • ezCater branding stripped from ~/catering-landing/audit/index.html (sidebar leak callout + marketplace question label) and from ~/services/catering-audit-scoring.js (flagged-leak string). PM2 reloaded.
  • Generalized "3rd party online ordering" detection built in ~/services/detect-online-ordering.js (replaces detect-ezcater-links.js). Tiers ezCater into white_label (/pvt/ or ?fcv=) vs marketplace; also detects OLO, ChowNow, Toast Catering, Square Catering. Smoke-tested on Chicken Salad Chick → correctly identified as olo with URL https://chickcatering.olo.com/.
  • Caterzen-already detector at ~/services/mark-caterzen-customers-in-leads.js. Name-matches enriched_leads against the 1,438-row customer xlsx (jaccard ≥ 0.75). Found 23 prospects who are already Caterzen customers: 8 active, 15 cancelled. Flagged all 23 with caterzen_already=TRUE, status preserved in caterzen_already_url for UI to split active vs former.
  • Migration at ~/services/migrations/042-online-ordering-detection.sql adds online_ordering_vendor + caterzen_already columns, backfills from existing ezCater data.
  • API extended at ~/services/catering-leads-webhook.js with uses_third_party_oo, oo_vendor, and exclude_caterzen_already (default ON) query params; new stats fields; new lead-row fields.
  • Leads UI relabeled at ~/catering-landing/leads/index.html: "Uses ezCater" → "3rd-Party Online Ordering" + new "Hide Caterzen customers" filter chip (default ON). Vendor + Caterzen status surfaced in drawer overview tab. Net effect on the leads page Michael will land on: defaults to 12 valid prospects (down from 736 caterers) — Chicken Salad Chick + Goodrich Gourmet auto-excluded as Caterzen customers, ezCater marketplace-only listings auto-excluded as wrong-tier. Reply email drafted at data/2026-05-05-reply-to-michael-feedback.md. Awaiting Ricki send.
May 5MILESTONE
Catering Growth Audit form + scoring engine shipped end-to-end

Built the qualifying form Michael asked for on the 5/1 call — live at https://catering.cynthiaconcierge.com/audit/ (4-step mobile-responsive form, JetBrains Mono / Cynthia × Caterzen co-branded). Backend at POST https://app.cynthiaconcierge.com/catering-audit (port 3109, cynthia-catering-leads PM2 service) runs the scoring + persists to new Supabase table catering_audit_submissions (42 cols). Scoring module: ~/services/catering-audit-scoring.js — pure module, 5 category scores (volume / channel control / conversion / growth / overall), 8 auto-flagged revenue-leak rules. End-to-end verified: Michael's sample data (3 stores, $721k volume, 0% marketplace, "no_system"/"rarely"/"minimal" answers) scores 40/100, qualified (≥$100k), 7 leaks flagged — matches Michael's spreadsheet exactly. Below-$100k threshold submissions correctly route to nurture without notifying Michael. Routing: all submissions → iMessage Ricki with full scorecard. Qualified only → iMessage Michael with audit hand-off. CRM event for tracking. OPEN: Michael's phone number (placeholder in code), audit deliverable spec, Catering Growth Playbook PDF for unqualified nurture, Cynthia sender inbox choice, enrichment of the 110 A-band (still blocked by Hetzner outbound flap). Full launch plan: analyses/2026-05-05-launch-plan.md. Files: ~/services/catering-leads-webhook.js (extended), ~/services/catering-audit-scoring.js (new), ~/services/migrations/catering-audit-submissions.sql (new), ~/catering-landing/audit/index.html (new, 26KB).

May 5MILESTONE
Empirical scoring shipped + 414 quick-win prospects surfaced in maps-seed

Wrote ~/reach/lib/caterzen-empirical-scoring.js — pure module, 100-point scoring (40 vertical / 12 rating / 12 reviews / 10 multi-loc / 8 income / 5+5 has-website/phone / 8 US). Vertical weights derived from retention table (Mediterranean 0.78, Cafe 0.76, …, American 0.0). Tier-C drop-list explicit (Pizza/Salad/Bar&Grill/American/Healthy-Salad). Sanity check verified: Mission BBQ (his whale) → 73.6 A, Taziki's Mediterranean → 85.2 S, generic Pizza → 48.4 drop. Wrote apply-script ~/reach/scripts/b2b/12-rescore-empirical.js and re-scored existing maps-seed cohort. Result: 110 A-band + 304 B-band = 414 prospects he can work today (top hits: Sahara Restaurant, Maiwand Kabob, Shawarma House, Everest Cuisine, Falafel's Drive In, Sabrina's Cafe, maman, Flying Biscuit, CAVA — all 4.6+ rating, 1k+ reviews). Distribution: 110 A / 304 B / 1,975 C / 226 drop. 0 S-band because maps-seed doesn't have multi-loc data populated; the new universe scrape will fix that. Tweaked ~/reach/app/api/b2b/companies/route.ts to support &value= filter parameter and surface discovery_score_v2/score_band_v2/empirical_vertical in responses. Built + restarted cynthia-reach. Filter URL: https://reach.cynthiaconcierge.com/api/b2b/companies?cohort=maps-seed&attribute=caterzen_empirical_band&value=A&limit=200. Michael can log in and see them.

May 5MILESTONE
Full Caterzen customer list (1,437) ingested + ICP fingerprint identified

Michael sent ~/incoming-screenshots/CaterZen_Accounts_-_Current_Former.xlsx — 1,438 rows of his entire current+former customer book with MRR, LTV, locations, sales, Google ratings, POS, prior catering software, billing dates. Wrote ingest script ~/reach/scripts/b2b/11-ingest-caterzen-customers.js with cohort caterzen-customers-2026-05-05. Dry-run confirmed zero name overlap with existing maps-seed/ezcater-universe cohorts → safe additive ingest. Live run: 1,437 Company nodes + 8,295 Attribute edges in 2.2s. Headline ICP finding (changes our targeting): Mediterranean retains at 78% active and Cafe at 76%, vs BBQ 34% / Caterer 26% / Pizza 11% / Bar&Grill 3% / American 0%. Mediterranean and Cafe should be the over-fish targets; Pizza/Salad/Bar&Grill/American/Healthy-Salad should be DROPPED from the universe scrape entirely. Other signals tagged in graph: 29 top-spender anchors (LTV ≥$50k), 64 multi-location chains (≥5 locs), 119 with disclosed prior software (ezCater 18 = #1 displaced), 402 active / 60 suspended / 974 cancelled. Active-client fingerprint: 4.46 mean Google rating, median 710 reviews, 77% single-location, mean 5.8 years a client, $90k median area income. Full analysis at analyses/2026-05-05-caterzen-customer-fingerprint.md. Targeting decision shift: the new universe scrape (the proper Apify Maps run we discussed) gets re-weighted scoring derived from this empirical fingerprint instead of heuristic weights. Mediterranean/Cafe category sweeps added; Pizza/Salad/Bar-Grill dropped. The 29 top spenders + 64 multi-loc chains become the lookalike anchors for nearest-neighbor scoring.

May 5DECISION
Don't wipe his Reach graph — additive new cohort instead

Discussed full graph wipe. Decided against — risk of bad DELETE on shared Neo4j outweighs cost of dead-weight ezCater stubs. The 139k stubs and 2,615 maps-seed cohort stay untouched; new work uses the fresh caterzen-customers-2026-05-05 and (next) customer-lookalike-2026-05-XX cohorts. The 33 link-back-confirmed Companies + 22 Apollo Persons remain in place as a regression check for the new pipeline.

May 5ANALYSIS
Confirmed 139k ezCater stubs are wrong-ICP

Michael clarified ezCater has TWO products: Marketplace (DoorDash-style; restaurants pay commission) vs Online Ordering (restaurant adds an "Order Catering" link to their OWN site that goes to *.ezcater.com/brand/pvt/{slug}; pays 7% + 3% CC). Only Online Ordering customers feel the "paying for my own customers" pain that the cold-email savings angle relies on. Verified: of 139,432 stubs in ezcater-universe-2026-05-01, 0 are /brand/pvt/ (Cloudflare blocks them, not in public sitemap) — they're all marketplace pages. Wrong bucket. Online Ordering customers are detectable only via link-back from their OWN site (script 06 already does this against the 2,615-cohort and found 31 confirmed). De-prioritizing the 967 Tier A randomized brand pages from the v1 priority list.

May 1MILESTONE
Full EzCater universe (139,432) ingested + top-1k v1 priority list tagged

Pulled all 7 chunks of ezCater's public sitemap (static.cdn-ezcater.com/landings/sitemaps/) — 139,700 unique restaurant landing URLs. Ingested 139,432 as Company stubs in Michael's tenant under cohort ezcater-universe-2026-05-01, all tagged with ezcater_listed=true Attribute. Bucket: 29,648 multi-location brand pages + 109,784 single-location restaurant pages. Each stub has ezcater_listing_url, ezcater_slug, name-derived-from-slug; everything else (real name, address, phone, own website) unscanned because ezCater's listing pages sit behind Cloudflare bot protection — needs CloakBrowser or FireCrawl proxy for Phase 1b. Then ran ranking script (reach/scripts/b2b/10-rank-ezcater-universe-v1.js) to pick the top 1,000 for v1 work without scraping. Strategy: Tier S = 33 link-back-confirmed from script 06 (already gold), Tier A = 967 randomized public brand pages (/brand/{slug}, no /pvt/) for diversity instead of alphabetical bias. Tagged all 1,000 with ezcater_priority='v1' Attribute + ezcater_priority_tier ('S' or 'A'). Output: data/2026-05-01-ezcater-v1-priority-1000.csv. Filter URL: https://reach.cynthiaconcierge.com/api/b2b/companies?attribute=ezcater_priority&limit=1000. Sample diversity check: hits Asian, Italian, Latin, BBQ, brunch, dessert, indie operators across many states — exact ICP for Caterzen mid-market regional positioning.

May 1MILESTONE
EzCater data fully persisted + filterable in Michael's Reach tenant

Per Ricki "save it in his graph; don't send anything yet." Verified all V1 data is in tenant user_u221db309b1cb: 33 Companies tagged ezcater_user=true Attribute, 22 Apollo Person nodes (20 with verified emails) with :WORKS_AT edges. Backfilled entity_role='decision_maker' on existing Apollo Persons + patched script 08 so future runs set it correctly. Added ?attribute=ezcater_user filter to /api/b2b/companies route + exposed ezcater_link_status/ezcater_link_url/phone in the response. Built + restarted cynthia-reach. Verified end-to-end with Michael's tenant token: filter returns 33 companies, decision_maker_count populated for the 12 enriched ones. Full data-layout doc at notes/2026-05-01-reach-graph-data-layout.md. Filter URL: https://reach.cynthiaconcierge.com/api/b2b/companies?attribute=ezcater_user&limit=200. UI deep-link chip queued as MA-WK18-20 (low priority — API works).

May 1MILESTONE
V1 send list ready — 19 verified contacts at 12 companies, $1.52 spent

After V1 scan completed: ran FireCrawl recovery pass (script 07) on the 1,404 unreachables — blocked at 402 Payment Required after ~46 successful scrapes (recovered 1 high). FireCrawl account needs top-up for a real recovery; deferred to v1.5 push. Then ran Apollo enrichment (script 08) on the 31 confirmed hits (20 high + 10 medium + 1 ezcater_as_website). Apollo searched 32 → 38 candidates → 34 matched → 20 with verified email → after dedup + dropping 1 suspect personal-email match (Perkins/shaw.ca) → 19 contacts at 12 companies. Quality: mix of multi-location chains (Dick's Last Resort, Eatzi's, Golden Chick, Rainforest Cafe, RA Sushi) + high-fit independents (Taylor Made BBQ, Main Squeeze Juice, Pine State Biscuits, Lefty's, Frank & Furter's, Rosamunde, Jerry's Kitchen). Owner/CEO/GM/Marketing-Director title spread. Files: data/2026-05-01-ezcater-send-ready-cleaned.csv (AgentMail import) + data/2026-05-01-v1-send-list-for-michael-review.md (Michael's review doc with grouped contacts + the specific ezCater URL we found per company). AWAITING Michael's go/no-go on 5 questions before send.

May 1MILESTONE
V1 EzCater scan complete — 66 confirmed hits across 2,615 caterers

Run finished in 987s. Distribution: 20 high / 10 medium / 35 low / 1 ezcater_as_website / 1,395 none / 1,404 unreachable. The high+medium tier is the immediate send list — quality is excellent: Dick's Last Resort, Eatzi's Market & Bakery, International Smoke (Stephanie Izard), Golden Chick, Perkins American Food Co., Rainforest Cafe, RA Sushi, The Hampton Social, Pine State Biscuits, Angelina Bakery, Menchie's, Charlie's Bakery & Creamery, Picasso's Pizza. Mostly multi-location chains — exact ICP for Caterzen's mid-market positioning. Output CSV: data/2026-05-01-ezcater-online-ordering-prospects.csv. Neo4j props (ezcater_link_status, ezcater_link_url, ezcater_link_pages) and ezcater_user=true Attribute edges written for high+medium hits — filterable in Reach UI. Concerning: 53.7% unreachable rate from this Hetzner box (the long-tail mom-and-pop site flap pattern). Firing FireCrawl re-scan (script 07) immediately to recover false negatives. After re-scan → Apollo enrichment (script 08) for verified emails on confirmed hits.

May 1EVENT
[confirmation+execution] Michael confirmed all 4 EzCater questions; V1 homepage scan launched

Michael confirmed verbatim: "7% is just to use online ordering tech. Plus they pay to process credit cards. We can offer free credit card processing. Huge savings. We provide online ordering plus a suite of catering sales and operational tools. Whether they are on the marketplace or not, they should be targeted if their web site links to EzCater. Catering companies and any/all restaurants on their platform." Locks: 7%+CC processing fees stack (FREE CC processing is the new wedge), website-link signal alone, universe expands to all restaurants (V1 = 2,615 caterers, V2 = restaurant expansion). Updated analyses/2026-05-01-ezcater-two-products-and-targeting.md with confirmed answers + refined cold-email frame. Wrote new script reach/scripts/b2b/06-detect-ezcater-links.js and launched against 2,615 cohort with concurrency=16. Smoke-test on top 20 found 1 medium hit + revealed an "ezcater_as_website" noise bucket (companies whose Apify-recorded website IS already an ezcater.com URL — fixed by detecting + bucketing separately). Early signal at 150/2615: ~5-6% confirmed-hit rate, ~49% unreachable (Hetzner outbound flap — needs second-pass scan via FireCrawl). Output → data/2026-05-XX-ezcater-online-ordering-prospects.csv + Neo4j props.

May 1ANALYSIS
EzCater two-product breakdown + targeting cut written

Confirmed via ezCater's own marketing pages that they sell two distinct products: Marketplace (ezCater drives traffic, restaurant pays commission on orders received) and Online Ordering (restaurant adds an ezCater checkout link to their OWN site, drives their own traffic, pays a smaller fee — likely the 7% Michael cited). Only Online Ordering users feel the "paying for my own customers" pain that the cold-email savings angle relies on. Diagnostic signal: outbound link from caterer's homepage to *.ezcater.com/catering/*. Wrote full breakdown + open questions for Michael at analyses/2026-05-01-ezcater-two-products-and-targeting.md. Awaiting Michael's confirmation on (1) is 7% the Online Ordering rate, (2) include both-products operators or filter, (3) savings calculator, (4) offer attached. Once confirmed, ~30-60 min homepage scan against the 2,615-cohort produces the seed list.

May 1CALL
2026-05-01 outbound + form-first funnel alignment call (31 min)

Michael flipped direction from the 04-30 refocus plan. Instead of building the Audit-to-Pitch Toolkit, he wants outbound + a qualifying form NOW. Two parallel cold-email tracks: (1) EzCater fee-savings angle for EzCater Online Ordering users, (2) generic Caterzen Growth Audit. Form filters by catering revenue (≥$100k qualifies for full audit + sales call; <$100k → nurture). Michael / Joel building the form in HubSpot; we owe vetted lead list + first send within 24-48 hr. Pricing benchmark from grocery proposal: $2,500 setup + $1,200/mo. Transcript at notes/2026-05-01-outbound-and-form-alignment-call.md. Action items + extracted pains/qualifying info captured in row analysis.

May 1EVENT
Fixed manual-upload "fetch failed" bug in meet app

Reprocessed Michael's call required fixing meet/lib/upload-processor.ts — Hetzner→Deepgram routes flap on a sub-minute cadence and the original single-fetch implementation kept landing on route-broken IPs. Replaced with parallel race across 7 known Deepgram backend IPs using native https module + servername SNI, two-phase timeout (8s connect / 10min wall-clock for batch processing). All future manual uploads will be resilient. Failed session a5fba7f0… reprocessed cleanly: 1,875s, full structured analysis.

Apr 2026
Apr 30ANALYSIS
Refocus + game plan published to analysis.cynthiaconcierge.com/caterzen

After re-reading both call transcripts, recognized we've been solving the wrong problem. Michael never asked for leads — both calls were dominated by him asking for delivery/build help (vibe-coding, restricted UI for end customers, AI voice, lead dashboard). The 04-23 call was 89 min of Avi asking technical questions, not "where are my leads." Wrote analysis at https://analysis.cynthiaconcierge.com/caterzen with the honest reset: stop building outbound infra, start building the Audit-to-Pitch Toolkit (mystery-shop + audit + site mockup + pitch deck — all auto-generated, ~20 hours of build, takes per-prospect time from 15 hrs → 3 hrs = 4× more closes/month with same operator). The 2,615-caterer cohort sits in reserve until he asks. Source file: /home/cynthia/analysis/caterzen.html.

Apr 30MILESTONE
Catering vertical classifier + ICP scoring shipped

Built Phase 2 + Phase 3 of Reach catering pipeline. New modules: lib/company-attributes.js::classifyCateringVertical (14 buckets per Michael's ICP), lib/catering-scoring.js::scoreCateringCompany (0-100 weighted score). New scripts: scripts/b2b/02-classify-catering-verticals.js, scripts/b2b/03-score-catering.js. Applied to all 2,615 companies. Result: 1,389 A-band (≥80), 670 B-band, 504 C-band. Top BBQ A-band: Agape BBQ (TX), B-ACK Yard BBQ (MA), BEAST Craft BBQ (IL). Verified via /api/b2b/companies?vertical=bbq&min_score=80 returns scored, sorted, filtered list. Michael's pipeline is now usable end-to-end via the existing Reach UI.

Apr 30MILESTONE
Reach tenant provisioned + 2,615 caterers seeded

Created Reach account michael@caterzen.com / cynthia2026, tenant_id user_u221db309b1cb (mirror of Dane/Wendy provisioning pattern). First tenant on local-business data source — built lib/local-business-ingest.js + scripts/b2b/01-ingest-catering-businesses.js since the existing LinkedIn pipeline (Dane) doesn't fit restaurants. Ingested 3,153 Apify Maps records → 2,615 unique Companies + 30,795 attribute edges in 5.6s. Industries: 1,087 Caterer / 166 Mobile caterer / 113 Event venue / 61 Catering supplier / 57 BBQ. Top states: CA 558 / TX 248 / FL 143. 1,642 high-rated (≥4.5). UI: https://reach.cynthiaconcierge.com/data-center/b2b.

Apr 30ANALYSIS
Workspace fully backfilled + lead-gen plan written

Spotlight surfaced the empty workspace. Pulled both call recordings (04-14, 04-23) into notes/. Wrote synthesis + lead-gen plan to analyses/2026-04-30-where-michael-is-and-what-he-needs.md. Core finding: Michael has product + Avi + first close (Brooks Grocery) — what's missing is top-of-funnel volume. Plan: turn on done-for-you cold email outreach against the 9k EasyCater list, branded as a Caterzen Growth Audit, replies routed to Michael's calendar. ~16 hours of build work; needs 4 decisions from Michael before sending. Queue updated.

Apr 30EVENT
04-23 transcript extracted from Supabase

Pulled 89-min Meet recording transcript (1,160 segments, 3 speakers) and converted to clean markdown at notes/2026-04-23-vibe-coding-followup-transcript.md. Chapter summaries preserved. Showed Michael actively building with Avi (Lovable, barbecuecateringbusinessacademy.com) and pursuing Brooks Grocery (Tupelo MS) as first closed client.

Apr 30EVENT
04-14 transcript copied into workspace

Copied ~/recordings/ricki-michael-caterzen-growth-call-2026-04-14-transcript.mdnotes/2026-04-14-growth-call-transcript.md for completeness.

Apr 29MILESTONE
Workspace created from Stripe sync

Surfaced via Stripe sync 2026-04-29. $2K/mo subscription active since 2026-04-10. Workspace stub created with state.yaml, queue.md, README. Backfill required: scope of engagement, decision maker context, north star.