Recorded run · Oct 20, 2026 · demo · fictional shop · PayPal test money · bugs are planted by us

PayPal refunded $48.00. Your books still say paid.

No error anywhere.

Doorbell is the tool that looks. It finds the PayPal your shop never heard or never saved, has an AI point at the changed line of your code behind it, rings them again, and tells you exactly what it still cannot prove.

Order #2 at Maple Mug, a fictional coffee shop: a “Gift set: three coffees and a mug”. The went through at PayPal. The shop's own books never heard about it, so the order still reads as paid. Nothing crashed and nothing logged an error, so nobody is looking.

Doorbell checked the shop's 3 : the payments PayPal took, one per order. 2 refunds ($96.00) are missing from your books: the shop answered 200 but did not save them.

The chapters below follow order #2 from PayPal to your books. The other , order #3, comes back in Ring again.

Each hop said OK. The books never changed.

PayPal made the refund . About 9 seconds later Doorbell heard it and checked its with PayPal's verify-webhook-signature call. Your shop got the and answered 200 OK in 321 milliseconds. A 200 is the polite answer, “got it, thanks”, and it tells PayPal to stop trying. So nobody tried again.

Then nothing: the books were never written. Doorbell's check at 10:42:58 looked each capture up at PayPal, read PayPal's , and found the gap.

The handler says OK before it saves the refund, so the save can be lost

The AI read what changed in the shop's handler and proposed two lines as the cause. Its category is work after acknowledgement. In plain words: a changed line answers PayPal before the booking work is finished, so that work can be lost after the 200.

The AI only proposes. Two checks run in plain code, with no model involved, and both pass.

Same messages, two builds. Only one saves them.

To test it, Doorbell replays the two real signed events against the shop's good build and its bad build. Both answer 200, 200, so from the outside they look the same. Only the books differ.

On the same events, the good build books the refund and the bad build does not. That is a tested result for the whole change, not a proof about any one line.

Fixing the code does not rewrite the books. Only another delivery of the same event can.

The shop's developer deploys the last good build. The shop now runs good.ts instead of ack-drop.ts, planted by us. A refund that arrives from now on is booked.

But the refund that already came is not booked: PayPal got its 200 and stopped trying.

Doorbell looked again at 10:43:12: the books still differ from PayPal on two captures.

Claude also proposed a patch for the cited lines. Plain code checked it first. Then it was run on real signed events and compared with the shop's last good build and with PayPal's own answer.

Proposed by Claude · not deployed in this demo

// Maple Mug webhook handler. PayPal posts here when a payment is captured or refunded.

import { bookingOf, rank } from "../lib/shop/events.ts";

import type { Handler } from "../lib/shop/types.ts";

 

lines of the file that the patch does not change

if ((await ctx.verify(event)) !== "SUCCESS") return { status: 401 };

 

const booking = bookingOf(event);

if (!booking) return { status: 200 };

 

// Never move an order backwards: a late "paid" must not undo a "refunded".

const current = await ctx.books.get(booking.captureId);

if (current && rank(current.state) > rank(booking.state)) return { status: 200 };

 

await ctx.books.set(booking.captureId, { state: booking.state, amount: booking.amount, eid: event.id, at: ctx.now() });

// Acknowledge first, book later.

queue.push(event);

return { status: 200 };

};

Highlighted: the lines the AI cited as the cause.

Behaves like the shop's last good build and PayPal's answer on these 15 inputs.The 15 inputs are 5 deliveries from 3 orders, run three ways: in arrival order, reversed, and with one amount changed.

What the code checked

  • The edits name changed lines of the diff, and replace or delete only lines the cause cited.
  • The patched file parses.
  • It uses only the imports and names a handler may use.
  • Lines of the bad deploy that the cause did not cite are unchanged, byte for byte.
  • The edits stay inside the bad deploy's changed hunks.

What the replay compared

  • The events in the order they arrived: same answers and same books as the good build. (5 deliveries)
  • The same events, last one first: same answers and same books as the good build. (5 deliveries)
  • One amount in each body changed: 401 and nothing booked, like the good build. (5 deliveries)
  • The books equal PayPal's own answer for the order (GET capture). (6 comparisons)

The same patch with its signature check removed (written by us) fails the tampered control and passes the other three.

Compared with the shop's last good build, the patch still has: a comment that may no longer match the code; “queue”, a value nothing reads. The checks do not look at comments or leftover code.

The demo does not run this patch. It runs good.ts, the shop's last good build, which the patch matches on these 15 inputs.

The comparison ran at 10:43:12 UTC, on this run's own signed events. The edits are a stored recording from claude-sonnet-5-5; this page makes no model call.

Ask PayPal to send it again.

