Repository navigation
fix: using declarations stay statements, snippet threads stop with their run, host cap for timeoutMs - #9
Merged
Conversation
…eir run, host cap for timeoutMs - C#: a top-level using declaration (`using var x = ...;`, `using T x = ...;`, `await using ...`) was parsed as a using directive in script code (CS1002/CS0825/CS0103). It is now a statement wherever it stands; `using X;`, `using static`, `using unsafe`, aliases and `global using` stay directives. `global using` goes before the runtime's usings (CS8915 before). - C#: delegates handed to new Thread / ThreadPool.QueueUserWorkItem / Task.Run / TaskFactory.StartNew / new Task are wrapped so the work belongs to the run and stops at its next guard check once the run has ended. A thread entry swallows the stop: before, a time stop on a snippet's thread was an unhandled exception that ended a CoreCLR host. A warning reports unfinished work; a budget spent in work the snippet waited for is a Timeout. - Python: threads the snippet starts are stopped when it ends (async exception while they run the agent's code), threading.Timer not fired yet is cancelled, a warning counts them. - Both: hosts can cap timeoutMs (CodeRunnerOptions.MaxTimeoutMs, code_exec.set_max_timeout_ms); spec recommends exposing a timeout argument with a ~30 s default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rd's nested closures from stack traces Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C# - Work carries its run in a thread-static while synchronous and in an AsyncLocal only for asynchronous task work, so timers and async void continuations started from a worker no longer inherit it (an orphan stop there ended the process). - Asynchronous task work stays pending until its task ends; End turns on orphan checks whenever the run started work (fenced against Spawn), so a continuation after the run ended is stopped and reported. - Thread entries (Worker) swallow stops, task entries (TaskWorker) fault: a void task no longer completes after a stop. - A stack stop in a thread the snippet waited for is a Runtime error, not success. - Using declarations: a keyword after `using` or a type with two names in a row is no declaration; a detected declaration that does not become a statement keeps its `using` (re-parse), so invalid code keeps its own error. Python - One Thread.start dispatcher installed while any snippet runs (nested runs on snippet threads restore correctly); the runner's own threads start untracked; stop() never raises and runs after flushing logs. - A stop is raised only while the agent's code is the running frame, never once the thread is leaving; cancelled timers are not counted; a thread started twice is tracked once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Local only once async task work ran After a run that started work, a reused (Mono) assembly paid a thread-static or AsyncLocal read on every clock check: fib(27) went from 1.5 ms to 2.8 ms. Now the check is skipped while no work of any run is executing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unwrapped continuations carry the run) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes from wave-6 testing (Godot/DeepSeek). No release, no version bump, no workflow changes.
1.
using var x = ...;as a snippet statement (C#)Script parsing took a top-level using declaration for a using directive (CS1002/CS0825/CS0103), also as the first line.
SnippetWriternow finds top-level[await] usingdeclarations by token scan (Type name =afterusing), blanks thekeywords before parsing (positions stay) and writes the agent's own text back.
using X;,using static,using unsafe,aliases and
global usingstay directives; invalid forms keep their own error.global usingnow goes before theruntime's usings (was CS8915).
2. Threads and tasks a snippet starts stop with their run
new Thread,ThreadPool.(Unsafe)QueueUserWorkItem,Task.Run,TaskFactory.StartNew,new Taskarewrapped (
Worker/TaskWorker, cast to the delegate type they already convert to, so overloads stay). The work belongs tothe run, including asynchronous task work across awaits and the threads and tasks it starts in turn. After the run it
stops at its next guard check. Thread entries swallow the stop, tasks fault. Found on the way: before this change, a timeout stop on a
thread the snippet started was an unhandled exception that ended a CoreCLR host (test
StoppedThreadsNeverEndTheProcess).A warning reports unfinished work. A stop in work the snippet waited for is a
TimeoutorRuntimeerror.Thread.startdispatcherinstalled only while a snippet runs. At the end, timers not yet fired are cancelled. Other threads get
SnippetThreadStopped(async exception) while the agent's code is their running frame. A warning counts them.async voidcode after its first await, waits and host calls, native threads,_thread.start_new_thread.3. Timeout ergonomics
Hosts can cap
timeoutMs: C#CodeRunnerOptions.MaxTimeoutMs, Pythoncode_exec.set_max_timeout_ms. A longer budget, or none,becomes the cap. The spec recommends exposing
timeoutMsas atimeouttool argument, with a default of about 30 s and a capbelow the tool timeout.
Quality stages
simplify:9ddee5ecode review:4f833a0 (three reviewers: using/SnippetWriter, C# thread guard, Python threads)perf:3d6659b, reviewed afterwards; that review's fix iscode review:d5a812dOverhead
Task.Run(1.0–1.4 µs unguarded); thread start is unchanged within noise.Local verification
ROSLYN_VERSIONS="3.8.0 5.9.0" scripts/test-all.shis green: net8/net10 267 tests, SourceConsumer, pack + consumer, Python 60.🤖 Generated with Claude Code