Skip to content

feat: own Codex, ACP and Claude room lifecycles through one retained-room contract - #709

Merged
AlexanderZ-Band merged 201 commits into
mainfrom
feat/host-idle-release-codex
Oct 14, 2026
Merged

AlexanderZ-Band merged 201 commits into
mainfrom
feat/host-idle-release-codex

Conversation

@bandzalkin

@bandzalkin bandzalkin commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Why

Native adapter rooms must retain their conversation identity, workspace, settings and concrete process ownership through interrupted startup, failed cleanup and restart. Independent lifecycle implementations could lose a live handle or admit replacement work before closure was confirmed.

This is the ownership stage of INT-1768, building on the shared retention foundation from #781.

What

  • Compose Codex, Claude SDK, OMP ACP, Cursor ACP and Copilot ACP rooms with one shared RetainedRoom/RoomRetention contract. Accepted prompt and settings work is enrolled before it runs and leased through native work and reporting.
  • Fence admission immediately on leave or stop, give accepted work its configured settle grace, then cancel and join it. Detached turns cancelled by final cleanup report their outcome once. Ordinary ACP prompts also participate in direct adapter cleanup.
  • Retain processes, workspace claims and native continuation through failed, cancelled or timed-out startup and close. Concurrent cleanup joins one attempt; retry and restart finish the previous owner's cleanup before replacement.
  • Keep strict restore separate from bootstrap/crash fallback, preserving native identity and effective settings. Route Codex requests by native origin and reject stale-generation callbacks; Claude uses one continuous native reader per room.
  • Share one reporting deadline across room and MCP shutdown. A common real-subprocess contract suite exercises all five provider profiles, with focused regressions for provider protocol and cancellation behavior.

Scope

Idle retention remains disabled for every profile, and provider activity remains UNKNOWN. Configuration validation and the shared owner reject idle release before provider callbacks run. Native safety qualification and live suspension acceptance are required for future enablement; they are separate from merging this gated ownership stage.

Public changes: ACP cleanup_all no longer accepts final, and stopped adapters refuse turns until on_started completes restart. ACP start_timeout_s is replaced by retention.transition_timeout_s. All three provider families share a non-negative turn_settle_timeout_s. Unused room-scoped DecisionRegistry methods and its register_minted room argument are removed; OMP_CWD_FLAG centralizes the OMP workspace flag.

#710 and #711 are incorporated and closed as superseded. No Rust core, platform, Fern or new dependency changes are included.

Separate follow-ups: INT-1785 for detached-turn release/cancel consolidation, INT-1786 for remaining test-file splits, and INT-1787 for shared test barriers.

@bandzalkin bandzalkin changed the title feat(codex): release idle app-servers and resume their threads feat(integrations): release idle Codex app-servers and resume their threads Sep 29, 2026
@AlexanderZ-Band
AlexanderZ-Band force-pushed the feat/host-idle-release-hook branch from b1292e8 to b5d3bef Compare September 30, 2026 06:40
@AlexanderZ-Band
AlexanderZ-Band force-pushed the feat/host-idle-release-codex branch from 7aa21eb to 6fe9f2a Compare September 30, 2026 06:40
@AlexanderZ-Band
AlexanderZ-Band added this pull request to stack #767 October 10, 2026 06:21
@AlexanderZ-Band
AlexanderZ-Band force-pushed the feat/host-idle-release-hook branch from b8aee29 to d9c5b56 Compare October 10, 2026 07:01
@AlexanderZ-Band
AlexanderZ-Band force-pushed the feat/host-idle-release-codex branch from 5a29125 to 4d75666 Compare October 10, 2026 07:01
Base automatically changed from feat/host-idle-release-hook to main October 11, 2026 11:40
AlexanderZ-Band and others added 20 commits October 12, 2026 06:21
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Agent, PlatformRuntime and OneShotInvoker keep failed or cancelled
cleanup, and the single-instance guard, until a retry succeeds, while
preserving the primary error during unwind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Also updates the Agent lifecycle tests to the honest-stop contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Shutdown now refuses new events synchronously and waits, without a new
timeout, for every accepted handle_event (turns, acks, room cleanup,
cancellation unwinding) to settle before cleanup_all and disconnect.
A shutdown requested from inside an accepted event reports
CleanupIncompleteError instead of joining itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Events that arrive before a first execution is routed are dropped
unclaimed, so every still-desired admission resyncs to recover them;
an obsolete admission neither routes nor resyncs. Startup stays
unbounded: leave and stop wait for it, then retire it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Config, residency vocabulary, clock, owned-cleanup reporting, one room's
lifecycle and the adapter-wide owner each get their own module; the
package re-exports the same public surface.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq
RoomExecutions owns each room's admission, routing and retirement;
band.runtime.control owns control dedup, targeting and dispatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmiQGxJR2FrTVuRP85Y1dq

@AlexanderZ-Band AlexanderZ-Band left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full-PR cycle 2: no new verified in-scope findings across all six review groups; converged. Cycle 1’s ACP cleanup issue and documentation nit are fixed and their threads resolved. Full unit validation: 8,673 passed, 115 skipped; pre-commit, type checking and 34 executable-doc checks passed. Idle retention remains disabled; native qualification and live enablement acceptance are separate gates.

