Skip to content

format: a JSON document can be minified or indented - #84

Merged
donislawdev merged 2 commits into
mainfrom
format/json-settings
Sep 7, 2026
Merged

format: a JSON document can be minified or indented#84
donislawdev merged 2 commits into
mainfrom
format/json-settings

Conversation

@donislawdev

Copy link
Copy Markdown
Owner

json gains one setting: formatting, taking record-per-line, minified
or indented. It defaults to the layout this format has always written, pinned
by two new golden values.

tfg generate --format json --size 1mb --set formatting=minified

The measurement that shaped this is a negative one

No reader can tell the three apart. The same records written four ways, on two
implementations in two languages:

layout bytes CPython json V8 JSON.parse
minified 130 ok ok
record-per-line 135 ok ok
indented (2) 260 ok ok
indented (4) 356 ok ok

So the value of the setting sits entirely outside the parser. Measured on our
own 64 KB files: minified holds zero newlines and ends without one,
record-per-line holds 292, indented holds 3419 - and indented fits 201
records where record-per-line fits 290, so the same size carries a third less
data.

It also means the structural checker cannot work the layout out for itself, and
has to be told, for the reason the CSV dialect is told.

That falsified what the existing checker said about itself

check_json read "the manifest states one record per line" and counted lines
against it, so both new layouts would have broken it. The sentence was not wrong

  • it stopped being true the day the layout became something a person can ask
    for. Second time in one session that a comment had to be rewritten rather than
    deleted for exactly this reason.

Each layout answers for its own floor

216 B minified, 219 B a record per line, 318 B indented. The registry
declares the default layout's floor - MinBytes is one number - and the
generator answers for the rest through SmallestAccepted, the same split as the
CSV dialect. The refusal names the layout it is about, because the same size is
legal in another one.

The canary

A checker handed a file and the right layout name would pass even if it
ignored the name entirely, so the guard hands it every wrong name instead.
Six pairs, six refusals.

Verification

  • targeted guards green, gofmt, vet
  • six mutations, all caught - including one already in the list that this
    refactor had staled, found by staleness.py rather than by reading
  • 300 of 300 checks on the built binary, 15 of them new
  • 12 documents read by the structural checker across the three layouts

The whole local suite was not run for this branch - CI covers it.

🤖 Generated with Claude Code

donislawdev and others added 2 commits September 7, 2026 20:48
json gains a formatting setting taking record-per-line, minified or indented,
with the layout literals held on a style so the arithmetic that hits an exact
byte count measures whichever one is in use rather than predicting it. The
default is the layout this format has always written, pinned by two new golden
values.

The measurement that shaped this is a negative one: no reader can tell the
three apart. The same records minified, one per line, indented by two and
indented by four all parse in CPython's json and in V8. So the value of the
setting is entirely outside the parser - a minified document of any size is one
line and ends without a newline, an indented one holds about a third fewer
records in the same bytes - and the structural checker has to be TOLD which
layout to expect, for the reason the CSV dialect is told.

That immediately falsified what the existing checker said about itself. It read
"the manifest states one record per line" and counted lines against it, so both
new layouts would have broken it. The sentence was not wrong - it stopped being
true the day the layout became something a person can ask for.

Each layout answers for its own floor: 216 B minified, 219 B a record per line,
318 B indented. The registry declares the default layout's, the generator
answers for the rest, and the refusal names the layout it is about because the
same size is legal in another.

The canary is the half that makes the rest mean anything: a checker handed a
file and the RIGHT layout name would pass even if it ignored the name, so the
guard hands it every wrong one instead. Six pairs, six refusals.

Six mutations, all caught - including one already in the list that this
refactor had staled, which staleness.py found rather than a reader.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The engine gained property:json.formatting and neither parity list named it, so
TestEveryEngineCapabilityIsClassifiedForBothSurfaces refused the run on all four
jobs. That is the guard doing its job: a setting reaching the engine without
anybody answering whether the window offers it is exactly the drift D1 forbids.

The bar for the reachable list is two things rather than one - a control on the
screen, and a guard that presses it and finds the value on the other side - and
both were measured before the name went in. The field is drawn from the
declaration and nothing else, the menu opens on its declared default and is
named among the twenty that do, and the path from a field to the manifest is
pinned by the guard that types a value and reads it back off the disk.

One thing was worth asking rather than assuming. The window sends every setting,
because a menu cannot be empty, so a run started there says record-per-line out
loud where the command line says nothing at all. Those two have to be one file,
and the guard that pins them already exists.

D1 parity: 114 of 125 capabilities reachable from the window, eleven still to go.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@donislawdev
donislawdev merged commit e953fa5 into main Sep 7, 2026
18 checks passed
@donislawdev
donislawdev deleted the format/json-settings branch September 7, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant