v0.28.3.md
docs/release-notes/v0.28.3.md
Tesserae v0.28.3 — the extractor's one-turn cap, and what it silently cost
<!-- translations:start -->
한국어 · 中文 · 日本語 · Русский · Español · Français · Deutsch
<!-- translations:end -->
Released 2026-07-31 · PyPI · GitHub release · pip install --upgrade tesserae==0.28.3
One flag. It had been in the Claude extractor since the first pipeline commit, and on a machine with MCP servers configured it stopped LLM extraction from working at all — without failing the compile.
--max-turns 1 was never a decision
Both Claude-CLI call sites spawned:
claude -p --output-format text --max-turns 1
--max-turns counts tool calls, not replies. If the CLI's config dir has MCP servers or hooks, the model's first move can be a tool call — which spends the only turn. The CLI then exits 1 with Reached max turns (1) before emitting a single byte of JSON.
Tesserae catches that and falls back to deterministic extraction, because a provider failure should never abort a compile. So the compile succeeded, the graph looked plausible, and the LLM contributed nothing.
The flag was never chosen. It arrived with the original pipeline commit, and ClaudeCLIJsonClient copied it verbatim three months later because its docstring says it "mirrors the pattern in run_claude_cli". No commit message mentions it.
--strict-mcp-config is what one-shot actually means
The intent behind the cap was "answer once, don't run an agent loop." The correct expression of that is to load no MCP servers, so there is no tool to spend a turn on:
claude -p --output-format text --strict-mcp-config
The model's first reply is the answer, and a configured MCP server can no longer starve the call. Both call sites are fixed, and a regression test asserts the turn cap stays gone from each.
Check whether this cost you a graph
The failure is invisible in the compile summary — it lives only in the log:
grep -c 'Reached max turns' <your compile log>
Anything above zero means those files were extracted deterministically, and a recompile on this version will recover them. On this project's own graph, restoring genuine LLM extraction took it from 5,155 nodes to 13,182 — the deterministic fallback had been costing roughly 60% of the graph.
That the compile reports success while losing LLM extraction on most of its files is a separate defect, tracked in #92 and not fixed here. This release removes one cause of the silent fallback, not the silence.
Upgrading from v0.28.2
Drop-in. No API, schema, or config change. If your previous compiles were affected, recompile to pick up the extraction you were missing — cached LLM responses in ~/.tesserae/llm_cache are reused, so only the files that fell back cost anything.