Skip to content

test(windows): guard clean MCP stdio startup - #2952

Merged
DeusData merged 1 commit into
mainfrom
distill/2217-windows-mcp-stdio-guard
Nov 11, 2026
Merged

DeusData merged 1 commit into
mainfrom
distill/2217-windows-mcp-stdio-guard

Conversation

@DeusData

Copy link
Copy Markdown
Owner

What does this PR do?

Adds a native Windows regression guard for #654: a successful MCP initialize + tools/list exchange, run against an isolated cache and runtime directory, must leave nothing on stderr except the server's own structured log lines.

  • tests/windows/test_mcp_stdio.py (new): the guard.
    • The English and Spanish "path not found" messages reported in [Windows] MCP stdio startup emits localized path-not-found message on stderr #654 are named cases, so a red run says exactly which known leak came back.
    • Any other non-empty stderr line that is not a structured level=<name> msg=<event> record fails as well, so the same leak on a Windows machine in any other language is caught without listing its translation.
    • The log format is pinned to text (CBM_LOG_FORMAT=text), so an inherited JSON setting cannot change the verdict.
    • Cache and runtime live under one temp root, so both are removed together, also when the run fails, after the daemon is stopped.
  • tests/windows/mcp_stdio.py: close() joins the stderr reader, and the new stderr_complete() reports whether the reader reached EOF. The guard reads stderr only after it has. A reader still running after the server exited is a SETUP result (exit 2), never a verdict on a partial capture; the wait there is a liveness backstop only and never decides pass or fail.
  • scripts/test-windows.ps1: registers the guard in the green guard list and documents it in the header.

Evidence

  • Hosted CI: the Windows guards job runs this guard on this PR (the change selects that lane).
  • Pending before merge: a run on our local Windows 11 ARM64 machine with a native build of this branch on current main, covering the guard list, a .cmd wrapper that prints the Spanish message (expected red), a German-message wrapper (expected red only with the raw-line rule), a wrapper that keeps stderr held open (expected SETUP), and a cleanup check with an exception injected after initialize (no cbm-mcp-stdio-* directory left). The results will be posted here.
  • Locally on macOS: the stderr classifier puts the Spanish and English lines into their named cases and a German line, a JSON line and a bare level=info into the raw-line case, and a clean log yields nothing; stderr_complete() is false while a background child holds stderr open and true once it is released (driven through a FIFO, so the result does not depend on timing).

Credit

Distilled from #2217 by @lorenzozanee, with the cleanup by @Shinken009 (both Co-authored-by on the commit); the original could not merge because its commit has no DCO sign-off, which only the author can add. #2213 was an earlier duplicate of the same check.

Refs #654

Checklist

  • Every commit is signed off (git commit -s)
  • Tests pass locally (Windows run pending, see Evidence)
  • Lint passes (no C sources changed; the PowerShell file stays pure ASCII)
  • New behavior is covered by a test (the guard itself)

Adds a native Windows guard for #654: a successful MCP initialize +
tools/list exchange, run against an isolated cache and runtime directory,
must leave nothing on stderr but the server's own structured log lines.

- tests/windows/test_mcp_stdio.py: the guard. The English and Spanish
  path-not-found messages reported in #654 are named cases; any other
  non-empty stderr line that is not a structured "level=<name> msg=<event>"
  record fails as well, so the same leak on a machine in another language
  is caught without listing its translation. The log format is pinned to
  text so an inherited CBM_LOG_FORMAT=json cannot change the verdict. Cache
  and runtime live under one temp root, so both are removed with it, also
  on failure, after the daemon is stopped.
- tests/windows/mcp_stdio.py: close() joins the stderr reader, and the new
  stderr_complete() reports whether the reader reached EOF. The guard reads
  stderr only after it has; a reader still running after the server exited
  is a SETUP failure (exit 2), never a verdict on a partial capture.
- scripts/test-windows.ps1: registers the guard in the green guard list
  and documents it in the header.

#2213 was an earlier duplicate of the same check.

Refs #654.

Distilled from #2217.

Co-authored-by: lorenzozanee <[email protected]>
Co-authored-by: Shinken009 <[email protected]>
Signed-off-by: Martin Vogel <[email protected]>
@DeusData
DeusData merged commit ff812bf into main Nov 11, 2026
36 checks passed
DeusData added a commit to htarnacki/codebase-memory-mcp that referenced this pull request Nov 12, 2026
Bring DeusData#2360 up to date with main b3ec08d (DeusData#2427 registry test verdict,
DeusData#2962 MSan CI, DeusData#2952 Windows stdio guard). The merge is clean and needs
no follow-up edit: DeusData#2360's code makes no cbm_registry_add* call and never
used is_test_qn, and Scala definitions register through the shared
seeders in pass_definitions.c, pass_parallel.c and pipeline_incremental.c,
which DeusData#2427 already passes the extractor verdict through for every
language. The branch's own change against main is byte-identical to
28948f2's against f5d5746.

Signed-off-by: Martin Vogel <[email protected]>
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