{"slug":"rentv-ad-engine","total":40,"limit":100,"offset":0,"since":null,"commits":[{"hash":"a5fc8be","date":"2026-08-30 23:53:34 -0700","author":"Steve Abrams","subject":"deploy-safety: exclude data/ from rsync (TK-10984)","body":""},{"hash":"b8c7114","date":"2026-08-30 22:58:53 -0700","author":"Steve Abrams","subject":"add creds-in-URL fetch guard to gated pages (TK-10984)","body":""},{"hash":"9a979b6","date":"2026-08-25 10:49:00 -0700","author":"Steve","subject":"creds-safe fetch guard: resolve relative fetch vs credential-free location (creds-in-URL trap)","body":"Fleet inoculation — opening this basic-auth app with credentials in the URL\npoisoned document.baseURI and made relative fetch('/api/…') throw. Guard resolves\nnon-absolute request URLs against location instead. Ref: creds-in-url-fetch-guard-fleet-pattern.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"72e1963","date":"2026-08-07 15:55:48 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-07T15:54:54 (1 data files) — package-lock.json","body":""},{"hash":"fa2ec3f","date":"2026-08-07 15:50:56 -0700","author":"Steve Abrams","subject":"chore: refresh.sh deploy-guard (keep backup until push succeeds, rollback on rsync fail) + version bump (session close)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"6782e69","date":"2026-08-07 15:40:18 -0700","author":"Steve Abrams","subject":"add refresh launchd plist","body":""},{"hash":"28ca24e","date":"2026-08-07 15:40:18 -0700","author":"Steve Abrams","subject":"scheduled auto-refresh: refresh.sh (deploy only on NEW episodes, extract-frames promo miner, atomic rollback, wobble-tolerant guard) + harvest preserves co-owned podcast manifest + launchd plist","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"8993674","date":"2026-08-07 15:28:28 -0700","author":"Steve Abrams","subject":"add Analytics as an in-page tab in the directory (iframe of charts.html, toolbar hidden on that view) — concurrent index.html editor confirmed done","body":""},{"hash":"14dc718","date":"2026-08-07 14:21:53 -0700","author":"Steve Abrams","subject":"analytics: ad-spend flow sankey (category->sponsor) + new-advertiser acquisition chart (per-episode + cumulative roster)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"e1a34a2","date":"2026-08-07 14:21:50 -0700","author":"Steve Abrams","subject":"5x: sweep logs + REPORT (favicon 404 fixed, clean twice)","body":""},{"hash":"cabb3d4","date":"2026-08-07 14:18:44 -0700","author":"Steve Abrams","subject":"5x sweep 1: serve branded favicon route (fixes /favicon.ico 404 console error)","body":""},{"hash":"74b0fd7","date":"2026-08-07 14:16:49 -0700","author":"Steve Abrams","subject":"analytics: sponsor-tenure Gantt (first->last episode per client, dots per sponsored ep, teal=active / amber=lapsed) — churn + retention at a glance for ad-sales","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"e0aef11","date":"2026-08-07 14:14:13 -0700","author":"Steve Abrams","subject":"analytics: guest<->sponsor network graph (zero-dep force-directed canvas — gold sponsor hubs sized by reach, teal guests, links = shared episodes)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"9302761","date":"2026-08-07 14:13:52 -0700","author":"Steve Abrams","subject":"fix(deploy): HEALTH_URL 9789->9793 (app's real remote port; 9789 is ventura-claw-leads)","body":""},{"hash":"6985df0","date":"2026-08-07 14:12:04 -0700","author":"Steve Abrams","subject":"analytics: executive-summary KPI strip (clients/airings/episodes/top client/est. value/guests) + Print-Save-PDF with print stylesheet — hand-to-a-prospect one-pager","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"c5ebed2","date":"2026-08-07 14:00:01 -0700","author":"Steve Abrams","subject":"TK-10343: scale ad-engine harvest to all 123 Vimeo videos (advertisers+guests+airings)","body":"- New scripts/extract-frames.py mines the 85 caption-less client PROMO videos'\n  poster/title-card OCR (data/frames.json, local qwen2.5vl already run, $0) into\n  advertiser records — company name, category, on-card website/phone/email/pitch.\n- extract.py rebuild now folds in poster_ocr extractions; tags each merged\n  advertiser source=transcript|mixed|poster_ocr + promo_only.\n- build-adairings.py: promo_only advertisers get an exact whole-clip promo airing\n  and are excluded from the fuzzy transcript scan (fixes Wilshire-Grand 153->2\n  phantom over-match).\n- Coverage: 123/123 canonical videos extracted (38 transcript + 85 poster-OCR).\n  advertisers 30->92, guests 44, airings 179->269 across 94 videos. All $0 local.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"91e1534","date":"2026-08-07 11:48:23 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-07T11:47:33 (14 data files) — data/advertisers.json data/emails.json data/guests.json data/soundcloud/adclips.json data/soundcloud/adclips/873500326-capitol-rivers-commercial.mp3","body":""},{"hash":"59cc977","date":"2026-08-07 11:29:28 -0700","author":"Steve Abrams","subject":"analytics: per-client airing-history CSV (one download per advertiser) + guest-location map (geo scatter) + sponsor-overlap matrix (shared-episode heatmap)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"39e94f3","date":"2026-08-07 11:26:25 -0700","author":"Steve Abrams","subject":"analytics: add guest-topics word-frequency cloud + ad airing history table (search-all/sortable/column-toggle/CSV-export/reset, per-airing deep-links)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"d81a056","date":"2026-08-07 11:21:31 -0700","author":"Steve Abrams","subject":"analytics page: add per-client trend sparklines (rising/easing), estimated sponsorship value (transparent model + adjustable rate), and guest analytics (interview/panel/verified split + top companies)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"b873f8f","date":"2026-08-07 11:18:35 -0700","author":"Steve Abrams","subject":"add Client Analytics page (charts.html): animated liquid-fill share-of-voice gauges + clients-by-airings bars + category donut + airings-over-run timeline; linked from header (Steve-directed)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"2ed2dbe","date":"2026-08-07 11:16:32 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-07T11:14:36 (8 data files) — data/soundcloud/adclips.json data/soundcloud/adclips/873500326-capitol-rivers-commercial.mp3 data/soundcloud/adclips/873500326-redwood-mortgage.mp3 data/soundcloud/adclips/881852191-capitol-rivers-commercial.mp3 data/soundcloud/adclips/881852191-redwood-mortgage.mp3","body":""},{"hash":"db15224","date":"2026-08-07 11:12:21 -0700","author":"Steve Abrams","subject":"wire as-aired ad timeline into dossier (per-airing ▶ deep-link + spoken copy) + add CRE Talk producer page (/Producers/View/618) source link to header (Steve-directed)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"4864f38","date":"2026-08-07 11:03:55 -0700","author":"Steve Abrams","subject":"deep-frame build: PROVEN real-browser frame capture (postMessage on authorized rentvreview embed) + FINDING that CRE Talk has no on-screen sponsor slate (sponsors read over static title card). Deliver the real 'exact ad-slate timings' = adairings.json (179 precise as-aired ad spots w/ deep-links + spoken copy from VTT timing) + /api/adairings. UI wiring deferred (index.html held by concurrent soundcloud editor)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"74ce7ce","date":"2026-08-07 10:47:22 -0700","author":"Steve Abrams","subject":"engagement emails: name the RIGHT RENTV property per sponsor (podcast vs CRE Talk vs both)","body":"Podcast-only sponsors (e.g. Capitol Rivers Commercial) now reference RENTV's 'Weekly CRE News & Views' podcast; cross-source sponsors (Redwood Mortgage) reference both. Fixed in the batch drafter (draft-emails.py show_phrase from episode source) AND the live /api/email drafter (server.js infers from context). Regenerated all 30 drafts.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"ae55801","date":"2026-08-07 10:45:45 -0700","author":"Steve Abrams","subject":"LIVE: mounted at rentv.agentabrams.com/advertisers — Kamatera pm2 rentv-ad-engine :9793 (9789 was taken by ventura-claw-leads), nginx /advertisers block added to rentv vhost with auto-restore guard + backup; app-auth only. Verified 200/301/401 + rentv+ventura unaffected","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"290f01a","date":"2026-08-07 10:43:12 -0700","author":"Steve Abrams","subject":"regenerate engagement email drafts incl podcast sponsors (Capitol Rivers Commercial); DRAFT-ONLY","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"05adab8","date":"2026-08-07 10:42:07 -0700","author":"Steve Abrams","subject":"SoundCloud podcast source: harvest+transcribe rentvnews, extract sponsors, clip spoken ads, unify into advertisers.json + Podcasts viewer","body":"- 3 rentvnews episodes (Ep 9/10/11 'Weekly CRE News & Views') → audio (yt-dlp) + local faster-whisper transcripts ($0), timestamped segments\n- piggybacks the UNMODIFIED extract.py (SC transcripts at data/transcripts/<id>.txt + manifest upsert) so podcast sponsors land in the unified advertisers.json → feeds the engagement-email drafter\n- clip-ads.py: cuts the ACTUAL spoken-ad audio per advertiser via whisper timestamps (6 clips: Capitol Rivers Commercial + Redwood Mortgage ×3 eps); enriches advertisers.json with per-episode source + adclips + has_podcast; conservative fuzzy-merge fixes the Capitol/Capital whisper-variant split + sanitizes leaked categories\n- viewer: Podcasts tab (episode audio, chapter-seek, spoken-ad players, transcript expander, one-click Draft engagement email) + /api/soundcloud,/api/adclips,/api/transcript,/media (Range audio)\n- one-command pipeline: scripts/build-soundcloud.sh\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"87ad1ae","date":"2026-08-07 10:02:35 -0700","author":"Steve Abrams","subject":"make ad-engine mountable under a path prefix (BASE_PATH -> <base> injection + relative client paths); add nginx /advertisers proxy snippet — verified locally, standalone unaffected","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"c3eae5f","date":"2026-08-07 09:51:18 -0700","author":"Steve Abrams","subject":"Full REview reconciliation: producer-page harvest maps 20/22 episodes (16 with official sponsors + real air dates); reconcile-review.py cross-verifies 7 advertisers vs RENTV official record + stamps 15 episode air dates; UI shows REview-verified badge + air dates","body":"Transcript extraction agrees with RENTV official on all 7 recurring sponsors (Rockefeller/Provident exact); ours slightly higher (also catches panels + 4 unparsed episodes).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"750f51f","date":"2026-08-07 09:43:25 -0700","author":"Steve Abrams","subject":"Integrate RENTV podcast (SoundCloud rentvnews) + The REview authoritative source: harvest-rentvreview.py maps 7 episodes with official sponsors/guest/date; dossier shows 'Verified via The REview' block; header podcast+REview links","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"6eeb40a","date":"2026-08-07 09:33:52 -0700","author":"Steve Abrams","subject":"Phase 2b: web-search address enrichment — 24/29 advertisers now have mailing addresses (16 Exa searches ~$0.16, Steve-approved); cleaned Rockefeller/Provident; deduped firm variants","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"e9257f6","date":"2026-08-07 09:27:12 -0700","author":"Steve Abrams","subject":"Phase 2b: advertiser ADDRESS field via free website lookup (regex + local-LLM fallback) — deep in-video frames blocked by Vimeo DRM + addresses are read verbally not shown; UI shows address (maps link) + needs-web-search flag","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"8ae82f6","date":"2026-08-07 09:23:16 -0700","author":"Steve Abrams","subject":"Emails tab: batch-drafted client emails for all 29 advertisers (draft-only, never sends), editable + copy + regenerate, DRAFT banner; /api/emails endpoint + scripts/draft-emails.py","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a3bfc8b","date":"2026-08-07 09:18:19 -0700","author":"Steve Abrams","subject":"per-video DOSSIER flow: Vimeo embed + poster screenshot + in-episode ads + guests + AI synopsis + 'Generate email to client' (local Ollama drafter, /api/email); clean pm2 restart to clear stale code","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"0c8d277","date":"2026-08-07 09:07:14 -0700","author":"auto-commit-fleet","subject":"auto-data-snapshot: 2026-08-07T09:05:06 (12 data files) — data/frames/812981342.json data/frames/812982818.json data/frames/830276773.json data/frames/830279080.json data/frames/831673533.json","body":""},{"hash":"012f0c1","date":"2026-08-07 09:07:09 -0700","author":"Steve Abrams","subject":"gitignore .venv (local yt-dlp/curl_cffi toolchain)","body":""},{"hash":"a441274","date":"2026-08-07 09:06:59 -0700","author":"Steve Abrams","subject":"Phase 2 (poster tier): local qwen2.5vl OCR of video title frames — on-screen texts+logos, self-contained thumbnails, poster-confirmed guest verification; UI shows posters + on-screen logos on Coverage/Guest cards","body":"Deep mid-video sponsor-slate frames remain blocked by Vimeo stream DRM (yt-dlp impersonation unavailable on this box); poster frames are the free on-screen asset. Next unblock = RENTV source MP4s or real-browser play-and-seek capture.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"0c18e9b","date":"2026-08-07 08:58:35 -0700","author":"Steve Abrams","subject":"harden extraction: union-find advertiser dedup, email split, regex-site attach; guest hygiene (drop hallucinated/thin, add verified flag); emails + verified badge in UI","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"017da30","date":"2026-08-07 08:49:36 -0700","author":"Steve Abrams","subject":"initial scaffold: RENTV ad engine — harvest + extract pipeline + viewer","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n"}]}