Skip to content

Label Alfred's own outbound mail instead of dropping it silently (#285)#392

Merged
99Yash merged 2 commits into
mainfrom
feat/285-label-self-mail
Jul 3, 2026
Merged

Label Alfred's own outbound mail instead of dropping it silently (#285)#392
99Yash merged 2 commits into
mainfrom
feat/285-label-self-mail

Conversation

@99Yash

@99Yash 99Yash commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Closes #285.

Problem

Alfred's own outbound — the daily briefing and HIL-approval requests — ships through Resend and re-enters the connected Gmail as ordinary inbound mail. Since #211/#266 it's dropped at ingest (isSelfAuthoredoutcome: "ignored") so it never becomes a document, never gets triaged into the demanding lanes, and never seeds a sender prior — that closed the self-amplification loop. But it also left this mail unorganised and invisible: it just vanishes.

Fix

Apply a dedicated Alfred Gmail label on the same drop path, so the user gets a coherent, findable stream — without reopening the loop. The message is still dropped from documents / triage / briefing input; the only new effect is a label.

Changes

  • labels.ts
    • ensureAlfredSelfLabel — ensures the Alfred label exists, cached on integrationCredentials.metadata.alfredSelfLabel (jsonb_set so it never clobbers alfredLabels/watch state), race-safe create (409 → re-list), force-rebuild for a deleted-out-of-band label. Mirrors ensureAlfredLabels.
    • labelSelfAuthoredMail — idempotent (skips the modify round-trip when the label is already on the message, which matters because the 5-min realtime poll re-lists self-mail every window — it never becomes a documents row so the known-id pre-filter can't drop it), self-healing (a stale-label 404 triggers a force-rebuild + one retry), and takes injectable deps so the skip/retry logic is unit-tested without a live mailbox.
    • Deliberately not part of AlfredLabelMap.allIds — that set is the triage category labels the relabel path strips/swaps between, and self-mail is never triaged, so the two must not intersect.
  • ingestor.tspersistMessage tags the message in the isSelfAuthored branch before returning ignored. Best-effort: a labelling failure is logged and never blocks the drop (the drop is the real guardrail). Threads credentialId + accessToken through (all three ingest paths already have them).
  • backfill-label-self-mail-committed.ts — one-off catch-up for self-mail that landed before this shipped. Those messages were dropped from the DB (Briefing: Alfred re-ingests & re-triages its own briefing emails (self-feedback loop) #211/Residual self-ingestion: Alfred's own briefing + HIL-approval mail tagged urgent on personal account (#211 follow-up) #266), so it reads Gmail directly: from:(<self addrs>) -label:"Alfred", then batchModify in ≤1000-id chunks. Matches the current send address ∪ historical aliases (--aliases, default yash@croisillies.xyz) — the retire-backfill precedent. Dry by default; --commit writes. Bundled as a tsdown entry.

Acceptance criteria

  • Self-sent briefing + HIL-approval mail carries a dedicated Alfred label.
  • Labelling does not reintroduce them into triage's demanding categories or briefing input (the drop is unchanged; only a label is added).
  • Applies to both briefing + HIL-approval — they share one send identity (RESEND_FROM_EMAIL), so isSelfAuthored covers both.
  • Covers existing self-sent mail via a backfill.

Verification

  • pnpm check-types ✅, pnpm lint ✅ (2 pre-existing unrelated web warnings), server bundle builds with the new entry ✅

  • 5 new tests + existing self-authored-drop + reconcile-thread-label regression suites — 47 pass

  • Prod DRY-RUN (read-only, via a self-contained railway ssh count): 159 unlabelled self-mail across 2 accounts

    Account total self-mail hey@alfred.beauty yash@croisillies.xyz (alias)
    yashgouravkar@gmail.com 126 72 54
    yash.k@oliv.ai 33 29 4

    58 of the 159 come from the historical alias — a current-address-only match would miss them, confirming the alias handling.

Rollout (post-merge)

Deploy, then run the backfill against prod:
node dist/scripts/backfill-label-self-mail-committed.js --emails=yashgouravkar@gmail.com,yash.k@oliv.ai --commit

🤖 Generated with Claude Code

99Yash and others added 2 commits July 3, 2026 18:07
Alfred's briefing + HIL-approval mail ships through Resend and re-enters
the connected Gmail as inbound mail. Since #211/#266 it is dropped at
ingest (never a document, never triaged, never a sender prior) to break
the self-amplification loop — but that left it unorganised and invisible.

Apply a dedicated `Alfred` Gmail label on the same drop path so the user
can find that stream, without reopening the loop: the message is still
dropped from `documents`/triage/briefing input; only a label is added.

- labels.ts: `ensureAlfredSelfLabel` (cached on
  `metadata.alfredSelfLabel`, race-safe create, force-rebuild) +
  `labelSelfAuthoredMail` (idempotent skip when already labelled,
  self-healing force-retry on a stale-label 404, injectable deps for
  tests). Deliberately kept out of `AlfredLabelMap.allIds` — self-mail is
  never triaged, so it must not intersect the relabel/strip set.
- ingestor.ts: `persistMessage` tags the message in the `isSelfAuthored`
  branch before returning `ignored`. Best-effort — a label failure never
  blocks the drop.
- backfill-label-self-mail-committed.ts: one-off catch-up over existing
  self-mail (dropped from the DB, so it reads Gmail directly), matching
  the current send address ∪ historical aliases; dry by default. Bundled
  as a tsdown entry.
- Tests: 5 cases over the DI seam (apply / skip / retry / bubble).

Prod dry-run: 159 unlabelled self-mail across 2 accounts (58 from the
historical alias, which a current-address-only match would miss).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@99Yash 99Yash merged commit 531a231 into main Jul 3, 2026
3 checks passed
@99Yash 99Yash deleted the feat/285-label-self-mail branch July 3, 2026 14:54
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.

Label Alfred's own outbound mail (briefing + HIL-approval) with a dedicated Gmail label instead of dropping silently

1 participant