Skip to content

feat(mcp): resolve room-scoped servers during owned Codex startup - #797

Open
bandzalkin wants to merge 2 commits into
mainfrom
feat/codex-owned-mcp-resolver
Open

bandzalkin wants to merge 2 commits into
mainfrom
feat/codex-owned-mcp-resolver

Conversation

@bandzalkin

@bandzalkin bandzalkin commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Rebased onto main d7ab3429cbdb (2026-10-15)

Rebased onto current main (after #709, #804, #789/#775, #796 and #802) as one commit; head e38e7ffb63dfd2daeeb415c9da3a6550d8ef9ed0. Integrated into #709's retained acquisition/release instead of restoring the removed lifecycle bookkeeping; shared core/retention and turn_lifecycle gain the cancellation-settlement hooks the resolver needs (default stop budget unchanged). After the first CI run, Codex close no longer fails with "process leader remained unreaped" when a forced kill's exit is reported late (seen on Windows 3.12): it waits for the reap, as callers are already bounded by the room owner's budget; regression test_forced_close_waits_for_an_exit_reported_late.

CHANGELOG.md edits are dropped: Release Please generates it.

Verified at the new head (macOS, Python 3.13): uv sync --all-packages --locked --extra dev, all pre-commit hooks, and the full pytest -q: 8708 passed, 738 skipped. Verification notes further down refer to the previous head.


Summary

Resolve room-scoped external MCP servers inside owned Codex connection startup rather than capturing ambient configuration before room startup/cleanup ownership exists. Related: #709.

Changes

  • Resolve one fresh room snapshot and preserve Band's endpoint and launch precedence.
  • Retain startup/readiness ownership through cancellation/failure; settle the owned process group before releasing resources and preserve failed cleanup for retry.
  • Extend the shared TurnTask lifecycle at its existing owner, with cancellation/readiness and sibling-adapter regressions rather than an adapter-local scheduler.
  • Update examples, operator docs and user-facing Unreleased entries.

Diagnostic correction

RPC method and payload contents are never logged. Non-JSON/non-object/unknown payload diagnostics report transport, type and length; stderr diagnostics report byte length; cleanup diagnostics report exception type. Queue-full warnings report only the dropped event kind. A synthetic credential matching the old protocol-identifier grammar was reproduced in logs, so that grammar and its helper were removed in 39c2d473. No redactor runs in transport log paths. Forwarded error freezing/redaction is preserved. No CodeQL alert is waived.

Test portability and observer corrections

The Windows held-resolver fixture matches the host-native workspace basename instead of a POSIX slash suffix. B retains its one-second startup bound while A remains held; A's admission/release are bounded and asserted. No product timeout increased.
The shared OpenCode wait_for test helper observes readiness before checking an expired deadline, fixing deterministically reproduced lost observations after a delayed poll. The one-second budget and 0.01-second interval are unchanged; false readiness at/after expiry fails without another wait. Four edge regressions remain. This is a test-helper change, not a shared product-runtime change; its exact failing coverage wake delay is unmeasured. Test-only changelog entries were removed.

Windows support boundary

ad176506 refuses stdio servers with nonempty env on Windows during snapshot validation, before constructing or connecting a client. The safe category is unsupported-platform: “secret-bearing stdio MCP servers require POSIX exec”. Windows env-free stdio, all HTTP servers (including secret headers/bearer tokens), and POSIX behavior are unchanged. Windows os.execvpe spawns and exits rather than replacing the owned process; quoting alone cannot preserve ownership. No Windows supervisor is included; an owned supervisor is a separate follow-up.
The refusal regression forces the platform predicate on every OS and checks the actual adapter construction boundary. The POSIX alias-launch/ownership case is skipped on Windows with that explicit reason; configuration-only POSIX tests force their platform, not the real launch case.

Stack and merge order

No prerequisite; based on upstream d7ab3429cbdb5381b9ca572cf7eac210a8196052.
Exact feature-only range: d7ab3429cbdb5381b9ca572cf7eac210a8196052..e38e7ffb63dfd2daeeb415c9da3a6550d8ef9ed0.
Merge #797 before #800, which includes this prerequisite. OMP and Copilot lanes are independent.

Testing

Final local correction scope: snapshot/launch, startup/recovery, 13 diagnostic cases and all 125 OpenCode consumers. Python 3.11.16: 265 passed / 1 eager-host skip; Python 3.12.14 and 3.13.14: 266 passed each. All five static hooks passed.
The method-privacy regression failed four cases before 39c2d473; all 13 diagnostics pass after it. Eighteen grammar/format cases were replaced with eight request/notification privacy cases. Actual parser output changed from disclosing a synthetic credential to event-kind-only warnings.
The Windows refusal regression failed before the guard and failed again when the guard was removed; the restored interpreter matrix passed. Actual rendered error: unsupported-platform: Codex MCP startup failed: secret-bearing stdio MCP servers require POSIX exec. The forced-Windows supported-transport case launches an env-free stdio target alongside secret-bearing HTTP without passing its aliases to that target.
Prior published 200293f3 had three Windows alias-launch failures, one Windows 3.13 PowerShell timeout and two high CodeQL alerts. The complete matrix and code-scanning clearance at this corrected head are awaited; the unchanged PowerShell test retains its timeout. No failure rerun, timeout relaxation or alert dismissal. Local proofs are not native-provider/live-room receipts or staged-package validation.

Comment thread src/band/integrations/codex/rpc_base.py Fixed
Comment thread src/band/integrations/codex/rpc_base.py Fixed
Comment thread src/band/integrations/codex/rpc_base.py Fixed
Comment thread src/band/integrations/codex/rpc_base.py Fixed
Comment thread src/band/integrations/codex/rpc_base.py Fixed
Comment thread src/band/integrations/codex/rpc_base.py Fixed
Comment thread src/band/integrations/codex/rpc_base.py Fixed
@bandzalkin

Copy link
Copy Markdown
Contributor Author

CodeQL diagnostic findings

Fixing commits: bc0df019 removes wire-payload contents, 39c2d473 removes RPC method contents, and ad176506 adds the prelaunch Windows secret-bearing stdio refusal.

RPC frame/queue diagnostics retain only event-kind and length metadata: queue drops identify server requests or notifications; parse/unknown-frame diagnostics retain their transport/type labels and length. No payload or method content is logged by these diagnostics. Forwarded error freezing is unchanged.

Recorded CodeQL instances are fixed without dismissal. All seven bot threads below are resolved; the two existing replies remain. This summary replaces further per-thread replies.

bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 14, 2026
Source-Base: 97f8330
Source-Head: ad17650
Applied-Over: 22d8498
Conflict-Notes: None; exact source delta, excluding CHANGELOG.md and FORK-CHANGES.md
Upstream-PR: band-ai#797
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 14, 2026
Source-Base: 97f8330
Source-Head: ad17650
Applied-Over: 22d8498
Conflict-Notes: None; exact source delta, excluding CHANGELOG.md and FORK-CHANGES.md
Upstream-PR: band-ai#797
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 97f8330
Source-Head: ad17650
Applied-Over: 1ab35a4
Conflict-Notes: band-ai#709 replaced Codex startup and retirement with RetainedRoom acquisition/release; keep its generation, enrollment and retryable-close ownership, port resolver/readiness/redaction into that owner and add cancellation guards. Dropped obsolete lifecycle fields and replaced deleted test helpers with codex/kit.py and lifecycleprofile.py. Inherited ownership and failed-close probes fail when their band-ai#709 mechanisms are removed, pass restored; no deleted upstream test files restored.
Upstream-PR: band-ai#797
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 97f8330
Source-Head: ad17650
Applied-Over: be88e79
Conflict-Notes: band-ai#709 replaced Codex startup and retirement with RetainedRoom acquisition/release; keep its generation, enrollment and retryable-close ownership, port resolver/readiness/redaction into that owner and add cancellation guards. Dropped obsolete lifecycle fields and replaced deleted test helpers with codex/kit.py and lifecycleprofile.py. Inherited ownership and failed-close probes fail when their band-ai#709 mechanisms are removed, pass restored; no deleted upstream test files restored.
Upstream-PR: band-ai#797
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 97f8330
Source-Head: ad17650
Applied-Over: be88e79
Conflict-Notes: band-ai#709 replaced Codex startup and retirement with RetainedRoom acquisition/release; keep its generation, enrollment and retryable-close ownership, port resolver/readiness/redaction into that owner and add cancellation guards. Dropped obsolete lifecycle fields and replaced deleted test helpers with codex/kit.py and lifecycleprofile.py. Inherited ownership and failed-close probes fail when their band-ai#709 mechanisms are removed, pass restored; no deleted upstream test files restored.
Upstream-PR: band-ai#797
@bandzalkin
bandzalkin force-pushed the feat/codex-owned-mcp-resolver branch from ad17650 to 81ed02c Compare October 15, 2026 03:43
@bandzalkin

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (d7ab3429) at 81ed02c178b3; the description's new first section lists the conflict resolutions and the verification at this head.

@bandzalkin
bandzalkin force-pushed the feat/codex-owned-mcp-resolver branch from 81ed02c to e38e7ff Compare October 15, 2026 05:05
@bandzalkin

Copy link
Copy Markdown
Contributor Author

Pushed e38e7ffb63df: Codex close now waits for the reap after a forced kill instead of failing at 1s (Windows 3.12 CI failure); regression test added. Description updated.

bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Port the reviewed cancellation correction from dd8f3af..942759f4. Delegate acquisition cancellation explicitly to the matching startup owner, preserve first abandonment/cleanup diagnostics, and cover public caller/cleanup orderings after uncancel. Keep Claude-owned retention changes in the stacked Claude PR.
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 16, 2026

This branch has not been deployed

No deployments
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.

2 participants