Doorbell can ask PayPal's call to send the same event again, but only while the event is in PayPal's events list. Then it checks that the event arrived and that the books now match PayPal. Ring again rings each open gap: order #2, then order #3.

A replay of the real resend from Oct 20, 2026, sped up. Nothing is sent to PayPal.

Each wait was cut to about a second: order #2's 66 s and 66 s between resends, the 19 s before order #3's first resend.

2 of 3 captures did not match PayPal.

$96.00 across 2 refunds not in books.

First, what Doorbell cannot prove

  • 3 rows are inside PayPal's event-list lag (median about 80 s, up to 163 s measured): an event missing from the list proves nothing yet.
  • Orders that were approved but never captured cannot be counted (PayPal has no list API for them).
  • An event that is not in PayPal's event list cannot be shown to have existed.
  • Transaction Search lags about 97-128 minutes, so the last 2 hours of transactions were not used.
  • The proposed patch's comments and leftover code are not checked.
  • This certificate is not signed: anyone could edit it.

What it did check

  • Each of the 3 captures, looked up again at PayPal and compared with the books.
  • The AI's cited line is a changed line, and its category fits what the shop answered.
  • A replay of the real signed events on both builds showed the difference the AI's category predicts.
  • Claude's proposed patch passed 5 code checks. Replayed on 15 signed events, it behaved like the shop's last good build and PayPal's answer.
  • The resend has not run yet, so the gaps are still open.

Open the owner view, a printable page in plain sentences.

PayPal refunded $48.00. Your books still say paid.

PayPal says

Refunded

$48.00

Your books say

Paid

$48.00

Order #2, gift set. No error anywhere.

Doorbell finds the PayPal your shop never heard or never saved,has an AI point at the changed line of your code behind it,rings them again,and tells you exactly what it still cannot prove.

More

Doorbell is the tool that looks.

Order #2 at Maple Mug, a fictional coffee shop: a “Gift set: three coffees and a mug”. The went through at PayPal. The shop's own books never heard about it, so the order still reads as paid. Nothing crashed and nothing logged an error, so nobody is looking.

Doorbell checked the shop's 3 : the payments PayPal took, one per order. 2 refunds ($96.00) are missing from your books: the shop answered 200 but did not save them.

The chapters below follow order #2 from PayPal to your books. The other , order #3, comes back in Ring again.

Each hop said OK. The books never changed.

A 200 tells PayPal to stop trying, so nobody tried again.

  1. 10:42:28PayPal created the refund
  2. 10:42:37Doorbell heard it, checked
  3. 10:42:37.982Your shop answered 200 OK, 321 ms later
  4. 10:42:58Doorbell's check: books never changed
More

PayPal made the refund event. About 9 seconds later Doorbell heard it and checked its signature with PayPal's verify-webhook-signature call. Your shop got the and answered 200 OK in 321 milliseconds. A 200 is the polite answer, “got it, thanks”.

Then nothing: the books were never written. Doorbell's check at 10:42:58 looked each capture up at PayPal, read PayPal's , and found the gap.

The handler says OK before it saves the refund, so the save can be lost

The AI only proposes; two checks in plain code, with no model involved, both pass.

The AI proposed this change in handlers/ack-drop.ts, planted by us

handlers/good.ts:18

− await ctx.books.set(booking.captureId, { state: booking.state, amount: booking.amount, eid: event.id, at: ctx.now() });

handlers/ack-drop.ts:11

+ queue.push(event);

  • The cited line is a changed code line
  • The category fits the symptom: the shop answered 200 OK, but its books do not match PayPal

AI receipt: claude-sonnet-5-5 picked 1 of 8 categories (work after acknowledgement) and cited 2 changed lines. The answer is a stored recording; this page makes no model call. On a held-out set sealed before the run (2026-10-26) it named the right category in 34 of 35 cases; the README has the rest.

More

The AI read what changed in the shop's handler and proposed two lines as the cause. Its category is work after acknowledgement. In plain words: a changed line answers PayPal before the booking work is finished, so that work can be lost after the 200.

Same messages, two builds. Only one saves them.

To test it, Doorbell replays the two real signed events against the shop's good build and its bad build.

Good build

good.ts

Answers 200, 200

Books say

Refunded

$48.00

Bad build

ack-drop.ts, planted by us

Answers 200, 200

Books say

No entry

Confirmed by replay

More

Both answer 200, 200, so from the outside they look the same. Only the books differ.

On the same events, the good build books the refund and the bad build does not. That is a tested result for the whole change, not a proof about any one line.

Fixing the code does not rewrite the books.

Only another delivery of the same event can.

Proposed by Claude · not deployed in this demo

// Maple Mug webhook handler. PayPal posts here when a payment is captured or refunded.

