case studies

Selectivity Isolates Numeric Precision Loss in JSON Lines

An input can be perfectly valid and still expose a disagreement between two consumers. In this example, one path keeps an integer identifier exactly as parsed. The other deliberately sends the identifier through a floating-point conversion before turning it back into an integer. Most of the generated JSON Lines records produce the same answer. One does not: 9007199254740993 becomes 9007199254740992 in the lossy path.

Selectivity starts with 150 independently valid records totaling 4144 bytes. The predicate parses every remaining line, checks its schema, then compares the exact identifier sequence with the lossy sequence. In one run of Selectivity 0.1.1 on Linux x86_64 with Python 3.12.14, the result is one 41-byte record. The reducer makes 36 predicate executions across 12 candidate checks, with three observations per candidate and a five-second timeout. There are no unresolved checks.

Selectivity reduces 150 JSON Lines records to the single record that exposes the numeric conversion difference in 36 predicate executions

The complete reduced input is:

{"id":9007199254740993,"value":"row-73"}

The fault is in the deliberately lossy consumer, which uses int(float(id)). This does not demonstrate a bug in Python’s JSON parser. The exact path reads the same input and retains the original integer. That distinction matters when writing a bug report: a small counterexample should identify the operation that differs, rather than casting suspicion over every component that touched the file.

The predicate treats an empty JSON Lines file as valid input with no disagreement, returning 1. A malformed record or a record with the wrong schema returns 125. In this generated fixture, removing whole lines never breaks the surviving records, so reduction reaches its one-line result without unresolved candidates. The completed summary reports local deletion minimality. Its scope is lines: it does not say that the value field, the row label or every character in the remaining record is necessary. Selectivity’s first version does not attempt those edits.

The example is useful wherever a developer can provide two deterministic paths whose outputs should agree: an old and new implementation, a reference routine and an optimized one, or two serialization adapters. The wrapper needs to classify invalid candidates separately and compare the behavior that actually matters. Comparing a precise identifier sequence is a sharper test here than merely checking whether both consumers finish successfully. Both paths can finish and still disagree.

The example bundle contains jsonl_predicate.py and the generator for all 150 records. The recorded evidence includes the reduced record, summary and audit. The source digest remained unchanged. These figures describe one controlled run with a known numeric counterexample, rather than a benchmark of JSON processing speed or a guarantee about how an arbitrary differential test will reduce.