Skip to content

Close idle tasks and let clients start fresh after a task closes - #87

Merged
wolfiesch merged 4 commits into
mainfrom
host-idle-task-reaper
Oct 26, 2026
Merged

wolfiesch merged 4 commits into
mainfrom
host-idle-task-reaper

Conversation

@wolfiesch

@wolfiesch wolfiesch commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

Tasks stayed active in state.sqlite3 until an agent finished or closed them, so every session that disconnected without finishing left an open task behind indefinitely.

  • Host idle close: the journal closes a task after 24 hours with no connection, pending resume, owned tab, or staged Commit. It checks at startup and before each mutation. A task still connected when the host stopped counts its idle time from the restart, so a restart cannot close it immediately. Tasks that own tabs are never closed this way.
  • Resume rejection reason: the connection acknowledgement now carries resume_rejection (task_closed or unknown_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.
  • SDKs: on 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.
  • Python store clear(): added the method that finish_task already called.

Verification

  • cargo test --workspace --locked --manifest-path host-rs/Cargo.toml
  • python3 tests/architecture/verify_protocol_schemas.py
  • python3 -m unittest discover -s packages/sdk-python/tests
  • bun run workspace:typecheck, plus the SDK, MCP, OMP, and GPT-Control package tests
  • The new host and SDK tests fail without the change.
  • Live check against a locally installed host built from this branch:
    • a stored capability for a closed task now connects as a new task and clears the store;
    • an unknown capability still refuses and keeps the store;
    • before the change, both refused.

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.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T08:43:45.231913Z 62a24ce PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread host-rs/crates/agenttab-host/src/journal.rs
Comment thread host-rs/crates/agenttab-host/src/journal.rs
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.
@wolfiesch wolfiesch changed the title Close idle disconnected tasks after 24 hours Close idle tasks and let clients start fresh after a task closes Oct 26, 2026
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.
@wolfiesch
wolfiesch merged commit 71e9f1a into main Oct 26, 2026
9 checks passed
@wolfiesch
wolfiesch deleted the host-idle-task-reaper branch October 26, 2026 09:05
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.

1 participant