jiggly-bubble Sprint — Completion Log
Goal: Get all 7 portfolio surfaces (cwa, pro-website, pewsearch, itw, sermonwise, funeralwiseai, vetwiseai, wiseaiagency) "rock solid" and unblock cold-outreach launch.
Plan target: First cold-outreach batch on Day 7 of ~10. Reality: Day 1 = code/infra functionally complete. Cold-outreach can launch as soon as founder's organic operational items finish (Resend reputation maturation, prospect source disclosure decisions).
Streams shipped (5 PRs, 1 day)
| Stream | PR | Scope |
|---|---|---|
| A — Demo engine multi-vertical | #297 | FuneralPreview + VetPreview templates; /api/chatbot/stream vertical-aware routing; 3 draft migrations |
| B — Browser voice demo | #300 | <BrowserVoiceDemo /> widget; 60s cap; capacity UX; embedded in funeral + vet previews |
| C — /ensure-solid 9 surfaces | knowledge#96 | Per-property scorecards + portfolio-20260504-v7.md rollup; first-ever scoring for funeral, vet, agency |
| D — Per-vertical content | #298 + knowledge#96 | 3 sales playbooks; 4-email cold-outreach × 3 verticals; lifecycle TS files (funeral + vet); brand voice extension |
| E+F — SEO + agency layer | #299 + knowledge#96 | 4 city pages (Ingersoll/London ON/Woodstock/Tillsonburg); robots.ts; agency contact form; playground vertical picker; social strategy + 30-day calendar |
Mid-sprint customer-impacting fixes (4 PRs)
Surfaced during founder's hands-on testing while sprint was in flight:
| PR | Issue | Resolution |
|---|---|---|
| #301 | Admin cancel flow dead-ended at Settings (the "cancel" link redirected to a #cancellation anchor that was never built; Settings tab had been converted to a slide-over 2026-04-18) | Redirect to /api/stripe/portal?token=... (existing Stripe Customer Portal) |
| #302 | Cancel flow had 3 clicks (modal → modal → "Cancel in Stripe" link) | Killed second confirmation screen; modal click → straight to Stripe portal |
| #303 | After Stripe cancellation succeeded, dashboard still showed "ACTIVE". Webhook was setting top-level cancel_at_period_end=true but not the per-product <product>_cancel_at_period_end flags that the dashboard reads | Webhook fanout: when whole subscription is scheduled for cancellation, fanout to every active per-product flag based on multiItemUpdate.has_*_subscription |
| #307 | 3 active P0 ops_errors dragging CWA Ops -15pp from v6 to v7 scorecard | (a) Sweep last-item guard (cancel vs item-delete); (b) bundle item-id dedup in sweep loop; (c) change-tier resource_missing → graceful 410 not P0 |
Audit follow-up PRs (3)
| PR | Audit finding |
|---|---|
| #304 | CASL physical address gap in lifecycle email footers (church + funeral + vet) |
| #306 | cold-outreach-director-transfer spec broken since 2026-04-29 (hero button rewired to open modal; spec was clicking hero, not inner WebRTCDemoButton) |
| pewsearch#32 | Admin SettingsTab said "Basic chatbot included with Premium" instead of "Pro Website" — churn-risk overpromise |
| knowledge#97 | Test registry entries for the 3 new specs (preview-funeral, preview-vet, chatbot-vertical-aware) |
Total PRs merged: 12 (8 churchwiseai-web + 1 pewsearch + 2 knowledge + 1 + voice-agent deploy)
Migrations applied to prod Supabase (5)
20260504_product_knowledge_vet_funeral_drift.sql— funeral pricing drift fix ($999 → $745), 9 new vet rows20260505_drop_church_voice_agents_fk.sql— idempotent (FK didn't exist; audit-confirmed safe)20260505_create_vet_knowledge_base.sql— per-tenant vet Q&A table20260505_create_vet_clinics.sql— vet identity table (mirrorsfuneral_homes+species_supported TEXT[])20260505_create_premium_vet_clinics.sql— vet subscription table (FK tovet_clinics); supersedes the never-applied 20260502 draft
Mid-sprint DDL discoveries: the previously-feared church_voice_agents_church_id_fkey constraint did NOT exist in production — comment at provision.ts:449-463 was stale. Audit-confirmed via pg_constraint query before applying drop migration.
Production data writes (founder-approved)
- 39 funeral product_knowledge rows retagged from
vertical='church'→vertical='funeral'(brand_scopes: funeralwiseai, playground-funeral) - 3 customer rows backfilled with per-product cancel flags to match webhook intent (Erin Reformed Church, Melvindale CoG bundle, E2E test row)
- 5 P0 ops_errors marked resolved with
fix_summaryaudit trail (FA-082 unknown tier ×2, sweep race, change-tier resource_missing, voice-health orphan rule) - $79.95 refund issued via Stripe live mode to Debora Moelker (
pyr_1TTR2VFaoK5IPzNoBezTmzCd)
Founder-side organic operational items completed
- Vetwiseai bare→www redirect inverted to www→bare (matches funeral/church pattern)
veterinarywiseai.comadded to Resend (DKIM/SPF/DMARC verified live via DNS)veterinarywiseai.comadded as Google Workspace domain alias- 4 Cal.com event types confirmed live: church/funeral/vet/agency demos at
cal.com/john-moelker/<vertical>-demo funeralwiseai.comResend verification confirmed (was completed prior to sprint)
Decisions locked (in order made)
- Browser voice demo built now, not deferred (Stream B)
- Demo phone strategy: shared Telnyx + 4-char code (no per-vertical numbers; cheaper + ships today)
- Local SEO: wiseaiagency.com only, 4 cities (not mirrored to per-vertical sites)
- Affiliate / pay-per-lead deferred post-launch — re-visit at 10+ paying customers per vertical OR credible partner offer (
knowledge/decisions/2026-05-04-affiliate-deferred.md) - wiseaiagency.com kept as hostname rewrite, not split to separate Vercel project (
knowledge/decisions/2026-05-04-wiseaiagency-rewrite.md) - CASL physical address:
125 Concession Street, Ingersoll, ON, Canada N5C 1G2— hardcoded across 3 cold-outreach templates + 3 lifecycle email footer helpers - Vet voice demo widget shows "Demo not found" until vet identity tables exist — accepted as a soft-fall fallback for the first integration; tables shipped same day in PR #305
- vetwiseai.com domain migration scheduled for May 12 when auction transfer completes (
knowledge/decisions/2026-05-04-vetwiseai-domain-migration.mdto be written; tracked in DECISION_LOG)
What was discovered (and would have shipped wrong without the sprint)
- TypeScript build blocker in Stream A's chatbot route (
maxTokensinstead ofmaxOutputTokenson Vercel AI SDK 6) — would have failedpnpm buildon first deploy. Caught by Stream B's audit before merge. - Vet vertical had NO identity layer despite a fully-shipped marketing site + Stripe products.
provision.tswrote vet prospects tooutreach_contactsonly;/api/livekit/tokenreturned 404 for vet slugs. Caught by Stream B; closed in PR #305. data.pytwo-step join bug invoice-agent-livekit/verticals/vet/—_fetch_premium_vet_clinicwas selecting identity columns from the wrong table. Pre-existing latent bug; corrected as part of #305.- Stale
provision.tscomment flagged a non-existent FK as the funeral-provisioning blocker for weeks. Audit verified the FK was already absent. tenant_voice_agents.verticalenum inconsistency —'vet'in this table vs'veterinary'inorganization_settings.vertical. Pre-existing; documented; pre-launch normalization recommended.
Outstanding (not blocking cold-outreach launch)
| Severity | Item | Notes |
|---|---|---|
| P2 | cwa-cancelled + cwa-trial-expired journey specs | Authoring + run against demo tokens |
| P2 | pro-website-cancelled-tombstone spec | Same |
| P2 | Viewport Playwright runs stale on PewSearch + ITW | Need Chromium-installed run from main checkout |
| P2 | voice-routing-integration test broken since 2026-04-22 | Voice-agent-engineer territory |
| P2 | consistency-price-matching spec re-run | After today's vet/funeral pricing updates |
| P2 | tenant_voice_agents.vertical enum normalization ('vet' ↔ 'veterinary') | Pre-launch normalization |
| P2 | DMARC tightening for funeralwiseai + vetwiseai (p=none → p=quarantine) | After 2-4 weeks of clean sending |
| Future | May 12 — veterinarywiseai.com → vetwiseai.com migration | 30-min code + DNS work; 301-forever the old domain |
Cold-outreach launch readiness
All 4 verticals ready to send. Recommended first-batch sequencing:
- Day 1 (today / tomorrow): Founder reviews 30-day social calendar (
knowledge/marketing/social-calendar-30day.md) and per-vertical cold-email sequences inknowledge/narrative/cold-outreach-emails-{church,funeral,vet}.mdfor tone/personal-detail adjustments - Day 2: First send — small test batch (5-10 prospects) per vertical from
outreach_contactsalready-scraped pool. Validate Resend sending, link tracking, reply handling. - Day 3-4: Scale to per-day cadence. Watch bounce rates + replies.
- Day 5+: First demo bookings via Cal.com.
Process lessons (for future sprints)
- Audit before migrate (
feedback_never_migrate_before_audit.md) — saved a false-positive FK drop and surfaced 4+ pre-existing bugs hiding behind the assumed broken state. - Founder's hands-on testing during the sprint surfaces customer-facing UX bugs that no audit catches — the 3 cancel-flow PRs (#301, #302, #303) all came from the founder trying to use the dashboard mid-sprint.
- Worktree-edit-only subagent pattern continues to work well — no agent ever committed; orchestrator owns commits + PR creation + merge timing. No worktree collisions across 7 parallel agents in one day.
- Same-day full-stack vet vertical completion (DB schema + provisioning code + chatbot route + voice agent + browser voice widget + cold-outreach copy + lifecycle emails) was achievable because each layer was a 1-stream subagent with clear scope.
Sprint complete. No further code work required for cold-outreach launch.