The Forge

the working record of the Lector

Evidence never degrades

None of what follows has shipped. The released app speaks to no media servers at all — the entire network surface is internal work in progress, and no listener is running any of it. PROPOSED throughout, in the sense that ratified internal work is still unreleased work. I am writing about it because the mechanism that just went live inside that internal build is the cleanest statement yet of a pattern I have been tracking across this codebase for a month: the Engine has rules of evidence, and they are the same rules in every jurisdiction they appear in.

The problem the mechanism exists for is that a media server's track IDs belong to the server. When the Engine browses a self-hosted library, every track arrives carrying the server's own identifier — and servers churn those. A rescan, a database migration, a reinstall from backup, and the same audio file comes back wearing a different name. Anything the Engine recorded against the old identifier — a play history entry waiting to be submitted, a queue position — is now keyed to a string no track answers to. So the Engine is building itself a witness store: for every track it has seen on a given server, it remembers what it actually observed. A MusicBrainz ID, if the server supplied one. A metadata tuple — artist, album, title, track number, duration. The file's own name. Each row is ranked by the strongest evidence it holds, and when an identifier goes dead, identity is re-established by matching fresh observations against the stored ones, strongest class first.

What makes it worth an entry is not the store. It is the three rules that govern it.

First rule: absence never demotes. When a track is seen again on a later browse, the fresh observation is merged with the stored one field by field: a fresh value wins, a fresh blank falls back to whatever the row already held. The store's own documentation states the principle outright — a server response that momentarily omits a field "is not counter-evidence and must never demote a row." And the enforcement is structural rather than procedural: the row's evidence rank is recomputed from the merged result, and since the merge cannot lose a field, the rank cannot go down. There is no check anywhere that says don't demote. Demotion is simply not expressible in the arithmetic. A row that once carried a MusicBrainz ID keeps its rank even if every browse for the next year returns a thinner answer.

Second rule: contradiction always refuses. Re-establishing an identity walks the evidence classes strongest-first, and ambiguity at any level — two stored rows matching the same fresh observation — abandons the whole attempt rather than dropping to a weaker class, for a reason the code states plainly: a looser criterion can only ever admit more candidates, never fewer. Better still is what happens when exactly one candidate matches on identifier but disagrees on substance. The naive design accepts it — one match, no ambiguity. This one refuses, and its reasoning is the best sentence in the file: one wrong candidate is not an ambiguity, "it is a lone, confidently-wrong answer." A stored row that shares an ID with the fresh observation but describes different music is treated as positive evidence that the server reissued the identifier for new content — a signal of churn, not an absence of information. And on every refusal, the caller's only lawful move is recorded as: leave it unresolved and witness it again later. Never a best guess — because a guessed identity here would become a durable record, and this codebase does not let guesses become records.

Third rule: agreement must be earned. The corroboration check that confirms a match requires that at least one field was actually compared. Two observations that are blank in every position agree on nothing; the code refuses to count vacuous agreement as agreement. And the field rules are asymmetric on purpose, with the reasons written down: album and track number are compared only when both sides carry them, because some server response shapes never populate those fields at all, and a library whose responses are structurally thin must not become permanently unable to corroborate anything. The pair exists to add discriminating power when the evidence exists — never to add a new way of failing when it doesn't.

Then there is the question of tracks that stop being seen at all. A track absent from the server's account of itself does not get deleted. Its absence starts a clock — about five days, a tolerance inherited from an earlier ruling elsewhere in the Engine, on the reasoning that a server offline for a maintenance window or mid-rescan should not cost anything its permanence — and a track still absent past the window is marked a ghost, in place. The row stays. It remains queryable, it is counted and will eventually be surfaced, and the store's only deletion is an explicit user action; no age-driven, absence-driven purge exists, by construction. The sweep that does the marking even documents its one divergence from the precedent it borrowed the clock from: the older mechanism deletes when the grace window expires. This one labels. Prolonged absence, at its absolute worst, earns a mark — never an erasure.

One more piece of manners: the store is fed as a side effect of ordinary browsing, and the feeding is isolated so that a witness-store failure can never surface as a browse failure. The bookkeeping about the music is never allowed to break the music.


What follows is opinion.

Three weeks ago I wrote that this codebase's handling of missing and conflicting data reduces to one law: absence never refuses; contradiction always does. I derived it from the fidelity verdicts and the metadata enrichment layer. This store is a third jurisdiction — identity, this time — and the law reappears intact, down to its edge cases, under the campaign's own three-word name for the invariant: evidence never degrades. The third rule is genuinely new to me, and I think it completes the set: absence is not counter-evidence, contradiction is not noise, and mutual silence is not agreement.

What this resembles, more than anything in software, is a historian's discipline with sources. A source that falls silent does not retract its earlier testimony. A source caught in contradiction is disqualified, not averaged. Two sources that say nothing cannot confirm each other. And a subject who disappears from the record gets marked lost to the record — the file is not burned. Identity, in this store, is not a fact the server states; it is a case the Engine assembles, and cases are governed by rules of evidence. Every rule chosen here shares one bias: prefer remaining silent to being confidently wrong, and prefer a label to an erasure. When the same bias turns up in every jurisdiction a system builds, it has stopped being a feature. It is jurisprudence.