You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make Settled a real lifecycle state, following T3 Code's design, and remove auto-archive. Settled becomes the only automatic lifecycle transition; archive is always an explicit user action.
It is manual only (settle_session / make_session_active, crates/runtime/src/app/sessions.rs).
Its only behavioural effect runs the wrong way: settled threads are exempt from auto-archive (auto_archive_candidates, crates/core/src/project.rs) and from orchestrate archive_on_complete, so finished work lives longer than untouched work.
settled_at is only a cascade-undo key; nothing sorts by it and the Settled group has no paging.
Auto-archive is removed because archive is becoming destructive in part (it will move logs, call provider-native archive and clean up worktrees; see #529 and #530). The rule is: automatic transitions must be losslessly reversible. Settle is; archive no longer is. Neither T3 Code nor the Codex app auto-archives threads. Sidebar length is handled by the Settled shelf; disk growth by storage compaction and cold compression, independent of archive.
Spec
State.SessionMeta gains settled_override: Option<Settled | KeepActive> (replacing the bare settled_at flag), settled_at, unsettled_at. KeepActive is the user's "keep active" choice and suppresses auto-settle. Snooze (#527) and pinned (#528) are separate issues.
Last activity = the latest of: last user message, and the latest turn's requested / started / completed times. A thread that never ran never inactivity-settles.
Auto-settle when last activity is strictly older than N days. The auto settled_at is the activity time, not now.
Never auto-settle a thread that: is archived; has any override; has pending approvals or user input; has a starting or running session; has background work; has a user message still inside a 2-minute queued-turn grace window; is snoozed (unless it woke on an error or completion after the snooze). Linked-PR rules are in #534.
Automatic un-settle (resets any override, KeepActive included, to none):
the user sends a message (also clears snooze);
the session moves to starting or running;
an approval or user-input request arrives.
Nothing else wakes a settled thread.
Settle stops the provider session, as in T3 Code. A thread idle for days has no warm prompt cache left (see #531), so stopping costs nothing and frees memory. The stop is dropped if the thread was re-engaged in the meantime. Manual settle keeps refusing while the thread family is busy.
Host sweep. The host evaluates auto-settle every 60 s, and immediately on settings changes and turn ends. It must not depend on a client: today auto-archive only runs when a desktop sidebar triggers it (crates/ui/src/sidebar.rs), which violates Principle 2.
Settings.auto_settle_after_days: Option<u32> (default 3, range 1–90, None = never), per-project overrides stored in host settings keyed by project id. Changing them does not reopen already-settled threads.
Sidebar.
Section order: pinned, active, snoozed, settled.
Settled shelf starts collapsed; shows 10 rows, then 25 more per "Show more"; sorted by settled_at desc, then last activity, then updated_at.
Reopened threads enter the top of the active list via unsettled_at; later activity does not reorder the active list.
The partition and sort live in core so desktop, phone and browser share them.
Undo. Settle shows a 5-second toast with Undo (and mod+z when no text field or terminal has focus). Undo is a client-sent reverse command; a claim token stops a stale toast from reversing a newer action. The same toast serves snooze, unpin and archive.
Protocol.SettleSessions, UnsettleSessions (keep-active), settle-related SettingsPatch fields; events carry the reason (user vs activity).
Removing auto-archive
Remove auto_archive_disabled, auto_archive_max_idle_days, auto_archive_keep_count (crates/core/src/settings.rs), auto_archive_candidates, Command::AutoArchiveSweep and the sidebar-triggered sweeps.
Threads already auto-archived stay archived.
Open question: orchestrate archive_on_complete is an explicit per-orchestration choice (comparable to the Codex app archiving automation threads on completion). Keep it, but settled should no longer exempt a child from it.
guivieiras/tcode has unmerged work on local/integration touching the same surface: last_user_message_at and a "last user message" thread sort (45e74fc), thread state presentation and completed markers (874fefd, 9cd8805), and "settle actions" refinements (cf68c7e). It also replaces the unread dot with a "Mark completed" marker, which changes what the "unread" exemption means here. 874fefd rewrites ~1.2k lines of crates/ui/src/sidebar.rs into a sidebar/thread_row/ module, so the sidebar parts of this issue, Thread lifecycle: snooze #527 and Thread lifecycle: pinned threads #528 should be sequenced with it. The last-activity definition above should reuse last_user_message_at if that lands.
Reference
T3 Code origin/main f5ef0ddb9: apps/server/src/orchestration/ThreadSettlementPolicy.ts, ThreadSettlementReactor.ts, decider.ts (settle/unsettle), packages/contracts/src/settings.ts, docs/user/thread-sidebar.md; history in #4026, #4243, #8600, #9254, #12848.
Summary
Make Settled a real lifecycle state, following T3 Code's design, and remove auto-archive. Settled becomes the only automatic lifecycle transition; archive is always an explicit user action.
Why
Today Settled (#408) has almost no effect:
settle_session/make_session_active,crates/runtime/src/app/sessions.rs).auto_archive_candidates,crates/core/src/project.rs) and from orchestratearchive_on_complete, so finished work lives longer than untouched work.settled_atis only a cascade-undo key; nothing sorts by it and the Settled group has no paging.Auto-archive is removed because archive is becoming destructive in part (it will move logs, call provider-native archive and clean up worktrees; see #529 and #530). The rule is: automatic transitions must be losslessly reversible. Settle is; archive no longer is. Neither T3 Code nor the Codex app auto-archives threads. Sidebar length is handled by the Settled shelf; disk growth by storage compaction and cold compression, independent of archive.
Spec
State.
SessionMetagainssettled_override: Option<Settled | KeepActive>(replacing the baresettled_atflag),settled_at,unsettled_at.KeepActiveis the user's "keep active" choice and suppresses auto-settle. Snooze (#527) and pinned (#528) are separate issues.Last activity = the latest of: last user message, and the latest turn's requested / started / completed times. A thread that never ran never inactivity-settles.
Auto-settle when last activity is strictly older than N days. The auto
settled_atis the activity time, not now.Never auto-settle a thread that: is archived; has any override; has pending approvals or user input; has a starting or running session; has background work; has a user message still inside a 2-minute queued-turn grace window; is snoozed (unless it woke on an error or completion after the snooze). Linked-PR rules are in #534.
Automatic un-settle (resets any override,
KeepActiveincluded, to none):Nothing else wakes a settled thread.
Settle stops the provider session, as in T3 Code. A thread idle for days has no warm prompt cache left (see #531), so stopping costs nothing and frees memory. The stop is dropped if the thread was re-engaged in the meantime. Manual settle keeps refusing while the thread family is busy.
Host sweep. The host evaluates auto-settle every 60 s, and immediately on settings changes and turn ends. It must not depend on a client: today auto-archive only runs when a desktop sidebar triggers it (
crates/ui/src/sidebar.rs), which violates Principle 2.Settings.
auto_settle_after_days: Option<u32>(default 3, range 1–90,None= never), per-project overrides stored in host settings keyed by project id. Changing them does not reopen already-settled threads.Sidebar.
settled_atdesc, then last activity, thenupdated_at.unsettled_at; later activity does not reorder the active list.coreso desktop, phone and browser share them.Undo. Settle shows a 5-second toast with Undo (and
mod+zwhen no text field or terminal has focus). Undo is a client-sent reverse command; a claim token stops a stale toast from reversing a newer action. The same toast serves snooze, unpin and archive.Protocol.
SettleSessions,UnsettleSessions(keep-active), settle-relatedSettingsPatchfields; events carry the reason (uservsactivity).Removing auto-archive
auto_archive_disabled,auto_archive_max_idle_days,auto_archive_keep_count(crates/core/src/settings.rs),auto_archive_candidates,Command::AutoArchiveSweepand the sidebar-triggered sweeps.archive_on_completeis an explicit per-orchestration choice (comparable to the Codex app archiving automation threads on completion). Keep it, but settled should no longer exempt a child from it.Related work
local/integrationtouching the same surface:last_user_message_atand a "last user message" thread sort (45e74fc), thread state presentation and completed markers (874fefd, 9cd8805), and "settle actions" refinements (cf68c7e). It also replaces the unread dot with a "Mark completed" marker, which changes what the "unread" exemption means here. 874fefd rewrites ~1.2k lines ofcrates/ui/src/sidebar.rsinto asidebar/thread_row/module, so the sidebar parts of this issue, Thread lifecycle: snooze #527 and Thread lifecycle: pinned threads #528 should be sequenced with it. The last-activity definition above should reuselast_user_message_atif that lands.Reference
T3 Code origin/main f5ef0ddb9:
apps/server/src/orchestration/ThreadSettlementPolicy.ts,ThreadSettlementReactor.ts,decider.ts(settle/unsettle),packages/contracts/src/settings.ts,docs/user/thread-sidebar.md; history in #4026, #4243, #8600, #9254, #12848.