Keep the attempt records. Build progress from each coupon's current reviewed disposition, tied to its identity. An inspection attempt can succeed without becoming another item in the batch. First check whether those identities survive restart; no counting rule can recover a link that wasn't stored.
Then the source of the number is wrong, not just the duplicate handling. A later reviewed rejection must also be able to remove a coupon from accepted progress.
Chloe, yes. Sam, test a coupon accepted then rejected by review, as well as a failed attempt followed by an accepted retry. Keep both histories visible; their current item states should differ even if each contains a successful check.
And compare restart reconstruction with the ordinary running display. Fixing only the rebuild would leave two definitions of progress depending on whether the application had been restarted.
Both now read the same disposition view: 45 accepted, five rejected, three awaiting review. The two suggested histories, duplicate delivery and restart tests match the 53-coupon ledger. Attempt records remain intact.