v1.14.4 ·
The refresh that rewrote everything it read
aidlc knowledge rebuild is documented as rebuilding the SQLite index from the YAML sources. The index is a gitignored, disposable cache, so the command should have nothing to say to the tracked files it reads. It rewrote all of them: a 685-line diff across seven files from a command that changed nothing anyone asked for.
Nothing was corrupted. The parser tolerates what the writer produced. But a diff stopped being readable. Any real edit to the knowledge graph arrived buried in separator churn, and the only way to know a rebuild meant nothing was to read all of it.
Two causes
The visible one was a writer bug. These files are multi-document YAML streams. The writer joins documents it re-serializes, which carry no --- marker, with documents it copies from the parse, which carry their own. Joining both with a separator doubled the marker on everything copied and put an empty document between each pair of real ones.
The deeper cause was that the rebuild wrote anything at all. It stamped _meta.lastIndexed into every file. That field was written in two places and read in none. Keeping it current turned an index refresh into a whole-graph write, for a value nothing consulted. The module's own requirements already said this could not happen.
What changed
Rebuild now refreshes the index and nothing else. The timestamp and the method that maintained it are gone. The field stays in the file format because seven committed files carry it, and it now means when the file was created.
The writer adds a separator only where one is missing, so running it on its own output changes nothing. An in-place update copies the documents it is not changing straight out of the file, using the position the parser already recorded.
That second part was not in the original report, and it mattered most. I ran the fix on this repository's two damaged files. It should have removed 108 lines and touched nothing else. It rewrote 829. The branch meant to preserve documents was re-serializing them at whatever line width was in force, and the files had been written at two different widths over several weeks. The doubled separator was a seventh of the diff and had taken all the attention. Matching the width would have been a near miss, because it still reflows anything written at another width. Copying the bytes reformats nothing ever, and a test fails against the nearly-right version.
Those two files had carried 108 empty documents since an earlier rebuild. They are normalized here, checked by comparing parsed contents before and after, not by reading the diff. It is 108 deletions and no changed content.
What I did not add
The report ranked three fixes. I took the smallest and let the others shrink.
A separate formatting command would have duplicated the one sanctioned way to rewrite these files wholesale, which already exists. A new health check for an index that remembers an entity the sources no longer have would have duplicated rebuilding the index, which already fixes exactly that. What was missing was a sentence. The failure named a file it could not find, which reads like corruption. It now says which half is stale and which command reconciles it.
Every new check is a cost for all future work. Making an existing one unnecessary is worth more than adding a good one.