Run #017 · 2026-05-05 · 8 agent review

Buyside Hunt Routine Review

Conductor: Ewing · Mission: turn the buyside acquisition target hunt into a Slack-callable routine. SHIP with three fixes applied same day, seven items in backlog.

What it does

A buyside searcher gives Mark or Ewing their criteria (geography, EBITDA band, verticals). The routine produces a polished HTML letter with a 15 to 25 company shortlist in 8 minutes. Letter format. Operator to operator voice. PDF ready. Zero em dashes.

First customer: Jonathan, self funded searcher in Carmel Valley San Diego, 16 month search, $500,000 to $2,000,000 EBITDA, route based and equipment driven service shops inside 50 miles. 22 qualified targets across 5 verticals on the first run. Two verticals were swapped (septic and dumpster came back too thin). Final five: window cleaning, pressure washing, landscape, pest, pool.

Run KPIs

22
Qualified targets
5
Verticals delivered
116
Candidates screened
85.4
Avg score
8 min
Run time
~$3
Exa cost / run
8 / 8
Agents agreed: SHIP
3 / 7
Fixes done / backlog

Per agent verdicts

AgentPhase 1 VerdictHeadline
architectCOHERENT_HOMEOne BLOCKING flag: confirm Slack signing secret. No new repos or DBs.
data-architectSCHEMA_DRAFT_NEEDEDThree new tables: buyers, buyside_runs, vertical_margin_bands. All canonical from day one.
quarterbackGAPS_EXISTFive plumbing gaps, additive only. Lazy scaffold deal manager skill only after engagement signed.
audit-dataREWORK 58/100HQ false matches, cross vertical dupes, no DNC pre screen. All three fixed same day.
audit-skillsREADY_TO_BUILDSkill registered at ~/.claude/skills/buyside-hunt/. One trigger collision with writer's "buyer list" resolved.
audit-qualityCONCERNS 80/100Ten point checklist: high on copy + security + observability, low on reusability + production readiness.
writerPASSBanned phrases scan clean. Three Slack reply templates drafted.
storytellerNEEDS_NARRATIVE_DESIGNMandatory human review gate before delivery. Buyer state continuity for run to run.

Three fixes shipped same day

Cross vertical dedup added after per vertical scoring. Same company can no longer appear in two verticals (was: All Pro Pressure Washing in window cleaning AND pressure washing).
HQ mismatch hard fail gate added before scoring. Parses Exa's "Headquartered in X, Y" first. Drops Nashville, Tempe, and Sacramento companies that previously survived as score 94 entries because Places API force resolved them to the buyer's city.
_template.json backfilled to full v1.1 schema. Every new buyer config now inherits the preamble block, adaptive threshold floor, min per vertical, and per vertical required keywords / exclude keywords. The "drop in JSON, get polished report" claim is no longer hollow.

Backlog (7 items, ranked)

1. Promote buyer configs to Supabase buyers table at >= 10 buyers. Schema in data architect Phase 1 verdict.
2. buyside_runs table for audit trail. Every Slack invocation logs a row.
3. vertical_margin_bands lookup table so margins are editable without code deploy.
4. DNC and active deal pre screen against existing pipelines (Capstone, Design Precast, HR.com).
5. Slackbot pre flight before external exposure: cost ceiling, allow list of buyer slugs, async dispatch behind a queue, microsecond run id resolution.
6. Buyer state continuity so successive runs reference the prior run ("we widened the radius and dropped pool service per your note").
7. Tighten extract_owner regex to reject names with whitespace anomalies or company tokens.

How to use

From CLI today:

doppler run --project clawdbot --config dev -- \
  python3 engine/contacts/pipeline/buyside_hunt_v1.py \
  --buyer <slug> \
  [--per-query 20] \
  [--push-supabase]

To onboard a new buyer: copy engine/contacts/configs/buyers/_template.json to <slug>.json, fill in geo / EBITDA band / verticals / preamble, run.

To iterate copy without re running Exa: add --rerender-only <run_dir>. Costs zero API calls.

Slash command (planned): /buyside-hunt <slug> in Slack hits an API route at next-chapter-os/api/slack/buyside-hunt, enqueues a job row in Supabase, Mac mini Hermes worker runs the pipeline, posts public URL back to channel.

Patterns banked

  • Audit-data: if a signal is strong enough to trigger a warning, it's strong enough to drop the row. No middle ground.
  • Writer: rules with carve outs become rules of permission, not rules of restraint. Tighten when in doubt.
  • Storyteller: if the artifact's voice promises a human read every row, a human must read every row before delivery.
  • Quarterback: every new Hermes pipeline ships as "the script runs" and stops there. The deal orchestration tax is the last 20% of the work.
  • Architect: every "make it Slack callable" feature defaults to "stand up a new webhook receiver." The canonical answer is "use the existing next-chapter-os Next.js API surface."

Files

  • Skill: ~/.claude/skills/buyside-hunt/SKILL.md
  • Pipeline: engine/contacts/pipeline/buyside_hunt_v1.py
  • Runbook: engine/contacts/pipeline/buyside_routine.md
  • Template: engine/contacts/configs/buyers/_template.json
  • HTML template: engine/contacts/templates/buyside_report.html.j2
  • Banned phrases (W7 tightened): skills/maxswarm/banned_phrases.md
  • Notebook entry: skills/maxswarm/notebook/2026-05-05__009__buyside-hunt-routine-review.md
  • Per agent journals: skills/maxswarm/notebook/journals/009__<agent>.html