import { bookingOf, rank } from "../lib/shop/events.ts";

import type { Handler } from "../lib/shop/types.ts";

 

lines of the file that the patch does not change

if ((await ctx.verify(event)) !== "SUCCESS") return { status: 401 };

 

const booking = bookingOf(event);

if (!booking) return { status: 200 };

 

// Never move an order backwards: a late "paid" must not undo a "refunded".

const current = await ctx.books.get(booking.captureId);

if (current && rank(current.state) > rank(booking.state)) return { status: 200 };

 

await ctx.books.set(booking.captureId, { state: booking.state, amount: booking.amount, eid: event.id, at: ctx.now() });

// Acknowledge first, book later.

queue.push(event);

return { status: 200 };

};

Highlighted: the lines the AI cited as the cause.

Behaves like the shop's last good build and PayPal's answer on these 15 inputs.

Books still say Paid $48.00

More

The shop's developer deploys the last good build. The shop now runs good.ts instead of ack-drop.ts, planted by us. A refund that arrives from now on is booked.

But the refund that already came is not booked: PayPal got its 200 and stopped trying.

Doorbell looked again at 10:43:12: the books still differ from PayPal on two captures.

Claude also proposed a patch for the cited lines. Plain code checked it first. Then it was run on real signed events and compared with the shop's last good build and with PayPal's own answer.

The 15 inputs are 5 deliveries from 3 orders, run three ways: in arrival order, reversed, and with one amount changed.

What the code checked

  • The edits name changed lines of the diff, and replace or delete only lines the cause cited.
  • The patched file parses.
  • It uses only the imports and names a handler may use.
  • Lines of the bad deploy that the cause did not cite are unchanged, byte for byte.
  • The edits stay inside the bad deploy's changed hunks.

What the replay compared

  • The events in the order they arrived: same answers and same books as the good build. (5 deliveries)
  • The same events, last one first: same answers and same books as the good build. (5 deliveries)
  • One amount in each body changed: 401 and nothing booked, like the good build. (5 deliveries)
  • The books equal PayPal's own answer for the order (GET capture). (6 comparisons)

The same patch with its signature check removed (written by us) fails the tampered control and passes the other three.

Compared with the shop's last good build, the patch still has: a comment that may no longer match the code; “queue”, a value nothing reads. The checks do not look at comments or leftover code.

The demo does not run this patch. It runs good.ts, the shop's last good build, which the patch matches on these 15 inputs.

The comparison ran at 10:43:12 UTC, on this run's own signed events. The edits are a stored recording from claude-sonnet-5-5; this page makes no model call.

Ask PayPal to send it again.

Doorbell can ask PayPal's call to send the same event again, but only while the event is in PayPal's events list.

A replay of the real resend from Oct 20, 2026, sped up. Nothing is sent to PayPal.

  • #1 House blend, 250 g

    $14.00Tied

    PayPal says Paidbooks say Paid

  • #2 Gift set: three coffees and a mug

    $48.00Gap

    PayPal says Refundedbooks say Paidbooks say Refunded

  • #3 Gift set: three coffees and a mug

    $48.00Gap

    PayPal says Refundedbooks say Paidbooks say Refunded

More

Then it checks that the event arrived and that the books now match PayPal. Ring again rings each open gap: order #2, then order #3.

Each wait was cut to about a second: order #2's 66 s and 66 s between resends, the 19 s before order #3's first resend.

2 of 3 captures did not match PayPal.

$96.00 across 2 refunds not in books.

First, what Doorbell cannot prove

  • 3 rows are inside PayPal's event-list lag (median about 80 s, up to 163 s measured): an event missing from the list proves nothing yet.
  • Orders that were approved but never captured cannot be counted (PayPal has no list API for them).
  • An event that is not in PayPal's event list cannot be shown to have existed.
  • Transaction Search lags about 97-128 minutes, so the last 2 hours of transactions were not used.
  • The proposed patch's comments and leftover code are not checked.
  • This certificate is not signed: anyone could edit it.
What it checked
  • Each of the 3 captures, looked up again at PayPal and compared with the books.
  • The AI's cited line is a changed line, and its category fits what the shop answered.
  • A replay of the real signed events on both builds showed the difference the AI's category predicts.
  • Claude's proposed patch passed 5 code checks. Replayed on 15 signed events, it behaved like the shop's last good build and PayPal's answer.
  • The resend has not run yet, so the gaps are still open.

All captures

OrderAmountPayPalBooksResult
#1 House blend, 250 g$14.00PaidPaid $14.00Tied
#2 Gift set: three coffees and a mug$48.00RefundedPaid $48.00Gap
#3 Gift set: three coffees and a mug$48.00RefundedPaid $48.00Gap