Matthew Meszaros
|
55c5bdcf61
|
feat: let inbox tagging confirm an out-of-office return date by asking whether the phrase the parser read it from says when the sender is back, send the hold to the workspace fallback on a clear no below 0.40, store the date asked about in a new inbox_tag_results.return_date column (migration 000223), and show the date and answer on the tagging review page
|
2026-09-27 20:28:44 -07:00 |
|
Matthew Meszaros
|
1dbbee61c6
|
Merge pull request #716 from warmbly/feat/localized-optout-and-unsubscribe-page
feat: read opt-out replies and serve the unsubscribe page in every tagging language
|
2026-09-27 12:10:48 +00:00 |
|
Matthew Meszaros
|
5e745618b1
|
feat: read opt-out replies in every tagging language with a phrase list per language, quote markers for the 16 tagging languages that had none, and a matcher that folds accents and handles scripts without spaces, and serve the recipient-facing unsubscribe pages (backend and tracking-domain proxy) in the browser's language across all tagging languages with right-to-left layout and an English fallback
|
2026-09-27 04:54:57 -07:00 |
|
Matthew Meszaros
|
98f8841347
|
Merge pull request #714 from Skylinerffm97/fix/german-return-dates
fix(replyclassify): read German return dates after a weekday, in calendar weeks and at the end of a range
|
2026-09-27 11:53:31 +00:00 |
|
Matthew Meszaros
|
8594eda3a2
|
Merge pull request #713 from Skylinerffm97/fix/not-interested-is-negative
fix(replyclassify): read "not interested" as a negative reply
|
2026-09-27 11:38:24 +00:00 |
|
Matthew Meszaros
|
25ec1aceca
|
feat: keep a German "ab" date and a sentence that opens on "Bis" as two statements in ParseReturnDate by marking the capitalized sentence start before lower-casing
|
2026-09-27 04:37:26 -07:00 |
|
 Skylinerffm97andClaude Opus 5.5
