Where you left off
Do next — in order
Overdue since 07-31 — decide before building more
Virtual address, ~$10–30/mo — the legal floor for cold email
One word; nothing sends without it
APG · Alan Joel · Barrington · Bradley · LiNC · Trinity · NAI Nashville · Asset Alliance · HND Realty · Teal Door
VAULT/VOXA/Registry/CRM-Mock.html — waiting on your verdict
9 of 11 erroring or stubbed — green runs, empty output
Blocked / not working
Hard gate — zero sends until bought and wired into the signature
Explicit, in writing — the per-email /approve verdict never relaxes after it
Arms in Phase 3 — week 1 at 10/day, never a blast
0 pm_target for 9 straight nights · A2/B1 error, 7 more are stubs — the pipeline looks green but produces nothing
smartlead_setup.md connects founder@orvoma.com — conflicts with the anchor invariant; reconcile before the next connection pass
Shipped so far
Still to build
Working files: VOXA/Pipeline/Queue.md · VAULT/VOXA/VOXA.md · VAULT/VOXA/Registry/CRM-Mock.html
The loop — 7 layers
Click any layer box or chip for its complete blueprint — agents, contracts, gates, failure model.
Phase plan — with steps
n8n service · headless claude · CRM scaffold · voice rules
Chain runs overnight, stops at the queue by design
Mailbox · warm-up ramp (10/day → 200/wk) · your written GO
Replies negotiated in-thread · follow-ups · 1,000 leads/wk
Pipeline funnel
The 12-agent roster
The 12-agent roster
VOXA/agents/, fired as headless claude runs. No daemon: read vault state, act, exit.| Agent | Layer | Runs | Model | Job |
|---|---|---|---|---|
| HUNTER | 1 | 00:30 chain | Haiku | Raw discovery across free source tiers, parallel, field-level voting |
| PROFILER | 1 | 00:30 chain | Sonnet | Stitches field claims into one profile; provenance per field |
| VERIFIER | 1 | 00:30 chain | Sonnet | Credibility gate — email validity, person-still-there, domain health |
| SIGNALS | 1 | 00:30 chain | Sonnet | Inefficiency triggers — the personalization ammo |
| SCORER | 1 | 00:30 chain | Sonnet | ICP fit score, tier A/B/C, promotes toward the send window |
| WARDEN | 1 | 00:30 close | Sonnet | Dedupe, suppression ledger, CAN-SPAM, budget sentinel |
| DRAFTER | 2 | 02:00 nightly | Sonnet | Writes 1:1 cold drafts as Andrew with cited facts; self-scores |
| GATEKEEPER | 3 | /approve | Fable live | Presents the queue for per-item verdicts; last QA before you |
| SENDER | 4 | inside /approve only | script | Executes approved sends via Gmail — the only agent that can |
| REPLYWATCH | 5 | every 3h, 08–20 | Sonnet | Sweeps inbox, classifies replies, queues reply drafts top-priority |
| SEQUENCER | 6 | 23:30 nightly | Sonnet | Per-thread follow-up state machine; queues follow-up drafts |
| SCRIBE | 7 | closes every run | inherits | Appends CRM events, updates metrics, commits state |
Roster-wide prohibitions
Master schedule
| Time | Run | What fires | Phase |
|---|---|---|---|
| 00:30 | SCOUT chain | HUNTER → PROFILER → VERIFIER → SIGNALS → SCORER → WARDEN | 2 |
| 02:00 | DRAFTER | Cold drafts for send-ready prospects → queue | 1 |
| 08–20 / 3h | REPLYWATCH | Inbox sweep, classify, queue reply drafts | 4 |
| 23:30 | SEQUENCER | Follow-up state machine sweep → queue | 4 |
| morning | /approve | GATEKEEPER presents · you verdict · SENDER executes | 2–3 |
| every run | SCRIBE | Closing step everywhere — never scheduled separately | 1+ |
The Queue — one approval surface
VOXA/Pipeline/Queue.md · priority: reply > follow-up > cold, FIFO within class — a 2-day-old reply kills the deal; a 2-day-old cold draft costs nothing.| Field | Contents |
|---|---|
| id | Deterministic per class — never serial, so re-runs collide instead of duplicating |
| prospect | Link to the CRM note in Pipeline/Prospects/ |
| class | cold / reply / follow-up |
| tier | A / B / C from SCORER |
| draft | Subject + full body, plain text, written as Andrew |
| facts | 2–3 cited personalization facts, each with provenance |
| self-score | Drafting agent's confidence; low scores get scrutiny, never auto-kill |
Status lifecycle
edited-sent — you edited before sending; edits feed DRAFTER's calibration · approved-unsent — a pre-send gate failed at fire time, retried next session · skipped — resurfaces next /approve at same priority · killed — logged with reason; prospect returns to pool or suppression ledger.
CRM note — one prospect, one file
| Key | Values |
|---|---|
| stage | staging → enriched → verified → scored → send-ready → contacted → replied → booked / suppressed |
| tier / score | A/B/C · 0–100 — ICP weights recalibrate monthly from outcomes |
| verified | Date, 30-day TTL — stale send-ready drops back to scored |
| catchall | Unverifiable domain; sends throttled against the bounce kill-switch |
| signals | SIGNALS output — the personalization inventory |
Body carries two mandatory blocks: a provenance table per critical field (a claim without provenance does not count) and an append-only event log — one timestamped line per touch, never rewritten.
The two-sided ICP
Buyer of management services · 5–50 properties, $50M–$2B AUM. Frame: "Your manager's flat fee absorbs $X/yr of labor you pre-pay whether delivered or not." Headline: $778K/yr unbudgeted labor on a $1.8M PM contract.
Seller under MSA · 50–500 doors. Frame: "Your contract structurally gives away $X/yr of margin — restructure at renewal." Headline: 43% of management-fee margin absorbed.
ICP scoring — 100 points to a tier
icp_scorer.py; email-pattern confidence <90% drops to Tier B rather than risk a bounce.Warm-signal override: ≥10 on the pain sub-rubric alone (recent acquisition, fund close, hiring asset managers, RFP, public margin-pressure statement) = Tier A regardless of everything else.
Geography + decision-makers
Atlanta · Charlotte · Nashville · DFW · Phoenix · Tampa · Indianapolis · Columbus · KC · MSP · SLC
TIER C — EXCLUDEDNYC · SF · LA · Boston · DC · Seattle · Chicago — outbound CAC explodes
Hard disqualifiers — skip without scoring
Public REIT >$5B · pure brokerage (no owned assets — CBRE, JLL, Cushman, etc.) · CRE-tech vendor · portfolio wind-down <12mo · bankruptcy/receivership · HQ outside US/Canada · multifamily/retail/hospitality/self-storage primary (cohort 2+).
Doctrine — for an audience that does not tolerate spam
Sender architecture
| Mailbox | Role |
|---|---|
| andrew@orvoma.com | Anchor — never in Smartlead; real replies + manual send only; protects brand reputation |
| orvomahq.com · getorvoma.com · tryorvoma.com | Satellites, warmup ON — absorb cold volume and reputation risk |
| Smartlead | $59/mo, warmup lane only — campaigns tool, explicitly NOT the ship |
Authentication + warmup
One TXT record, ends ~all/-all, no duplicates
Selector CNAME, signing domain aligned to sender
p=none to monitor · rua → dmarc@orvoma.com
Gmail "Show original" — all three PASS + aligned
| Warmup setting | Value |
|---|---|
| Daily ramp-up | +5 emails/day |
| Max daily volume | 40/day |
| Reply-rate target | 35% |
| Schedule | Mon–Fri, business hours |
| Bounce kill-switch | 2% — outranks everything |
Open flag
smartlead_setup.md connects founder@orvoma.com into Smartlead — conflicts with the anchor invariant. Reconcile before the next connection pass.
AEGIS enforcement — structural, not procedural
Failure model — every run disposable
Read state → compute delta → write → exit. Crashed runs re-run, not repaired.
Overlapping cron fires exit clean; stale locks broken with a logged warning
sending marker before the Gmail call, message-id confirm after; crashes reconcile against Gmail Sent
Malformed entries quarantine and surface in /approve; API errors exit non-zero and retry next fire
START/FINISH to the swarm board; SCRIBE closes every run with a committed snapshot
Cost model
SOURCING PLAN — field-by-field root sources + the exact run
DOCTRINEWorkflow mind map
Person fields → root sources
| Field | Root source (free, most accurate) | Fallback chain |
|---|---|---|
| Full name + title | Firm site /team /about /leadership (current-role truth) | SoS officer filings → conference speaker bios → LinkedIn public |
| Principal / owner | State SoS annual report (officers/members) + statutory agent | SEC EDGAR (if filer) → county deed signatory names |
| Emails published on the firm site (pattern truth) | MX + domain-pattern derivation → paid verifier only if inconclusive | |
| Phone (work) | Firm site /contact page | Google Business Profile listing → SoS agent phone |
| Manual capture in /dossier phase 3 (ToS-safe — never scraped) | — | |
| Bio / experience / education | Firm-site bio (self-published, current) | Speaker bios → podcast show notes → LinkedIn public |
| Wealth & influence | FEC individual-contribution records + IRS 990s (ProPublica/TEOS mirrors) | County assessor (personal residence) → board seats via 990 officer lists |
| News / recent | Google News RSS per firm + principal name | BizJournals metro feeds → county recorder new filings |
Company fields → root sources
| Field | Root source (free, most accurate) | Fallback chain |
|---|---|---|
| Legal name vs DBA | State corporation registry (AZ Corp Commission wave 1) — THE identity root | County DBA/trade-name registry |
| HQ address | SoS principal-office address of record | Firm site footer → Google Business Profile |
| Founded | SoS incorporation date | Wayback Machine earliest site capture (proxy) |
| Ownership type | SoS entity type + EDGAR 10-K (public/REIT) | Form D filings (PE-backed signal) |
| Portfolio / AUM / doors | County assessor parcel search by owner-LLC variants → sum parcels · units · sq ft | Deed registry cross-check → EDGAR XBRL (public) → firm-site claims (lowest trust) |
| Headcount | DOL Form 5500 filings (EFAST, participant counts) | Careers-page open roles → LinkedIn company page (proxy) |
| Org chart / roster | Firm site /team page extraction | SoS officers → EDGAR exec lists → 990 officer tables |
| Transactions | County deed recorder (grantor/grantee search) | BizJournals deal coverage → press releases |
| Funds raised | SEC EDGAR Form D | Press releases |
| Tenants | Tenant-improvement building permits | LoopNet public listings → firm-site property pages |
| Pain signals | County tax-appeal dockets + code-enforcement records | Google/BBB tenant reviews · Glassdoor (verbatim quotes) |
| Tech stack | Job postings naming the PMS (Yardi · AppFolio · MRI · Buildium) | MX/DNS records → site headers |
Phase 0 deep-dive — the weekly seed, chunk by chunk
0.1 Maricopa + Pima parcel data, class = office / industrial / mixed-use
0.2 Statewide: Pinal · Yavapai · Coconino · Mohave · Yuma, then rural fill (8 counties) · ADOR centrally-valued rolls
0.3 Situs-city sweep inside each county — PHX metro (13 cities), Tucson metro + Pinal (10), north/west/south towns (14) · city business-license + permit portals verify situs
0.4 Group parcels by owner → count + total sq ft; out-of-state mailing address = remote-owner flag
0.5 Keep owners with 5–50 parcels · snapshot raw exports to .raw/seed/
0.6 AZCC eCorp keyword search + foreign-entity registrations (operates here, HQ elsewhere)
0.7 AZ SoS trade-name registry — the legal-name↔DBA link
0.8 ADRE licensee database — every PM firm's employing broker, statewide by law (Side-B root)
0.9 ADOR TPT commercial-lease licenses — every landlord collecting AZ rent; bot-walls → CloakBrowser
0.10 NAIOP-AZ · AZCREW · SIOR · ULI · CCIM Central + Southern · IREM PHX + Southern AZ · BOMA PHX + Tucson · MPA · chambers (TUS · FLG · Prescott · Yuma)
0.11 Extract firm + site + listed member person
0.12 Tag association-member; AMA = multifamily, name-source only
0.13 GBP category search per metro: PHX · TUS · FLG · Prescott · Yuma · Havasu · Sierra Vista · Casa Grande
0.14 PBJ + Inside Tucson Business Books of Lists · AZ Big Media rankings
0.15 LoopNet/Crexi "managed by" lines · permit applicants · AZ property-manager job postings
0.15b AZBEX/DATABEX + ACA Prospector — construction pipeline, future contracts (S23-S24)
0.15 Lowercase · strip LLC/Inc/LP · collapse punctuation
0.16 Merge chunks on normalized name — every source hit kept as a provenance line; assessor + registry + roster = instantly credible
0.17 Alias table for multi-entity families ("X Holdings" + "X Management" → one firm)
0.18 Nothing discarded — tag every firm with a takeover-map segment: pm_target · brokerage · asset_mgmt · facilities_ops · development · valuation · debt_capital · adjacent_ring (sub-tags: vendors · tax-appeal · title · insurance · environmental · A&E · construction)
0.19 Parked bycatch pre-seeds future verticals for zero tokens · only true kill = suppression ledger (gov/tribal owners still dropped)
0.20 Upsert to companies.db — NEW insert · KNOWN append provenance · SUPPRESSED skip; candidates.md + CSV exported as read-only views (pm_target · new)
0.21 SCRIBE line: counts per chunk, drops per rule · git commit
The run — every step, in order
Pull AZ Corp Commission actives filtered on PM/realty keywords · union with AMA + NAIOP + AZCREW rosters · dedupe on normalized legal name → candidate file
Per new firm: fetch SoS record — legal name, status, incorporation date, statutory agent, officers. Snapshot raw HTML to .raw/
Assessor API query on owner-LLC name variants → parcel list → sum sq ft / units / parcel count. Deed registry cross-check on the top parcels
Fetch /about /team /contact /careers · extract names, titles, emails, phones, PMS mentions · every claim recorded with URL + date
Deterministic aggregator merges field claims across sources · quorum ≥0.65 or the field stays open · one CRM note written with the full provenance table → enriched
MX + SPF lookup on the domain · email pattern derived from published addresses · DM address constructed + format-checked → verified; inconclusive → paid gap-fill queue (under the $15 cap)
Tax-appeal dockets · permits · code enforcement · evictions/foreclosures · Treasurer delinquents · ROC complaints · PACER · Google News RSS · job postings · review mining → signals[] each with provenance
icp_scorer: size 25 · vertical 20 · geo 15 · DM 25 · pain 15 — sizing now fed by assessor totals (kills the Tier-C cap) · warm-signal override ≥10 → Tier A
Suppression check · dedupe vs registry · one-active-contact rule · budget check → send-ready
Stage events + spend counters appended · swarm-board line · git commit. Crash anywhere? Re-run resumes at the last stage transition
L1 · SOURCE — "SCOUT"
PHASE 2HUNTERHAIKU · → STAGING
Raw discovery across the free source tiers, fired in parallel with field-level voting across sources
PROFILERSONNET · → ENRICHED
Stitches field claims into one profile — provenance per field: source + date + confidence
VERIFIERSONNET · → VERIFIED
Credibility gate — email valid, person still there, domain healthy. Paid checks just-in-time only
SIGNALSSONNET · + AMMO
Inefficiency triggers — hiring, tax appeals, permits, bad reviews. The personalization ammo
SCORERSONNET · → SCORED
ICP fit 0–100 → tier A/B/C. Weights recalibrate monthly from real reply outcomes
WARDENSONNET · → SEND-READY
Dedupe · suppression check · CAN-SPAM · budget sentinel — halts paid calls at 80% of cap
Rollout
Credibility rules
Permanent append-only ledger, checked before any promotion
Stale send-ready drops back to scored and re-verifies
No source + date + confidence = doesn't count in the vote
Two mapped per firm; fallback fires only after thread 1 closes
Unverifiable domains flagged + throttled vs the kill-switch
Reply outcomes retrain SCORER weights monthly
L2 · DRAFT — "DRAFTER"
BUILT · VERIFIED 07-22The nightly run
Queue already full? DRAFTER writes ZERO and exits — a correct run. Fresh beats deep.
Pre-draft gate
On the ledger → no draft, log, done
Back to scored — no draft from stale data
Uncited fact never reaches a stranger's inbox
Draft normally, mark throttled for L4 pacing
The 7 quality laws
Counted. Needs more? The point is wrong
About THEIR firm, cited to a provenance line
A short call, an opinion, a yes/no
2–5 words, lowercase-natural, never a headline
No links, attachments, or images. Ever
No "hope this finds you well," urgency, or flattery
Voice.md is the arbiter — editing it retrains the voice
Self-score — 3 axes, 1–5
Is the observation about THEM, verifiably?
Against Voice.md samples
One ask, answerable in one line
Any axis ≤3 → one redraft. Still ≤3 → flagged "weak — needs Andrew", never rides through on a skim. Weekly Fable audit → Voice.md proposals you ratify.
L3 · APPROVE — "GATEKEEPER"
BUILDING NOWThe morning ritual
Each card shows
Name, firm, and the trigger signal — pulled live, never cached
Verify no hallucinated personalization in ten seconds
Low scores get scrutiny — never auto-kill
Past-SLA items carry a staleness warning up top
Your four verdicts
→ manifest slot → script fires 09:00–16:00, all 5 gates re-run, message-id logged
Fix inline → send. Diff logged verbatim → weekly Voice.md proposals you ratify
One-line reason required → suppress or recycle. Rising kills = fix that agent's prompt
Stays pending, ages toward the SLA. Free — not a quiet kill
No blind bulk approve, ever. "Send the rest of tier A" expands every item on screen first, then fires one-by-one. Mini-/approve: an interested reply opens an anytime one-item session.
Session health — watch these
Falling → upstream drafting problem
Falling over weeks = the voice is learning
The per-agent quality signal
Must stay under 24h
L4 · SEND — "SENDER"
GATEDFive gates — per message, at fire time
Real mailing address in the footer — zero sends until bought
"If you'd rather I not write again, just say so" — no link machinery
A "no" from an hour ago stops a send approved yesterday
Daily script check — a failing domain sends nothing that day
Above it: all sends halt, budget lifts to re-verify
That send only → approved-unsent, failing gate named
Warm-up ramp
Verdicts in /approve → immutable manifest → judgment-free script drains it 09:00–16:00 recipient-local, random 3–8 min spacing, all 5 gates re-run per fire. Nothing enters the manifest outside /approve.
Never double-send
Derived from the queue id — recovery is a Gmail search, never a guess
sending before the call · sent after — the only ambiguous window
Search first: found = backfill sent · missing = retry. Ambiguity resolves to "already sent"
Suppressed forever + kill-switch counter + CRM back to scored
One retry next session — second soft = hard
Message-id + thread-id + timestamp → CRM log. No thread-id = bug
L5 · REPLIES — "REPLYWATCH"
PHASE 4Every reply lands in one of 7 buckets
Booking negotiation starts → mini-/approve flag, stage negotiating
Grounded answer from audit framing — needs judgment? Flag, no draft
Optional one-line ack → nurture pool, re-touch in 60–90 days
Suppressed immediately + gracious one-liner — never a rebuttal
No action — SEQUENCER clock shifts past the return date
Suppression + kill-switch counter, thread closed
Suppressed + confirmation draft + CAN-SPAM audit line
NOT auto-handled — quoted verbatim under a needs-Andrew flag. Guessing costs more than asking
Booking — the no-link doctrine
A Calendly link is delegation of effort; a negotiated invite is service. No scheduling links at any step.
Mechanics
Advances only after full processing — crashes re-scan clean
One queue entry per inbound message-id, ever
No thread match → needs-Andrew, never dropped
Target <20%, falling as the taxonomy matures
L6 · FOLLOW-UP — "SEQUENCER"
PHASE 4The touch clock
Banned forever
No unused signal left → the thread closes, even with touches in budget. Logged filler-blocked — non-zero is healthy; it proves the bar has teeth.
Stop conditions — checked before every draft
REPLYWATCH owns the thread — SEQUENCER never touches it again
Closed + suppressed permanently
Closed as won-to-pipeline
Sequence halts — human intent outranks the clock
Clock pauses, resumes at hold expiry
A thread never holds two pending drafts
Nurture + safety
Exhausted + not-nows return in 60–90d, drop to scored, must re-verify before any new sequence
used-in marks are forever — recycled prospects get genuinely new ammo or wait
Queue id = (thread, touch#) — a crash cannot produce duplicate touches
L7 · LOG — "SCRIBE"
PARTIAL — TICKERS LIVECloses every run
One event = one line, forever
- 09:41 · evt:0941-a3f2 · sent · queue:t-88f1-t2 · msg:<CAJx…> · by:/approve
- 14:02 · evt:1402-b8c1 · replied:interested · thread:<t-88f1> · by:REPLYWATCH
Never edited or deleted — corrections are new events. Lock-guarded writes + git auto-commit = the CAN-SPAM compliance record.
The scoreboard
Replies ÷ sends — the ONLY engagement metric, no open tracking by design
The conversion that feeds the 15-streak
Approval / edit / kill share — the quality signal
Tracked against the 2% kill-switch
voxa-metrics.py rebuilds it all from events — corruption costs nothing
Feedback loops — where the log pays rent
Reply traits → SCORER weight proposals → /approve
Your edit diffs → Voice.md proposals — never self-applied
Reply-by-touch analysis → cadence tuning
The one unacceptable state: an unlogged send. The sent event writes BEFORE the next queue item is offered; 3 failed retries = sending halts for the session.