v0.28.0.md
docs/release-notes/v0.28.0.md
Tesserae v0.28.0 — hooks that cannot spend your money by accident
<!-- translations:start -->
한국어 · 中文 · 日本語 · Русский · Español · Français · Deutsch
<!-- translations:end -->
Released 2026-07-27 · PyPI · GitHub release · pip install --upgrade tesserae==0.28.0
Upgrade for the first item. It is a spend bug, and it was reproduced on a real machine.
The $HOME trap
A knowledge base at ~/.tesserae makes $HOME look like a project root. The plugin's resolve_project_root() walked up from the working directory to the first .tesserae/ it found — so any session started outside a registered project resolved to $HOME, and the PostToolUse hook backgrounded tesserae compile --changed-only over the entire home directory.
15k files, a 795 MB graph, roughly 10 hours of LLM spend, from a setsid'd process that outlived the session that spawned it. It fired on every Edit/Write.
The fallback made it worse than it looks. When no .tesserae/ was found the resolver did this:
echo "$PWD"
return 0
It claimed any directory was a project. Callers then tested -d "$root/.tesserae" — which passed for any working directory under $HOME. That test was the last line of defence and the fallback walked straight through it.
Two refusals now. $HOME is never a project root, by either the walk-up or the git-root path. And a no-match returns empty with a non-zero status, so callers no-op instead of guessing.
Hooks that spend are opt-in. TESSERAE_HOOK_AUTOCOMPILE=1 enables automatic recompiles; absent, they do nothing. Applied only to the two that actually spend — posttooluse-edit.sh and session-end.sh. session-start.sh runs deterministic code sync and pretooluse-compile.sh only intercepts a compile you typed, so neither is gated.
A hook that backgrounds model work should be switched on deliberately, not switched off after the bill arrives.
The Python CLI never had this bug: ProjectWiki.load() uses the path it is given and does not walk up, so a manual tesserae compile outside a project fails cleanly. The trap was only ever in the shell hooks.
OKF v0.2
Google's Open Knowledge Format v0.2 makes provenance, trust, lifecycle and attestation first-class. Tesserae now emits v0.2 and still consumes v0.1.
Emitted: generated: {by, at} from extractor and agent markers; sources with the credibility signals (usage_count from session counts, usage_window, last_modified, and author only where exactly one authored_by Person exists); status: deprecated and stale_after derived from supersedes edges.
Not emitted: verified, and therefore no trust tier above unverified. Tesserae has no recorded verification event with an actor and a timestamp. Its four provenance classes are edge properties — how strongly the graph licenses a triple — while OKF's trust family is a per-concept verification event. Different axes; mapping one onto the other would launder trust through a spec. Verified over 5,193 real concepts: verified emitted 0 times, generated.by claims human: 0 times.
Three consumer bugs are fixed, all found by importing the spec's Appendix A verbatim through the real CLI, where it previously crashed: unquoted YAML timestamps resolve to datetime and broke serialization; the v0.1 timestamp fallback silently no-opped on that same unquoted form; and §6.1's recommended bundle-relative link (/tables/customers.md) produced zero edges, so a spec-following bundle imported as disconnected nodes.
A validator written from the spec's own clauses passes a 5,193-concept export with zero failures, losslessly and byte-idempotently.
Tautological verdicts are named
About 40% of verify_claim's SUPPORTED verdicts were evidenced_by edges whose cited span is the edge's own target — "C evidenced_by S", confirmed by reading S. True, uninformative, and previously indistinguishable from a genuine document-backed verdict.
The payload now says which it is. Across all 15,284 edges: every evidenced_by SUPPORTED flagged, nothing else flagged, and no verdict changed truth value. Additive, so v0.27.0's seven-verdict contract is unchanged.
Upgrading from v0.27.0
Drop-in for the library. Reinstall the plugin to get the hook fix, and if you want automatic recompiles back, set TESSERAE_HOOK_AUTOCOMPILE=1.
If a stray .tesserae exists at $HOME from an earlier accidental compile, it is now inert — but it is also large, and removing it is safe once you have confirmed your registry and config live elsewhere.