feat(#298): Sender→Label Memory — Auto-Decay alter Einträge #306

Merged
admin-mrrm merged 1 commit from feat/298-sender-memory-decay into main 2026-05-16 13:22:40 +02:00
Owner

Summary

  • SenderMemoryService.decayStaleEntries({ cutoffDays, factor }): halbiert confirmCount/removeCount (Integer-Division im SQL) für Einträge mit lastSeenAt < now() - cutoffDays, dann hard-prune aller Einträge die danach auf (0, 0) stehen.
  • SenderMemoryDecayCron: wöchentlich (default Sonntag 03:00), analog zu den bestehenden Crons. ScheduleModule.forRoot() ins MailModule gehoben.
  • ENV-Vars: SENDER_MEMORY_DECAY_CRON, _DISABLED, _AFTER_DAYS (default 60), _FACTOR (default 2, ≥2).

Designentscheidung — Soft-Decay statt Hard-Delete

Der Match-Threshold im Categorizer ist confirmCount ≥ 2 AND confirm > remove. Halbieren reicht, damit ein lange unangefasster Eintrag seinen Einfluss verliert; der User sieht ihn aber noch in der UI, bis er auf 0 fällt. Erst dann wird er entfernt. Adaptionsgeschwindigkeit + Sichtbarkeit ohne unnötigen Speicher-Wachstum.

Test plan

  • Unit-Tests für decayStaleEntries (Halbierung, Prune, no-op, rowCount-undefined, Input-Validation)
  • pnpm vitest run — 245/245 grün
  • pnpm typecheck clean
  • pnpm lint clean
  • Smoke-Test auf dev-neu nach Deploy: SENDER_MEMORY_DECAY_FACTOR=2, manueller runOnce()-Trigger via Logger-Check

Closes #298

## Summary - `SenderMemoryService.decayStaleEntries({ cutoffDays, factor })`: halbiert `confirmCount`/`removeCount` (Integer-Division im SQL) für Einträge mit `lastSeenAt < now() - cutoffDays`, dann hard-prune aller Einträge die danach auf `(0, 0)` stehen. - `SenderMemoryDecayCron`: wöchentlich (default Sonntag 03:00), analog zu den bestehenden Crons. `ScheduleModule.forRoot()` ins MailModule gehoben. - ENV-Vars: `SENDER_MEMORY_DECAY_CRON`, `_DISABLED`, `_AFTER_DAYS` (default 60), `_FACTOR` (default 2, ≥2). ## Designentscheidung — Soft-Decay statt Hard-Delete Der Match-Threshold im Categorizer ist `confirmCount ≥ 2 AND confirm > remove`. Halbieren reicht, damit ein lange unangefasster Eintrag seinen Einfluss verliert; der User sieht ihn aber noch in der UI, bis er auf 0 fällt. Erst dann wird er entfernt. Adaptionsgeschwindigkeit + Sichtbarkeit ohne unnötigen Speicher-Wachstum. ## Test plan - [x] Unit-Tests für `decayStaleEntries` (Halbierung, Prune, no-op, rowCount-undefined, Input-Validation) - [x] `pnpm vitest run` — 245/245 grün - [x] `pnpm typecheck` clean - [x] `pnpm lint` clean - [ ] Smoke-Test auf dev-neu nach Deploy: `SENDER_MEMORY_DECAY_FACTOR=2`, manueller `runOnce()`-Trigger via Logger-Check Closes #298
feat(#298): Sender→Label Memory — Auto-Decay alter Einträge
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
8f6d4ac275
- decayStaleEntries() im SenderMemoryService: halbiert confirm/removeCount
  von Einträgen mit lastSeenAt < now() - cutoffDays (Integer-Division im SQL),
  prunt anschließend Einträge die auf (0,0) gefallen sind.
- SenderMemoryDecayCron: wöchentlich (default Sonntag 03:00), analog zu
  TrackingSyncCron/MailScannerCron. ScheduleModule jetzt im MailModule.
- Neue ENV-Vars: SENDER_MEMORY_DECAY_CRON, _DISABLED, _AFTER_DAYS (default 60),
  _FACTOR (default 2, ≥2 erzwungen).

Soft-Decay statt Hard-Delete: der Match-Threshold (confirmCount ≥ 2 und
confirm > remove) verliert nach 1–2 Decay-Zyklen seine Wirkung, der Eintrag
bleibt aber für die UI sichtbar bis er auf 0 fällt und entfernt wird.

Closes #298
admin-mrrm deleted branch feat/298-sender-memory-decay 2026-05-16 13:22:40 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp!306
No description provided.