11.4 KB · updated 2026-07-06 · md

v0.4.0.md

docs/release-notes/v0.4.0.md

Tesserae v0.4.0 — Extraction-feedback loop, research mode, evolution on by default

<!-- translations:start -->

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

<!-- translations:end -->

Released 2026-05-26 · PyPI · GitHub release · pip install --upgrade tesserae==0.4.0

Tesserae 0.4.0 turns the knowledge base into something the user can correct, grow, and trust by default. The headline is an extraction-feedback loop: corrections the user makes in the Obsidian vault are collected as typed FeedbackEvents, clustered into LLM-phrased guidance, and fed back into the next extraction so the engine stops making the same mistake. Alongside it ships research mode (tesserae project research) — a dzhng-style agentic plan → search → reflect → synthesize loop that mints typed OpenQuestion / SessionHypothesis nodes so a research thread survives across compiles. Two evolution passes that were opt-in in v0.3.0 — community summaries and the prose-to-code discusses linker — are now on by default, and the LLM backend gets a batch of robustness fixes (auto-discovery of ~/.claude* credentials, graceful handling when the Claude CLI is not logged in). All additive, no breaking changes.

Table of contents:

  1. Extraction-feedback loop (feature E)
  2. MD0 — agentic research mode (feature G)
  3. Evolution on by default — community + insight-link
  4. LLM-backend robustness + graph-view groundwork
  5. Upgrading from v0.3.0
  6. Strategic context

1. Extraction-feedback loop (feature E)

What it is

A closed correction loop between the user and the extractor. When you edit a node body in the Obsidian vault — fix a wrong type, delete a hallucinated fact, reword a garbled insight — Tesserae's vault overlay records the edit as a typed FeedbackEvent in a deduped JSONL store. Those events are clustered, an LLM phrases each cluster into a short piece of extraction guidance (with a negative filter so noise doesn't become a rule), and that guidance is sliced and injected into the prompt on the next compile. The net effect: a correction made once stops recurring, instead of having to be re-applied after every re-extract.

The loop has four moving parts:

PartRole
FeedbackEvent model + JSONL storeDurable, deduplicated record of every correction.
Vault-overlay adapterCollects correction events while back-syncing the Obsidian vault.
Guidance build (cluster + LLM-phrase)Turns raw corrections into cached, reusable guidance, with fallback and a negative filter.
Guidance render / parse / sliceRenders guidance to markdown, parses it back, and slices the relevant portion into each extraction prompt.

How to use

The loop is wired into the normal vault round-trip. Edit nodes in Obsidian, run an obsidian-sync (or the refresh chain), and the corrections are collected automatically. On the next tesserae project compile, the accumulated guidance is in play.

# 1. Edit node bodies in the Obsidian vault (fix types, prune hallucinations)
# 2. Sync the vault back — corrections are collected as FeedbackEvents
tesserae project obsidian-sync

# 3. Re-compile — the clustered guidance is injected into extraction
tesserae project compile

When to enable

  • You curate the vault by hand and are tired of the same extraction mistake reappearing after every compile.
  • Your corpus has domain-specific phrasing the generic extractor keeps mistyping — a few corrections teach it your conventions.

Where it lives

Core implementation: tesserae/feedback/ (the FeedbackEvent model, JSONL store, guidance build/render/parse/slice) and the vault-overlay collection path. Design spec and the 7-task TDD plan were brainstormed with Codex and merged in PR #20.

Caveats

  • The deterministic baseline extractor still honors guidance only through the LLM path; with the LLM backend off, corrections are recorded but not yet re-injected. (Honoring guidance on the deterministic path is tracked as later work.)
  • Guidance is cached; a large change in your correction patterns may take a compile or two to fully reflect as clusters re-form.

2. tesserae project research — agentic research mode (feature G)

What it is

A new tesserae project research <query> subcommand that runs a breadth/depth-bounded plan → search → reflect → synthesize loop against the compiled graph and writes a cited markdown report to .tesserae/research/<slug>.md. It is modeled on the dzhng deep-research pattern but grounded in your own knowledge base rather than the open web.

Crucially, the loop mints typed nodes and edges as it goes, so a subsequent compile can recover the research thread:

  • one OpenQuestion per sub-question (with metadata.parent_question_id for follow-ups and derived_from edges),
  • one SessionHypothesis per LLM-generated hypothesis, with references edges to the evidence node ids it drew on,
  • and (when a WebFetcher backend is wired) one SourceDocument per web result.

All backends are injected via Protocols, so the loop is fully deterministic under test and never touches the network unless you wire a fetcher.

