Repository navigation
Preserve bridge replies while requests finish - #264
Merged
Merged
Conversation
The declared Python floor cannot execute Path.write_text with newline. Encode UTF-8 explicitly and write bytes so BOM and CRLF content stay exact on every platform. Replace all 30 unsupported calls, without removing assertions or changing CI work. Validation: Python 3.9.25 full suite passed all 39 files. Python 3.12.14 full 16-step gate passed, including all 39 files, CSharpier and npm pack. Fast check and strict pyright for all nine changed files passed. Whole-tree pyright retains the same 85 baseline diagnostics, tracked on #171. Unity 6000.5 host passed 393 EditMode and 15 PlayMode tests; shipped C# is unchanged. Timing: full gate samples were 26.2 seconds before and 48.1 seconds after, with different concurrent local load; these do not prove a speed change. CI workflow, suite discovery and assertions are unchanged. Iterate with the scoped fast check from the native filesystem checkout. Fixes #257.
Windows can report parent termination before its process handle signals exit. Wait for the bounded terminal result before classifying a partial taskkill error. Force cleanup before reporting a still-live parent, and retain command output plus forced-cleanup errors. The expanded data-driven cleanup regression fails on the old code and passes on the fix, including delayed exit, already-exited and remains-live cases. Preserve the earlier check=True failure simulation. Add forced kill/wait failure and successful-taskkill fallback cases without sleeps. Existing bridge assertions, timeouts and CI workflow are unchanged. Validation: cleanup cases pass on Python 3.9.25 and 3.12.14; strict pyright, scoped fast check, and all 16 whole-tree gate steps pass, including all 39 harness files, CSharpier and npm pack. Unity assembly/test inputs equal main's validated 393 EditMode and 15 PlayMode tree; no Unity behavior changes. Full gate 19.4s is validation, not controlled CI timing proof. Fixes #260.
Project virtual environments add interpreter redirects to the stdlib harness. Run scope, lints and tests through uv without project discovery or managed Python, while enforcing the declared Python floor. Keep setup-uv, every check, suite selection and worker limits. A cold-context regression fails on the old workflow and passes on this change. It supplies incompatible project requirements and a fake dependency, then verifies system-Python execution without a venv or lockfile. The workflow contract reads the interpreter requirement from pyproject.toml so the standalone launch cannot drift from the floor. Validation: strict pyright and fast check pass; all 16 whole-tree gate steps pass, including all 39 harness files, CSharpier and npm pack. Unity source/test inputs are unchanged from main's validated 393 EditMode and 15 PlayMode tree. The 19.7s local gate is not controlled speed evidence. Refs #171.
Credential fixtures wait for the HTTP server's polling loop during shutdown. Set its polling interval to 10ms instead of the default 500ms. Preserve every request, assertion, close operation and test case. Seven direct samples measured median shutdown 500.6ms before and 9.95ms after. Reject the standalone interpreter experiment and restore the workflow and its tests exactly to main. Same-runner standalone medians were Ubuntu +2.5% and Windows -4%, but the Windows candidate had a large outlier; cold full jobs were flat on Ubuntu and slower on Windows. Those results do not support the intended CI-budget improvement. Final diff: two added lines and one removed line in one existing fixture. Strict pyright, fast check and all 16 whole-tree gate steps pass, including all 39 files, CSharpier and npm pack. Full gate 22.6s is uncontrolled validation, not a speed claim. Unity inputs stay identical to validated main. Refs #171.
The measured long bridge suite enters the queue late and adds an I/O tail to full harness runs. Submit it first while retaining four concurrent file workers and stable ordering for every other selected file. Keep all executions, alphabetical output and failure accounting. An event-based regression fails on the old queue and passes when the bridge overlaps the other files. Existing selection, repeated/full-scope, spawn-failure and worker-cap coverage stays intact. Strict pyright, fast check and all 16 whole-tree gate steps pass, including all 39 files, CSharpier and npm pack. The 21.4s local gate is validation rather than controlled timing proof. Revert HTTP polling changes: direct shutdown improved 50x, but the complete credential file and CI workload did not show a consistent gain. Paired polling medians were Ubuntu current +5.1%, original -4%, Windows current -1.8%; original Windows failed baseline sample 3 on the already-fixed crash-recovery assertion. Retain all rejected measurements and do not present a micro-operation as the requested CI speedup. Refs #171.
Windows profiles show archive validation is another long suite queued near the end. Submit both measured long suites first while preserving the four-worker executor and all output/failure semantics. The event regression now requires both long suites to overlap a short file; bridge-only priority fails it. Strict typing, fast check and all 16 whole-tree gate steps pass, including all 39 harness files, CSharpier and npm pack. Harness phase 8.5s; full gate 9.9s. These single local observations need matched timing confirmation. Final base diff remains two files, 39 additions and one deletion; no environment, polling, workflow, dependency or coverage reduction remains. Refs #171.
Starting the bridge early reproduced cold-start failures in Windows CI and the local full suite. Preserve its relative position and all startup assertions. Prioritize only measured long archive validation, overlapping it with other work without changing the four-worker cap. The event regression requires archive overlap and verifies every other submission retains its input order. Existing scope, full-suite, spawn-failure and worker-cap coverage remains. Strict typing, fast check and all 16 whole-tree gate steps pass with all 39 files, CSharpier and npm pack. Harness phase 14.7s and full gate 16.4s are uncontrolled observations, not performance proof. Reject the failed two-priority measurements; do not retry for green. Refs #171.
Matched Linux full-suite samples regressed with archive-first scheduling: median 13.599s to 14.801s. Keep its existing order and apply the archive priority only on Windows, where profiles identify the long archive tail. Preserve every other suite's relative order on Windows. The event-based regression exercises Windows overlap plus unchanged Linux and macOS ordering without weakening any existing check. Strict typing, fast check and all 16 whole-tree gate steps pass with all 39 files, CSharpier and npm pack. Full local gate 19.8s is validation only. Final base diff: two files, 51 additions and one deletion. Refs #171.
Blind early scheduling reproduced cold bridge startup failures. Give the bridge a quiet startup, consume an internal marker after its first successful MCP initialization, then overlap its remaining I/O and archive validation with other files. Keep four workers and every existing assertion and timeout. The event regression proves overlap before completion, retains output while filtering the private marker, preserves repetitions, and releases remaining work after failed, skipped or unlaunchable startup. Existing selections, sorted reporting and failure accounting remain. A real fixture emits readiness at 0.284s and finishes at 6.208s, confirming the early boundary. Strict pyright, fast check and all 16 whole-tree gate steps pass with all 39 files, CSharpier and npm pack. Full gate 20.0s is uncontrolled validation rather than timing proof. Final diff is three existing files, 133 additions and one deletion; no workflow, dependency, sleep or timeout change. Rejected environment/polling/blind-priority trials are retained in prior commits and measurements, not the final behavior. Refs #171.
Linux paired full-workload medians improve about 20%, while Windows shows no benefit. Preserve the existing launch path and queue order on other platforms. Add platform bypass regressions that fail the previous all-platform implementation. The original Windows whole-CI budget remains unresolved. Refs #171
Closing early HTTP replies while the client is still sending its body can reset Windows connections before urllib reads the status. A split-request probe reproduced WinError 10053 on DELETE; the same probe passes 100 request pairs after draining. Send status and payload immediately with exact content lengths, then finish after the request stream ends. Discard request bytes without buffering and preserve Node request timeouts, authorization rules, response bodies and statuses. Apply the same lifecycle to health, missing routes, authorization, DELETE and method rejection. The existing integration case now checks six delayed-body replies and observes that response.end follows request consumption. All six fail against main and pass here without sleeps or retries. Preserve ordinary urllib rejection, notification and parallel-ID assertions; close expected HTTPError responses. Strict typing, actual Python 3.9 auth regression, scoped checks and the full 16-step gate/all39 pass. Fixes #263
This was referenced Oct 16, 2026
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.
DISCLOSURE: LLM-GENERATED TEXT
Why: Closing replies over unread request bodies can reset Windows clients.
What:
Fixes #263
Note
Medium Risk
The bridge HTTP layer and early-route response lifecycle change in ways that affect all MCP clients on Windows; risk is mitigated by broad integration tests but still touches auth and connection handling.
Overview
Fixes #263 by changing how the Unity MCP HTTP bridge answers routes that reject or short-circuit before reading the POST body. A new
sendEarlyResponsehelper writes status, headers, and body immediately, thenresponse.end()only after the client request stream finishes (or ends at once if already drained), so Windows clients are not reset when the server closes over an unread body./healthz, auth failures, 404/405/204, and similar early paths now use that helper; MCP POST handling is unchanged aside from stronger coverage. Integration tests add a drain probe, delayed-body cases across methods/routes, and an abandoning-client check; Windowsstop()handling is tightened around partialtaskkillfailures.On Linux,
run_all.pystartstest_unity_mcp_host.pyfirst, waits for a harness startup marker, then overlaps the rest of the suite (with new self-tests). Elsewhere, many scripts and tests switch fromwrite_text(..., newline="")towrite_bytesso fixture bytes stay stable across platforms.Reviewed by Cursor Bugbot for commit 969b207. Bugbot is set up for automated code reviews on this repo. Configure here.