Skip to content

feat(sessions): opt-in Host-owned archiving of idle tasks #5919

Description

@liugddx

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.

  • 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.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.

PR plan

  1. Refactor (no behaviour change). After feat(storage): opt-in retention for archived tasks #5902, move the clock guards and setting serialization into a shared helper.
  2. 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.

Refs #5776, #5899, #5902.

Activity

  1. garvit-arora commented on Oct 8, 2026

    @garvit-arora
    Contributor

    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.

  2. liugddx commented on Oct 9, 2026

    @liugddx
    MemberAuthor

    Thanks @garvit-arora, assigning this to you. Please follow the PR plan in the issue, so each step stays reviewable:

    1. 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.
    2. 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".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions