Skip to content

Honor sessions_enabled on every surface, and make the MCP schema budget deterministic#559

Merged
tobocop2 merged 2 commits into
mainfrom
fix/sessions-enabled-parity
Jul 18, 2026
Merged

Honor sessions_enabled on every surface, and make the MCP schema budget deterministic#559
tobocop2 merged 2 commits into
mainfrom
fix/sessions-enabled-parity

Conversation

@tobocop2

@tobocop2 tobocop2 commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Problem

sessions_enabled was only honored by the TUI. With sessions off, the MCP tools stayed on the wire and kept writing, the HTTP routes still created and appended, and lilbee sessions still worked.

Separately, the MCP schema budget test measured whatever tools the environment happened to register (wiki_ on cfg.wiki, memory_ on cfg.memory_enabled, crawl on the installed extra). The same commit read 9672 bytes in the docs-site job and 10143 locally, which is why it failed only in Pages and blocked the index deploy.

Solution

Gate the seven MCP tools with _tool_if(sessions_enabled()) plus a body check, matching memory. On HTTP and CLI the check lives in the _store() helper every caller already routes through. Same for the two TUI writes that outlive the toggle (assistant turn, compaction summary).

The budget test now excludes the ambient families and pins the default tool set by name, so an ungated tool fails by name instead of as a byte overflow. Pinned, the default surface including all seven session tools is 8799 bytes, under the original 8800 cap. Ceiling set to 9500 for headroom.

Tests cover the refusal on each surface and assert nothing is written.

tobocop2 added 2 commits July 18, 2026 14:30
sessions_enabled was read only by the TUI. With it off the TUI hid the
drawer and stopped saving, but the seven session MCP tools stayed on the
wire and still wrote session files, the HTTP routes still created and
appended, and lilbee sessions still worked, so "turning sessions off
writes nothing to disk" held on one surface out of four.

Gate the MCP tools with _tool_if(sessions_enabled()) and refuse inside
each body, matching memory exactly: the decorator keeps them off the wire
when sessions are off at import, and the body check covers the flag being
toggled at runtime. On HTTP and CLI the check lives in the _store()
helper every handler and command already routes through, so the
invariant is structural rather than eight or four call sites that can
drift, which is how this was missed the first time.

The schema budget test measured whatever the environment happened to
register. wiki_ depends on cfg.wiki, memory_ on cfg.memory_enabled, and
crawl on whether the crawl4ai extra is installed, so the same commit read
9672 bytes in the docs-site job and 10143 on a developer box. That is why
a schema regression passed every release job and took down the website
deploy instead. Exclude the ambient families, pin the default surface by
name so an ungated tool fails by name rather than as a byte overflow, and
measure only that. Pinned, the default surface including all seven
session tools is 8799 bytes, under the original 8800 cap, so sessions
never actually breached the budget. The ceiling moves to 9500 to replace
one byte of headroom with room for a tool or two.
Blast-radius review found the same runtime-toggle hole this PR closed on
MCP, HTTP, and CLI still open in the TUI. _persist_user_turn returns
early when sessions are off, but by then the session id is already set,
so switching sessions off mid-chat left _persist_assistant_turn and the
compaction summary write appending to a conversation the user had turned
off. Re-check the flag at both sites.

The compaction test initially asserted nothing: it never enabled
chat_compaction, so _compact_history took the free default path and
returned before any fold. It now asserts the fold actually ran and landed
in memory, and only then that nothing reached the disk.

Convert the new MCP and HTTP refusal tests to parametrize, matching the
convention in the rest of the suite and giving one result per surface
rather than stopping at the first failure.
@tobocop2
tobocop2 merged commit 5df287f into main Jul 18, 2026
33 of 34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant