5.0 KB · updated 2026-07-31 · md

v0.27.0.md

docs/release-notes/v0.27.0.md

Tesserae v0.27.0 — agents can write to the graph, and ask it what it licenses

<!-- translations:start -->

한국어 · 中文 · 日本語 · Русский · Español · Français · Deutsch

<!-- translations:end -->

Released 2026-07-26 · PyPI · GitHub release · pip install --upgrade tesserae==0.27.0

Until now an agent could only hand Tesserae prose and hope the extractor guessed the right types back out. This release opens the write path and the verification path: agents record findings as typed structure, and can ask the graph whether it actually licenses a claim.

Agents write typed findings

graph_write takes schema-validated typed nodes and edges with mandatory provenance. It refuses rather than coerces — untyped edges, types outside the controlled vocabulary, dangling endpoints and missing provenance are all rejected; duplicate writes are idempotent.

Agent-written nodes survive a full recompile, a deleted graph.json, --limit, and total corpus deletion. Under adversarial testing, 60 concurrent writes against a live compile came through with zero torn reads across 1,483 reads.

Agents verify against the graph

verify_claim answers whether the graph licenses a triple. The verdict is a pure function of graph bytes: no LLM, no embedding, no fuzzy matching anywhere on the decision path. A verifier that hallucinates is worse than no verifier.

It takes (subject, predicate, object) and has no natural-language parameter — deliberately. Seven verdicts, including PRESENT_UNEVIDENCED (the edge exists but nothing document-backed stands behind it) and ABSENT ("this graph does not assert that" — never a refutation).

Two guarantees worth stating plainly. supersedes never produces a verdict: it says a node was replaced, not that a triple is false. And an agent write can only ever weaken a provenance class, never upgrade one — nothing an agent asserts can present as document-grounded.

Also

  • Semantic entity resolution. Embedding-clustered candidates now feed the existing review queue rather than auto-merging. Precision over recall: a wrong merge silently fuses two real entities and every downstream traversal inherits the error.
  • Question-shape routing for ask. Graphs win multi-hop, temporal and synthesis questions and lose simple fact lookup and cost, so paying graph prices for everything is a loss. The routing decision is in the envelope so a cheap answer is auditable; --route overrides.
  • Validity intervals on temporal facts, derived from source timestamps — never wall-clock.
  • --llm-limit holds under concurrent extraction. Since v0.26.0 made extraction parallel, the old check-then-increment let every worker read the counter before any of them wrote it, so --llm-limit 1 bought one call per worker. It is a spend cap, so it now fails closed.
  • Compile coverage is an invariant, not a claim. Four silent-data-loss paths closed, then the machinery behind them removed entirelycompile(loader=…) has no production caller, and defending that library-only API was the source of every serious defect across several review rounds. One of them was a regression v0.26.0 itself introduced.
  • New documentation for the write, verify and routing surfaces.

What did not ship, and why

A contrast pass to mine contradicts_claim / derived_from / criticizes edges was built, measured, and cut. It minted 0 edges from 80 judged pairs across two real corpora, and 60 of 60 judge rationales gave the same reason: the pairs were near-duplicates with nothing to contradict.

The cause was structural. Candidate generation blocked on shared rare tokens, which optimises for similarity — but contradiction and derivation hold between claims that differ. A redesign evaluated five new generators offline, at zero LLM cost: the high-volume one scored 0/10 on hand inspection (its "conflicting numbers" were arXiv IDs and publication dates), and the only precise one produced six candidate pairs on one corpus and none on the other.

A control run settled it — judging 15 reasoning edges that already exist returned recall 7/15. The judge was always working; the candidates were always wrong.

The REASONING_EDGE_RATIO lint rule stays, and pins the honest baseline: 7.5% of edges carry reasoning, with contradicts_claim, derived_from, attributes_improvement_to and criticizes at zero instances.

Upgrading from v0.26.0

Drop-in. If you set TESSERAE_CONTRAST_PASS, it no longer does anything — the pass is gone.