@AlexanderZ-Band
AlexanderZ-Band added this pull request to the merge queue Oct 14, 2026

@AlexanderZ-Band AlexanderZ-Band left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the complete gated ownership change in two full-PR cycles. The ACP direct-cleanup defect and documentation nit are fixed, all 237 threads are resolved, and CI plus the full local validation are green at 400a4de. Idle retention remains disabled.

Merged via the queue into main with commit ed329fc Oct 14, 2026
29 checks passed
@AlexanderZ-Band
AlexanderZ-Band deleted the feat/host-idle-release-codex branch October 14, 2026 11:21
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Head: 9e84760b4cb44105eeb922832e980fe109f35641
Applied-Over: 2a98142
Conflict-Notes: Watchdog probe keeps its try/finally over band-ai#789's TurnOutcome.ADVANCED result; adds band-ai#762's wedged-process scenario to roomownership/test_recovery.py as the probe proving band-ai#709 supersedes it; ledger lists the f807d62 port
Always replay; fork process and coverage dispositions only.
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 97f8330
Source-Head: 4184abb
Applied-Over: 3643b7c
Conflict-Notes: Resolved band-ai#709 modify/delete conflicts by replacing OMP ACP with native RPC; retained the workspace flag and current form-policy test class, removed obsolete ACP profile fixtures, migrated the new room-rejoin test and matrix row, and preserved band-ai#804 owner-module imports. No behavioral source hunks dropped; CHANGELOG.md and FORK-CHANGES.md excluded.
Upstream-PR: band-ai#763
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 4184abb
Source-Head: a625466
Applied-Over: fda806c
Conflict-Notes: None; exact feature delta over the ported native OMP lifecycle; retained upstream band-ai#709 and band-ai#804 adaptations from the prerequisite. CHANGELOG.md and FORK-CHANGES.md excluded.
Upstream-PR: band-ai#798
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: c18df71
Source-Head: 56a679d
Applied-Over: 850b0c3
Conflict-Notes: Reimplemented resolver and shared initializer on band-ai#709 ACPRoom/RetainedRoom custody; dropped superseded parallel retirement/shutdown/respawn APIs and restartable cleanup flags; retained narrow child-reaping and closing-connection guards; moved legacy coverage to clientadapter/ and roomownership/ without restoring deleted files. Stacked after band-ai#763: docs/acp.md keeps band-ai#763's removal of OmpACPAdapterConfig beside resolve_mcp_servers. The room records the initializer its last waiter abandoned, so a callback that uncancel()s cannot publish a session or hand its late result to a successor (the original's SessionInitializer.invalidated). A setup already settling its own cancellation is recorded as abandoned too, without a second cancel. A successor joining a setup that was only settling its own cancellation reuses the live session it published.
Upstream-PR: band-ai#799
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: ad17650
Source-Head: e083173
Applied-Over: 80fe9e6
Conflict-Notes: band-ai#709 replaced Claude command queues and local retirement maps with RetainedRoom. Port resolver, private launch files, readiness and safe diagnostics into ClaudeRoomSession acquisition/release; keep upstream native no-resolver cancellation and callback contracts. Reuse SharedBandMCPBackend close custody and retained self-disposal instead of obsolete backend/deferred-cleanup fields; an optional stop reporting budget keeps whole-adapter teardown owned. Migrate tests into current one-class files and plain helpers; retain authoritative upstream workspace/backend/startup tests. Dropped duplicated enrollment and retryable-close machinery: mutation of upstream owned-work and failed-close mechanisms fails their probes, restored mechanisms pass. MCP readiness waits on the server set bound at resolution.
Upstream-PR: band-ai#800
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Head: 9e84760b4cb44105eeb922832e980fe109f35641
Applied-Over: 8e06491
Conflict-Notes: Watchdog probe keeps its try/finally over band-ai#789's TurnOutcome.ADVANCED result; adds band-ai#762's wedged-process scenario to roomownership/test_recovery.py as the probe proving band-ai#709 supersedes it; ledger lists the f807d62 port
Always replay; fork process and coverage dispositions only.
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 97f8330
Source-Head: 4184abb
Applied-Over: 1cd5845
Conflict-Notes: Resolved band-ai#709 modify/delete conflicts by replacing OMP ACP with native RPC; retained the workspace flag and current form-policy test class, removed obsolete ACP profile fixtures, migrated the new room-rejoin test and matrix row, and preserved band-ai#804 owner-module imports. No behavioral source hunks dropped; CHANGELOG.md and FORK-CHANGES.md excluded. Over band-ai#802: OMP image and turn-outcome probes move into its imageprobes.py/outcomeprobes.py registries; uv.lock regenerated over band-ai#796.
Upstream-PR: band-ai#763
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 4184abb
Source-Head: a625466
Applied-Over: 00f3dfb
Conflict-Notes: None; exact feature delta over the ported native OMP lifecycle; retained upstream band-ai#709 and band-ai#804 adaptations from the prerequisite. CHANGELOG.md and FORK-CHANGES.md excluded.
Upstream-PR: band-ai#798
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: c18df71
Source-Head: 56a679d
Applied-Over: 27431ce
Conflict-Notes: Reimplemented resolver and shared initializer on band-ai#709 ACPRoom/RetainedRoom custody; dropped superseded parallel retirement/shutdown/respawn APIs and restartable cleanup flags; retained narrow child-reaping and closing-connection guards; moved legacy coverage to clientadapter/ and roomownership/ without restoring deleted files. Stacked after band-ai#763: docs/acp.md keeps band-ai#763's removal of OmpACPAdapterConfig beside resolve_mcp_servers. The room records the initializer its last waiter abandoned, so a callback that uncancel()s cannot publish a session or hand its late result to a successor (the original's SessionInitializer.invalidated). A setup already settling its own cancellation is recorded as abandoned too, without a second cancel. A successor joining a setup that was only settling its own cancellation reuses the live session it published.
Upstream-PR: band-ai#799
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
bandzalkin added a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: ad17650
Source-Head: e083173
Applied-Over: 5a2fc6f
Conflict-Notes: band-ai#709 replaced Claude command queues and local retirement maps with RetainedRoom. Port resolver, private launch files, readiness and safe diagnostics into ClaudeRoomSession acquisition/release; keep upstream native no-resolver cancellation and callback contracts. Reuse SharedBandMCPBackend close custody and retained self-disposal instead of obsolete backend/deferred-cleanup fields; an optional stop reporting budget keeps whole-adapter teardown owned. Migrate tests into current one-class files and plain helpers; retain authoritative upstream workspace/backend/startup tests. Dropped duplicated enrollment and retryable-close machinery: mutation of upstream owned-work and failed-close mechanisms fails their probes, restored mechanisms pass. MCP readiness waits on the server set bound at resolution.
Upstream-PR: band-ai#800
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Head: 9e84760b4cb44105eeb922832e980fe109f35641
Applied-Over: 8e06491
Conflict-Notes: Watchdog probe keeps its try/finally over band-ai#789's TurnOutcome.ADVANCED result; adds band-ai#762's wedged-process scenario to roomownership/test_recovery.py as the probe proving band-ai#709 supersedes it; ledger lists the f807d62 port
Always replay; fork process and coverage dispositions only.
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 97f8330
Source-Head: 4184abb
Applied-Over: 1cd5845
Conflict-Notes: Resolved band-ai#709 modify/delete conflicts by replacing OMP ACP with native RPC; retained the workspace flag and current form-policy test class, removed obsolete ACP profile fixtures, migrated the new room-rejoin test and matrix row, and preserved band-ai#804 owner-module imports. No behavioral source hunks dropped; CHANGELOG.md and FORK-CHANGES.md excluded. Over band-ai#802: OMP image and turn-outcome probes move into its imageprobes.py/outcomeprobes.py registries; uv.lock regenerated over band-ai#796.
Upstream-PR: band-ai#763
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: 4184abb
Source-Head: a625466
Applied-Over: 00f3dfb
Conflict-Notes: None; exact feature delta over the ported native OMP lifecycle; retained upstream band-ai#709 and band-ai#804 adaptations from the prerequisite. CHANGELOG.md and FORK-CHANGES.md excluded.
Upstream-PR: band-ai#798
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: c18df71
Source-Head: 56a679d
Applied-Over: 27431ce
Conflict-Notes: Reimplemented resolver and shared initializer on band-ai#709 ACPRoom/RetainedRoom custody; dropped superseded parallel retirement/shutdown/respawn APIs and restartable cleanup flags; retained narrow child-reaping and closing-connection guards; moved legacy coverage to clientadapter/ and roomownership/ without restoring deleted files. Stacked after band-ai#763: docs/acp.md keeps band-ai#763's removal of OmpACPAdapterConfig beside resolve_mcp_servers. The room records the initializer its last waiter abandoned, so a callback that uncancel()s cannot publish a session or hand its late result to a successor (the original's SessionInitializer.invalidated). A setup already settling its own cancellation is recorded as abandoned too, without a second cancel. A successor joining a setup that was only settling its own cancellation reuses the live session it published.
Upstream-PR: band-ai#799
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
github-actions Bot pushed a commit to bandzalkin/band-sdk-python that referenced this pull request Oct 15, 2026
Source-Base: ad17650
Source-Head: e083173
Applied-Over: 5a2fc6f
Conflict-Notes: band-ai#709 replaced Claude command queues and local retirement maps with RetainedRoom. Port resolver, private launch files, readiness and safe diagnostics into ClaudeRoomSession acquisition/release; keep upstream native no-resolver cancellation and callback contracts. Reuse SharedBandMCPBackend close custody and retained self-disposal instead of obsolete backend/deferred-cleanup fields; an optional stop reporting budget keeps whole-adapter teardown owned. Migrate tests into current one-class files and plain helpers; retain authoritative upstream workspace/backend/startup tests. Dropped duplicated enrollment and retryable-close machinery: mutation of upstream owned-work and failed-close mechanisms fails their probes, restored mechanisms pass. MCP readiness waits on the server set bound at resolution.
Upstream-PR: band-ai#800
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