ClientsFlow Pipeline · Owner Handoff

Where the project is — and how to harden it

One branch, one link. Build bf9e15c+v106 · both apps live · 632 tests green · 2026‑06‑25

🔗 Dashboard: matyas--clientsflow-pipeline-web.modal.run/dash (append your ?token=…)
🔗 Booking: matyas--clientsflow-booking-web.modal.run

1 · Current state converged

Every workstream is merged onto the single local main (bf9e15c) and deployed to one live link (v106, both apps). The whole convergence was suite‑gated (607 → 632 green) and render/console‑smoked clean. No remote push — main is 134 commits ahead of origin, local‑only, per your hard constraint.

WorkstreamStateVerification
b1–b6 live‑test backlogmerged + FINAL‑QA all PASSTDD red→green, per‑bug Sonnet QA‑twin, live Opus final‑QA (B4/B5/B6 live; B1 render‑verified; B2/B3 seam + owner‑residual)
Fireflies fixes (B1/B2/B4/B5)merged (0e288c8)TDD, 579 green standalone; clean 3‑way merge; dedup verified
F1–F6 (bnf‑finish)merged (bf9e15c)separately final‑QA'd in its own run; one stale cancel‑test reconciled to b1's signed behavior
UX polish (J/JX)mergedrelative‑time cards, new‑lead recency bar, sticky stage‑nav, cancel pill buttons, optimistic‑save banner
Combinedlive bf9e15c+v106632 pytest green · 0 JS console errors · correct paint

2 · Reliability — most unstable / ambiguous parts ranked

Ranked by business risk. Each row cites the real code site and a concrete hardening step.

🔴 High — address before leaning on it in production 🟡 Medium — monitor / harden opportunistically 🟢 Mitigated — fix shipped this round; verify live
#AreaRiskEvidenceHardeningSev
1Calendar‑invite delivery (DWD)Leads may not actually receive the Google Calendar / Meet invite — the booking "succeeds" but no invite lands.SA scopes are drive+calendar only (gmail.send is a separate credential); delivery is gated by GCAL_DRIVEN_CONFIRMATION + domain‑wide delegation. Owner‑blocker noted at flows_calls.py:942.Finish DWD calendar scope in Admin Console; set GCAL_DRIVEN_CONFIRMATION=1; send one real invite to confirm; alert on meet_invite_blocked (the code already surfaces it honestly).🔴 High
2Categorization‑AI false negativesPositive leads wrongly flagged negative → real prospects silently sidelined. Highest business risk.F1 shipped an eval harness (app/classify_eval.py) — it measures accuracy but does not auto‑correct the live classifier.Run the frozen‑set autoresearch eval loop, declare a metric, keep a champion prompt only on improvement; route borderline scores to a human glance.🔴 High
3AUTOSEND in productionIf any path bypassed the human gate, copy could reach a lead unreviewed.Env‑gated AUTOSEND_ENABLED (config.py:397); protected by the human gate + send‑allowlist (+zz) + safe_click refusing send/arm.Keep the gate invariants intact; add an outbound audit log (who/what/when) per lead‑bound send; confirm the current prod env value before campaigns.🟡 Med
4Identity‑only deal matchingA transcript / inbound whose email ≠ the CRM email won't link to its deal (falls back to a Slack flag).Match chain = clientReferenceId → email → meeting_id → cal_id; CRM dedup matches exact email/phone only.B5 cal_id leg shipped this round; consider a human‑confirmed fuzzy fallback for the residual.🟡 Med
5Per‑container cache stalenessA new mutating endpoint that forgets to invalidate leaves a stale board on some web containers.Invalidation is manual per endpoint (_cache.pop(...) across dash.py); fast_poll._warm_today re‑warms the web container over HTTP (fragile if unreachable).Centralize cache invalidation behind the mutation helpers; add a fallback TTL so a missed pop self‑heals.🟡 Med
6Modal 5‑cron capNo room for new scheduled work without consolidation.4 crons (*/3, */10, daily 08:00, 07:00) + web = the 5 slots (modal_app.py).Consolidate into one dispatcher cron that fans out by minute, freeing slots.🟡 Med
7Smart‑relay >3 routing dormantThe participant‑driven bot/bot‑free routing isn't firing on real Meets yet./meet/participant-joined has no Workspace‑Events push subscription (B8 deferred); Fireflies record‑all auto‑join covers capture regardless.Stay on record‑all (works today) OR build the Workspace‑Events subscription (needs SA Meet scopes + admin consent).🟡 Med
8Fireflies webhook unsignedUntil the secret is set both sides, the webhook accepts unsigned POSTs.B4 HMAC verify shipped, fail‑open when the secret env is empty (mirrors GHL/Stripe).Paste FIREFLIES_WEBHOOK_SECRET into the Fireflies UI Signing‑Secret field (the env side is already wired) to close fail‑open.🟢 Mitig
9Fireflies date / early‑webhook crashesPreviously: a transcript created no calls row (Notion 400) and an early webhook 500'd.B1 (ms→ISO date) + B2 (early‑webhook 200 guard, leaves retry to the backup poll) shipped + unit‑tested.Verify with one real live transcript that a Notion calls row + recording link land.🟢 Mitig
10134 unpushed commitsNo off‑machine backup of the converged work.main is local‑only, 134 ahead of origin; git bundle backups exist under .tmp/backups/.Push main to the private remote when you're ready (your explicit trigger — I will not push unprompted).🟡 Med

3 · Owner residuals only you

Things that need your Workspace / account, not code

4 · Next steps open

Fireflies bot‑free live test

The SDK is connected; the test needs a real ZZ Meet with audio (a silent recording yields no transcript). Success = recording + Notion calls row. Owner‑involved or two Chrome profiles + an audio source.

Whole‑journey visual QA

Aggregate every prior EBO (round‑3, duo2, board‑card, live‑test, b1–b6, Fireflies, F1–F6) into one vision‑truthful pass over v106 — ingestion → lead → sequence → booked → sales‑call → proposal → sign → payment.

Categorization eval loop

Stand up the frozen‑set eval for the #2 risk; keep a champion classifier prompt only on measured improvement.

Remote backup

When ready, push the 134 local commits to the private remote so the converged build is backed up off‑machine.