2026-10-01 22:41:11 -07:00
..
2026-05-23 17:10:40 +00:00
2026-07-22 17:05:08 +02:00
2026-09-03 20:18:43 -07:00
2026-09-24 20:12:29 -07:00
2026-09-29 10:11:17 -07:00
2026-09-29 10:11:17 -07:00
2026-09-03 20:18:43 -07:00
2026-09-14 09:26:06 -07:00
feat: stop one un-sendable lead parking a whole campaign and stop the contact drawer's next-action time walking forward on every refresh (issue #437): route up to config.CampaignPlacementCandidates due leads per pass instead of one, classify a placement refusal that belongs to a single lead (ESP-strict finding no mailbox for that recipient's provider, a bound lead inside its own mailbox's minimum gap or waiting for it to reopen, a recipient's send-time-optimized hours) as the new ErrLeadDeferred so the pass moves to the lead behind them and only defers the campaign when every candidate is refused, log the ESP-strict deferral once a day rather than once per refused lead per tick, and make PreviewContactSend a pure read that answers unchanged state identically on every call by running placement with the even-distribution, jitter, conflict-resolution, distribution-curve and sub-minute layers off, taking a behaviour profile's gap at its floor instead of drawing it, picking the mailbox deterministically instead of re-rolling rotation, reporting the next sending day's first open minute instead of a jittered twenty-four-hours-from-now, and reporting a due step's time as the campaign chain's own stored wakeup
2026-09-12 02:58:48 -07:00
feat: stop one un-sendable lead parking a whole campaign and stop the contact drawer's next-action time walking forward on every refresh (issue #437): route up to config.CampaignPlacementCandidates due leads per pass instead of one, classify a placement refusal that belongs to a single lead (ESP-strict finding no mailbox for that recipient's provider, a bound lead inside its own mailbox's minimum gap or waiting for it to reopen, a recipient's send-time-optimized hours) as the new ErrLeadDeferred so the pass moves to the lead behind them and only defers the campaign when every candidate is refused, log the ESP-strict deferral once a day rather than once per refused lead per tick, and make PreviewContactSend a pure read that answers unchanged state identically on every call by running placement with the even-distribution, jitter, conflict-resolution, distribution-curve and sub-minute layers off, taking a behaviour profile's gap at its floor instead of drawing it, picking the mailbox deterministically instead of re-rolling rotation, reporting the next sending day's first open minute instead of a jittered twenty-four-hours-from-now, and reporting a due step's time as the campaign chain's own stored wakeup
2026-09-12 02:58:48 -07:00
feat: scope campaign analytics to an optional from/to send cohort (summary, step performance, engagement and the daily chart read the same UTC days, total_contacts and emails_pending stay campaign-wide, date_range reports the resolved period), count the whole last day in campaign compare and daily stats, add a 7d/30d/90d/all-time/custom period picker to the campaign overview and its share image, take the period in get_campaign_stats, the warmbly and warmblyctl CLIs and the Make and Zapier modules, close a date picker's calendar alone on Escape, and document it in the analytics guide, API reference, MCP table and OpenAPI
2026-09-26 22:42:19 -07:00
2026-09-24 01:43:58 -07:00
feat: stop a campaign email going out twice when the progress write after dispatch is lost: a step is now RESERVED before its SEND_EMAIL reaches the bus (migration 000093 adds campaign_contact_progress.dispatched_at + dispatch_task_id, and ReserveSend takes the claim and the day's counters in one transaction) and routing treats a step as attempted on sent_at OR dispatched_at, so a crash or a failed stamp in the dispatch window can no longer read as "never sent" and email the same person again; the ON CONFLICT claim is exactly-once so two ticks racing the same pair cannot both send (the loser ends skipped_duplicate), the stamp is retried and escalated to the campaign feed instead of warned and swallowed, HandleEmailSent repairs a lost stamp from the worker's own confirmation, ReleaseSend gives a reservation back only when the command provably never left (a publish failure is ambiguous via ErrSendDispatchUnknown and keeps it), and StartStuckSendReclaimer walks back a reservation nobody answered after 30 minutes so a worker that died mid-send cannot park a lead in flight forever; live-tested in TestLiveLostProgressWriteDoesNotResend, TestLiveDispatchedSendIsNeverOfferedTwice, TestLiveConcurrentTicksSendOnce, TestLiveStuckDispatchIsReclaimed, TestLiveReclaimBelievesADeliveredSend and TestLiveInFlightSendIsNotOfferedAgain
2026-08-24 09:15:06 -07:00
2026-09-19 04:05:34 -07:00
2026-09-12 03:47:36 -07:00
2026-09-24 01:56:23 -07:00
feat: send each mailbox's reply-to as a Reply-To header on campaign, unibox, test and placement mail (never warmup), record it on every campaign send attempt (tasks.reply_to, migration 000236) and credit a reply landing in that shared reply inbox to the campaign and its sending mailbox across reply attribution, the sync priority lane and copied-contact replies, show the sending mailbox on thread messages, recent activity and the reply webhook, start unibox and inbox-agent replies from the mailbox that emailed the contact, flag an untracked reply-to in mailbox settings, let the sandbox simulator answer Reply-To, and document the shared reply inbox (#756)
2026-09-30 05:33:34 -07:00
2026-10-01 22:41:11 -07:00
2026-10-01 22:41:11 -07:00
2026-08-26 06:03:20 -07:00
2026-09-10 09:28:00 -07:00
2026-06-03 05:05:53 +02:00
2026-09-14 03:36:04 -07:00
2026-09-25 20:48:15 -07:00
feat: send each mailbox's reply-to as a Reply-To header on campaign, unibox, test and placement mail (never warmup), record it on every campaign send attempt (tasks.reply_to, migration 000236) and credit a reply landing in that shared reply inbox to the campaign and its sending mailbox across reply attribution, the sync priority lane and copied-contact replies, show the sending mailbox on thread messages, recent activity and the reply webhook, start unibox and inbox-agent replies from the mailbox that emailed the contact, flag an untracked reply-to in mailbox settings, let the sandbox simulator answer Reply-To, and document the shared reply inbox (#756)
2026-09-30 05:33:34 -07:00
feat: send each mailbox's reply-to as a Reply-To header on campaign, unibox, test and placement mail (never warmup), record it on every campaign send attempt (tasks.reply_to, migration 000236) and credit a reply landing in that shared reply inbox to the campaign and its sending mailbox across reply attribution, the sync priority lane and copied-contact replies, show the sending mailbox on thread messages, recent activity and the reply webhook, start unibox and inbox-agent replies from the mailbox that emailed the contact, flag an untracked reply-to in mailbox settings, let the sandbox simulator answer Reply-To, and document the shared reply inbox (#756)
2026-09-30 05:33:34 -07:00
2026-09-28 09:16:42 -07:00
feat: forms v2, a full redesign of the hosted form and its builder: eight one-click themes, card/wide/split layouts with a brand cover panel, classic paged and Typeform-style focus modes split on a new page_break block, logo/cover/background uploads with size, fit and veil controls, an optional header bar that can span the page or sit with the form, a real HSV colour picker and font preview, per-contact personalized links that prefill and attribute without email verification, a render-token gate so the form JSON cannot be scraped without loading the page, funnel analytics with per-page drop-off and identified visitors, a leads-style forms list and responses table, and an organization custom forms domain verified by CNAME with hourly re-checks
2026-09-01 09:27:28 -07:00
feat: forms v2, a full redesign of the hosted form and its builder: eight one-click themes, card/wide/split layouts with a brand cover panel, classic paged and Typeform-style focus modes split on a new page_break block, logo/cover/background uploads with size, fit and veil controls, an optional header bar that can span the page or sit with the form, a real HSV colour picker and font preview, per-contact personalized links that prefill and attribute without email verification, a render-token gate so the form JSON cannot be scraped without loading the page, funnel analytics with per-page drop-off and identified visitors, a leads-style forms list and responses table, and an organization custom forms domain verified by CNAME with hourly re-checks
2026-09-01 09:27:28 -07:00
2026-09-14 08:11:52 -07:00
2026-09-03 04:00:33 -07:00
2026-09-15 00:42:45 -07:00
2026-09-09 06:34:43 -07:00
2026-09-14 08:11:52 -07:00
2026-09-15 00:42:45 -07:00
feat: make warmup spam placement only slow a mailbox down (watch at 10%, half-volume throttle at 20%, never quarantine, block or appeal) and judge it only at Google, Microsoft and Yahoo over verified deliveries, keep small-host spam out of the health bands, warmup and cold ramps and the advisor while still showing it beside the headline rate on the drawer and Deliverability, draw small-host partners whose own filter junks warmup mail less often, send each quarantine or block webhook once plus health_changed, release placement-only quarantines in 000220, and update the warmup, deliverability, advisor and API docs
2026-09-26 22:26:58 -07:00
2026-09-17 21:15:28 -07:00
2026-09-26 06:30:22 -07:00
2026-09-29 09:34:32 -07:00
2026-09-29 09:34:32 -07:00
2026-09-12 03:13:38 -07:00
2026-09-15 00:42:45 -07:00
2026-09-25 20:48:15 -07:00
2026-06-08 15:04:53 +02:00
2026-09-04 06:16:16 -07:00
2026-09-12 03:37:31 -07:00
2026-09-04 03:11:53 -07:00
2026-09-23 21:22:17 -07:00
2026-09-15 00:42:45 -07:00
2026-08-24 09:02:29 -07:00
2026-09-17 10:26:25 +00:00
2026-09-16 03:42:58 -07:00
2026-09-23 21:29:24 -07:00
2026-09-23 21:38:59 -07:00
2026-09-23 21:48:54 -07:00
2026-07-22 12:11:19 +02:00
2026-09-25 21:47:36 -07:00
2026-09-26 06:30:22 -07:00
2026-08-27 03:02:56 -07:00
2026-09-28 09:16:42 -07:00
2026-08-29 07:09:04 -07:00