|
618099d689
|
fix: read German return dates after a weekday with a comma ("ab Montag, 12.10.", "ab Montag, den 12.10.") for every workday instead of only "ab Montag den", read calendar weeks ("ab KW 42" as that week's Monday, "bis KW 41" and "bis KW 40/41" as the Monday after the last week, a week under way as back now), and take the end of an "ab ... bis ..." range instead of its first day unless a sentence or a return word comes between, so these out-of-office replies hold a lead until the day they name instead of the flat fallback or the start of the absence
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
2026-09-27 10:59:23 +00:00 |
|
 Skylinerffm97andClaude Opus 5.5
|
89b8e9790a
|
fix: count a German GDPR objection only when the writer objects in the first person and the same sentence goes on to what is objected to behind an article (der Verarbeitung, dem Erhalt weiterer E-Mails, jeglicher Kontaktaufnahme), so a formal disagreement like "ich widerspreche hiermit Ihrer Preisberechnung" and a signature's privacy notice ("Sie können der Verarbeitung jederzeit widersprechen") stay normal replies, while objections worded with "ausdrücklich", "gem. Art. 21 DSGVO" or a compound like "Datenverarbeitung" still opt out
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
2026-09-27 10:59:03 +00:00 |
|
 Skylinerffm97andClaude Opus 5.5
|
1ba3d5df9d
|
fix: read "not interested" and the other declined-interest replies (aren't, not really, not that, no longer, would not be, uninterested) as negative before the interest phrases, whose "interested" took them for positive replies and sent people who said no down a campaign's positive-reply branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
2026-09-27 10:44:38 +00:00 |
|
 Skylinerffm97andClaude Opus 5.5
|
fad04c5efc
|
feat: read German opt-out replies (bitte austragen, keine weiteren E-Mails, löschen Sie meine Daten, a GDPR objection and more) in the reply opt-out check and the lexicon layer, bind meeting-sense words like abmelden and austragen to bitte or the writer, always cut the German quote markers before reading opt-out so the sender's own German opt-out line in an Outlook, GMX/web.de or T-Online quote never opts anyone out, add GMX's date-first header block and the Original-Nachricht divider to the German rules, fold umlauts and line breaks before matching, and mention German replies in the unsubscribe guide
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
2026-09-27 10:00:47 +00:00 |
|
Matthew Meszaros
|
dd98c4b1fe
|
feat: record the campaign an inbox tag verdict was made with (migration 000216) so --recheck-cold-inbound asks only about verdicts made without one and never re-bills, keep the recheck from removing labels when no verdict was stored, let the campaign lookup use the tasks Message-ID index, require the Gmail address tail on the Russian and Japanese quote markers so a proposed meeting time is not cut, keep workspace question labels off notifications, and key and lock tagging question edits by id
|
2026-09-24 21:21:11 -07:00 |
|
Matthew Meszaros
|
6a13fd5238
|
feat: report the Message-ID Gmail stamps on a send and resolve a reply's campaign through the Gmail thread and In-Reply-To so campaign replies stop tagging as sales pitches (with a warmblyctl --recheck-cold-inbound backfill that clears the stale labels and a tasks thread index), let a workspace add its own yes/no and pick-one tagging questions with plain-word labels and hold/stop/task actions, and add tagging languages (44 named to the classifier; for 27, only once chosen, tagging also cuts their quoted history and reads their away and non-delivery subjects), documented in the inbox tagging guide and the OpenAPI schema
|
2026-09-24 21:08:35 -07:00 |
|
Matthew Meszaros
|
256010725b
|
feat: count only email steps in every sent total (contact drawer, Leads view and statuses, campaign progress, guardrails, org conduct, verification evidence, segments, admin, advisor), keep line breaks in synced body text and strip quoted history in any shape, classify delivery failures before out-of-office and tag them as bounces, record statusless failure notices from X-Failed-Recipients as permanent bounces, limit reply and inbox-tag opt-outs to people answering our outreach (never bounces, auto-replies or list mail), and recheck earlier reply opt-outs, lifting with an audit entry only those the message that wrote them no longer supports
|
2026-09-24 09:44:17 -07:00 |
|
Matthew Meszaros
|
addb956ad6
|
feat: shared TypeSafe client under internal/pkg/typesafe with inbox tagging phases 2 and 3 (hold, stop, task, suppress behind workspace switches, reversible ones on by default), labels seeded at workspace creation and by the follow-up sweep, premade inbox views (hot leads, needs a reply, follow up, declined, automated), typed reply classification and a reply_intent branch condition, an inbox agent draft gate, Advisor copy judgment with a cached editor re-check, warmup content lint, bounce cause classification that keeps a blocked address sendable, and per-form submission triage
|
2026-09-19 23:33:37 -07:00 |
|
Matthew Meszaros
|
ffd27bc46d
|
fix: stop every out-of-office notice and bounce opening a high-priority CRM follow-up by classifying machine replies from their headers and gating the task on a per-intent setting, and give the Tasks page multi-select with select-all-matching, bulk status, priority and delete over new PATCH and DELETE /crm/tasks endpoints (issue #471)
|
2026-09-14 12:20:47 -07:00 |
|
Matthew Meszaros
|
13e9ce8e10
|
feat: hold a lead whose mailbox answers out of office until they are back, resuming at the return date it names, plus a manual per-contact pause in one campaign that unsubscribing and the suppression list were the only stand-ins for
|
2026-09-14 09:26:06 -07:00 |
|
Matthew Meszaros
|
64f2d1637b
|
feat: address the review on the unsubscribe PR: register the suppression family in warmblyctl, require the confirm field on the browser unsubscribe POST and cap its body, render a chosen A/B variant through the template engine so its merge fields and unsubscribe link resolve, fold curly apostrophes before opt-out phrase matching, write pasted suppression lists in one transaction, clamp copy by runes instead of bytes, add the constraints NOT VALID plus a lower(email) index in migration 000123, scope the unsubscribe link type-ahead to email bodies, and document DELETE /suppressions/:id
|
2026-09-03 02:20:47 -07:00 |
|
Matthew Meszaros
|
5eb92c601c
|
feat: give every campaign email a working opt-out: a reply-to-opt-out line by default or an unsubscribe link (workspace setting under Settings > Sending with a per-campaign override and a {{.UnsubscribeLink}} variable), signed per-recipient unsubscribe links served on the API origin so the List-Unsubscribe header no longer points at a dead warmbly.com page, a confirm page on GET with RFC 8058 one-click on POST and a resubscribe button, reply opt-out detection through the whole-word compliance lexicon with quoted history stripped, a first-class suppression list (Contacts tab, GET/POST/DELETE /suppressions with address and domain entries, audited removal, contact drawer action), the contact Subscribed flag enforced in campaign routing, migration 000122 with a shared recipient_suppressed() predicate, and docs for all of it
|
2026-09-03 01:52:40 -07:00 |
|
Matthew Meszaros
|
e64b0b161d
|
feat: sweep stale OPENAI_API_KEY/AI_LOCAL_MODEL mentions out of comments, the provider-not-configured and warmup-admin error strings, env.example, and the deployment guide now that AI_* is the only config surface
|
2026-07-16 06:39:07 +02:00 |
|
Matthew Meszaros
|
a067bf5922
|
feat: AI action nodes in automations - ai_classify/ai_extract/ai_generate run one generation.Provider completion per node over the event data and merge the result back as a variable (ai_class, output_keys[], ai_text) so downstream conditions branch on it, charging 1 credit per node with a run_id+node_id idempotency key, refund on provider failure, out-of-credits fails only that node while the run continues, and a per-automation ai_credit_failures counter (migration 000064) auto-pauses a flow after 20 consecutive credit misses; classify/extract run deterministic (temperature 0), dry-run executes AI nodes for real and is charged but never touches the auto-pause lifecycle, provider + credit ledger wired into both backend and consumer integration services, plus the reply-classifier Layer 3 ported off its bespoke OpenAI client onto the platform provider via an injected ModelClassifyFunc (platform-paid, deterministic), a CompletionRequest.Temperature primitive threaded through the OpenAI and Anthropic providers, the flow builder palette/config panels/validation for the three AI steps, and a new AI-steps-in-automations guide
|
2026-07-14 05:30:55 +02:00 |
|
Matthew Meszaros
|
3117284095
|
feat: add layered reply classifier
|
2026-06-07 11:46:31 +02:00 |
|