Skip to content

[Bug]: Enabling retention activates eight days before a different initial age can be chosen #14743

Description

@tris203

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

Also affects desktop's shared Settings UI and server cleanup.

Steps to reproduce

Source-established reproduction; an integrated current-client/deletion run has not yet been performed.

  1. Use isolated test state with automatic cleanup disabled. Prepare an otherwise eligible T3-managed worktree whose latest activity is 15 days old: clean working tree, no protected ignored files, no live provider session or terminal, no running/queued turn or pending input, and no shared/project-root ownership blocker.
  2. Open Settings → Storage for that environment and try to enable Delete inactive worktrees with a retention period of 30 days.
  3. While the rule is Off, the age input is hidden. Enable the switch to make it editable.
  4. The switch immediately saves 8 days and the server enqueues cleanup. Leave that value in place until the settings-triggered sweep completes, then commit 30 days. The 15-day worktree qualifies under the intermediate 8-day rule even though it should be retained under the intended 30-day rule.

For an automated reproduction, observe the setting publication and cleanup worker drain rather than relying on a sleep. During a normal quick edit, removal depends on whether the sweep reaches deletion before the later 30-day update; it is not guaranteed on every interaction.

Expected behavior

A user can choose the initial retention age without first activating a shorter cleanup period they did not choose. The exact interaction is a maintainer design decision.

Actual behavior

Enabling the rule persists 8 days before its age can be edited. Cleanup can run during that intermediate state and remove items that the intended longer retention period would retain.

The same RetentionControl serves inactive worktrees, browser captures and rotated logs, so this activation sequence affects all three. Worktree cleanup preserves branches and conversation history; this report does not claim that commits are deleted. Old captures/logs have their own deletion behavior.

Impact

Minor bug or occasional failure

The deletion window depends on sweep timing. The underlying inability to enter a different initial age before enabling is present whenever the rule starts Off.

Version or commit

main @ 99e08526e5ec84f294940cba5929841518c52fec, inspected on 2026-10-02.

Environment

Source investigation of the shared web/desktop Settings UI and Node server. No browser/device or live user database was used; no integrated UI or actual-filesystem deletion reproduction is claimed.

Source evidence and verification

  • RetentionControl renders the number input only when value !== null; its switch invokes onChange(enabled ? 8 : null).
  • Settings callbacks immediately dispatch the rule update. The server settings subscription enqueues a sweep when cleanup settings change.
  • The age predicate makes a 15-day worktree eligible at 8 days and ineligible at 30. The final policy recheck prevents removal if the later update arrives in time; it cannot undo completed removal.
  • A scratch Node check extracted and executed the actual switch callback and age predicate from this source: enabling writes 8, and the 15-day fixture is eligible at 8 but not 30. It also checked the hidden-input condition and settings-change enqueue path. This verifies the source-level causal chain, not rendered UI behavior or end-to-end deletion.

This is not a per-keystroke save bug: the current number field keeps typed changes local until commit. General immediate application of a deliberately chosen cleanup rule is documented behavior.

Scope for triage

Please confirm the intended behavior for choosing the first enabled age. This report is limited to activating an unwanted intermediate retention period. It does not require storage reporting, changed cleanup eligibility, or a panel-wide Save/Discard workflow. The broader proposal in #14653 remains a separate direction-approval question; #13836 concerns ignored-file eligibility, not this activation sequence.

Workaround

Leave the rule Off until the initial-age workflow is addressed if an intermediate 8-day policy would remove items you intend to retain. Changing it quickly to 30 is not a reliable workaround because cleanup may already have run.

Investigated with GPT-6-Astra through the Codex harness in T3 Code.

Activity

  1. juliusmarminge commented on Oct 2, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the careful source trace, @tris203. This is a real bug, and I confirmed it on current main (99e08526e5). I didn't find another open issue for this activation sequence, and I didn't run a live deletion.

    What's happening

    RetentionControl in apps/web/src/components/settings/StorageSettings.tsx hides the age field until the rule is on, and the switch saves 8 right away (onCheckedChange={(enabled) => onChange(enabled ? 8 : null)}). That update goes straight to the server, and any change to the cleanup settings queues a sweep in storageCleanup.ts. A 15-day-old worktree qualifies at 8 days but not at 30. The policy re-check just before git.removeWorktree skips the worktree if the 30-day value arrives in time, but it can't bring back one the sweep already removed. Browser captures and rotated logs use the same control, so they have the same race.

    The number field already keeps edits local until you commit, and applying a period you actually committed is documented behavior. The bug is only the 8-day policy you never saw, which gets saved on the way from Off to the age you meant.

    Likely fix

    Keep the fix inside RetentionControl. Turning the switch on should show a local draft of 8 and not call onChange until you commit an age you can see. Turning it off can still save null immediately, and leaving without committing should keep the rule off. No storage reporting or panel-wide Save/Discard flow is needed.

    Related

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 2, 2026
  3. added a commit that references this issue on Oct 2, 2026
    eb1cf14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions