ClientsFlow pipeline · autonomous E2E test runner

Continuous funnel test → Stripe TEST payment

Branch feature/funnel-automation · live app matyas--clientsflow-pipeline-web.modal.run · 2026-06-20 · ZZ sentinels only

RESULT — GREEN. Two unbroken runs drove the whole funnel from a real cold email to a received Stripe TEST payment (deposit_paid), self-healing real bugs along the way. 191 pytest green throughout; deployed v051→v053. A second round fixed a DocuSeal-sweep safety bug + ran a 20-check Phase-2 layer; a third VISUAL re-walk (reading every screenshot, opening the post-call wizard UI) caught a real wizard-crash bug the API-only walk hid.
Why the visual re-walk mattered. The first run drove the post-call wizard via its API endpoints and saved screenshots to disk without viewing them. Opening the wizard in the actual browser immediately threw TypeError: (s||"").replace is not a function — the HTML-escape helper crashed on the numeric price, so the wizard never rendered for any real priced deal. That class of bug is invisible to API-only testing. Lesson baked in: look at the screens.

The continuous happy path run_002 · 10 steps · green

Each leg was driven against the real production handlers and asserted before the next. Deal deal_2d460d341b50 — "ZZ E2E — Happy B" (matyas.sarudi00+zze2eb).

#LegHow it was drivenProof
1Cold emailReal HU email matyas@clientsflow.hu+zze2ebGmail msg id returned
2Reply → New-Lead cardReal reply sent; live /missive/incoming handler driven (cold-inbox account)Deal minted, stage new_lead, Notion CRM page created
3Booking/dash/api/call/schedule (GHL retired → dashboard path)Stage booked; Google Meet + invite email delivered
4Call / transcriptHU transcript → /dash/api/transcriptai.extract_transcript_extract: price 450 000 Ft, deposit 225 000, confidence high
5Post-call wizardStep 2 AI proposal preview → step 3 eager DocuSealProposal generated; DocuSeal both sign links + Stripe link (fix)
6Sign bothClient + rep DocuSeal embeds signed via Chrome DevTools MCP"Document has been signed!" ×2 → signed=True, contract_signed
7Proposal email (human gate)/dash/api/seq/arm — the explicit operator actionproposal_chase armed; email queued into the send window (weekend-throttled, by design)
8Stripe TEST paymentCard 4242 on the hosted checkout via Chrome DevTools MCP"Thanks for your payment"; webhook → deposit_paid, paid=True, onboarding fired

Bugs found & fixed self-healed

The runner fixed code, redeployed via snap_deploy.sh, kept 191 pytest green, and (for the funnel bug) restarted the run from scratch.

WhatTypeRoot causeFix
Post-call wizard crashes on a numeric priceProduct (UI)Found in the VISUAL re-walk: esc=(s||"").replace(…) isn't string-safe; pcStep1 renders value="${esc(f.price)}" where the price is the number 450000 → (450000).replace → TypeError. The wizard never opens for any real priced deal. API-driving bypassed this.esc() made string-safe: String(s==null?"":s).replace(…). v053.
Missing deposit Stripe link in the wizardProductThe post-call wizard (preview→step3) never minted the deposit Stripe link — only the legacy /review page-1 did. So the DocuSeal doc, proposal email & step-3 panel all lost the payment link.flows.ensure_deposit_stripe_link() called inside ensure_docuseal_submission() (parity with /review). v051.
Evidence HTML always emptyHarnesse2e_evidence.py built each step but never appended it to steps[].One-line append fix.
ZZ-DocuSeal sweep was a silent no-opSafetye2e_reset.py detected submissions via a board field the API never exposed → the mandated post-attempt DocuSeal archive never ran. A stale cross-container cache also made the verify lie.Board now exposes has_docuseal; reset detects via it and reads fresh=1. v052. Verified end-to-end.

Phase 2 — rigorous board-card-qa layer 18 / 20 pass

