Skip to content

Parse Local-method evaluator code with the session's context state - #255

Closed
rhennigan wants to merge 2 commits into
mainfrom
bugfix/249-bad-global-context-parsing
Closed

rhennigan wants to merge 2 commits into
mainfrom
bugfix/249-bad-global-context-parsing

Conversation

@rhennigan

Copy link
Copy Markdown
Member

Fixes #249.

Problem

With the evaluator's "Method" -> "Local", Chatbook parses the tool's code string in the server kernel and only evaluates it in the sandbox subkernel. The session context (Sessions`<id>`) was only set in the subkernel, so the parse used the server kernel's $Context and $ContextPath:

  • Typed symbols were created in Global`, which every session of the server shares, so definitions leaked between sessions.
  • Names on the server kernel's $ContextPath resolved there (CellToString, StartMCPServer, …).
  • Contexts that the session added with Get/Needs were never used for parsing, so packages could only be called with fully qualified names.
  • Symbols created at run time (ToExpression) went into Sessions`<id>` while typed ones went into Global`.
  • Chatbook's undefined-symbol check (which only looks at Global` symbols) warned about functions defined in earlier calls.

Fix

Before each evaluation under "Local", withSession calls the new syncParseContext (new "Local Parse Context" subsection in Kernel/Tools/WolframLanguageEvaluator.wl):

  1. codeSymbolNames collects the symbol names in the code with CodeParser`CodeConcreteParse (strings, comments, and operators are ignored; qualified and relative names stay whole; code with syntax errors still works).
  2. In the eval subkernel, parseContextInKernel returns the session's $Context, $ContextPath, and $ContextAliases, plus the full name of the symbol each name refers to there, found with ToExpression exactly as the parser would.
  3. Back in the server kernel, those symbols are created (the server kernel may not have loaded the session's packages) and the session's context state is applied for the rest of the call. withSession already scopes these variables with Internal`InheritedBlock, so the state also covers the UI path's output formatting and is restored afterwards.

Applying the context state alone (a Block around the Chatbook call) isn't enough: a context on $ContextPath only helps if its symbols exist in the parsing kernel, so a name from a package that only the session loaded would be created in Sessions`<id>` and shadow the package symbol.

The in-process methods ("Session", "Cloud") are unchanged. Under "Local", the extra subkernel round trip adds about 15 ms per call.

Behavior after the fix matches "Session", including standard Wolfram Language behavior: a context that Needs adds is used for parsing from the next call on, since the whole input is parsed before it is evaluated.

Follow-up

The wolfram-debugging skill on feature/wolfram-debugging-skill describes the old behavior in its passages labeled #249, which need updating once this is merged. WolframDebugging`RunTestsByID's Global` prepend for MCP Local can probably be dropped.

Test plan

  • New unit tests in Tests/EvaluatorSessions.wlt: codeSymbolNames, parseContextInKernel (resolution order, creation of new names, relative/qualified names, invalid names left out), syncParseContext with a stubbed eval kernel, and a no-op check for in-process methods
  • New "Local" integration tests (real sandbox subkernel; skipped if it can't be started): typed symbols in the session context and cross-session isolation, a package loaded with Get plus a Needs alias resolving by short name in later calls, no Symbol::undefined warnings, and the server kernel's context state restored after the call
  • Without the kernel change, the three behavioral integration tests and the unit tests fail
  • EvaluatorSessions.wlt (68/68), WolframLanguageEvaluator-UI.wlt, Tools.wlt, ToolOptions.wlt, MCPRoots.wlt, AgentSkillsBuild.wlt pass; CodeInspector is clean
  • Drove a real dev-mode server (Scripts/StartMCPServer.wls with MCP_TOOL_OPTIONS={"WolframLanguageEvaluator":{"Method":"Local"}}) over stdio with the issue's examples: all now behave as under "Session"
  • CI: the "Local" integration tests need a sandbox subkernel; if CI's license doesn't allow one, they are skipped rather than failed

🤖 Generated with Claude Code

https://claude.ai/code/session_0126WqqLgeZKSK3FkAmUxRpG

rhennigan and others added 2 commits October 8, 2026 15:50
Under the "Local" method, Chatbook parses the tool's code string in the
server kernel and only evaluates it in the sandbox subkernel, so typed
symbols were created in the server kernel's Global` context (shared by
all sessions) and names resolved against the server kernel's packages
instead of the session's.

Before each evaluation, withSession now calls syncParseContext, which
asks the eval subkernel for its $Context, $ContextPath, and
$ContextAliases and for the symbol each short name in the code resolves
to there, creates those symbols in the server kernel, and applies the
same context state for the duration of the call. Packages loaded only in
the session (Get/Needs, including aliases) therefore resolve by short
name, and the false Symbol::undefined warnings for session definitions
disappear. In-process methods are unaffected.

Fixes #249

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126WqqLgeZKSK3FkAmUxRpG
Collect the code's symbol names from CodeParser`CodeConcreteParse instead
of a lexical scan, so words in strings and comments are no longer looked
up and qualified and relative names stay whole. In the eval kernel,
resolve each name with ToExpression, which finds it exactly as the
parser would (creating it in $Context if needed) instead of leaving
names that do not exist yet to the parse in the controlling kernel.
Names that are not valid as written are left out rather than aborting
the sync.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126WqqLgeZKSK3FkAmUxRpG
Copilot AI balanced review requested due to automatic review settings October 8, 2026 16:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-kernel symbol binding still has correctness gaps that require fixes and final human review.

2 open findings
What changed in this PR

Updates AgentTools’ Local evaluator to use session-specific parsing state, addressing #249.

Changes:

  • Synchronizes symbol names and context state from the evaluation subkernel.
  • Adds unit and integration tests for session isolation, package resolution, and context restoration.
File Description
Tests/​EvaluatorSessions.wlt Adds parsing-state and Local-session regression tests.
Kernel/​Tools/​WolframLanguageEvaluator.wl Synchronizes Local parsing with session symbols and contexts.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

(* Full names, so no aliases may apply; Quiet suppresses General::shdw for names that exist in several
contexts here. *)
Block[ { $ContextAliases = <| |> },
Quiet @ Scan[ ToExpression[ #, InputForm, Hold ] &, state[ "Symbols" ] ]
Needs[ "CodeParser`" -> None ];
DeleteDuplicates @ StringReplace[
Cases[ cp`CodeConcreteParse @ code, cp`LeafNode[ Symbol, name_String, _ ] :> name, Infinity ],
esc: ("\\[" ~~ LetterCharacter.. ~~ "]") :> unescapeLetter @ esc
@rhennigan

Copy link
Copy Markdown
Member Author

This was fixed at the source in WolframResearch/Chatbook#1677

@rhennigan rhennigan closed this Oct 8, 2026
@rhennigan
rhennigan deleted the bugfix/249-bad-global-context-parsing branch October 8, 2026 22:00
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.

Evaluator "Local" method parses tool-call code into the shared Global` context instead of the session context

2 participants