How to use

tesserae project research "How does our retrieval stack rank candidates?"
# → writes .tesserae/research/how-does-our-retrieval-stack-rank-candidates.md
#   and mints OpenQuestion / SessionHypothesis nodes recoverable on next compile

Web search is intentionally punted in v1: --no-web is a forward-compatible no-op until a WebFetcher backend ships.

When to enable

  • You want a cited synthesis over your own graph, not a single-node lookup or a flat ask answer.
  • You want research questions and hypotheses to persist as graph nodes so future sessions build on them instead of re-asking.

Where it lives

Core implementation: tesserae/research/ (reuses LLMJsonClient, LLMWikiMCPServer.search_nodes, ResearchGraphBuilder, and stable_id). CLI wiring: the research subparser in tesserae/cli.py. Twelve tests cover plan/search/reflect/synthesize, graph wiring, max_iters capping, and planner/synth failure fallbacks. Merged in PR #18.

Caveats

  • v1 synthesizes only over the local graph; the web tier is a forward-compat no-op until a fetcher backend lands.
  • Atomic disk writes use the PID + random tmp-suffix pattern from batch._write_manifest, so concurrent research runs don't collide.

Two passes that were opt-in in v0.3.0 are now default-on, so the out-of-the-box graph is richer without extra flags:

  • Community summaries (PR #14) — Louvain community detection plus LLM summaries now run in the default compile instead of being gated behind a flag. The graph ships with cluster-level overviews by default.
  • Prose-to-code discusses linker (PR #13) — the v0.3.0 feature-H insight-symbol linker (TESSERAE_INSIGHT_SYMBOL_LINK) is on by default in v0.4.0, so session findings are linked to the code symbols they mention without you having to set the environment variable. (You can still disable it explicitly if your corpus is mostly prose with little code discussion.)

The intent is that a first compile produces a graph that already has community overviews and prose-to-code edges, matching the "self-improving base, ready to hand to agents" mission instead of requiring the user to discover and toggle each pass.


4. LLM-backend robustness + graph-view groundwork

A batch of reliability fixes to the LLM backend, plus a spec for the upcoming graph view:

  • Auto-discover ~/.claude* credentials (PR #19) — the default LLM path now finds Claude credentials across ~/.claude* directories and populates the environment for the default backend, so first-run setup is less fiddly across multi-account machines.
  • Graceful "Claude CLI not logged in" (PR #17) — when the Claude CLI is installed but not authenticated, Tesserae degrades cleanly with an actionable message instead of crashing mid-compile.
  • PostToolUse sync-code hook (PR #15) — complements the v0.3.0 SessionStart sync-code hook so the code graph also refreshes after tool edits within a session.
  • Graph-view v1 spec — the design that ports the HypePaper encoding and a node drawer into Tesserae's site was brainstormed with Codex and landed as spec + plan, setting up the visual graph work that follows.

Upgrading from v0.3.0

pip install --upgrade tesserae==0.4.0

That's the whole upgrade — v0.4.0 is additive with no breaking changes. The one behavior change to be aware of is that community summaries and the prose-to-code discusses linker now run by default; if you previously relied on them being off, disable them explicitly.

New CLI subcommand to add to your muscle memory:

tesserae project research "<question>"   # agentic plan→search→reflect→synthesize over your graph

Behavior now on by default (previously opt-in):

  • Community summaries (Louvain + LLM).
  • Prose-to-code discusses edges (the v0.3.0 TESSERAE_INSIGHT_SYMBOL_LINK pass).

Everything else — graph_ppr, hybrid search_nodes, sync-code, the live SessionStart hook, embedding_status, fresh_insights, decay scoring, supersedes, schema-drift, slash commands, the wiki / Obsidian projection — is unchanged from v0.3.0.


Strategic context

v0.3.0 connected prose decisions to the code symbols that implement them. v0.4.0 is the release where the base starts correcting and growing itself: the extraction-feedback loop closes the gap between "the user fixed it once" and "the extractor learns it," and research mode lets the agent grow the graph with its own typed questions and hypotheses rather than only ingesting what already exists. Turning community summaries and the discusses linker on by default is the same theme from the product side — the engine should hand agents a rich base without making the user hunt for flags.

This is the bridge release. v0.3.0 proved the typed prose-to-code graph; v0.5.0 turns the whole thing into a continuously-running engine with an on-demand context compiler. v0.4.0 is where the self-improving pillar gets its first real surface (feedback corrections, agentic research threads) ahead of the v0.5.0 spine that makes it all run continuously.

See also: