Stop rebuilding the RDF graph that is already there master
oxigraph-sync ran every 30 minutes and spent 8.5 of them at 134% CPU on a two-core box — the spike that was pinning lith. Its own log showed where the time went: Mongo answered in under a second and Oxigraph accepted 26.3 MB in nine, while 499 of 508 seconds went to expanding Linked Art JSON-LD into CIDOC CRM triples. Consecutive runs produced byte-identical output (223821 triples, twice) and PUT all of it anyway. Almost none of that work was necessary. Paintings, pieces and moods are immutable once created — 62% of the corpus — so they expanded to the same triples every half hour forever. What blocked caching was that expansion wasn't deterministic: docToNTriples scoped each doc's blank nodes with a running counter, so the same painting became _:d5b0 in one run and _:d900b0 in the next. Output depended on position in the batch, which left "rebuild everything and replace the store" as the only possible operation. Scope on a digest of the doc's own IRI instead and expansion becomes a pure function, which is what the rest of this rests on. The scope is 48 bits of SHA-256, not a cheap 32-bit hash: across ~8k docs the latter collides about 0.7% of the time, and a collision merges two works' blank nodes — the exact corruption the scoping exists to prevent. On that footing: cache expansions by doc content, expand misses over a small pool, and skip the PUT entirely when the dump digest matches what was last loaded. The digest is recorded only after the store accepts it, so a failed load retries rather than being remembered as applied. That last check is also the redundancy an event-driven trigger would need: if a change event is ever missed, the next sweep still catches it, and when nothing was missed the sweep costs nothing. Blank-node labels change, so the first run after this reloads the store once. Verified: same doc expands identically twice, no collisions across docs, and a concatenated dump keeps every blank node distinct. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>