Changelog

0.2.1 — Dial header search opens Search mode instead of pinning

Picking a lead from the header search now displays it in an ephemeral Search mode that never enters the bucket queue or bypasses filters.

What's fixed

  • A lead tagged Lost no longer reappears in a bucket whose filter says "Tags is not Lost". The root cause was header search: picking a lead unconditionally pinned the row past every filter and persisted the pin to localStorage with no un-pin action. Each subsequent dial refreshed the pin's staleness guard, so once a pinned lead was later tagged Lost, it was trapped in the bucket indefinitely.

What changed

  • Search mode is ephemeral. Picking a header-search result now sets an in-memory Search mode that displays the lead with the bucket's render config (field map, scripts, detail columns) but never enters the queue and never bypasses filters, cap, cooldown, or the active-appointment check. A header Search pill shows the lead name, an "outside filters" hint when the row wouldn't normally match the bucket, and an exit button back to the queue.
  • Disposition / skip returns to the queue. Recording a result against the searched lead writes the activity, then drops you back into the bucket's auto-cycle where you left off. Search mode clears automatically.
  • Pins are session-only. localStorage pin persistence is removed entirely. The mid-call anti-yank carve-out still protects the active queue lead from filter changes, and the next-meeting badge still pins the linked lead past the active-event filter — but both are session-only and clear on reload. Legacy persisted pinnedRowIds records from older clients are ignored on read.

Under the hood

  • New searchedLead = { bucketId, rowId, outsideFilters } state decouples render config from queue membership. currentRow reads searchRow || queueRow; pinnedRowIdRef stays bound to the queue row so the search path can't re-enter the filter carve-out.
  • loadLeadIntoDialer (which pinned) is now called only by the next-meeting badge. Every other "jump to this lead" surface flows through Search mode.
  • Regression coverage: dialBucketRuntime.test.js asserts that a row matching has YTQ but also carrying not_has Lost is excluded when unpinned; DialSearchWiring.test.jsx was rewritten to assert search picks set searchedLead and never pin or move the queue cursor; dialCursorStorage tests cover the dropped pin helpers and the legacy-payload guard.

On this page