Record the old parser's output over every in-repo query before replacing the parser
RecipeVerified 27 Sep 2026Holds anywhere
Recipe. When to use it, the steps, and what showed that they work.
When to use#
You replace a parser (a query language, a config format) and promise that every input accepted before keeps its meaning. Unit tests of the new parser do not prove that: they test what you thought of, not what the repo already writes.
Steps#
- Before touching the old parser, collect every input string the repo uses: scan tests, docs, examples and benchmarks for the call sites that take the language (for a query DSL:
from_string(,parse(,.query(,--query,query=), decoding raw strings and escapes. Deduplicate. - Build a small recorder against the current library, outside the repo (a scratch source compiled with the compile and link lines of an existing test target, from
ninja -t commands <target>). For each input, write one JSON line: the input, whether it parsed, and the old parser's printed tree. - Commit that file as a golden corpus, and add a test that parses each input with the new front end and requires the same printed tree, or the same failure.
- Run it right after the cutover. Every difference is either a listed, intended break or a regression to fix.
Evidence#
- dftracer-utils duql stage 12a1 (2026-09-27):
scripts/collect_duql_corpus.pyfound 402 filter strings (393 parsed with the old parser);tests/duql/golden_filters.jsonlandtest_duql_golden. The first run after the cutover found two regressions that the new unit tests had missed:"sub" in any(tags)no longer parsed, and a numeric key after a dot (tags.0 > 5) failed. Both were fixed before the change was done.