Repository navigation
Close idle tasks and let clients start fresh after a task closes - #87
Merged
Merged
Conversation
A task stayed active until an agent finished or closed it, so every session that disconnected without finishing left an open task in state.sqlite3 indefinitely. The journal now closes a task once it has had no connection, pending resume, owned tab, or staged Commit for 24 hours, at startup and before each mutation. Closed tasks keep their existing 24-hour deletion. Resuming a closed task already starts a new task, so adapters need no change.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62a24ce53c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Clients refused to connect when a stored resume capability no longer resumed, so once the host closed an idle task, every adapter holding its capability failed until the state file was deleted by hand. The connection acknowledgement now carries resume_rejection: task_closed when the capability belongs to a finished or closed task, unknown_capability otherwise. The host keeps closed tasks' capability hashes for a year after deleting their rows so the reason stays known. On task_closed the TypeScript and Python SDKs clear the stored capability and connect as a new task; any other rejection still refuses and keeps the capability. A task still connected when the host stopped now counts its idle time from the restart instead of its last attach, so a restart cannot close it immediately. Also adds the missing clear() to the Python capability store, which finish_task already called.
A client that crashed between the host confirming a rotated capability and activating it locally keeps the old capability as active and the confirmed one as pending. Once that task closed, the pending candidate reported task_closed but was skipped, and the rotated-away active capability was unknown, so connect refused until the state was deleted by hand. Both candidates belong to the same task, so task_closed on either one now clears the store and connects as a new task.
Cleanup ran only at startup and before mutations, so on a host with no recent mutations a task idle past 24 hours could still resume, contrary to the documented contract.
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.
Summary
Tasks stayed
activeinstate.sqlite3until an agent finished or closed them, so every session that disconnected without finishing left an open task behind indefinitely.resume_rejection(task_closedorunknown_capability) when a supplied capability does not resume. Closed tasks' capability hashes are kept for a year after their rows are deleted, so the reason stays known.task_closed, the TypeScript and Python SDKs clear the stored capability and connect as a new task, instead of failing with "rejected the stored resume capability" until the state file is deleted by hand. Every other rejection still refuses to connect and keeps the capability. The MCP, OMP, Pi, and GPT-Control adapters inherit this through the TypeScript SDK.clear(): added the method thatfinish_taskalready called.Verification
cargo test --workspace --locked --manifest-path host-rs/Cargo.tomlpython3 tests/architecture/verify_protocol_schemas.pypython3 -m unittest discover -s packages/sdk-python/testsbun run workspace:typecheck, plus the SDK, MCP, OMP, and GPT-Control package tests