Add drift fingerprint + incremental mint/supersede publishing - #1
Merged
Conversation
Publishing was append-only: mint_publish skipped any term already in the id-map keyed solely on its old id, so a change to an already-published term -- whether to its content or to a batch-level wrapper (template, part-of, nanopub-type, license) -- was never detected or re-issued. Add a semantic drift fingerprint and an incremental publisher that acts on it: - fingerprint.py: a key-independent SHA-256 over the identity-defining inputs only (URDNA2015-canonicalized assertion + suggester/derived_from + license/introduces/nanopub-type/template), computed on the placeholder form so the thing URI never feeds its own hash. Excludes the build timestamp, signature and blank-node/order noise (no-op tier) and the signing key/toolchain (build-provenance tier), so a key rotation cannot read as content drift. - idmap.py: fourth `fingerprint` column; reads legacy 3-column files. - incremental.py: publish_incremental() -- per term, mint (new), skip (fingerprint unchanged), or supersede (drifted) against the existing fixed thing URI so the term keeps its identity across versions. Legacy rows without a fingerprint are backfilled as a baseline, not mass-superseded. - cli/mint_publish.py: build a matching SupersessionBuilder, drive publish_incremental, write minted and superseding nanopubs by their own artifact code, and persist fingerprints in the id-map. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Publishing was append-only.
mint_publishskipped any term already in the id-map keyed solely on its old id, so a change to an already-published nanopub — whether to its content or to a batch-level wrapper (template,dcterms:isPartOf, nanopub-type, license) — was never detected or re-issued.What this adds
A semantic drift fingerprint and an incremental publisher that acts on it.
fingerprint.py— a key-independent SHA-256 over the identity-defining inputs only: the URDNA2015-canonicalized assertion plus suggester/derived_from/license/introduces/nanopub-type/template. Computed on the placeholder form (subject =…/~~~ARTIFACTCODE~~~) so the thing URI never feeds its own hash. Excludes the build timestamp, signature and blank-node/order noise (no-op tier) and the signing key / toolchain (build-provenance tier), so a key rotation cannot masquerade as content drift.idmap.py— fourthfingerprintcolumn; still reads legacy 3-column files (empty fingerprint).incremental.py—publish_incremental(): per term, mint (new), skip (fingerprint unchanged), or supersede (drifted). A superseded term is re-stated against its existing fixed thing URI in a nanopub thatnpx:supersedesthe recorded one, so the term keeps its identity across versions (only the nanopub URI advances). Legacy rows without a fingerprint are backfilled as a baseline, not mass-superseded.cli/mint_publish.py— builds a matchingSupersessionBuilder, drivespublish_incremental, writes minted and superseding nanopubs by their own artifact code, and persists fingerprints in the id-map.Behavior
Tests
test_fingerprint.py,test_incremental.py, and additions totest_idmap.py/test_cli_mint_publish.pycover determinism, cosmetic/no-op invariance, content and each wrapper field moving the fingerprint, key-independence, the mint/skip/supersede/backfill decisions, and the CLI end-to-end (superseding.trigwith the rightnpx:supersedesand a repointed id-map). Full suite: 120 passed.Not included
biochementity-vocabularystill pinsv0.2.1; consuming this needs a release + pin bump there (no Makefile change — same CLI flags).eu-parcyet.🤖 Generated with Claude Code