Repository navigation
fix: close out #1025 step 2 — the 2026-07-28 era on the packaged artifacts, a 2025-era backend on request, three leftover fixes - #1126
Merged
Conversation
…ue (#1025) The three HTTP reaper parsers quoted the rejected environment value in their warning, so a secret pasted into the wrong variable, or a value with a line break, reached the server log. They now name the variable and the default in force, the rule the idle-policy parser already follows. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
#1025) A session the idle policy removed with nothing running in it (never launched, or its program already over) was recorded as "its program was ended", or as "released ... keeps running" under an attach root. The record gains a third outcome, closed, and the answer says "It had no running program by then." Which sessions those are is read when the policy decides to close the tree: a child that ends while the cascade is running was alive at the decision and stays "ended". A child an earlier detach released stays "released". The sentence also states the idle time in the unit of the window. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…the backend (#1025) The proxy negotiates the era with its backend, so against a current backend it always lands on 2026-07-28 and nothing driven through it exercises the 2025 era most clients still speak. DEV_PROXY_BACKEND_ERA is auto (default, negotiate) or legacy (open with initialize); any other value refuses to start, naming the variable and not the value. Also cites modelcontextprotocol/typescript-sdk#3133 beside the BackendStdioTransport workaround it explains. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…rotocol 2026-07-28 (#1025) The packaged-artifact smokes only ever spoke the 2025 era. The Docker and npx helpers take protocol: 'modern', which pins the SDK client to 2026-07-28 over a transport subclass (the base class probes on a sibling process, a second docker run with the same name); one new Python case in each proves discover, the full tool list and a breakpoint cycle. The existing cases stay on the 2025 era. canary-smoke.mjs gains --era 2026-07-28 (server/discover, then the same cycle with the per-request envelope) and canary.yml one such Python cycle per channel, gated on the artifact's own version by canary-era-gate.mjs: skipped with a notice before 0.27.0, strict from it, prereleases included; an unreadable version is a usage error. Measured: the 2026 cycle fails on the published 0.26.0 (-32601) and passes on this tree's build and image; the 2025 cycle passes on both. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ee survey corrections (#1025) The restart_debugging description said "Not available for attach sessions"; a Flutter session hot-restarts in place, attached or not (24 tool-list snapshots move by that sentence). session-tree.md: M2 PR 2 merged as #1096; the Ruby and CodeLLDB survey rows say where a re-read of the engine's source disagrees with them (the debug gem's accept serves the inherited socket first; CodeLLDB 1.12 has codelldb.start_debugging). Both unmeasured. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… image leg can false-fail (#1025) Review follow-ups, no behaviour change: a launch root that had already ended while its child still runs records the root as closed and the child as ended; a comment says a detached attach root reads closed beside its released children; the canary's image step notes the one window in which a scheduled run can read the new version for the old image. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Read the Docker artifact version from its synchronized shared package, not npm's independently moving dist-tag. Allow successful pending launches to reach their breakpoint through wait_for_stop before inspecting locals. Add regression cases for immediate, delayed, timed-out and exited launches.
debugmcpdev
commented
Nov 11, 2026
debugmcpdev
left a comment
Collaborator
Author
There was a problem hiding this comment.
Reviewed the full diff and the surrounding idle-session close cascade. Fixed two test reliability findings in e5e39e7:
- The Docker canary queried npm's mutable dist-tag to classify an already-pulled Docker image. During publication those versions can differ. It now reads the synchronized shared-package version from that image, with the workflow assertion updated.
- The modern artifact smoke required start_debugging to return paused immediately, although a successful launch may return running with pending:true. It now uses a bounded wait_for_stop before reading locals. Regression tests cover immediate and delayed stops, timeout, and early exit, including cleanup on failure.
A dependency-free harness reproduced the delayed-stop failure before the fix and verified the corrected success/failure paths. Local cloning was unavailable due to a network error, so full repository validation is being performed by CI on this exact commit. Lint/typechecks, both MCP conformance lanes, CodeQL, and Go/Dart/Flutter/COBOL jobs have passed; the main Windows/Linux and container suites are still running. No other actionable findings from the review.
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.
Closes out #1025 step 2 after the five-PR stack merged (#1114–#1118). Nothing here changes how a debug session behaves; it finishes what the issue's own "done when" still asked for, fixes three siblings of the bugs fixed during the merge, and corrects what the docs and one tool description said.
Why
tests/e2e/docker,tests/e2e/npxor the canary spoke 2026-07-28 to a packaged server./testdebuggerand/testpublishedpass would exercise only the new era, while most clients will still speak 2025-11-25 to 0.27.f1338709stopped the idle-policy parser from logging a rejected environment value; the threeMCP_HTTP_*parsers still did.91a7e7f8made the idle-expiry outcome per session; the outcome was still wrong for a session with nothing running.What changes
The 2026-07-28 era on the packaged artifacts
createDockerMcpClientandcreateNpxMcpClienttakeprotocol: 'legacy' | 'modern'.modernpins the SDK client to 2026-07-28 over a transport subclass: for its exact base stdio transport the SDK probes on a sibling process spawned from the same parameters, which here would be a seconddocker run --name <same>.docker-smoke-pythonandnpx-smoke-python: the artifact answersserver/discover, lists all 29 tools, and runs a Python breakpoint cycle with no MCP session behind it. The existing cases are untouched and stay on the 2025 era.scripts/canary-smoke.mjsis a raw JSON-RPC client that opens withinitialize; that stays.--era 2026-07-28runs the same cycle opened withserver/discover, each request carrying its envelope.canary.ymladds one such Python cycle per channel (npm, Docker), gated by the artifact's own version throughscripts/canary-era-gate.mjs: skipped with a notice before 0.27.0, strict from 0.27.0, prereleases included — so the beta rehearsal runs the leg the final is waiting on. A version the gate cannot read is a usage error, never a skip. The Docker leg reads the synchronized shared-package version inside the pulled image, so npm and Docker dist-tags moving at different times cannot misclassify it.DEV_PROXY_BACKEND_ERAauto(default) negotiates as today;legacyopens withinitialize, so a sweep through the proxy can exercise the 2025 era against a server that serves both. Any other value refuses to start, naming the variable.dev_server_statusalready shows the era in force.Fixes
MCP_HTTP_*warnings name the rejected setting and the default in force, not the value (the rule off1338709).closed. A session the policy removes that had no running program — never launched, or already over — used to be recorded as "its program was ended", or as "released … keeps running" under an attach root. It now answers "It had no running program by then." The set is read when the policy decides, so a child that ends during the cascade is stillended, as91a7e7f8pinned. A child an earlier detach released staysreleased. The sentence also states the idle time in the window's unit.restart_debuggingdescription said "Not available for attach sessions". A Flutter session hot-restarts in place, attached or not; the description now says so (24 tool-list snapshots move by that one sentence).Provenance and docs
BackendStdioTransportcites [v2] Client.connect():signalis ignored during the server/discover probe modelcontextprotocol/typescript-sdk#3133, which reports the ignoredconnect()signal this class works around; the abort handling goes when a release carries the fix.docs/architecture/session-tree.md: M2 PR 2 is merged (feat(javascript): enable child debugging for launches and local attaches #1096); the Ruby and CodeLLDB survey rows now say where a re-read of each engine's source disagrees with them (unmeasured in both cases — spike: rdbg forked children — does the debug gem's child server become reachable, and can a second connection debug it (session tree, Ruby, Linux) #1085 for Ruby).Evidence
tests/e2e/npx/npx-smoke-python.test.tstests/e2e/docker/docker-smoke-python.test.ts--era 2026-07-28-32601 Method not found— the leg can fail--artifact-version 0.26.0--artifact-version 0.27.0-beta.1--artifact-version latestEvery behaviour change was written test-first; the red runs failed at the assertion they were written for.
Calls I made
closedoutcome is decided when the policy decides, not at each session's own close. The plan said per-close. Per-close would have turned91a7e7f8's "a child that ends while an earlier close waits isended" intoclosed; that child was running when the policy came for the tree.DEV_PROXY_BACKEND_ERAerror does not quote the value, unlike its two neighbours inbackend-env.mjs, which do and are pinned to. I followed the newer rule for new code and left the neighbours alone.changelog.d/1025-idle-policy.added.mdwas amended rather than afixedfragment added: the policy is unreleased, so no reader ever saw the old wording.Review
One independent review of the whole diff before the push: no critical or important findings, five minor.
8d21f7a2): a test for the mixed tree (a launch root that had already ended, its child still running:closedandended); a comment that a detached attach root readsclosedbeside itsreleasedchildren.e5e39e7): the Docker canary reads the version from the pulled image rather than the npm registry, removing the publication race; the modern artifact smoke accepts a successfulpending:truelaunch and uses a boundedwait_for_stopbefore reading locals. Regression cases cover immediate and delayed stops, timeout, and early exit.server-tool-list-snapshot.test.tsalready pins thattools/listis inTOOL_NAMESorder).The reviewer had no shell, so it read the tests and did not run them; the runs in the table above are mine.
Not in this PR
docs/tool-reference.mdlacks C/C++, COBOL and Dart rows; filling it needs a VS Code measurement.trackAll()in the proxy's subscription relay still mutates state outside the queue. It is reachable only as the front client leaves, when the proxy exits.🤖 Generated with Claude Code