Skip to content

v0.6.32: the truth cut — RDFC-1.0 graph_digest, VALUES-on-graph-var refuses, staged refuses in txn blocks (#117, #109, #123) - #126

Merged
styk-tv merged 3 commits into
mainfrom
feat-0-6-32-canonical-digest
Aug 17, 2026
Merged

v0.6.32: the truth cut — RDFC-1.0 graph_digest, VALUES-on-graph-var refuses, staged refuses in txn blocks (#117, #109, #123)#126
styk-tv merged 3 commits into
mainfrom
feat-0-6-32-canonical-digest

Conversation

@styk-tv

@styk-tv styk-tv commented Aug 16, 2026

Copy link
Copy Markdown
Owner

v0.6.32 — the truth cut

Closes #109. (#117 closed by the feat commit; #123 closed by the guards commit.)

Three deliverables, every one measured before it was coded:

pgrdf.graph_digest(graph_id) -> text (#117)

RDFC-1.0 canonical graph digest — identity of meaning that survives reload. In-engine
over our own quad rows (no second RDF term model): first-degree hashing, related-hash,
full hash-n-degree gossip-path tie-breaking, canonical issuance, sorted canonical
N-Triples, sha256. Algorithm label rdfc-1.0-sha256. Asserted-only (I13).

Conformance proven, not claimed: ten vendored W3C rdf-canon cases pass with our
digest equal to sha256 of the suite's own expected canonical documents — byte-for-byte,
first run. The poison graph (test074, NegativeEval) hits the budgets and raises
pgRDF#117: refusing under budget is the conforming behaviour, so the fail-closed
doctrine and the spec turned out to be the same sentence. Fixtures vendored with W3C
dual-license attribution.

VALUES on a graph variable refuses (#109)

Re-confirmed live on 0.6.31 before coding: three nonexistent graphs in a VALUES, and
the query answered over every graph in the store. Now: stable pgRDF#109 refusal on
both assembly paths, unconditionally (the repro has no UNION), filter_clauses_dropped
incremented, plain-variable VALUES regression-pinned as still working.

Staged loader refuses in transaction blocks (#123)

The 31-minute silent hang (workers commit per phase; a caller transaction can never
allow it) becomes a pgRDF#123 refusal-with-rewrite at load_turtle_staged_run entry,
and load_turtle's N-Triples auto-dispatch falls back to the standard parser in that
context — auto-selection never picks a path that cannot work. The deeper discovery
(the coordinator's wait observes no interrupts in any contextstatement_timeout
never fired across 600 s) is filed as #125 with the measurement.

Verification

  • TDD throughout: every test watched failing first (canon on the missing function; the
    guards on absent errors; error strings are exact-match contracts per the lock-module
    precedent — pgrx compares ==, verified in its source)
  • Full suite 381 passed / 0 failed · clippy -D warnings clean · fmt clean
  • Release modeled before code as a sealed Ticket (proposed); the recheck inverts on
    the bench after the chain

Merge is not release: the tag follows the standing cadence on the merge word + tag
confirm.

 VALUES-on-graph-var refuses

Two silent failure modes become refusals, both measured before coded:

#123 - staged workers commit per phase; inside a caller transaction the
coordinator waited on workers that waited on the caller's locks - 31 min
at 0% CPU, and statement_timeout NEVER fired (the wait sits in
wait_for_shutdown, which does not observe interrupts - that deeper
uncancellability is measured and goes up as its own issue). Guard at
load_turtle_staged_run entry raises pgRDF#123 with the rewrite before
any slot is taken; load_turtle's auto-dispatch adds !IsTransactionBlock
to staged eligibility so the sniff defers to the standard parser.

#109 - re-confirmed live on 0.6.31: VALUES binding a graph variable
contributed nothing and the query answered over EVERY graph.
refuse_values_on_graph_variable runs beside the #114 sibling on BOTH
assembly paths, unconditionally (the repro has no UNION), increments
filter_clauses_dropped, and names the rewrite. Control pinned: VALUES
on a plain variable keeps applying.

Error texts are exact-match test contracts (pgrx compares ==, verified
in framework.rs:174 - the lock-module precedent followed).
Graph identity that survives reload: canonical blank-node relabelling
per W3C RDFC-1.0, canonical N-Triples serialization, sha256. Algorithm
label rdfc-1.0-sha256 (per the sealed interface contract - values are
NOT comparable with first-degree structural pins, by design). Asserted
triples only: inferred is a check value, never content (I13).

Implementation is in-engine over pgRDF's own quad rows - no second RDF
term model. Reuses the shacl.rs graph-read join, the sha2 dep that
arrived with #118, and the term_type constants. First-degree hashing,
related-hash, and the full hash-n-degree gossip-path tie-breaker with
temporary issuers and lexicographic early-abort. Three budgets RAISE
pgRDF#117 rather than degrade (calls 10k, permutation group 7, depth
32) - and the W3C poison test (test074, NegativeEvalTest) expects
exactly that: refusing under a resource budget IS conforming.

Verification: contract tests (reload-equality across relabelling;
conclusive difference) plus a ten-case W3C rdf-canon conformance
subset asserting our digest equals sha256 of the suite's OWN expected
canonical documents - byte-for-byte spec exactness, first run. Vendored
fixtures under tests/fixtures/rdfc10/ with W3C dual-license attribution.

Closes #117
Canonical graph identity lands: pgrdf.graph_digest, RDFC-1.0, proven
byte-for-byte against the W3C suite's own expected documents on first
run, poison refusing under budget exactly as the spec demands. Two
silent failure modes become refusals: VALUES-on-graph-variable
(pgRDF#109) and staged-in-transaction-block (pgRDF#123).

Release plumbing per the standing pattern: version 0.6.32 across
Cargo.toml/lock, pgrdf.control, META.json (both fields), compose
mount, CHANGELOG entry; upgrade script carries the generated
graph_digest DDL; rolling bridge renamed with the delta appended;
00-smoke expected version strings advance.

Full suite 381/381. Release modeled before code as
ticket-1786916192416285000 (proposed); the recheck inverts on the
bench after the chain.

Closes #109
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SPARQL: VALUES bound to the graph variable is silently ignored — query answers over ALL graphs

1 participant