[object Object]

← back to Rentv Sheet Enrich

Session wave: +88 verified contact-LinkedIn (511->599, warmth-first wb_000-004, 65-73% yield); add WARM-RESUME.md (self-correcting rebuild + 2-concurrent cadence + measured yields)

c9ad67cbcf68befc0a52872de1d77907a5dcb072 · 2026-08-21 06:55:08 -0700 · Steve Abrams

Files touched

Diff

commit c9ad67cbcf68befc0a52872de1d77907a5dcb072
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Aug 21 06:55:08 2026 -0700

    Session wave: +88 verified contact-LinkedIn (511->599, warmth-first wb_000-004, 65-73% yield); add WARM-RESUME.md (self-correcting rebuild + 2-concurrent cadence + measured yields)
---
 WARM-RESUME.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/WARM-RESUME.md b/WARM-RESUME.md
new file mode 100644
index 0000000..042aa0d
--- /dev/null
+++ b/WARM-RESUME.md
@@ -0,0 +1,64 @@
+# RENTV contact-LinkedIn enrichment — WARM resume procedure (TK-10533)
+
+The one thin field left on the master "Unique Contacts (all tabs)" tab (gid 3823360)
+is **LinkedIn (Contact)**. Everything else (websites 3230, phones 770, company-LI,
+emails @ 92% reachability) is DONE. This is a warmth-prioritized long-tail grind,
+resumed by the doing-board NUDGE loop.
+
+## Each resume session
+1. **Rebuild warm batches from LIVE missing** (self-correcting — already-filled contacts
+   drop out automatically, so no done-tracking needed):
+   ```
+   cd ~/Projects/rentv-sheet-enrich
+   python3 - <<'PY'
+   import lib,json,re,os,csv
+   def norm(s): return re.sub(r'[^a-z0-9]','',(s or '').lower())
+   warm={}
+   for row in csv.DictReader(open('rentv_CRE_worklist.csv')):
+     try: w=float(row['Warmth'] or 0)
+     except: w=0
+     warm[(norm(row['Contact Name']),norm(row['Company']))]=w
+     warm.setdefault((norm(row['Contact Name']),''),max(w,warm.get((norm(row['Contact Name']),''),0)))
+   tok=lib.access_token();GID=3823360
+   title={s["properties"]["sheetId"]:s["properties"]["title"] for s in lib.get_meta(tok)["sheets"]}[GID]
+   rows=lib.read_tab(tok,title);hdr=rows[0]
+   H=lambda l:next((i for i in range(len(hdr)) if (hdr[i] if i<len(hdr) else "").strip()==l),None)
+   NAME,CO,LIC=H("Contact Name"),H("Company/Venue"),H("LinkedIn (Contact)")
+   C=lambda r,i:(rows[r][i] if i is not None and r<len(rows) and i<len(rows[r]) else "").strip()
+   def garbage(nm):
+     t=nm.split()
+     return (len(t)<2 or not re.match(r'^[A-Za-z]',nm) or bool(re.search(r'\d',nm))
+             or t[0].lower() in {'acq','vp','asst','jr','sr','mr','ms','dr','the','email'})
+   miss=[];seen=set()
+   for r in range(1,len(rows)):
+     nm=C(r,NAME)
+     if not nm or C(r,LIC) or garbage(nm): continue
+     co=C(r,CO);k=(norm(nm),norm(co))
+     if k in seen: continue
+     seen.add(k);miss.append((warm.get(k,warm.get((norm(nm),''),0)),{"company":co,"name":nm}))
+   miss.sort(key=lambda x:-x[0])
+   os.makedirs("data/warm_batches",exist_ok=True)
+   for f in os.listdir("data/warm_batches"): os.remove("data/warm_batches/"+f)
+   for n,i in enumerate(range(0,len(miss),30)):
+     json.dump({"targets":[m[1] for m in miss[i:i+30]]},open(f"data/warm_batches/wb_{n:03d}.json","w"))
+   print("missing",len(miss),"-> batches",-(-len(miss)//30))
+   PY
+   ```
+2. **Fan out web-researcher subagents, 2 CONCURRENT MAX** (the server rate-limits bursts of
+   3+ — 10-burst and 3-burst both got throttled; 1–2 run clean). Prompt = the per-contact
+   procedure in CONTACT_INSTRUCTIONS.md, WebSearch-only ($0), blank-beats-wrong,
+   company+name copied VERBATIM. Each writes `/tmp/ctresult_wb_NNN.json`.
+3. **Write back centrally & serially** (race-safe vs claude-rentv's concurrent yoloforever
+   writer on the same sheet): `python3 write_by_contact.py 3823360 /tmp/ctresult_wb_NNN.json`
+4. Commit + `tk log` the coverage delta.
+
+## Yield reality (measured 2026-08-21)
+- Warmth-first hot batches: **~65–73% LinkedIn yield** (major firms: Newmark/Matthews/JLL/etc).
+- Alphabetical/cool tail: **0–17%** (garbage names, common names @ obscure firms) — do LAST.
+- ⇒ Always warmth-order; the residual cool tail is diminishing-returns.
+
+## Guards
+- ADD-only, only-empty-cells, name-matched (row-shift immune). Green (#cbe6b4) auto-stamp.
+- NO fabrication: only /in/ slugs that literally appear in WebSearch results.
+- Sheet writes for THIS enrichment are Steve-authorized (reversible, internal, ADD-only).
+  RENTV *email SENDING* stays permanently blocked — this ticket never sends.

← f08c5b9 TK-10579 LinkedIn cycle4: 8 searched, 2 Cody-KEEP staged (Wa  ·  back to Rentv Sheet Enrich  ·  TK-10579 LinkedIn cycle5: 9 searched, 4 Cody-KEEP staged (Cu 0737e37 →