Delete only settled Sessions and confirm repeated owner deletion - #60
Merged
Merged
Conversation
Session DELETE now follows the observed official lifecycle (SES-29/30). Under the Session lock that orders Turn and input admission, a Session with a queued, running or waiting Turn or a pending input reservation returns 409 conflict_error with the official message and nothing changes. The owner's repeated deletion returns the same 200 without writing; foreign, missing and malformed IDs keep the identical 404. Tests cover the HTTP/PostgreSQL state matrix with a no-write digest, deletion racing Turn and input admission on one row lock, a Worker cancel-then-delete flow and the pinned-SDK script. Tests that exercise hidden work under deletion markers from earlier releases now create those markers explicitly.
The client exposes isSessionDeletionConflict for the 409 conflict_error that Core returns for a Session with pending work or input. The Web delete dialog explains that conflict and replaces its action with an explicit Cancel work and delete: one cancellation, bounded reads until the Session is idle or failed without required actions, then one deletion. Rejected or uncertain cancellation, a timeout, a connection change or another 409 stop without retrying; other 409 responses keep the generic message.
Document rows D1-D5, the lock-ordered decision, legacy deletion markers and the stricter local 409 right after an events.create 202 where the official service returned 200. Update the contributor rules, contract README, Environment reservation note and operation evidence row 10.
Session deletion now returns 409 for busy Sessions, so a finally-block delete after a failed assertion could replace the original error. A shared helper cancels once on the 409 conflict_error, polls briefly for idle or failed and deletes again. A cleanup failure is logged while another error propagates and raised otherwise.
Hosted provisioning with input and a connected self-hosted Session with a queued later input read idle, or await their Environment, while deletion returns 409, and Core rejects cancellation in those states. After a busy conflict the Web reads the Session once and, when only such input remains, explains that it must start, expire or fail first instead of offering Cancel work and delete. Turn-busy Sessions keep the existing flow.
When the Core connection changes after the cancellation but before any deletion, say that the cancellation was sent and no deletion was attempted, instead of blaming an earlier-connection deletion confirmation.
Deletion checks only root Turns and input reservations; subagent child Turns and pending Environment file writes do not block it, as before, and their official behavior is unobserved. State this in the handler annotation, OpenAPI, contributor rules and contract docs, and record it as a follow-up. Describe the Web pending-input explanation, the 30-second bound checked between reads, and re-wrap the Core Web paragraph.
A provisioning hosted Session with reserved initial input on a configured sandbox node now conflicts on deletion, so its placement keeps counting toward node capacity until the input is admitted or expires. A real store test checks the unreleased placement and unchanged node counts on the 409, release on the allowed deletion after expiry, unchanged timestamps on a repeat and 404 for another tenant. Record the capacity change in the contributor rules and the deletion alignment section.
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.
Session DELETE now follows the observed official lifecycle rules. A Session can be deleted only when it is durably idle or failed with no pending work. A repeated delete by the owner is idempotent. The pinned baseline is unchanged (SDK 3.13.0 / d7c41ef /
agents=v1).Behavior
conflict_error, param null, and message "session must be durably idle or failed without required actions before deletion". The check runs under the same Session row lock as Turn and input admission. Nothing changes on 409: no cancellation, no deletion marker, no event, no Runtime or placement release.{id, object: "agent.session.deleted", deleted: true}without writing anything. Foreign, missing and malformed IDs still get a byte-identical 404.isSessionDeletionConflict().Documented decisions
events.create202 returns 409. Official returned 200 in that window.Evidence
Campaign scan 1 findings SES-29 and SES-30, from owned official Sessions (all deleted), plus the 2026-09-22 official cleanup 409. Recorded in
official-semantics-alignment.mdandoperation-evidence.mdrow 10.Validation
Live acceptance through real Core, the daemon, native Codex and Kimi K3 (
environment: none):One Turn per phase. Cleanup and secret scans passed.
Real-PostgreSQL tests:
The pinned-SDK
official_session_delete.pycovers 409 → cancel → 200 → repeat 200 → 404.Server gate on the rebased code: all
make checktargets plus the Web typecheck, core-doctor, the unit tests and the build pass. The Playwright browser cases were not run on the server (no Google Chrome; the user approved the skip).make openapiis byte-identical.Reviews:
Deferred
Physical purge and retention. Child-work and pending-file-write gating, pending official evidence.
No full protocol compatibility is claimed.
Need help on this PR? Tag
@codesmithwith what you need. Autofix is disabled.