ClientsFlow · Email-System Overhaul · W4 · EBO

EBO — W4 Speed

FINAL · owner comments folded in · 2026-07-12. The target speed experience after W4 ships: every click in the Control Panel and on the public booking page feels like Notion/ClickUp — instant acknowledgment, fast settle, no mysterious hangs, no "did my edit actually save?" doubt. Pure latency/caching/plumbing — no new features, no visual redesign (W8), no send-gating changes (W1). Scenarios S1 … S8 (= handoff items W4-1 … W4-8).

✅ Decision register CLOSED — W4 carries no open questions.
D7 (S1·2) — settled 2026-07-12 (DECISIONS_FINAL): NO health-view change. The board's build-time numbers (build_ms / rows_ms / queue_ms / project_ms) are recorded in W4's QA evidence only — they are never surfaced on W0's health view, the dash, or any other screen, and no such change is filed to W0. Every W4 step is therefore GREEN or RED on measurement alone; there is no AMBER-allowlist.
All other thresholds (D1–D6) were settled by the 2026-07-12 comment round and are folded into the rows below.
What W4 owns
Raw speed of the Pipeline board and the clicks on it: how fast the board paints, how fast Log Call / stage moves / the Send-Emails modal respond, keeping the board cache warm, keeping slow external services (Google Calendar, Notion) off the critical path, and proving it with numbers the app already logs. Plus (owner comment): a plain hosting-cost tracker that Slack-notifies at $15 and $25 — and changes nothing by itself.
What W4 does NOT touch
The Today tab — owner ruling: "I don't care about the today tab, only the Pipeline dashboard view! Don't optimize anything for that!" Its existing warmer is referenced only as the pattern to copy; no Today-tab work ships in W4. W8 owns the live push board's look/animations (it stands on W4's cache coherence); W1 owns which emails send; W2 owns history content; W7 owns UI feedback affordances; W0 owns the fast_poll cron body — W4 files the board keep-warm request to W0 and verifies it, never edits that function.
You do → click/action/hover You should see → on-screen result Element changes → copy · look · where What changes underneath → data/state Must NOT happen → bug guard 🕓 Touchpoint history → impact on the card's history (or —)
🌱 Seeded test identities (STABLE — re-created VERBATIM on every reseed, never minted fresh per replay) — each scenario owns one ZZ-sentinel whose name is a constant, so the signed must_see strings stay findable across reverts and retries: ZZ-W4-S1 Kft (S1 — the card that must be visible on every board paint) · ZZ-W4-S2 Kft (S2 — cold/warm open) · ZZ-W4-S3 Kft (S3 — edited on one server copy, read from another) · ZZ-W4-S4 Kft (S4 — Log Call) · ZZ-W4-S5 Kft (S5 — booking) · ZZ-W4-S6 Kft (S6 — payment + inbound trace) · ZZ-W4-S7 Kft (S7 — stage drag + Send-Emails modal) · ZZ-W4-S8 Kft (S8 — the staging cost alert is tagged [ZZ-W4-S8 test] in its Slack message, so a test alert can never be mistaken for a real one).
Values that change per replay are NEVER in must_see: every timing threshold, deal id, spend figure, booked slot and timestamp is asserted in the step's probe (measured at runtime). must_see asserts the SHAPE + the seeded identity; the probe asserts the NUMBER. All ZZ data is purged after each pass.
🔌 Probe environment (the only bindings a probe may use) — probes run as shell commands (exit 0 = pass). The walker binds exactly one curly placeholder, {lead_id} (the scenario's seeded ZZ deal id, via probe.py --sub); everything else comes from shell env vars exported by the run: $BASE (pipeline app base URL — staging during the walk, prod on the final verify), $BOOKING_BASE (booking app base URL), $DASH_TOKEN (the live dash token). No other {placeholder} may appear in a probe — an unbound one aborts the step.
Owner rulings folded in — 2026-07-12 comment round (these OVERRIDE ANSWERS_ROUND3 and the W4 handoff wherever they conflict):
· Pipeline board only. "I don't care about the today tab… don't optimize anything for that." W4 spends zero effort on the Today tab (S2).
· Board cache window ≥ 240s so the 3-minute warmer always lands inside a live window (S2·1 — settles the old D2).
· Two-tier speed bar (S7 — settles D5): optimistic paths (drag, button press) ≈ instant, < 100 ms; request-bound paths < 300 ms to first feedback; everything settles ≤ 2 s. Cold board open ≤ 5 s (settles D1).
· Notion mirror catch-up ~10 s, failed mirror writes retried on the next sync pass, never dropped (S4·2 — settles D3).
· Booking: measure-first, then skip if unmeasurable. "The call booking works fine at the moment. Don't overcomplicate things. If you can't measure long loading times, failed logins, or anything, just skip." → S5: QA must first REPRODUCE a hung/slow booking confirm on staging. Reproduced → bound it with the existing 8-second wait cap (degraded worst case ≈ 9 s, settles D4). Not reproducible → the fix is skipped, one-line finding recorded, booking code untouched.
· Payments: the only thing that matters is that a payment arrives, is logged, and is seen in the dashboard app. The webhook mirror-write plumbing may ship only if it tests clean and changes nothing visible (S6).
· Cost: track and notify, never act. "Send me a Slack notification when we are at $15 for the monthly hosting cost and when we are at $25. That's it. Don't add any mechanisms that would change anything based on this info." → S8 = cost tracker + two Slack alerts. No dial-back, no throttling, no cap enforcement.
· Measure before building (S3, S5, S6): cache-coherence, the booking hang, and the inbound mirror call each start with recorded evidence; a non-fix is recorded as a finding, never as silence.

The speed invariant (the answer key for every scenario below) — extending the booking rule-file's UX2 invariant to the whole dash: feedback < 100 ms on optimistic paths / < 300 ms on request-bound paths, final result ≤ 2 s (board reads, Log Call, Send-Emails modal, stage moves, booking confirm). Where an external service (Google Calendar, Notion) is slow, the wait is bounded and off the human's critical path — the human never inherits a third party's hang. The canonical deal store is always written synchronously; only the eventually-consistent Notion mirror is deferred. W4 changes when things happen, never what happens — no copy, no gating, no schema changes.

S1 — Opening the Pipeline board: warm open paints in under 2 seconds (happy path / the daily moment)

Who: Mátyás  ·  When: He opens the Pipeline board — dozens of times a day, his one working surface. This is the moment that today feels "wonky and slow". After W4, the normal case is a cached, pre-warmed read.

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Mátyás opens the Pipeline board tab (normal day, board recently served or kept warm) The full board — all columns, all cards, including the ZZ-W4-S1 Kft card — is painted and interactive in under 2 seconds from click to usable board Copy: unchanged · Look: unchanged (no redesign — W8's job) · Where: Pipeline tab The board response is served from the warm cache; the payload's own timing fields show a near-zero build (build_ms ≈ 0) — served, not rebuilt Must NOT take 16–20s as historically reported; must NOT show a blank or "Loading…" board for more than 2s on a warm open; must NOT silently rebuild the whole store on every open
2 QA (not Mátyás) re-measures the board build 3× with the cache deliberately bypassed, before and after W4 A logged before/after number for the full board build, from the timing fields the endpoint already returns (build_ms / rows_ms / queue_ms / project_ms) — proving the 2026-07-11 store-read fix (~100s → ~9s full-store scan) actually reached the board path. Acceptance bar: the deal-store read (rows_ms) is ≤ 3 s for the current deal count Copy: — · Look: — · Where: QA evidence log ONLY — never the UI (D7, settled: no health-view change) 3 fresh (cache-bypassed) board builds are timed on staging then prod; rows_ms is compared against the pre-fix ~10s baseline. The numbers live in the run's QA evidence; nothing is surfaced on the health view, the dash, or any other screen Must NOT accept rows_ms > 3s without opening a follow-up; must NOT add new instrumentation — the fields already exist, read them; must NOT add any health-view / dash surface for board timing — D7 is settled: NO health-view change, the numbers stay in the QA evidence (this step is GREEN or RED on the measurement alone; there is nothing left to flag AMBER)

S2 — Cold open after idle: keep-warm cron + a cache window that actually covers it (happy path / always-warm ruling)

Who: Mátyás  ·  When: He opens the board after a longer break (lunch, a call, overnight) — the exact moment that today pays a full synchronous rebuild because the board cache expired and nothing keeps it warm. Owner pre-approved paying for warmth ("always-warm containers; pay for it"). Owner ruling: the Pipeline board is the ONLY surface W4 optimizes — the Today tab is left exactly as it is.

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Mátyás opens the board after 30+ minutes away Same experience as S1: the board (with the ZZ-W4-S2 Kft card on it) paints in under 2 seconds — because a background keep-warm step has been quietly rebuilding the board cache every 3 minutes, and the board cache now lives long enough that the warmer always lands inside a live window Copy: unchanged · Look: unchanged · Where: Pipeline tab Two changes: (a) the existing 3-minute cron gains a warm_board step mirroring the existing Today warmer — implemented by W0 inside its single-writer edit of that cron; W4 files the request and verifies; the cron heartbeat then shows warm_board: {"status": 200} every run. (b) W4 raises the board cache lifetime from 120s to ≥ 240s (owner: apply) so the 3-minute warmer can never fall into an expired ~60s window Must NOT have W4 edit the cron function itself (W0-exclusive seam); must NOT touch the Today tab, its cache, or its warmer (owner ruling — zero optimization work there); must NOT let the warmer mask a genuinely broken build (a failing warm step must appear in the cron heartbeat, not vanish); must NOT introduce a second cache dict — extend the existing one
2 Worst case: Mátyás hits the board at the exact moment the cache is genuinely cold (warmer missed a beat, fresh deploy) The board still arrives within the settled bound: ≤ 5 seconds click-to-board — never "however long it happens to take", never a spinner of unknown duration Copy: unchanged · Look: the normal loading state, briefly · Where: Pipeline tab A cold rebuild runs synchronously but on the already-fixed one-pass store read (S1·2's measurement is the proof this bound is honest) Must NOT exceed 5s — an over-run is a defect, not a footnote; must NOT regress to the per-deal read storm (one network call per deal) that caused the historic 16–20s reads

S3 — Your own change is visible immediately — the end of "edit… refresh… still not there" (happy path / trust repair)

Who: Mátyás  ·  When: He logs a call, moves a stage, or edits something — then looks at the board. Today his own change can stay invisible for up to 2 minutes: the cache-invalidation signal only reaches the server copy that handled his edit, not its siblings. This is the root of the "wasn't sure the edit actually saved" complaint, and the Q3=A push board (W8) cannot be built on top of it.

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Mátyás changes the ZZ-W4-S3 Kft card (logs a call / moves its stage) and then views the board — same tab, another tab, or a second browser window The board he sees already includes his change on the ZZ-W4-S3 Kft card — every time, on the first look, with no manual refresh ritual and no "wait two minutes" Copy: the changed card shows its new state · Look: unchanged · Where: Pipeline board The canonical deal store is written synchronously at the click (already true today); the fix guarantees that no server copy keeps serving a pre-edit cached board afterwards. QA must reproduce the stale case FIRST (two concurrent server copies: edit on one, read from the other) and only then prove it gone — a fix verified on a single copy proves nothing (owner: apply) Must NOT ever show a board missing an edit made more than 2 seconds ago; must NOT close this item on a single-container test; must NOT train him to refresh twice "to be sure" The logged call / stage move writes its history row exactly as today (W2 owns the content) — W4 only guarantees the board showing it is never stale.
2 QA measures first, before building: does this app ever actually run more than one concurrent server copy under Mátyás's real single-operator traffic? A recorded verdict with evidence, one of two: (a) yes — multiple copies observed serving within a 2-minute window → the cross-copy invalidation fix is built and S3·1 proves it; (b) no — traffic never triggers a second copy → the item is recorded as "observed non-issue, revisit if traffic grows", no distributed-cache machinery is built on spec, AND a written constraint is handed to W8: "the push board must carry the changed card's data in the push, or bust the board cache version on every push" (owner: apply) Copy: — · Look: — · Where: QA evidence log + the W8 handoff's dependency list Live evidence (distinguishable server-copy identity in logs, or a controlled burst test) decides build vs. defer; verdict (b) writes the W8 rider so the non-fix is a documented dependency, not a landmine Must NOT build a distributed cache-invalidation mechanism blind; must NOT mark the item closed with neither evidence nor fix; must NOT defer silently without the W8 rider

S4 — Log Call responds instantly; the Notion mirror catches up in the background (happy path / the item-36 complaint)

Who: Mátyás  ·  When: He clicks Log Call on a card — the exact flow from his own complaint (created a Meet invite, edited the confirmation email, "wasn't sure the edit actually saved"). Today the click blocks on a full synchronous Notion page rebuild before responding. After W4 the click frees him immediately and the mirror write moves off his critical path. The UI-feedback half of that complaint is W7's — W4 stays surgical and adds no new UI (owner: apply).

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Mátyás clicks Log Call on the ZZ-W4-S4 Kft card (with his edits to the confirmation email in place) and confirms The button acknowledges in < 300 ms and the panel completes and frees him in ≤ 2 s — the response no longer waits for the Notion CRM page rebuild. Everything he entered is saved the moment the click lands Copy: unchanged (no new toasts, no ceremony) · Look: unchanged, just fast · Where: the card's Log-Call panel The canonical deal-store write and the calendar/Meet work happen exactly as today; only the Notion mirror rebuild is handed to the existing background worker pool instead of blocking the response — the pattern the codebase already uses elsewhere, now applied consistently Must NOT hold the click hostage to Notion's response time; must NOT change what gets written — same call touchpoint, same edited email body driving the calendar description (the shipped Ferenc-Zemen behavior), just asynchronous mirroring; must NOT add a confirmation surface here (W7 owns feedback) The call touchpoint row appears exactly as today, with the edited copy — content unchanged, owned by W2. Probe: the row is present and correct even though the click returned before the Notion mirror finished.
2 Nothing — a rare failure: the background Notion mirror write fails after the click already returned Mátyás's board and the deal's real state are still correct — the canonical store was written synchronously at the click. Only the Notion CRM page is temporarily stale; normally the mirror catches up within ~10 s, and a failed mirror write is retried on the next regular sync pass, never dropped (owner: apply). The failure is logged on W0's existing health/alarm surfaces — no new W4 UI Copy: — · Look: — · Where: behind the scenes Deal store (canonical) written synchronously; the deferred mirror write failed, logged, and is re-attempted by the next sync pass — matching the documented invariant "the deal-store write stays synchronous; only the eventually-consistent mirror is deferred" Must NOT lose the logged call itself when only the mirror fails; must NOT report the click as failed when the canonical write succeeded; must NOT drop a failed mirror write (it must be retried); must NOT invent a new failure UI The touchpoint row exists (canonical); only the Notion page presentation lags until the next successful sync.

S5 — Lead books a call: verify the confirm screen — bound the hang only if the hang can be measured (existing flow · owner measure-or-skip gate)

Who: A lead (public booking page)  ·  When: A lead picks a slot and submits. Owner ruling: "The call booking works fine at the moment. Don't overcomplicate things. If you can't measure long loading times, failed logins, or anything, just skip." → This scenario is verification first: QA must reproduce a slow/hung confirm on staging before a single line of booking code is touched. Reproduced → bound it (worst case ≈ 9 s). Not reproducible → skip the fix, record the finding, leave booking alone.

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 The lead (ZZ-W4-S5 Kft) picks a slot and submits the booking form (normal day, Google Calendar healthy) Existing flow, verify unchanged: the confirmation screen renders in ≤ 2 s; the calendar invite, Meet link, notification email and the card's update all complete in the background moments later Copy: unchanged (client-facing Hungarian confirm copy as today) · Look: unchanged · Where: public booking page The already-shipped optimistic path: slot claimed + availability checked synchronously, everything heavy (CRM, Meet, email, board push) finalized on a background thread — the booking rule file's < 2s target, already honored in code Must NOT regress the ≤ 2s confirm; must NOT double-book (the claim + pre-filter protection stays exactly as is); must NOT redesign any part of a flow the owner says already works The booking lands in the lead's history exactly as today (W2 owns it) — booked-call touchpoint + confirmation-email record, written by the background finalize.
2 QA attempts to REPRODUCE the historic hang on staging: force the authoritative availability check to stall (mocked/blocked Google Calendar), then book a ZZ-sentinel slot One of two recorded verdicts: (a) reproduced — the confirm screen hangs far past 2s (the historic 60–90s class) → the one-line fix ships (the second, authoritative availability check gets the same 8-second wait cap its sibling pre-filter already has, failing open on timeout); or (b) not reproducible / not measurablethe fix is SKIPPED per the owner's rule, recorded as a one-line finding, and no booking code is touched Copy: — · Look: — · Where: QA evidence log (+ booking code only in case (a)) Case (a): only the wait is bounded — fail-open semantics, double-book posture (slot claim + pre-filter) are unchanged. Case (b): zero code change; the trace of the unbounded call is filed as a known-but-unobserved risk Must NOT change booking behavior, copy, or the double-book posture in either case; must NOT ship the fix without a reproduction (owner rule); must NOT leave the attempt unrecorded either way; must NOT leave ZZ test bookings behind ZZ-sentinel rows only, purged after the pass.
3 Close the loop: with the verdict in hand, re-book a ZZ-sentinel slot on staging and time the confirm screen Case (a): the confirm screen renders within ≤ ~9 s worst case (8s cap + overhead) under a stalled calendar, and still ≤ 2 s on a healthy one, with a green test asserting "availability check hangs > 8s → booking still returns within ~9s". Case (b): the confirm screen renders in ≤ 2 s exactly as before, and the skip is written into the W4 close-out notes Copy: unchanged · Look: unchanged · Where: public booking page + test suite Case (a): a unit/integration test mocks the availability call to hang and asserts the handler returns within ~9s. Case (b): the existing tests remain the only proof, unchanged Must NOT hang past ~9s in case (a) no matter what Google does; must NOT fail a booking because an availability read timed out; must NOT ship on a green typecheck alone; must NOT leave ZZ test data behind Unchanged — the booking's history rows are written by the background finalize whether or not the availability check timed out.

S6 — A payment arrives → it is logged and visible on the board (behind the scenes / owner-reframed)

Who: System (Stripe payment webhook, bank-transfer match, inbound email) + Mátyás (sees the result on the board)  ·  When: Money arrives, or a lead replies. Owner ruling: "The only important thing here is that a payment arrives and, if it arrives, it is logged and seen in the dashboard app." → That is the acceptance test. The latency plumbing (moving the webhook's Notion mirror write off the response thread, so a Notion hang can't trigger a provider retry storm) ships only if it tests clean and changes nothing visible.

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Nothing — a payment lands for ZZ-W4-S6 Kft (Stripe webhook or bank-transfer match fires) The owner's acceptance test: the payment is logged and the ZZ-W4-S6 Kft card on the board shows its payment progress, exactly as today — same amount, same stage, same history row. Behind the scenes the webhook response returns promptly instead of waiting out a full Notion page rebuild Copy: unchanged · Look: unchanged · Where: the paying deal's card (the Notion page follows within ~10 s) The two payment-path Notion mirror writes move to the same background-worker pattern as S4; the canonical payment state is still written synchronously. Every existing payment test stays green — that is the gate for shipping this at all Must NOT change any payment logic, amount, or stage transition — timing only; must NOT lose or delay the payment showing up on the board; must NOT let a webhook exceed the provider's timeout because of a Notion hang; must NOT ship this plumbing if any payment test goes red — drop it instead Payment history rows unchanged in content and order (W1/W2 own them) — only the Notion mirroring moment shifts by seconds.
2 QA traces (before any edit) the inbound-reply mirror write: does it run on the already-asynchronous fast-ack path, or synchronously inside the webhook response? A one-line recorded finding with the code trace: either "already off-thread — no fix needed" or "still synchronous — wrap it like S4". Only in the second case is the code touched Copy: — · Look: — · Where: implementation notes / QA evidence The inbound email webhook is documented as fast-ack (it spawns background processing immediately) — if the mirror write lives inside that spawned worker, it never blocked anyone and must be left alone Must NOT "fix" a call site that was never on a request thread (churn plus merge-collision risk with W1/W2, who also touch inbound); must NOT skip the trace and guess

S7 — The click-feedback invariant holds across the dash (two-tier bar) (guardrail / the Notion-feel acceptance sweep)

Who: Mátyás  ·  When: Any ordinary working click — moving a card between stages, opening the Send-Emails modal. The booking page has this invariant written down; the dash never did. This scenario writes it down and sweeps the main clicks against it, at the owner-approved two-tier bar. (Visual redesign, loading-state polish and double-click guards stay with W8/W7 — this is a pure timing sweep.)

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Mátyás drags the ZZ-W4-S7 Kft card to another stage column The card visually moves at once — < 100 ms, effectively one frame (the existing optimistic UI; owner: adopt the two-tier bar) — and the move is fully settled server-side in ≤ 2 s. The board never snaps the card back on a healthy save Copy: unchanged · Look: unchanged (existing optimistic move) · Where: board columns Optimistic UI applies the move instantly; the canonical store write settles behind it — existing behavior, now verified against the written invariant Must NOT block the drag on the server round-trip; must NOT leave the UI and store disagreeing after 2s; must NOT accept a 300 ms delay on an optimistic path (that tier is for request-bound clicks only) Stage-move history behavior unchanged (existing stage-sync rules own it).
2 Mátyás opens the Send-Emails modal on the ZZ-W4-S7 Kft card The modal gives feedback in < 300 ms (request-bound tier) and is fully usable in ≤ 2 s. This modal historically took 38 s; that fix already shipped — existing flow, verify unchanged, guarded against regression here Copy: unchanged · Look: unchanged · Where: Send-Emails modal No new work — the shipped fix is re-timed as part of this sweep so a regression cannot ride in silently under W1/W2's concurrent edits to the same surface Must NOT regress toward the historic 38s open while W1/W2 rework the modal's contents; must NOT re-fix what is already fixed (verification only)

S8 — Hosting cost: tracked, Slack-notified at $15 and $25 — and nothing changes by itself (guardrail / owner rewrite)

Who: Mátyás (pays the bill)  ·  When: Any month in which the warm-container / keep-warm spend adds up. Owner ruling (replaces the old cap-enforcement design): "Just track the costs and send me a Slack notification when we are at $15 for the monthly hosting cost and when we are at $25. That's it. Don't add any mechanisms that would change anything based on this info." → Two notifications. No dial-back, no throttling, no automatic sizing changes. (The $30 total cap remains the owner's own budget context; the app never enforces it.)

#You doYou should see Element that changes
copy · look · where
What changes underneathMust NOT happen 🕓 Touchpoint history
1 Nothing — the month's hosting spend crosses $15 (QA forces the tracked figure past the threshold on staging) Exactly one Slack message arrives, in English, naming the number and the month — e.g. "[ZZ-W4-S8 test] Hosting spend this month: $15.40 (heads-up threshold $15)" — on staging every alert carries the [ZZ-W4-S8 test] tag so a test alert can never be mistaken for a real one. The board, the crons and every timing behave exactly as before Copy: a new Slack notification (English) · Look: plain Slack message, no dashboard element · Where: the owner's Slack — nowhere in the app UI A cost tracker reads the month-to-date hosting spend on the existing cron cadence and stamps it into the state store (surfaced on the existing health endpoint); crossing $15 fires the Slack alert once and records that the $15 alert has been sent this month Must NOT send more than one $15 alert per calendar month; must NOT throttle, resize, dial back, or otherwise change ANY behavior based on the cost figure (owner: explicitly forbidden); must NOT add a cost widget to the dashboard UI; must NOT block a deploy or a warm container on spend
2 Nothing — the same month's hosting spend later crosses $25 A second Slack message arrives (same [ZZ-W4-S8 test] tag on staging), naming the $25 threshold and the current figure. Still nothing changes in the app; the counters reset with the new calendar month Copy: the second Slack notification (English) · Look: plain Slack message · Where: the owner's Slack The $25 alert flag is recorded alongside the $15 one; both flags reset at the month boundary so next month can alert again Must NOT repeat the $25 alert every cron tick; must NOT re-send the $15 alert after the $25 one; must NOT act on the figure in any way
🕓 Touchpoint-history note for W4:
W4 is a timing workstream — it never authors, edits, or reorders a touchpoint. Every history row in the scenarios above (the logged call in S4, the booking rows in S5, the payment rows in S6) is written with identical content and order to today, under W2's ownership; the only thing W4 moves is the moment the Notion mirror catches up (from "inside the click" to "seconds after the click"). The standing invariant is explicit: the canonical deal store is written synchronously at the click — a background mirror failure can never lose a touchpoint, only delay its Notion presentation, and a failed mirror write is retried on the next sync pass. QA for every deferred-write row therefore has two halves: the click is fast, AND the history row still lands, correct and complete.

Work-item → scenario-step mapping

Each build work item from the W4_SPEED handoff and the scenario steps that prove it works when clicked through / probed on staging, then on prod. This table is the acceptance contract for the /ebo-live-build run: after each work item ships to staging, exactly its mapped steps are walked; the full set is walked again before merge.

Work itemWhat it deliversProven by (scenario · step)
WI-1 · Board build re-measuredLive before/after timing of the full board build from the endpoint's own timing fields; confirms the 2026-07-11 store-read fix reached the board path; follow-up opened if the store-read portion is still > 3s. (D7 settled: the numbers stay in the QA evidence — no health-view change, nothing filed to W0.)S1·1 · S1·2
WI-2 · Board keep-warm + 240s cache windowA warm_board step in the existing 3-min cron (filed to W0, single-writer seam respected; heartbeat shows warm_board: 200) AND W4's own change: the board cache lifetime raised 120s → ≥ 240s so the warmer always lands inside a live window. Today tab untouched.S2·1 · S2·2
WI-3 · Booking hang: reproduce, then bound (or skip)Reproduction attempt first. Reproduced → the last unbounded Google Calendar call on the booking critical path gets the existing 8s wait cap, fail-open semantics unchanged (worst case ≈ 9s). Not reproducible → skipped by owner rule, finding recorded, booking code untouched.S5·1 · S5·2 · S5·3
WI-4 · Log-Call mirror write off-threadLog Call acknowledges < 300 ms and settles ≤ 2s; the Notion mirror is deferred to the existing background worker (catch-up ~10s, failed writes retried on the next sync pass); canonical write stays synchronous; existing Log-Call tests green.S4·1 · S4·2 · (visibility) S3·1
WI-5 · Payment path: arrives → logged → visibleThe owner's acceptance test for the money path, plus the two payment-webhook Notion writes wrapped the same way as WI-4 — shipped only if every payment test stays green and nothing visible changes.S6·1
WI-6 · Inbound mirror call traced firstA recorded one-line finding with the code trace — "already off-thread" or "wrap it" — before any edit to the inbound path.S6·2
WI-7 · Cache coherence: measure, then fix or defer + W8 riderThe stale case is reproduced across two concurrent server copies first; fix built only on evidence, or explicitly deferred WITH the written W8 push-board constraint. Either way "my own change is invisible" ends.S3·1 · S3·2
WI-8 · Dash click-invariant sweep (two-tier)The invariant written down for the dash and swept: optimistic paths < 100 ms, request-bound < 300 ms, everything settles ≤ 2s — stage moves, Send-Emails modal (regression-guarded), board opens.S7·1 · S7·2
WI-9 · Hosting-cost tracker + Slack alertsMonth-to-date hosting spend tracked on the existing cron cadence; one Slack notification at $15 and one at $25 per calendar month; no mechanism that changes anything based on the figure.S8·1 · S8·2
Sign-off — acceptance oracle. By signing, Sarudi Mátyás locks scenarios S1 … S8, the two-tier speed invariant and the settled thresholds (warm board ≤ 2s · cold board ≤ 5s · board cache ≥ 240s · feedback < 100 ms optimistic / < 300 ms request-bound · Notion mirror catch-up ~10s with retry · booking degraded ≈ 9s only if the hang is reproduced · hosting Slack alerts at $15 and $25 with no automatic action) as the acceptance answer key for W4 Speed. The decision register is closed — D7 is settled (no health-view change; board timing lives in the QA evidence only) and W4 carries no open questions. No W4 code is built or deployed before this signature.
Sarudi Mátyás  ✔ FINAL · 2026-07-12 · awaiting sign-off