ClientsFlow · Email-System Overhaul · W7 · EBO
FINAL — owner decisions closed · 2026-07-12. The Control Panel after W7 ships — the Create-Task button removed for good and its endpoint retired (Q15=A · R4), the top-level nav reduced to Pipeline ONLY — every other tab, dormant or daily, relocated into the ☰ hamburger without losing a single function (R1 · Q14 · Q16=A), the tax-number field validating its format (with near-miss auto-repair), and every remaining non-send action button disciplined: visible feedback under 300ms and no double-click ever doing a thing twice. Scenarios S1 … S6 (W7's six scenarios). Precedence applied: DECISIONS_FINAL.md (2026-07-12) > owner comments > ANSWERS_ROUND3 > the W7 handoff. The AMBER register is CLOSED — nothing in W7 may be guessed, defaulted or flagged amber.
POST /dash/api/create-task is removed together with the UI — no orphaned route survives the button (S1·3 proves it answers 404/405).POST /dash/api/create-task answers 404/405 after W7; tasks.create_task survives only for the automatic Call-lead / Follow-up-due integration). This overrides the W7 handoff's original plan to wrap Create-Task in a click-guard + idempotency key — you can't double-click a button that no longer exists, and you can't double-fire an endpoint that no longer answers. R1 (the round's biggest ruling) — top-level nav = PIPELINE ONLY: Focus/Today, Done, Calls, Outbox and every other tab move into the ☰. Q14 the hamburger absorbs them all plus every never-used dashboard part. Q16=A aggressive kill/hide appetite — when in doubt, hide it. Round-2 Q7: "He uses ONLY the pipeline view. Other tabs must not affect pipeline behavior; do not optimize for them." — R1 is that sentence taken literally. Comment rulings folded into the normative rows: the tax-number field auto-repairs near-misses instead of rejecting them (S4·2); the never-used-parts audit is evidenced from the mined session history, not new click tracking, and defaults a silent element to the ☰ (S3·1); the sweep's named acceptance benchmark is the owner's own Log Call → edited confirmation email uncertainty (S5·1).main (drawer Save button after close, Regenerate double-fire guard) — W7 verifies them live, it does not rebuild them; nothing here sends anything to a lead; all test data carries the ZZ… sentinel and is purged after the pass.ZZ-W7-S1 Kft (Create-Task removal) · ZZ-W7-S2 Kft (nav / relocation) · ZZ-W7-S3 Kft (decluttered board) · ZZ-W7-S4 Kft (tax number) · ZZ-W7-S5 Kft (action-button sweep) · ZZ-W7-S6 Kft (verify-only pair). Marker strings the build writes so the probes can find them: ZZ-W7-S5-EDITED (the edited confirmation text), ZZ-W7-S5-DBLCLICK (the double-clicked action's note), ZZ-W7-S6-DISCARDED (the edit that must never be saved). The two review artifacts carry sentinel headers ZZ-W7-S3-AUDIT and ZZ-W7-S5-SWEEP. Values that change per replay (ids, timestamps) are asserted only in the probes, never in the pixel checklist.$BASE = the staging dash base URL (https://matyas-staging--clientsflow-pipeline-web.modal.run) and $DASH_TOKEN = that environment's dash token, exported by the walker. {lead_id} is the only curly placeholder (bound per step by probe.py --sub to the seeded lead's identifier). All test data is purged after the pass.| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history |
|---|---|---|---|---|---|---|
| 1 | Mátyás opens a lead card's action row — in any pipeline column (new lead, scheduling, design presented, contract out, paying client, delivery stages), ZZ-W7-S1 Kft among them |
No "+ Create Task" button anywhere — the action row shows only the surviving actions (Log Call, Note, Move, Studio buttons where relevant); the row closes up cleanly with no gap or placeholder where the button used to be | Copy: "+ Create Task" label gone · Look: action row one button shorter, no empty slot · Where: every card layout that used to render it (all ten render sites) | The Create-Task control is deleted from every card template — removed from the interface, not hidden by CSS and not disabled; the served dashboard page no longer contains the dealCreateTask handler or the "Create Task" label anywhere |
Must NOT survive on even one card layout (the button renders from ten separate places today — a partial removal that misses one is a fail); must NOT leave a visually empty gap or a greyed-out stub; must NOT leave any link, tooltip or help text still pointing at "create a task"; must NOT remove any OTHER button in the same action row | — (removing the button creates no history; and no future "task created" entry can originate from the dash anymore) |
| 2 | Mátyás checks the Main-Tasks integration after the removal (his real task flows: 📞 Call-lead and Follow-up-due cards) | The task-driven cards on the board still work exactly as before — existing flow, verify unchanged: call and follow-up tasks still appear and complete normally | Copy: unchanged · Look: unchanged · Where: board task cards (Focus / call cards) | Only the manual Create-Task button is removed; the system-generated Main-Tasks integration (call / follow-up task types) is untouched and still returns its task feed | Must NOT break or degrade the automatic task integration while removing the manual button (they share the same Main-Tasks plumbing — the removal must be surgical); must NOT leave the task feed erroring or empty | — |
| 3 | The QA pass calls the old backend route directly — POST /dash/api/create-task — the way a stale cached page or an old bookmark/script would |
The route is gone: the call comes back as a 404 (not found) or 405 (method not allowed) — never a 200, never a created task. The endpoint was retired with the button (owner ruling D1/R4), so no orphaned way into Main-Tasks survives the removal | Copy: — · Look: — (backend surface) · Where: the dash API — the /dash/api/create-task route and its api_create_task handler are deleted |
The route registration and its handler are removed from the dash app; tasks.create_task itself survives ONLY as the automatic Main-Tasks integration's internal call path (Call-lead / Follow-up-due) — nothing user-triggerable reaches it anymore |
Must NOT still answer 200 or create a Main-Tasks row (a dormant endpoint is exactly what this ruling forbids); must NOT be left behind returning a 500 or an auth error instead of a clean 404/405 (that is a live route, not a retired one); must NOT delete or break tasks.create_task itself — the automatic Call-lead / Follow-up-due integration still needs it (S1·2) |
— (no dash path, UI or API, can author a task record anymore) |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history |
|---|---|---|---|---|---|---|
| 1 | Mátyás loads the dashboard | The top bar holds exactly one item — Pipeline — plus the ☰ hamburger. Every other panel, dormant or daily (Focus/Today, Done, Calls, Outbox, Templates, AI Usage, Health, CRM book, Test drive, Flowchart, Lost/nurture, Metrics, Costs, Lead radar, Finances, Journey copy, Debug), now lives inside the ☰ only. The board is the page | Copy: tab names unchanged, just moved; the nav shows "Pipeline" and nothing else · Look: one-item top bar + ☰ (drawn per W8) · Where: dashboard top nav | The nav's split is re-declared in one place: the primary list shrinks to a single entry (pipeline); every other panel is registered as a hamburger item. No tab's underlying page/panel changes — only its entry point. Routing (PANELS) still resolves every panel exactly as before |
Must NOT leave ANY second tab in the top bar — Focus/Today, Calls and Outbox are relocated too, and a top bar with two names is a fail (R1 is literal); must NOT delete any tab in the move (relocation ≠ deletion — Create-Task is the ONLY removal in W7); must NOT leave the same tab reachable from two places (old ⋯ Tools overflow AND the new ☰ — one home each); must NOT make the pipeline board itself harder to reach or slower to render because the nav shrank | — |
| 2 | Mátyás opens the ☰ and clicks each relocated tab, one by one — all eighteen, his daily four (Focus/Today, Done, Calls, Outbox) first — and inside each performs one real interaction (works a Focus card, marks a call, opens an outbox row, saves a template edit, expands a finance row, runs a health check, opens a radar hit) | Each tab opens and works exactly as it did before the move — Focus/Today still lists and completes today's cards, Calls still opens a call's detail, Outbox still shows the queued/sent audit trail and its failure rows, Templates still edits and saves a template, Health still shows live checks, Finances still opens its Glance/Operate/Deep views (owner-gated Personal still gated), Lead radar still lists radar hits, Debug still owner-only. Losing a click of speed is acceptable; losing a function is not | Copy: unchanged inside every tab · Look: unchanged inside every tab · Where: each relocated tab's own panel | Each hamburger item deep-links to the existing panel; zero behavioural change inside any relocated tab — same data, same buttons, same permissions (owner-gating intact); each tab's data fetch still resolves, not just its shell. The four daily tabs are exercised with the same rigour as the dormant thirteen — under R1 they carry real work now | Must NOT lose any function inside a relocated tab (a tab that opens but half-works, or renders its shell with a failed data fetch, counts as lost — and for the daily four this is a hard fail, not a nit); must NOT drop the owner-only gate on Finances-Personal or Debug in the move; must NOT need more than open-☰ + one click to reach any tab | — |
| 3 | Mátyás uses an old bookmark or a link from the Notion guide that pointed at a now-relocated tab (the old direct tab addresses, including the legacy Hungarian hash aliases #sablonok, #egeszseg, #hasznalat, #ma, #hivasok, #kimeno…) — including the daily tabs R1 just moved (Focus/Today, Calls, Outbox) |
The link still lands him on that tab, exactly as before — the relocation is invisible to old links; the tab just isn't in the top bar anymore. His muscle-memory bookmarks for Today / Calls / Outbox keep working, which is the escape hatch that makes the one-item nav safe | Copy: — · Look: the target tab opens; the top bar shows its one-item self · Where: whichever tab the link targets | Direct tab addresses (hash links and the legacy alias map, #ma/#hivasok/#kimeno included) keep resolving to their panels; only the visible nav entry moved |
Must NOT 404 or bounce-to-default any previously working tab link (the Notion GO-LIVE guide and his bookmarks reference tabs by address — breaking those silently strands documentation); must NOT drop the aliases of the four tabs R1 relocated (they are now the most-used direct links on the dash) | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history |
|---|---|---|---|---|---|---|
| 1 | Mátyás opens the declutter audit list the build pass produced (plans/email-system-overhaul-2026-07-11/W7_DECLUTTER_AUDIT.md) — one row per never-used part found on the working surface. Whole tabs are no longer candidates (R1 settles them: all of them move), so the audit is now purely about widgets and controls on the board surface itself: the CRM-book link, per-card Studio/Figma buttons on stages where he never uses them, any stats block he never reads |
A short, plain list, one row each: What it is · Where it sits today · Evidence from session history · Proposed new home (hamburger / stays / gone) — every row's evidence cites the mined sessions, or says "no mention in the record → default: hamburger". He marks each row keep-visible / relocate / (for true dead weight) remove | Copy: the audit list itself (a review artifact, not a UI feature) · Look: — · Where: delivered with this workstream's build, before the move | Nothing moves yet — the audit is the gate; his verdicts drive the relocation build. No usage-tracking code is added to the dash to produce it | Must NOT relocate or remove anything that isn't on an approved audit row (aggressive appetite ≠ silent disappearances — Create-Task is the only pre-approved removal); must NOT pad the list with things he clearly uses daily; must NOT invent usage numbers the mined record can't support (a silent element is marked "no mention → default hamburger", never "used 0 times") | — |
| 2 | After his verdicts land, Mátyás works a normal morning on the decluttered board | The working surface shows only what he uses; every relocated part is findable inside the ☰ under a sensible name and works there — nothing he approved for relocation turns out to be missing or broken | Copy: relocated items keep their names · Look: quieter working surface · Where: board + ☰ | Each approved audit row is executed exactly as marked; the executed audit list is kept with the ship record so every moved item is traceable | Must NOT execute a row differently from his verdict (marked "relocate" but actually deleted = fail); must NOT degrade anything left on the working surface while extracting its neighbours | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history |
|---|---|---|---|---|---|---|
| 1 | On ZZ-W7-S4 Kft's Details panel Mátyás types a genuinely wrong tax number (1234, or not-a-number) into the Tax number field and tries to save |
An inline red hint appears right under the field ("Expected format: 12345678-1-12") and the save is blocked for that value — typing is never blocked, only saving | Copy: hint "Expected format: 12345678-1-12" · Look: field border + hint in red · Where: Details panel, Legal group, Tax number field | The field carries a format check against the Hungarian tax-number shape (8 digits – 1 digit – 2 digits); a non-matching, non-repairable value never leaves the browser as a save | Must NOT block or reformat his typing mid-keystroke (he may paste, backspace, retype freely — only the save is gated); must NOT silently accept the bad value; must NOT flag a valid number as invalid | — |
| 2 | Mátyás pastes a near-miss — the right 11 digits with wrong separators (12345678 1 12 or 12345678112) — and saves |
The save goes through and the field shows the repaired, dashed value (12345678-1-12) — no red hint, no rejection, no retyping: the fixable is fixed |
Copy: the normalized value replaces what he pasted · Look: normal saved-field state (no red) · Where: Details panel, Tax number field | Both the browser and the server normalize a digits-correct value to ########-#-## before it is written; the lead record and Notion's Adószám property receive the dashed form, never the pasted spacing |
Must NOT reject a near-miss (rejecting a fixable value is the bug this ruling removes); must NOT normalize anything whose digits are wrong (a 10- or 12-digit value is a rejection, not a repair — never invent a digit); must NOT write the un-normalized text anywhere | — |
| 3 | A genuinely malformed value reaches the server anyway (a stale cached page, an old tab open from before the update) | The save round-trip comes back rejected with a visible reason on screen ("Invalid tax number format") — the field keeps his typed value so he can correct it; the lead's stored data is untouched | Copy: rejection reason shown ("Invalid tax number format") · Look: the failed field flagged red · Where: Details panel | The server independently re-checks the same format (and applies the same near-miss repair) on every lead-field save and refuses a non-matching tax number before it is written anywhere — the on-screen check is convenience, the server check is the guarantee; a valid value writes through to the lead record, to Notion's Adószám property, and later into the contract's Megbízó block exactly as saved | Must NOT write the malformed value to the lead record or forward it to Notion; must NOT fail silently (a rejection he never sees = the old bug with extra steps); must NOT wipe his typed text on rejection; must NOT add any extra confirmation step for valid values (the happy path stays exactly as fast as today) | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history |
|---|---|---|---|---|---|---|
| 1 | The benchmark case. On ZZ-W7-S5 Kft Mátyás uses Log Call, edits the confirmation email's text in the panel, and saves — then clicks any other action button on the card (Note, Move) |
Something visibly reacts within 300ms of every click — either the optimistic result itself (the card moves / the note toast fires instantly, as the board already does) or the button switches to a busy state until the request settles; and the edited confirmation text is visibly reflected as saved in the field he just edited — he never has to wonder whether the edit stuck. Then the UI is immediately his again — never a frozen wait | Copy: existing toasts/labels unchanged; the edited text shown as the field's saved state · Look: instant reaction on every action click, board-wide · Where: every non-send action button in the Control Panel; the Log-Call confirmation-email field | Every action click either goes through the existing instant-feedback path (card animates + toast before the network settles — already the case for moves, dispositions, notes) or gets the same disable-while-busy treatment the Studio-send buttons already have. The edited confirmation text is what the calendar event / confirmation email actually carries — the saved state on screen and the value downstream are the same string. Nothing waits silently | Must NOT leave any action button that shows nothing for the length of a network round-trip; must NOT hold the owner's flow hostage (feedback frees him immediately — reliability is proven in the background, not by making him watch a spinner finish); must NOT show the edit as saved while the calendar/email still carries the old text | Actions that already log a touchpoint (call logged, note saved) keep logging exactly one entry per real action — the sweep changes click mechanics, never history content (W2 owns content). |
| 2 | Mátyás double-clicks (or mash-clicks) any action button that changes real data, before the first click has finished | The result is identical to a single click — one note, one logged call, one move, one saved field. The second click lands on a disabled/already-done control and does nothing extra | Copy: one confirmation, not two · Look: button inert after the first click until settled · Where: every data-mutating action button | Exactly one request leaves the browser per action; where a stale page could bypass the client guard, the server treats a rapid duplicate of the same action as the same action (returns the first result instead of doing it again) | Must NOT create two of anything from a double-click (two notes, two logged calls, two rows anywhere); must NOT rely on the client guard alone for data-mutating actions — the server backstop must hold even from a stale cached page | Exactly one history entry per real action — a duplicate entry from a double-click is the sweep's canonical fail. |
| 3 | Mátyás (or the QA pass) opens the sweep's written audit (plans/email-system-overhaul-2026-07-11/W7_BUTTON_SWEEP_AUDIT.md) — one row per action button in the Control Panel |
A complete table: Button · What it does · Guard status (already covered / gap fixed / excluded) · Proof; every row previously marked "gap" carries a double-click test showing exactly one request fired | Copy: the audit table (ship-record artifact) · Look: — · Where: attached to this workstream's ship-ledger row | The sweep is exhaustive over the Control Panel's non-send buttons and its findings are recorded — "already covered" claims are verified, not assumed | Must NOT touch buttons owned by W1 (send-triggering) or panels W3 is still reshaping — the audit marks those "excluded (Wx seam)" rather than silently skipping them; must NOT rewrite the existing feedback machinery itself, only wrap the gaps | — |
| # | You do | You should see | Element that changes copy · look · where |
What changes underneath | Must NOT happen | 🕓 Touchpoint history |
|---|---|---|---|---|---|---|
| 1 | On ZZ-W7-S6 Kft Mátyás edits a Details-panel field, closes the drawer WITHOUT saving, then looks for the floating Save button |
The floating Save button is already gone the moment the drawer closes — there is nothing left to click that could silently do nothing. Reopening the drawer shows the field's last saved value (the unsaved edit was discarded with the close) | Copy: — · Look: no orphaned Save button after drawer close (current shipped behaviour) · Where: Details drawer + floating Save | Closing the drawer clears the pending-edit flag and hides the floating Save button (shipped fix, tag DT1) — verified live once, screenshot kept as proof; the lead's stored record is unchanged by the discarded edit |
Must NOT show a clickable Save that no-ops (the pre-fix bug); must NOT have written the unsaved edit to the record; if any OTHER code path re-shows the Save button, clicking it must either save correctly or show a visible error — never silence | — |
| 2 | Mátyás opens a ZZ-sentinel proposal's regenerate controls and double-clicks Regenerate (or clicks Regenerate then immediately Re-render) | Both buttons go inert on the first click and stay inert until the run finishes — one AI generation runs, one result appears; the buttons re-enable after | Copy: unchanged · Look: both buttons disabled during the in-flight run (current shipped behaviour) · Where: proposal panel regenerate controls | Both regenerate buttons are disabled synchronously before the request leaves and re-enabled only when it resolves (shipped fix) — exactly one paid AI call per human intent; the AI-usage ledger shows exactly one generation for the double-click | Must NOT fire a second paid AI generation from any click combination while one is in flight; must NOT leave the buttons stuck disabled if the run fails (they must re-enable with the failure visible) | — |
| 3 | The overhaul's findings record is updated after both live checks pass | The master findings entry for these two items reads "already fixed, live-verified <date>" with the proof attached — no builder in a later workstream re-implements a shipped fix | Copy: findings record correction · Look: — · Where: plans/email-system-overhaul-2026-07-11/MASTER_FINDINGS.md |
The stale framing (which described both as open bugs) is corrected at the source so the record matches production reality | Must NOT leave the stale "open bug" framing in place (a later agent reading it would rebuild — and possibly break — a working fix) | — |
Each build work item derived for W7, and the scenario steps that prove it works when clicked through on the staging dash. (The handoff's original "Create-Task click-guard + idempotency key" item is superseded by Q15=A + R4 — the button AND the endpoint are removed; its server-side double-fire concern survives generalized inside WI-5's backstop rule.)
| Work item | What it delivers | Proven by (scenario · step) |
|---|---|---|
| WI-1 · Create-Task removal (button + endpoint) | The button deleted from all ten render sites, the dealCreateTask handler deleted, and POST /dash/api/create-task retired (route + api_create_task handler removed → 404/405). No dead references or gaps, no dash path — UI or API — can create a Main-Tasks row; the automatic Call-lead / Follow-up-due integration untouched. | S1.1 · S1.2 · S1.3 |
| WI-2 · Hamburger relocation map (ALL non-pipeline tabs) | Top-level nav reduced to Pipeline only (R1); all eighteen other panels — the daily four (Focus/Today, Done, Calls, Outbox) included — registered under the ☰ (contents = W7, visuals = W8), one home each; all still fully functional (one real interaction per tab, daily four first); legacy links/aliases (incl. #ma/#hivasok/#kimeno) keep resolving. | S2.1 · S2.2 · S2.3 |
| WI-3 · Never-used-parts audit + relocation | A written audit (evidence = mined session history; silent element → hamburger) of never-used widgets/controls on the board surface (whole tabs are settled by R1, not audit material), owner verdict per row, verdicts executed exactly. | S3.1 · S3.2 |
| WI-4 · Tax-number validation + near-miss repair | Client-side format hint (blocks save, never typing), digits-correct/separator-wrong values auto-normalized to 12345678-1-12, independent server-side reject of genuinely malformed values; valid values flow to the lead record / Notion / contract untouched. | S4.1 · S4.2 · S4.3 |
| WI-5 · Action-button discipline sweep | Every non-send action button: feedback <300ms, double-click never duplicates a mutation (server backstop), the Log-Call → edited-confirmation-email case as the named benchmark, exhaustive written audit with per-gap double-click proof; W1/W3 seams excluded explicitly. | S5.1 · S5.2 · S5.3 |
| WI-6 · Verify-only pair + record correction | Drawer-close Save-button fix and Regenerate double-fire guard proven live once each (screenshots), master-findings stale framing corrected — zero rebuild. | S6.1 · S6.2 · S6.3 |