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
{{ message }}
Repository navigation
feat(sessions): opt-in Host-owned archiving of idle tasks #5919
Step 3 of the task lifecycle plan agreed in #5776, which also set the order for automatic archiving: Host-owned idle archiving first. Work Board completion and PR-driven archiving wait until those become Host-owned facts.
This adds one opt-in setting per Host, archive tasks with no activity for N days. It is off by default. The Host decides and executes; Desktop exposes the setting and shows what happened. Archiving is reversible: Settings › Archived tasks restores a task. Deleting old archived tasks stays a separate opt-in setting (#5899 / #5902), so every archived task, automatic or manual, keeps that policy's own clock and safeguards.
Rules
Idle. A task is idle when max(activity_at, committed_at) across its revision family and its direct ordinary subtasks is older than N days.
activity_at advances on messages and at the end of every run.
committed_at is included so that a task restored from the archive is not archived again on the next sweep.
Renames, pins and usage writes only touch committed_at, which can only delay archiving.
Candidates. Only root tasks are candidates. Subtasks follow their parent.
Never archived:
any family with a pinned member;
a task with unread results (has_unread), so a result the user hasn't seen is never hidden;
a task that is the target of an active WorkHub delegation, since archiving would silently end it;
a parent with live linked descendants;
Agent Graph operators and the WorkHub coordination session;
anything the existing archive path already refuses as busy: running or queued turns, pending interactions, active Goals, runtime resources, derived effects, Agent Graph activity, and scheduled tasks bound to the session.
Recheck inside the archive admission. As in feat(storage): opt-in retention for archived tasks #5902, the Host reruns the guard under the same admission the archive takes: settings revision, archive and pin state, idle time, unread, delegation, and descendants. A task that changes in the meantime is skipped.
Clock. It reuses the retention clock guards: it pauses if the wall clock went backwards, and holds for 24 h after a forward jump. A future-dated clock would otherwise archive everything at once and stamp future archived_at values that retention would then trip over.
Proposed design
Setting.{ enabled, days, enabledAt, revision } lives in its own Host document, auto-archive.json, with the same write path and constraints as archive-retention.json. Keeping it separate means the two switches never contend on one revision.
Days: 7, 14 or 30 (proposed default 14).
It takes effect on enable, after a confirm that shows the Host's count. Unlike retention, it does not wait N days, because archiving is reversible and a switch that does nothing for two weeks reads as broken.
Sweep. A lane in HostStorageMaintenance, run after Ready: every 15 min when idle, every 1 s while work remains, at most 8 families per tick.
Candidates come from a range scan on session_catalog_by_activity(activity_at, session_id) with a cursor. The other conditions are filtered on the joined metadata.
Shared code. The clock guards and the "wait for the in-flight tick" setting serialization move out of the retention coordinator into a small shared helper, so the two policies don't carry two copies.
Protocol.session.autoArchive.query and session.autoArchive.set (archiving isn't storage), with the next free compatibility epoch.
Desktop. A per-Host section on Settings › Archived tasks, next to retention, with:
an enable switch;
days;
the Host count ("up to N tasks", since busy checks only happen at run time);
the last run.
The copy says that archived tasks can be restored, and that pinned, running, waiting-on-you and unread tasks are kept. A one-time notice outside Settings, "Automatically archived N tasks", links to Archived tasks, where restoring a task undoes it. It reuses the notice being added for retention.
Known limits
Restoring. Restoring an auto-archived task behaves exactly like restoring a manually archived one. Archiving releases Goal authorities and backends, as manual archive already does.
Desktop-only state. The Host cannot see unsent composer drafts or which task a window has open. A task with no Host-visible activity for N days is archived even if a draft sits in an open window. It can be restored.
Long offline gaps. After a long offline gap (once any clock hold passes), many tasks can be archived in one catch-up. That is acceptable for a reversible action that comes with a notice.
Gap in manual archive (separate)
Manual archive today doesn't check active WorkHub delegations or live linked descendants either. Changing that changes manual behaviour, so it will be proposed separately rather than folded in here.
End-to-end idle archiving. The admission guard, the candidate query and count, the document, the lane, the protocol, the Desktop section, and the notice. Every rule above is tested with an injected clock.
I'd like to take this on. I plan to implement the opt-in Host-owned idle-archiving flow from the proposed design: shared clock/settings safeguards, bounded maintenance sweep with admission rechecks, protocol and Desktop settings/notice coverage. I will work on a separate branch and open a fork PR.
Thanks @garvit-arora, assigning this to you. Please follow the PR plan in the issue, so each step stays reviewable:
A refactor PR first, with no behaviour change. Move the retention clock guards (pause on a backwards clock, the 24 h hold after a forward jump) and the "wait for the in-flight tick" setting serialization out of the archive-retention coordinator into a small shared helper. Its tests should show retention behaves exactly as before.
Then end-to-end idle archiving. That covers the admission guard with the in-admission recheck, the candidate range scan on session_catalog_by_activity, auto-archive.json, the lane (15 min idle, 1 s while work remains, at most 8 families per tick), session.autoArchive.query/set, the Desktop section and the notice. Test every "never archived" rule with an injected clock. Claim the next free compatibility epoch only at merge time, because epochs have been colliding lately.
Out of scope here: manual archive not checking active WorkHub delegations or live linked descendants. That's tracked separately in #5956, because it changes manual behaviour. The retention notice from #5961 is the one to reuse for "Automatically archived N tasks".
Step 3 of the task lifecycle plan agreed in #5776, which also set the order for automatic archiving: Host-owned idle archiving first. Work Board completion and PR-driven archiving wait until those become Host-owned facts.
This adds one opt-in setting per Host, archive tasks with no activity for N days. It is off by default. The Host decides and executes; Desktop exposes the setting and shows what happened. Archiving is reversible: Settings › Archived tasks restores a task. Deleting old archived tasks stays a separate opt-in setting (#5899 / #5902), so every archived task, automatic or manual, keeps that policy's own clock and safeguards.
Rules
max(activity_at, committed_at)across its revision family and its direct ordinary subtasks is older than N days.activity_atadvances on messages and at the end of every run.committed_atis included so that a task restored from the archive is not archived again on the next sweep.committed_at, which can only delay archiving.has_unread), so a result the user hasn't seen is never hidden;archived_atvalues that retention would then trip over.Proposed design
Setting.
{ enabled, days, enabledAt, revision }lives in its own Host document,auto-archive.json, with the same write path and constraints asarchive-retention.json. Keeping it separate means the two switches never contend on one revision.Sweep. A lane in
HostStorageMaintenance, run after Ready: every 15 min when idle, every 1 s while work remains, at most 8 families per tick.session_catalog_by_activity(activity_at, session_id)with a cursor. The other conditions are filtered on the joined metadata.Shared code. The clock guards and the "wait for the in-flight tick" setting serialization move out of the retention coordinator into a small shared helper, so the two policies don't carry two copies.
Results. Latest-only:
lastRun { at, archived, skippedBusy, failed, paused? };lastArchive { at, count }.Protocol.
session.autoArchive.queryandsession.autoArchive.set(archiving isn't storage), with the next free compatibility epoch.Desktop. A per-Host section on Settings › Archived tasks, next to retention, with:
The copy says that archived tasks can be restored, and that pinned, running, waiting-on-you and unread tasks are kept. A one-time notice outside Settings, "Automatically archived N tasks", links to Archived tasks, where restoring a task undoes it. It reuses the notice being added for retention.
Known limits
Gap in manual archive (separate)
Manual archive today doesn't check active WorkHub delegations or live linked descendants either. Changing that changes manual behaviour, so it will be proposed separately rather than folded in here.
PR plan
Refs #5776, #5899, #5902.