Files
pad/.github
xarmian e776a64fcd chore(deps): bump libopenapi to 0.40.1; hold mcp-go at 1.1.0 (TASK-3298) (#1656)
* chore(deps): bump libopenapi to 0.40.1; hold mcp-go at 1.1.0 (TASK-3298)

Replaces dependabot #1635, which also moved mcp-go 1.1.0 -> 1.1.1.
That release (upstream #977) makes StdioServer.Listen cancel every
in-flight request's context when it reads stdin EOF. For `pad mcp serve`
fed a piped batch, each dispatcher-backed tool call and resource read
then answers `context canceled` instead of its result (measured: 3 of
4 ids failed on a build of #1635, 0 of 4 on main).

- go.mod/go.sum: pb33f/libopenapi 0.38.7 -> 0.40.1 (pulls
  pb33f/jsonpath 0.8.2 -> 0.8.3). Identical to #1635's change minus
  mcp-go.
- .github/dependabot.yml: ignore mcp-go 1.1.1 only, not the dependency.
- internal/mcp/stdio_eof_inflight_test.go: pins the behaviour. Three
  tool calls and one resource read are held inside a blocking
  dispatcher/fetcher, stdin is closed while all four are in flight,
  then they are released and every id must answer successfully.
  Passes 3/3 on mcp-go 1.1.0 and fails 3/3 on 1.1.1 (all four ids
  "context canceled"), run via a scratch -modfile.

Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9

* test(mcp): release held calls on observed EOF, not a sleep (TASK-3298)

Codex round 1 on df883744 (P2): a server that serves resources/read on
the read loop, as mcp-go 1.1.0 does, cannot read EOF while the held
fetch blocks it, so the 300ms sleep released everything before EOF was
processed. A version that kept read-loop serving but cancelled at EOF
would have passed.

The pin now wraps stdin in a reader that signals when the server's own
read returns io.EOF. Tool calls are released only after that signal
(+200ms, so a cancel-at-EOF server cancels before the release can win).
The resource read is released on the same signal, or after a 1s
fallback when it blocks the read loop; EOF cannot cancel it in that
shape. t.Cleanup now frees held calls and both pipes on a failure path.

Controls, one run each, same tree:
- mcp-go 1.1.0: PASS 5/5 under -race (1.2s each: the fallback path).
- mcp-go 1.1.1: FAIL 3/3 under -race, all four ids "context canceled"
  (0.21s: the EOF-observed path).
- mutant (1.1.0 patched to cancel at EOF, read-loop serving kept):
  FAIL 3/3, ids 10-12 "context canceled", id 20 answered. The previous
  version of this test PASSED 5/5 against the same mutant.

Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9

* test(mcp): widen the EOF settle and state the pin's two bounds (TASK-3298)

Codex round 2 on 5889ff62 (P2): the EOF signal fires inside Read, before
the server handles EOF, so the release after it is a timed settle. A
cancel-at-EOF server delayed past it would pass. Nothing observable
separates "EOF handled" from "server never cancels", so the ordering
cannot be made exact from outside mcp-go. The settle goes from 200ms to
500ms, and the comment now states the bound: the error runs one way
only, and a server that keeps in-flight calls alive can never be failed
by it.

The same round's table found that a server running tool calls on the read
loop fails the entry gate instead of exercising EOF. The comment now names
that too: it means the pin's premise changed, not that EOF cancelled.

Controls under -race, same tree: mcp-go 1.1.0 PASS 3/3; 1.1.1 FAIL 3/3;
the cancel-at-EOF mutant with read-loop serving FAIL 3/3.

Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9

* test(mcp): assert held calls saw no cancellation, not only the responses (TASK-3298)

Codex round 3 on 6e1d2685 (P2): once the release channel is closed, a
select does not prefer an already-cancelled ctx.Done, so a handler on a
cancel-at-EOF server could take the release branch and answer success.
Its population answer adds a second false-pass path: a server that
cancels contexts yet still returns successful responses.

Both handlers now read ctx.Err() after the select, whichever branch
ran, and count a cancelled return. The test asserts that count is zero,
a channel the JSON-RPC responses cannot mask. The entry-gate bound in
the comment now names the whole population codex gave: tool calls on
the read loop, fewer than three concurrent tool workers, or requests
no longer reaching the injected handlers.

Controls under -race: mcp-go 1.1.0 PASS 3/3; 1.1.1 FAIL 2/2 with
"4 held call(s) returned with a cancelled context"; the cancel-at-EOF
mutant FAIL 2/2 with 3 (its resource read returns before EOF).

Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9
2026-09-29 09:29:28 -04:00
..
2026-03-26 01:52:36 +00:00