The comma that ate seventeen nodes
The first backfill produced 55 nodes from five weeks of agent sessions. It was also the first real test of the tooling, and it found three things. This is the one worth telling, because the bug was silent.
History entries are written as YAML flow mappings, which are compact and read well in a diff:
- {date: 2026-08-02, status: running, note: kicked off on the cluster}
Now put a comma in the note:
# what was written - {date: 2026-08-02, status: running, note: scaled past 1,000 systems} # what YAML read - {date: 2026-08-02, status: running, note: scaled past 1, 000 systems: null}
The comma ended the scalar. note became scaled past 1,
and the tail of the sentence became a key. No error, no warning —
the file parsed, the node validated, the map rendered. 17 of the 55 nodes
were affected before anyone noticed.
The fix that mattered was not the writer
Making the writer quote flow scalars properly was ten minutes and is obviously necessary. It is also not the fix, because it only closes the path that happened to be found. These files are markdown that people edit by hand; the next unquoted comma will arrive by a different route.
The fix that mattered was in the validator:
a history entry may carry only date, status and
note. An extra key is now an error that blocks the commit,
with the message saying what it almost certainly means — an unquoted comma split a
note and turned its tail into a bogus key.
That converts a whole class of silent corruption into a loud failure, and it does so without knowing anything about commas.
Why this is the scariest bug this project has had
Cairn exists so that “did we already try this, and what happened?” has an answer. A crash is annoying. A record that quietly drops the second half of the sentence explaining why something failed is an attack on the only thing the project is for — and it is undetectable by reading the map, because the map shows you the truncated note and nothing indicates it is truncated.
Hence the general rule this settled: in a record you intend to trust, prefer a validator that rejects shapes it does not recognise over one that checks the specific mistakes you have already made.
The other two things the backfill found
- The pre-commit hook probed for the wrong thing. It looked for “a
python3that canimport yaml” — satisfied on the cluster by a 3.6.8 too old to parselib.py. So every commit was blocked by a SyntaxError reported as schema drift. Hencescripts/find_python.sh, and hence every command going throughbin/cairnrather than the scripts directly. - Untyped edges lost information. Three findings could only be
connected in prose. Hence
relates— the one schema addition in the project's life, and it took a written argument.
A backfill is also biased toward what worked, which is why the coverage table reports what share of a project's nodes were committed within a week of the work they describe. A project at 0% is a reconstruction, and a gap there means the graph does not know.