Skip to content

ARIA: split email 'active threads' per sender + filter promo senders#356

Open
holoduke wants to merge 1 commit into
mainfrom
aria/active-threads-email-split
Open

ARIA: split email 'active threads' per sender + filter promo senders#356
holoduke wants to merge 1 commit into
mainfrom
aria/active-threads-email-split

Conversation

@holoduke

@holoduke holoduke commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Problem

The brain-prompt Active threads section was bundling 15+ unrelated email senders (LinkedIn job alerts, AliExpress promo, PayPal, Guardian, Schoolkassa, GSC, 123accu…) into a single line, because every gmail observation shares the same `senderJid` (`gmail:`). `updateConversationThreads` then collapsed them into one `dm:gmail:` thread and joined the participants with commas. Result: pure noise in the prompt window, and real DMs (e.g. Maaike's "Julian heeft geen map") visually drowned in promo subjects.

Fix (both prongs requested)

  1. Split per sender. `updateConversationThreads` (memory/working-memory.ts) now keys email observations as `email::` instead of by `senderJid`. Each correspondent gets their own thread.
  2. Drop pure-promo senders. New `isPromoOrAutomatedSender` helper in observer.ts (no-reply/notifications/alerts/marketing local-parts + known promo domains: aliexpress, linkedin, quora, autoscout24, marktplaats, paypal, schoolkassa, 123accu, GSC). Promo senders are filtered out at thread-creation time and again at render time in brain-prompt.ts as defense-in-depth.
  3. Legacy cleanup. Existing `dm:gmail:*` bundled threads are evicted from working memory on next observe tick — they would otherwise linger up to 14 days. New threads will be re-built per sender from incoming observations.
  4. Render hardening. `brain-prompt.ts` now caps the participant list at 3 names with `+N` overflow, so even if a sender legitimately accumulates many participants the line stays bounded.

Risk

Low — purely affects how threads are keyed and rendered for prompt assembly. No change to observation recording, message sending, or memory writes. Promotional emails still flow through observations and downstream digests; they're just no longer surfaced as "active threads".

Verification

  • `npx tsc --noEmit` from /app: clean.
  • Behaviour confirmed by reading: thread key is now per-sender for gmail; promo filter applied both at write and read.

🤖 Generated with Claude Code

…senders

All gmail observations shared senderJid=gmail:<accountId>, so the thread keying
in updateConversationThreads collapsed every email into one bucket. The "Active
threads" section in the brain prompt then rendered a single line with 15+
unrelated promo senders comma-joined and one truncated subject — pure noise.

Changes:
- observer.ts: add extractEmailAddress() + isPromoOrAutomatedSender() helpers
  (no-reply/notifications/alerts/marketing local-parts + known promo domains).
- memory/working-memory.ts: for gmail observations, key thread by per-sender
  address (email:<accountId>:<addr>) and skip promo/automated senders entirely.
  One-time evict legacy dm:gmail:* bundled threads from working memory.
- brain-prompt.ts: defense-in-depth — drop email threads whose only
  participants look promotional; cap rendered participant list at 3+N overflow.

Real DMs like Maaike's "Julian heeft geen map" now get visually equal weight
instead of being buried beside a wall of promo senders.

Intent-summary: Active-threads brain-prompt block collapsed all gmail senders into one bundle so promo noise drowned real conversations.
Intent-tokens: threads, email, promo, noise, prompt, bundling, signal

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant