ClientsFlow · Email-System Overhaul · W3 · EBO
DRAFT for owner comments · 2026-07-12. The target board-card Details drawer after W3 ships — every piece of saved lead data shown as an editable field, sorted by how likely Mátyás is to need it, the {{greeting}} the AI opens every automated email with finally visible and fixable, a trust signal on AI-guessed legal data, and a way to re-run the legal lookup when a lead entered without a website. Assembled from the W3 handoff + owner rulings (REQUIREMENTS_INVENTORY items 25–28) under the ANSWERS_ROUND3 style calibration. Scenarios W3-1 … W3-9.
{{greeting}} value must be visible on the Details panel. Item 27: EVERY piece of saved lead data must be shown as an editable field — "including fields the agent might think are unimportant." Item 28: fields sorted by relevance = likelihood the owner needs to view/edit them; higher likelihood → higher on the panel. Applied conflict resolution (item 27 wins over the handoff): the handoff deferred four saved Deal fields (payment_plan, appendix_mode, price_expiry_date, price_after_expiry) as "not triaged high-relevance" — the owner's "every saved field, even ones the agent thinks are unimportant" ruling overrides that: all four get editable rows (placed low in the Deal group per item 28). English-only operator UI — all labels, badges, buttons English; Hungarian appears only inside the greeting value itself (client-facing copy, e.g. "Szia Bence").| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás clicks "Details" on a board card | The drawer opens with the familiar three groups — Contact → Deal → Legal — and every field the system saves for this lead has a row, pre-filled with its current stored value | Copy: group headers unchanged (Contact · Deal · Legal) · Look: same drawer, a fuller field grid · Where: the Details drawer | The drawer renders the full saved-field set from the lead's stored record; the board payload delivers every field the drawer lists (nothing stripped before it reaches the screen) | Must NOT show a field the backend would silently refuse to save (a visible field that can't round-trip is worse than a hidden one); must NOT drop any of the 18 existing fields while adding the new ones | — (opening the drawer reads state; it never writes history) | Critique: Growing 18 fields to ~25 makes the drawer taller and slower to scan — completeness fights glanceability. Suggestion: Keep the three groups but visually de-emphasize the rarely-touched tail of each group (smaller/muted labels below a subtle divider), so the top of each group stays as fast to scan as today. |
| 2 | Mátyás scans the Contact group | Directly under the lead's name sits a new "Greeting" field — pre-filled with the greeting captured from the lead's cold email (e.g. Szia Bence), the exact line every automated email to this lead will open with |
Copy: label "Greeting — opens every automated email" · Look: a normal wide editable text field, second slot in Contact (right after name — highest relevance, it drives every outbound first line) · Where: Contact group | The stored greeting value (captured at pipeline entry from the cold email) is projected into the drawer; when no greeting was ever captured the field shows empty with the fallback hint (see step 4) |
Must NOT show a raw {{greeting}} token instead of the value; must NOT show a greeting belonging to a different lead; must NOT render it read-only |
— (the greeting was captured at intake by the inbound flow; showing it adds no entry) | Critique: "Greeting" alone doesn't tell him the stakes — that this one line fronts every automated email to this lead. Suggestion: The label's suffix ("opens every automated email") carries that; keep it in the label, not a hover tooltip, so the stakes are visible even in a screenshot. |
| 3 | Mátyás scans the Deal and Legal groups | Deal now also lists the four previously-hidden saved fields — Payment plan, Appendix mode, Price expiry date, Price after expiry — placed at the bottom of the group (saved but rarely touched); Legal gains an editable "Legal form" field alongside the existing four | Copy: labels "Payment plan" · "Appendix mode" · "Price expiry date" · "Price after expiry" · "Legal form" · Look: normal editable rows, low in their groups per the relevance rule · Where: Deal group tail + Legal group | Each new row reads the corresponding saved value; the save whitelist and the Notion CRM mirror mapping are extended in lockstep so each new field round-trips (see W3-8) | Must NOT hide any of these because they "seem unimportant" (explicit owner ruling — every saved field gets a row); must NOT place a rarely-edited field above a daily-edited one | — | Critique: Free-text inputs for constrained values (payment plan is 50/70/100% advance; appendix mode is structured/freeform) invite typos that break downstream documents. Suggestion: Render those two as small dropdowns with exactly the valid options; the other new fields stay free text/date. Same editability, zero invalid states. |
| 4 | Mátyás opens Details on a lead whose cold email had no usable greeting line | The Greeting field is empty, with a muted placeholder: "empty — emails will open with 'Szia <first name>'" — so he knows exactly what the fallback does before any email goes out | Copy: placeholder text as quoted · Look: empty field, muted placeholder · Where: Greeting field, Contact group | No stored greeting → the field is blank; the existing fallback (first-name greeting) remains the resolution behavior, untouched by W3 | Must NOT invent/auto-fill a greeting into the stored record just to fill the box (an empty store must stay empty until a human or the capture flow writes one); must NOT hide the field when empty | — | Critique: An empty greeting is the one case where the field most needs attention, yet an empty box is the least eye-catching state. Suggestion: Give the empty state the same quiet amber tint used by the legal "verify" badge (W3-3) — one consistent "the AI is guessing here" color across the drawer. |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás edits the Greeting field (e.g. Szia Bence → Kedves Bence) and clicks the floating Save button |
The drawer stays free the instant he clicks — the existing floating Save button does its usual brief "Saved" confirmation in the corner; no modal, no spinner blocking him | Copy: the field holds his new text · Look: existing Save-button confirmation, nothing new · Where: Details drawer + floating Save | The new greeting is written to the lead's record and stamped as a manual field (so no future auto-capture/enrichment can overwrite it); the Notion CRM's existing "Greeting" property is mirrored in the background, best-effort, never blocking the save | Must NOT be silently dropped by the save whitelist (today a greeting write is discarded server-side — that is the exact bug W3 closes); must NOT block the UI on the Notion mirror; must NOT touch any other field in the same save | — (a field edit is not a lead touchpoint; history stays owned by W2) | Critique: He types a greeting with a trailing comma or without one — and can't tell whether the template adds punctuation, risking "Kedves Bence,," in a real email. Suggestion: A one-line preview under the field showing the exact rendered first line of an email ("Kedves Bence,") so what-he-typed vs what-the-lead-sees is never a guess. |
| 2 | Later, the next automated email for this lead is generated (Send-Emails modal or any template render) — Mátyás just reads it | The email copy opens with his edited line ("Kedves Bence,") — not the originally captured greeting, not the first-name fallback | Copy: the email's first line = the saved Greeting value · Look: unchanged email UI · Where: wherever email copy renders (Send-Emails modal, history preview) | The existing {{greeting}} resolution reads the stored value — W3 changed the stored value's visibility and editability, never the resolution logic (existing flow, verify unchanged) |
Must NOT render the stale pre-edit greeting anywhere copy is generated after the save; must NOT alter when/whether that email sends (W1's domain) | When that email actually sends, W2's history row must show the resolved edited greeting — parity between shown and sent is W2's hard bar; W3 just feeds it the right value. | — |
| 3 | Background proof (QA, not a click): probe the saved record and the CRM mirror after step 1 | — (nothing on screen; this row is the reliability check behind the non-blocking save) | — | The lead record holds the new greeting + the manual-field stamp; within a short background window the Notion CRM page's "Greeting" property shows the same value (capped at the same 300-char limit used at intake) | Must NOT find the store and the CRM mirror permanently disagreeing; a failed mirror write must not un-save the store value | — | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás opens Details on a lead whose legal lookup came back low-confidence | An amber badge sits next to the Legal group header: "⚠ AI guess — verify before contract"; the four legal fields below it are filled with the AI's best guess, all still editable | Copy: badge text as quoted · Look: small amber badge, read-only (it is a system signal, not lead data — no input box for it) · Where: Legal group header row | The drawer surfaces the stored lookup-confidence flag; nothing is written by displaying it | Must NOT render confidence as an editable field; must NOT show the badge when confidence is high or when no lookup has run yet (a badge with nothing behind it destroys its meaning) | — | Critique: The badge warns but the moment of danger is later — at contract generation, where he may no longer remember this lead was flagged. Suggestion: Flag for a follow-up (not built in W3): the contract flow could surface the same amber signal at generation time. W3 only records/shows it; noting here so the signal's endpoint isn't forgotten. |
| 2 | Mátyás verifies/corrects a legal field by hand (e.g. fixes the Tax number) and saves | The corrected value persists; the corrected field is now human-owned (future lookups can never overwrite it). The amber badge remains for the group until a later lookup returns high confidence — it describes the lookup, not his edits | Copy: his corrected value in the field · Look: normal save flow · Where: Legal group | The field gets the manual-field stamp (existing invariant); the stored confidence flag is untouched by a manual edit | Must NOT let a subsequent auto-lookup overwrite his corrected field; must NOT clear the badge as a side-effect of editing one field (the other three may still be guesses) | — | Critique: Once he has hand-verified all four fields, the amber badge is now crying wolf over data he personally confirmed. Suggestion: When all four legal fields carry the manual stamp, drop the badge automatically — human-verified everywhere means there is nothing left to warn about. Cheap rule, keeps the badge honest. |
| 3 | Mátyás opens Details on a lead with a high-confidence lookup, and on a lead where no lookup has run | No badge in either case: high-confidence legal data reads as normal filled fields; a never-looked-up lead shows empty Legal fields with no badge (nothing to be confident about yet) | Copy: — · Look: clean Legal group header · Where: Legal group | Badge renders only on the stored low-confidence state; absent/high states render nothing | Must NOT show a stale badge from a previous lead (drawer state must reset per lead); must NOT show a "high confidence" badge (silence is the high-confidence signal — only the warning earns pixels) | — | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás types the lead's website into the red-badge inline URL form and saves | The form confirms instantly, exactly as today — he is free to keep working immediately; no new dialog, no wait | Copy: unchanged existing form · Look: unchanged (existing flow, verify unchanged on the surface) · Where: the card's website-missing badge/form | The URL saves as before, plus: because this lead's legal enrichment never ran, a background enrichment pass (website scrape → AI legal lookup) is kicked off fire-and-forget — the save response never waits for it | Must NOT block or slow the URL save on the multi-second AI lookup; must NOT re-fire enrichment for a lead whose legal enrichment already completed (only the never-ran case auto-triggers) | — (enrichment fills CRM fields; it is not a lead touchpoint) | Critique: The re-fire is invisible — he saves a URL, walks away, and has no cue that legal data is now cooking (or that it finished empty-handed). Suggestion: No new UI needed: the Details drawer already tells the story on next open (filled fields, badge, or the Re-run button per W3-5). Deliberately leaving this silent — flagging only so the silence is a decision, not an oversight. |
| 2 | A little later, Mátyás opens the lead's Details drawer | The Legal group is populated — Legal name, Seat address, Tax number, Representative (and Legal form) carry the lookup's results; if the lookup's confidence was low, the amber "verify" badge (W3-3) sits on the group header | Copy: real legal values in the fields · Look: filled editable fields ± amber badge · Where: Legal group | The background lookup wrote the legal fields through the existing enrichment guard — any field Mátyás had already typed by hand was skipped, untouched | Must NOT overwrite a hand-typed legal field (the human-wins invariant); must NOT leave the contract's client block blank when this data now exists | — | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás opens Details on a lead whose lookup ran but produced nothing | Empty Legal fields, no confidence badge, and a small "↻ Re-run legal lookup" button on the Legal group header | Copy: button "↻ Re-run legal lookup" · Look: compact secondary button beside the group header · Where: Legal group, Details drawer | Nothing yet — the button only renders; the empty-result state is stored so the drawer knows the lookup ran and came back dry | Must NOT hide the button (it is the only retry affordance); must NOT show the amber "AI guess" badge over empty fields (nothing was guessed) | — | — |
| 2 | Mátyás clicks "↻ Re-run legal lookup" | The button acknowledges instantly (brief "running…" state) and he is free to close the drawer and move on — the lookup runs in the background; on his next drawer open the results (or the still-blank fields + button) tell him the outcome | Copy: button flips to "running…" then back · Look: button-only state change, drawer never locks · Where: Legal group header | The lead's enrichment-done marker is cleared and the existing enrichment machinery re-runs in the background (reused, not reimplemented); results write through the human-wins guard as always | Must NOT block the drawer while the AI call runs; must NOT stack duplicate lookups from double-clicks (the button is inert while one is in flight); must NOT overwrite any hand-typed field with the retry's results | — | Critique: "Click, close, reopen later, maybe it worked" gives no failure signal at all when the retry also finds nothing — indistinguishable from "never clicked." Suggestion: Store the last-attempt time and show it as one muted line under the button ("last lookup: today 14:32 — nothing found"), so a dry retry is visibly a dry retry, not a mystery. |
| 3 | The AI still finds nothing — Mátyás types the four legal fields by hand and saves | The values persist like any field edit; from now on those fields are human-owned and no future lookup (auto or manual re-run) touches them | Copy: his typed legal data · Look: normal field save · Where: Legal group | Each typed field gets the manual-field stamp — the existing, tested invariant (existing flow, verify unchanged) | Must NOT let the re-run button's next click clobber the hand-typed values; must NOT regress the existing manual-edit-wins test | — | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás edits a field by hand (any group — including the new Greeting and Legal form fields), saves, and a background enrichment pass completes afterwards | Reopening the drawer shows his value, exactly as typed — the enrichment filled only the fields he never touched | Copy: his value intact; other blanks filled by enrichment · Look: unchanged drawer · Where: Details drawer | Enrichment writes through the guard that skips every manually-stamped field — existing tested behavior, now also covering greeting and legal_form |
Must NOT overwrite any human-typed value, ever — including the new W3 fields; must NOT strip the manual stamp during any save/mirror path | — | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás edits any Details field (say, the Greeting) and clicks Save while the save path is broken | The existing "save failed" warning appears on the floating Save button — and his typed text is still sitting in the field, ready to retry, not reverted to the old value | Copy: the existing failure toast wording (unchanged) · Look: existing warning state on the Save button · Where: floating Save button + the edited field | The store write did not happen; the drawer keeps the unsaved text client-side so a retry click can resend it (existing flow, verify unchanged — extended to the new fields) | Must NOT show "Saved" when the write failed; must NOT wipe his typed text back to the stored value; must NOT leave the new fields (Greeting etc.) outside this failure path while the old 18 are inside it | — | Critique: A toast is transient — if he clicked Save and immediately closed the drawer, the failure flashed to an empty room. Suggestion: If a drawer with an unsaved-failed field is closed, keep the card's Details button in the warning state until the value is saved or re-opened — the failure should outlive the toast. |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | QA sweep (no owner click): edit-and-save every single field the drawer shows on a ZZ-sentinel test lead, then reopen the drawer | Every value comes back exactly as typed — all groups, old fields and new alike; zero fields accept input on screen but lose it on save | Copy: — · Look: — · Where: whole Details drawer, field by field | Every drawer field has a matching entry in the save whitelist and (where the CRM has the property) the Notion mirror mapping; a test fails the build if any of the three lists drifts from the others | Must NOT ship any field that renders but doesn't persist; must NOT let a future field addition touch one list without the guard test catching the other two | — | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history | 💡 UX critique + suggestion |
|---|---|---|---|---|---|---|---|
| 1 | Mátyás opens the Details drawer at desktop width (1280) | All groups, the Greeting field, the amber badge, and the Re-run button render cleanly in the drawer; no horizontal page scroll | Copy: full · Look: full drawer layout · Where: Details drawer | Standard layout; long values wrap or scroll inside their own field, never the page | Must NOT clip the badge or button off the drawer edge; must NOT overlap field labels and inputs | — | — |
| 2 | Mátyás opens the drawer at tablet (768) and mobile (390) widths | The field grid stacks to fewer/one column(s); every field is readable and editable by touch; the Save button, badge, and Re-run button are comfortably tappable; the drawer scrolls vertically, never sideways | Copy: full · Look: stacked single-column grid on narrow widths · Where: Details drawer | Responsive breakpoints reflow the grid; touch targets meet a usable minimum | Must NOT require pinch-zoom to edit a field; must NOT hide the tail-of-group fields (the new "unimportant" ones) off-screen with no scroll cue; must NOT make the Re-run button too small to tap | — | — |
Each build work item derived for W3, and the scenario steps that prove it works when clicked through on the staging dash.
| Work item | What it delivers | Proven by (scenario · step) |
|---|---|---|
| WI-1 · Greeting field | Editable "Greeting — opens every automated email" field in Contact (second slot), wired end-to-end: drawer → save whitelist → manual stamp → Notion "Greeting" mirror → template resolution picks it up. | W3-1·2 · W3-1·4 · W3-2·1 · W3-2·2 · W3-2·3 |
| WI-2 · Full field census | Every saved lead field gets an editable row (adds Payment plan, Appendix mode, Price expiry date, Price after expiry, Legal form), sorted by relevance — item 27/28, overrides the handoff's deferral. | W3-1·1 · W3-1·3 · W3-8·1 |
| WI-3 · Legal-confidence badge | Read-only amber "AI guess — verify before contract" badge on the Legal group when the stored lookup confidence is low; silent otherwise. | W3-3·1 · W3-3·2 · W3-3·3 · W3-4·2 |
| WI-4 · Auto re-enrichment on late URL | Saving a website URL for a never-legally-enriched lead fires the existing enrichment machinery in the background, without blocking the save. | W3-4·1 · W3-4·2 |
| WI-5 · Manual "Re-run legal lookup" | Retry button on the Legal group header — instant acknowledgment, background run, double-click-safe, human-typed fields untouched. | W3-5·1 · W3-5·2 · W3-5·3 |
| WI-6 · Human-wins invariant extended | The existing manual-edit-wins guard covers the new fields (greeting, legal form) on every auto-fill path; existing tests stay green. | W3-6·1 · W3-3·2 · W3-5·3 |
| WI-7 · Save-failure integrity | New fields ride the existing failure toast + keep-typed-text behavior; no silent loss on a dead save. | W3-7·1 |
| WI-8 · Field-list lockstep guard | A test that fails the build if the drawer field list, save whitelist, and CRM mirror mapping ever drift apart again. | W3-8·1 |
| WI-9 · Responsive drawer | The grown drawer holds at 1280 / 768 / 390 — stacked grid, tappable controls, no sideways scroll. | W3-9·1 · W3-9·2 |