Playwright DOM + API assertions across the funnel mechanics & scenarios (ZZ-gated, send-blocklisted). The 2 "fails" are stale tests, not product bugs.

R3A1/A4/A5 — step-2 preview, [bracket] template, variables, re-render vs AI R3B1/B2/B3/B5/B6 — step-3 DocuSeal both links + Stripe + proposal-email link + define&arm gate + rigorous create→archive I1/I2 — client-stage vs new-lead (ADR-0004) OC3 · K1 · R3C3 · Q1 · E2 · CL1 · HD1 · G1
The 2 stale tests (not product bugs): PC4 waits for #pc-email-draft, an element the R3 split-pane redesign retired — the proposal-email draft now lives in the seq-editor #se-body (covered by R3B3, PASS). B1 seeds a long inbound on S4, but S4 has a logged call-note last_touch that — by the intended LC2 rule ("last_touch wins over last_msg") — correctly renders instead; no truncation exists. The Playwright capture wave's S11 hit the same class of staleness (a step looking for the "Move" button that was intentionally removed — board-card-qa A2 asserts its absence).

Planning & execution weak points

Why some data was missing / testing was thinner than ideal — and what the second round tackled.

Weak pointImpactDisposition
"Real reply → Missive" (Q4=A) locked without verifying feasibilityThe cold-outreach inbox that mints a card isn't authed on the MCP and Missive's webhook is uncontrollable → the fully-real path isn't achievable autonomously.Drove the real production handler via the team's journey_e2e.py inject (only the Missive mailbox-sync hop substituted) + sent a genuine cold email & reply. Flagged transparently.
Stale "use /ghl/event for booking" guidancehandle_ghl_event is an inert stub (GHL retired).Used the live dashboard /dash/api/call/schedule path.
Instance 2 (techspec) never ran — no checklist / per-leg assertion listThe runner derived legs + assertions live, discovering the Stripe-link defect by hitting it.Legs + assertions reconstructed from the code; defect found & fixed.
Harness shipped "smoke-tested" but buggy (evidence append; reset DocuSeal sweep)Empty evidence; safety sweep silently did nothing.Both fixed & verified in this run.
My driver mistakes (preview missing email; passed problems dicts as strings)Two wasted wizard calls.Corrected; not app bugs. Lesson: inspect extract field types before building inputs.

Still open (documented, lower priority)

Not yet exercised: the proposal email's delivered contents (it's correctly weekend-throttled, so only the queued state was observed); the sequence-copy-edit-then-reuse-next-session flow; the legacy /review page-1 path; the onboarding email/portal artifact (stage reached deposit_paid but portal:false). The 2 stale board-card-qa tests (PC4, B1) and the journey S11 "Move" step are left for the team to retire/retarget — editing the assertions just to pass would be gaming them.
Currency presentment (from looking at the Stripe screen): the checkout displayed €664.88 (EUR) while the proposal/contract quote the deposit as 225 000 Ft (HUF). The code creates the link correctly in HUF (currency:"huf", unit_amount:225000) — the EUR figure is Stripe's Adaptive-Pricing presentment conversion (browser/locale), not a code defect. A Hungarian client would still pay the HUF-equivalent; disable Adaptive Pricing in Stripe settings to show HUF.

Evidence artifacts

FileWhat
.tmp/e2e/run_003_*.htmlThe VISUAL re-walk — every screen read & analyzed; found+fixed the wizard-crash bug; wizard steps 1-3 + DocuSeal doc + Stripe all visually verified
.tmp/e2e/run_002_*.htmlThe green run — screen-to-screen, think-aloud, 10 steps, screenshots
.tmp/e2e/run_001_*.htmlThe failed→fixed attempt (red callout at the missing Stripe-link leg)
.tmp/journey-qa/v3_journeys_qa.htmlPlaywright capture wave (S10 clean; S11 stale "Move" step)
plans/e2e-continuous-journey-test/RETROSPECTIVE.mdFull retrospective + second-round plan