v0.26.0.md
docs/release-notes/v0.26.0.md
Tesserae v0.26.0 — compiles that finish, and say what they did
<!-- translations:start -->
한국어 · 中文 · 日本語 · Русский · Español · Français · Deutsch
<!-- translations:end -->
Released 2026-07-26 · PyPI · GitHub release · pip install --upgrade tesserae==0.26.0
v0.25.1 stopped compiles from wedging. This release makes them fast, makes them honest about what they covered, and stops them ingesting junk.
Faster
- Parallel extraction. The batch loop spawned one CLI subprocess and blocked on it, one document at a time — wall-clock was the literal sum of every model round-trip, measured at ~2 h 40 m for 161 documents. Extraction now runs 4 documents concurrently by default (
TESSERAE_EXTRACT_CONCURRENCY=1restores sequential).
Concurrency changes speed, never output: the work-list is fixed in path order and results are collected by index. merge_graphs resolves duplicate node ids positionally, so completion-order collection would silently mint a different graph — pinned by a test whose extractor finishes in reverse path order.
- The response cache actually caches.
complete_jsonhas always taken acache_key, and both CLI clients accepted it and threw it away — only the Anthropic client ever used it. Identical content re-paid full price on every compile. Both now read and write a content-addressed cache under~/.tesserae/llm_cache, keyed on content plus model and reasoning effort so switching models re-asks instead of serving the previous model's answers. Only parseable responses are stored.TESSERAE_LLM_CACHE=0disables.
Honest
- Extraction failures are named, not swallowed. A failure taxonomy distinguishes transient faults (retried) from real ones,
--limitno longer forfeits graph coverage, and per-home auth scoping stops one bad profile poisoning a run. graphedcompleteness markers. A manifest row is stamped only after its content actually reachesgraph.json— so a compile that dies partway can no longer leave rows claiming coverage the graph does not have. Deleted and renamed documents get tombstoned rather than lingering forever.--retry-fallbacksscoping now re-attempts exactly the documents whose typed extraction failed, and nothing else.
Cleaner
- Junk directories stay out of the corpus. pytest tmpdirs (
pytest-of-<user>/pytest-N/) and pip scratch dirs land inside a configured source root whenTMPDIRresolves into the repo, planting thousands of throwaway fixture files that churn every test run — so the candidate set never repeats and--changed-onlycan never no-op. One real project manifest had 25,269 entries of which 16,110 (63%) pointed at files that no longer exist.
The walker now skips those families during recursive descent. It is a directory rule: docs/pip-install-guide.md is an ordinary document and stays indexed — Tesserae's own concept slugifier mints exactly that filename shape from any "pip install x" heading.
Also
- Codex model default is
gpt-5.6-luna. - New tuning reference documenting all 29
TESSERAE_*environment variables — defaults, what each gates, and when to change it. Several, including the extraction timeout shipped in v0.25.1, had no documentation at all.
Upgrading from v0.25.1
Drop-in. Two things worth knowing:
Extraction now runs 4-wide. If your provider account has a tight rate limit, set TESSERAE_EXTRACT_CONCURRENCY=1.
The first compile after upgrading may do more work than usual — graphed markers do not exist in older manifests, so rows that predate them are treated as unproven and re-stamped. That is one corrective recompile, not a permanent cost.