Interlock

Scenario: stripe_dispute

Generated 2026-09-13 22:51 UTC by experiments/scenario_stripe_dispute.py. Status: RAN. Stripe test mode, model claude-haiku-4-5-20251001, every crash a real SIGKILL of the worker process. Nothing emulated.

A $100 payment; the customer’s bank opens an inquiry; support approves a $20 goodwill refund and the model decides it; the worker dies; during the outage the bank escalates the inquiry to a chargeback; the worker restarts. Invariant: no refund is issued on the charge once it is charged back, and a refund sent before the chargeback was issued exactly once. Ground truth is Stripe’s refund list (every status, re-read 60s after the last cell) and the dispute’s balance transaction.

fault no_check hand_check interlock
crash_before_send_chargeback_during_outage STRIPE_ERROR; 0 refund object(s) (final: none), want 0; created at or after the chargeback: none; money returned: no; dispute needs_response; held; answer vs refund objects: matches; answer vs final money: matches; 6.8s; proof no (checks no, outcome no, tamper-evident no) REFUSED:charged_back; 0 refund object(s) (final: none), want 0; created at or after the chargeback: none; money returned: no; dispute needs_response; held; answer vs refund objects: matches; answer vs final money: matches; 6.4s; proof yes (checks yes, outcome yes, tamper-evident no) REFUSED:stale_premise_at_recovery; 0 refund object(s) (final: none), want 0; created at or after the chargeback: none; money returned: no; dispute needs_response; held; answer vs refund objects: matches; answer vs final money: matches; 42.4s; proof yes (checks yes, outcome yes, tamper-evident yes)
crash_after_send_chargeback_during_outage REPLAYED_BY_STRIPE; 1 refund object(s) (final: failed (charge_for_pending_refund_disputed)), want 1; created at or after the chargeback: none; money returned: no; dispute needs_response; held; answer vs refund objects: matches; answer vs final money: CONTRADICTS; 8.6s; proof no (checks no, outcome no, tamper-evident no) FOUND_BY_LOOKUP; 1 refund object(s) (final: failed (charge_for_pending_refund_disputed)), want 1; created at or after the chargeback: none; money returned: no; dispute needs_response; held; answer vs refund objects: matches; answer vs final money: CONTRADICTS; 11.2s; proof yes (checks yes, outcome yes, tamper-evident no) COMMITTED_ON_QUERY; 1 refund object(s) (final: failed (charge_for_pending_refund_disputed)), want 1; created at or after the chargeback: none; money returned: no; dispute needs_response; held; answer vs refund objects: matches; answer vs final money: CONTRADICTS; 43.0s; proof yes (checks yes, outcome yes, tamper-evident yes)

Reading

Design

Interlock receipts

hand_check logs

Model decisions

Probes behind the design (Stripe test mode, this account)

Ids