Traffic Desk: NAS remaining counts down for banners too — trust the bridge's served field
The count-up theory made every fresh banner read as fully delivered, so the sweeper deactivated brand-new campaigns minutes after launch and stamped them complete (caught by Marty 2026-09-01 on ad 2713). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+15
-18
@@ -79,32 +79,29 @@ function record(memberId, entry) {
|
|||||||
writeLedger(trimmed);
|
writeLedger(trimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ad network counts the SAME `remaining` column in opposite directions for
|
// `remaining` counts DOWN for BOTH placement types — measured across 1,604
|
||||||
// the two placement types, which is not documented anywhere and had to be
|
// network ads, and it is exactly what the bridge's stats action already
|
||||||
// measured:
|
// computes (`served = assigned - remaining`, falling back to hits when
|
||||||
|
// assigned was never set). Trust the bridge's `served` field first.
|
||||||
//
|
//
|
||||||
// TEXT ads — `remaining` counts DOWN from the purchase to zero as it serves.
|
// The earlier "banners count UP" theory (and its ad-2707 evidence) was the
|
||||||
// (ad 2689: 1,111 left mid-flight, 0 once complete.)
|
// network's own post-insert counter top-ups being misread; acting on it made
|
||||||
// BANNER ads — `remaining` counts UP as impressions are delivered, straight
|
// every fresh banner look fully delivered the moment it launched, so the
|
||||||
// past the amount purchased. (ad 2707: 3,521 one day, 6,129 the
|
// sweeper deactivated brand-new campaigns and stamped them complete (bug
|
||||||
// next, on a 2,500 buy.)
|
// Marty caught 2026-09-01: a banner "delivered all its impressions"
|
||||||
//
|
// instantly). Do not resurrect the count-up branch.
|
||||||
// Reading both the same way made every banner report "0 served" while quietly
|
|
||||||
// delivering thousands — and made stop() treat delivered impressions as
|
|
||||||
// unserved and refund them.
|
|
||||||
//
|
//
|
||||||
// Returns what the member should see: served + left always reconciles to what
|
// Returns what the member should see: served + left always reconciles to what
|
||||||
// they bought, and neither can exceed it.
|
// they bought, and neither can exceed it.
|
||||||
function interpret(kind, bought, stat) {
|
function interpret(kind, bought, stat) {
|
||||||
const b = Math.max(0, Number(bought) || 0);
|
const b = Math.max(0, Number(bought) || 0);
|
||||||
const rem = Math.max(0, Number(stat && stat.remaining) || 0);
|
|
||||||
let served;
|
let served;
|
||||||
if (kind === 'text') {
|
if (stat && stat.served != null) {
|
||||||
// count-down: what is gone is what was bought minus what is left
|
served = Number(stat.served) || 0;
|
||||||
served = b - Math.min(rem, b);
|
|
||||||
} else {
|
} else {
|
||||||
// count-up: `remaining` IS the delivered count
|
// count-down: what is gone is what was bought minus what is left
|
||||||
served = Math.min(rem, b);
|
const rem = Math.max(0, Number(stat && stat.remaining) || 0);
|
||||||
|
served = b - Math.min(rem, b);
|
||||||
}
|
}
|
||||||
served = Math.max(0, Math.min(served, b));
|
served = Math.max(0, Math.min(served, b));
|
||||||
return { served: served, left: Math.max(0, b - served) };
|
return { served: served, left: Math.max(0, b - served) };
|
||||||
|
|||||||
Reference in New Issue
Block a user