warmbox/docs/sprints/sprint-1.4.md

39 lines
1.4 KiB
Markdown

# Sprint 1.4 — Reply Rate Engine
Probabilistic reply sampling so warmup mimics real mailbox engagement (~30% default, max 45%).
## What shipped
- **`engaged_no_reply`** status on `WarmupStatus` enum
- **`reply-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` / `spamRescued` increment on rescue
- **`WarmupLog.placement`** — `inbox` or `spam`
- **`POST /api/jobs/rescuer/run`** — manual rescuer trigger
## Algorithm
Per [`docs/07-reply-rate-engine.md`](../07-reply-rate-engine.md):
1. If daily reply quota met → skip
2. If actual rate ≥ target → skip
3. Else probabilistic bias: `probability = needed / remaining`
## Manual QA
```bash
# 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.ts`
- `src/jobs/rescuer.job.ts`