Skip to content

← The log

A starter config that cannot drift from its parser

Unknown keys are an error, which makes the generated file the documentation — so a test uncomments the whole thing and feeds it to the real parser.

FixKonstantin Tarkus

engwire setup writes a config file, and Engwire’s parser rejects any key it does not know. Those two facts put more weight on the generated file than a template usually carries. Guessing at a setting is not a hint that gets ignored — it is an error that stops the runner, so anything the starter does not mention is a setting most people will never find.

Which is fine while the file and the grammar agree, and they are the two things most likely to drift apart. A key added to the parser and not to the template is one nobody discovers. A key left in the template after the parser dropped it is a file that fails to load on a first run.

Uncomment the file and parse it

The starter now lives in the same module as the parser, and the check is blunter than a schema comparison: the test uncomments every example assignment in the starter and feeds the result to the real parser.

That covers one direction. Every key the file writes has to be one the grammar takes, with a value it accepts, in a section where it is legal, or parsing throws.

The other direction is a loop over the parser’s own accepted-key lists, asserting each one appears in the file as an assignment. A key added to the grammar and not to the template fails on the missing line.

Those lists are not a third copy to keep in step — they are the same constants the parser validates against when it rejects an unknown key. What the pair pins is the key set, and only that. A setting could be accepted, documented, and read by nothing at all, and both halves would still pass.

Then it goes one step further, which is the part that makes the comments trustworthy:

parseConfig(uncommented).advanced  ==  parseConfig(starter).advanced

Uncommenting a tuning line changes nothing, so every tuning value the file shows is also the default applied when the line is absent. skip_drafts is checked the same way, by deleting it and confirming the rule comes out identical. The file cannot advertise a default the runner does not apply.

That is a claim about the commented lines only. repos and skill are required rather than defaulted, and the two binary paths are whatever setup found on the machine.

None of this says anything about whether the English in the comments is still true. That is prose, and prose has to be re-read by a person.

setup was writing in a grammar the parser does not read

Binary paths are quoted with Bun.TOML.stringify, not JSON.stringify.

The two grammars disagree about U+007F. JSON leaves it raw, escaping only below U+0020; TOML requires it escaped and refuses the file otherwise. And U+007F is a legal character in a filesystem path.

So on a machine where gh or claude sat under such a path, setup would report a config written and the runner would then decline to read it:

TOML Parse error: Control character must be escaped

Nobody has a DEL character in their gh path, and that is not the point. The bug is that setup was serializing with one grammar and parsing with another, and the character where they disagree happened to be one a path can legally hold. Any future divergence between the two lands in the same place — a file the tool wrote and the tool refuses. Using TOML’s own serializer means the writer and the reader cannot disagree about grammar, which is the same argument as the test above, applied to values instead of keys.

That principle is also why setup now offers only skill names a [[review]] rule could actually carry, rather than everything sitting in your skills directory. Offering a choice the parser would reject is the interactive version of writing a file it cannot read.

Three things produce configuration here — the template, the serializer, the picker — and one thing decides what is legal. None of the three gets its own opinion about the grammar, and the cheap way to keep it that way is to run each one’s output back through the real consumer, rather than checking both against a description of it.

engwire/engwire#16 →

Engwire reviews the pull requests that ask for you, on your own machine.

MIT · macOS and Linux · no account to make

curl -fsSL https://engwire.com/install.sh | sh

What Engwire does →