1.4 KiB
1.4 KiB
Sprint 1.4 — Reply Rate Engine
Probabilistic reply sampling so warmup mimics real mailbox engagement (~30% default, max 45%).
What shipped
engaged_no_replystatus onWarmupStatusenumreply-rate.service.ts—shouldReply(),getTodayReplyStats(), simulation helper- Campaign rescuer samples replies; non-replied messages still get read/flagged/spam-rescue
- Hard daily cap — skips reply when
actualReplies >= plannedReplies - Spam counters —
spamDetected/spamRescuedincrement on rescue WarmupLog.placement—inboxorspamPOST /api/jobs/rescuer/run— manual rescuer trigger
Algorithm
Per docs/07-reply-rate-engine.md:
- If daily reply quota met → skip
- If actual rate ≥ target → skip
- Else probabilistic bias:
probability = needed / remaining
Manual QA
# Start campaign, dispatch sends, then run rescuer repeatedly
curl -X POST http://localhost:3000/api/jobs/dispatcher/run -H "x-api-key: $API_KEY"
curl -X POST http://localhost:3000/api/jobs/rescuer/run -H "x-api-key: $API_KEY"
# Check mix of complete vs replied logs
curl "http://localhost:3000/api/logs?campaignId=<id>" -H "x-api-key: $API_KEY"
Expect some logs with engaged_no_reply → complete and reply rate trending toward replyRatePercent.
Key files
src/services/reply-rate.service.tssrc/jobs/rescuer.job.ts