v0.25.0.md
docs/release-notes/v0.25.0.md
Tesserae v0.25.0 — Descent: navigate any graph inside one context window
<!-- translations:start -->
한국어 · 中文 · 日本語 · Русский · Español · Français · Deutsch
<!-- translations:end -->
Released 2026-07-24 · PyPI · GitHub release · pip install --upgrade tesserae==0.25.0
A compiled project graph outgrows every context window — the reference project now serializes to 2.5M tokens, 12× a 200k window, and it keeps growing. Flat retrieval can find a node, but an agent could never survey the graph: the only bounded overview was the coarsest 47-community summary layer, and everything below it was invisible. This release ships Descent: hierarchy as a query-time contract, so an agent can navigate from a whole-graph overview down to a single node in a handful of bounded calls — at any graph size.
1 · graph_map — one descent tool for every graph
One new MCP tool, graph_map(scope, budget_chars, cursor), turns every knowledge source into the same thing: a scope tree answered with budget-packed cards. No scope returns the root map — graph counts, hub warnings, and the coarsest community cards. A community id descends one dendrogram level; the finest level lists member nodes. agent:<key> renders an agent's distilled L1 index, org:root the agent org tree, and <alias>:: a sibling project's map — same cards, same protocol, no special cases. Every card carries parent_scope, so ascending is just another graph_map call, and oversized levels paginate deterministically (+N more, cursor=K) instead of truncating silently.
2 · The hierarchy was always there — now it's kept
Louvain already computes a full dendrogram every compile; we used one level and threw the rest away. Compile now persists all of it to a .tesserae/hierarchy.json sidecar — 4 levels on the reference graph — as a pure, deterministic function of graph content: fixed seed, canonical ordering, zero LLM calls, at 5k or 1M nodes. graph.json bytes are untouched, full-vs-incremental parity now asserts identical dendrograms at every level, and stale community-summary caches are pruned against all-level liveness.
3 · CTX-01 — no tool response exceeds its budget, ever
A single fit_to_budget helper now clamps every MCP response: per-entry caps, deterministic admission, one continuation line. Tools that could flood a session are fixed — query_decisions and find_session_findings gained limit params, list_communities returns a member-count plus handle instead of thousands of raw ids, search_nodes/node_context/timeline/ search_facts truncate per item. Session cost is now depth × budget — independent of graph size.
4 · Summaries appear where you actually look
Fine-level communities get titles lazily: the first descent into an unsummarized scope makes one LLM call, cached by membership digest; without a client it falls back to a deterministic structural title — never blocking, never raising. Summary-of-summary prompts are citation-validated (prose that cites no child community is rejected), so upper levels can't drift from what they summarize. The daemon's sleep cycle gains a third op, SUMMARIZE, which pre-warms caches for the communities agents actually visit — spending a bounded per-tick LLM budget on demand, not on corpus size.
5 · Hierarchical context compilation
compile_context learns scope=<community> — retrieval restricted to a community's induced subgraph, structurally killing hub explosion — and strategy="hierarchical": match the summary layer first, descend the matched branches, then run PPR inside them. The PPR projection gains a flagged degree-cap and provenance-edge downweight to defang mega-hubs. Default paths stay byte-identical; both features are opt-in until A/B'd.
Upgrade
pip install --upgrade tesserae==0.25.0
Recompile once to write the hierarchy sidecar, then ask your agent to call graph_map() — the whole graph, one bounded page at a time.