case studies

Selectivity Finds the Two CSV Records Behind a Calculation Bug

A CSV importer can be wrong for a reason that disappears when a developer tests one record at a time. The example here needs a sequence: a discount for an order, followed later by a refund for that same order. A deliberately faulty importer deducts the refund twice when it has already seen a discount. A reference implementation deducts it once. The predicate compares the two results and asks Selectivity to preserve their disagreement.

The generated export contains a header and 122 data records. Most are unrelated sales, with the target discount and refund separated by many ordinary rows. In one run of the released Selectivity 0.1.1 binary on Linux x86_64 with Python 3.12.14, the 2469-byte input becomes a 59-byte file with three lines: the header and the two interacting records. Each candidate is observed three times, with a five-second timeout per execution. The run makes 201 predicate executions across 67 candidate checks, including baseline and final verification.

A generated CSV export with 123 lines becomes a three-line reproducer, while invalid headerless candidates remain unresolved

The reduced input is small enough to read without a search tool:

order,kind,amount
target,discount,5.00
target,refund,20.00

On this permitted partial history, the reference total for the target is minus 25.00. The faulty importer produces minus 45.00 because it subtracts the 20.00 refund again. The remaining sales were irrelevant to that disagreement. This is a controlled regression fixture, not a report of a defect in a commercial importer, and its predicate deliberately permits partial order histories. A production wrapper would need to enforce whichever history and schema constraints its importer actually expects.

The header makes the example more useful than a simple word search. Candidates without the exact header return 125, which means unresolved. They cannot justify a deletion. The run records 23 unresolved candidate checks and therefore reports locally_minimal as false, despite finishing with the expected header and target pair. That is the documented conservative rule in action: the result satisfies the predicate, while the summary withholds the stronger deletion-minimality claim because some candidates could not be evaluated.

The runnable example bundle includes the fixture generator and the complete predicate. Its csv_predicate.py validates the header and row schema, uses decimal arithmetic and compares the faulty accumulator with the reference. Run the bundle with an unpacked Selectivity executable, or point the reducer at your own generated orders.csv with the predicate supplied as an absolute path. The saved run evidence contains the summary, reduced input and compressed audit.

This case shows why the predicate deserves as much care as the removal algorithm. Keep the exact disagreement you are investigating, preserve the structure needed to evaluate it, and let unrelated records fall away. The original export’s digest was checked after the run and remained unchanged. The record counts here are from one generated fixture, rather than a claim about the number of checks another importer bug will need.