Human overview · for understanding

Meet recorder auto-join — tech spec overview

≤5s recorder dispatch + email-independent CRM touchpoint · 2026-07-08

≤5s recorder dispatch + email-independent CRM touchpoint

Master summary — the gist in 30 seconds

TL;DRWhen Mátyás joins a scheduled Google Meet, the pipeline must summon the Fireflies recorder within 5 seconds of our own webhook firing, and the finished transcript must land on the right CRM deal no matter which email the lead joined from.

Input: a calendar-poll signal saying 'someone joined this Meet'. Output: (1) Fireflies gets the record-this-meeting instruction in under 5 seconds of OUR half of the trip, and (2) once the call ends, the transcript shows up as a touchpoint on the lead's CRM card — even if the lead joined with a personal Gmail instead of the address on file.

Why this mattersA slow or silent recorder dispatch means a sales call goes unrecorded; a touchpoint that only matches by exact email means real calls silently vanish from the CRM whenever a lead joins from their phone or a colleague's email. Both failure modes look fine in the dashboard until you go looking for the missing evidence.
flowchart LR
 A["Calendar poll<br/>detects a join"] --> B["Our webhook<br/>/meet/participant-joined"]
 B -->|"≤5s budget"| C["Fireflies<br/>addToLiveMeeting"]
 C --> D["Call happens,<br/>Fireflies records"]
 D --> E["Transcript webhook<br/>handle_fireflies"]
 E -->|"match by event/link/title,<br/>NOT by email"| F["CRM touchpoint<br/>on the right deal"]

1 · Where the 5 seconds actually go (MR-01, MR-02)

TL;DRToday's clock starts too late to prove the real budget, and dispatch runs synchronously — fine only if measurement proves it's fast enough.

Input: the existing latency instrument, which starts timing only once the Fireflies call begins. Output: a timer that starts the instant our webhook receives the signal, so it captures ALL the pre-work (decoding, marker-writes, deal lookup) too — the true 'our half'. If that true number ever creeps past 5 seconds, the fix is to fire the Fireflies call in the background instead of making the calendar-poll wait on it.

Why it mattersYou can't hit a 5-second target you're not honestly measuring. The old timer flattered itself by skipping the setup work; the new one tells the truth, and only THEN do we decide whether synchronous dispatch is fast enough — no need to add background-job complexity unless the numbers actually demand it.
flowchart TD
 A["Webhook entry"] -->|"NEW: timer starts here"| B["Decode + write markers"]
 B --> C["Look up the deal"]
 C --> D["Call Fireflies"]
 D --> E["Fireflies acknowledges"]
 E --> F{"Full delta ≤ 5s?"}
 F -->|yes| G["Keep it synchronous"]
 F -->|no| H["Fire the call in the<br/>background instead"]

2 · Proving it on a real call (MR-03)

TL;DRThe only test that counts is a live 2-person Google Meet with Mátyás, joined from a non-CRM email.

Input: a real scheduled meeting, a second human joining from an email the CRM has never seen. Output: two proofs read straight from production — the measured signal-to-ack delay is at or under 5 seconds, and after the call ends a touchpoint appears on the lead's card with the right call type in Notion.

Why it mattersLatency numbers and attribution logic can look perfect in a unit test and still fail against Google's and Fireflies' real timing quirks. This is the step that turns 'should work' into 'proven to work,' capped at 4 attempts so it doesn't become an open-ended loop.
flowchart LR
 A["Schedule a ZZ-tagged<br/>test Meet"] --> B["Mátyás + 1 other<br/>(different email) join"]
 B --> C["Read dispatch_latency<br/>marker ≤ 5s?"]
 C --> D["Call ends,<br/>transcript arrives"]
 D --> E["Touchpoint appears<br/>on the CRM deal?"]
 E --> F{"Both true?"}
 F -->|no| G["Fix + retry,<br/>up to 4x"]
 F -->|yes| H["Ship it"]

3 · What's already solid — verify, don't rebuild (MR-04–06)

TL;DRThree pieces of this feature already shipped in earlier sessions; this pass only confirms they still hold, it doesn't redo them.

Input: the current deployed state (the 5-minute early-join window, the email-independent matching logic, the primary/fallback recorder split). Output: three confirm-only checks proving nothing regressed — no new code unless a check goes red.

Why it mattersRe-verifying settled work catches silent drift (a stale Apps Script deploy, a broken regex) without wasting effort re-designing something that already works. ADR-0001 records why the calendar-SDK is the primary path and our poll is only the fallback, so a future session doesn't relitigate it.
flowchart TD
 A["MR-04: early-join window<br/>still 5 minutes, deployed copy matches repo"]
 B["MR-05: a lead joining from<br/>any email still attributes correctly"]
 C["MR-06: primary (Fireflies SDK) +<br/>fallback (our poll) never double-record"]
 D["All green -><br/>no rebuild needed"]
 A --> D
 B --> D
 C --> D
HANDOFF.md (goal, decisions, constraints) →checklist.md (the executable worklist) →ADR-0001 (primary/fallback + single-flight) →PROMPT_to_execute.md (paste into a new chat to run Instance 3) →