Conversation
Adds an off-by-default "Auto-archive settled threads" setting (30 days when enabled) to Settings → General → Organization and mobile Thread behavior. The settlement reactor archives threads that stayed settled past the threshold through a new internal thread.auto-archive command, which the decider rejects if the thread was un-settled or re-settled since the snapshot. The setting is project-scoped, synced like the auto-settle preferences, and gated by a threadAutoArchive server capability. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| command, | ||
| threadId: command.threadId, | ||
| }); | ||
| if (thread.settledOverride !== "settled" || thread.settledAt !== command.settledAt) { |
There was a problem hiding this comment.
🟡 Medium orchestration/decider.ts:464
A queued thread.auto-archive can archive a thread after the user restores it. The guard only compares settledOverride and settledAt, while thread.unarchived leaves both values unchanged, so a snapshot taken before archive/restore still passes and re-archives the restored thread. Include an archive/lifecycle generation in the snapshot guard or invalidate the pending auto-archive on restore.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/orchestration/decider.ts around line 464:
A queued `thread.auto-archive` can archive a thread after the user restores it. The guard only compares `settledOverride` and `settledAt`, while `thread.unarchived` leaves both values unchanged, so a snapshot taken before archive/restore still passes and re-archives the restored thread. Include an archive/lifecycle generation in the snapshot guard or invalidate the pending auto-archive on restore.
There was a problem hiding this comment.
Confirmed, and it was broader than the queued-command race: thread.unarchived left settledAt untouched, so even without a race the next one-minute sweep would re-archive a restored thread immediately.
Fixed in 84ec6da. When the restored thread is settled, thread.unarchived now carries a fresh settledAt. The projector, projection, and client reducer apply it, so:
- a restored thread gets a new full window before it can auto-archive again
- any
thread.auto-archivequeued before the archive/restore carries the oldsettledAtand is rejected by the existing guard
Restoring an active thread is unchanged. Covered by new decider and projector tests.
There was a problem hiding this comment.
Sorry, I'm unable to act on this request because you do not have permissions within this repository.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces a substantial cross-layer capability that automatically archives user threads and adds a new 30-day enablement default. An unresolved lifecycle race can re-archive a restored thread, so the production behavior requires human review. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
Unarchiving left settledAt unchanged, so the next settlement sweep archived a restored thread again, and a thread.auto-archive queued before an archive/restore still matched its settledAt guard. thread.unarchived now carries a fresh settledAt when the thread is settled; the projector, projection, and client reducer apply it. Restores get a new window and any stale auto-archive command is rejected by the existing guard. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: pingdotgg/t3code/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (24)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe change adds an off-by-default setting for automatically archiving settled threads after a configurable number of days. It adds capability-aware web and mobile controls, server-side eligibility checks and archive commands, and resets the settled-time clock when a settled thread is restored. ChangesSettled-thread auto-archive
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~45 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant ThreadSettlementReactor
participant isAutoArchiveDue
participant Decider
ThreadSettlementReactor->>isAutoArchiveDue: Check thread age against the resolved archive delay
isAutoArchiveDue-->>ThreadSettlementReactor: Return eligibility
ThreadSettlementReactor->>Decider: Dispatch thread.auto-archive with settledAt
Decider-->>ThreadSettlementReactor: Accept or reject based on the current settled state
Suggested reviewers: Merge Risk: ⚪ Minimal · up to The auto-archive setting can be merged after normal checks; no outstanding behavior issue was established. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to Auto-archive is off by default and archived threads can be restored. However, an archive already queued under an enabled setting can still complete after that setting is turned off or its delay is increased. The impact is limited to eligible settled threads, but the setting may not take effect immediately for work in flight. Retained concerns
Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 20 functions across 23 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Settled threads pile up forever. Auto-settle clears finished work out of the active list, but the settled shelf keeps growing (hundreds of threads on a busy install) until someone archives them one by one.
This adds Auto-archive settled threads to Settings → General → Organization, under the auto-settle rows. It is off by default. Turning it on uses 30 days, and you can change the number. A thread archives once it has been settled for that many days. Archived threads stay in Settings → Archive and can be restored as usual.
How it works
sidebarAutoArchiveAfterDaysserver setting (null= off, 1–90 days, same bounds as auto-settle). It is project-scoped like the auto-settle settings, so a project can override or disable it. There's also a newthreadAutoArchivecapability so clients hide the controls on older servers, which would silently ignore the key.ThreadSettlementReactoralready runs a sweep every minute and on settlement-setting changes. After the settle pass, it archives threads that are still settled past their resolved threshold. It dispatches a new internalthread.auto-archivecommand that carries thesettledAtit observed. The decider rejects the command if the thread was un-settled or re-settled after the snapshot, so new activity can never race into an archive. It emits the existingthread.archivedevent, so projection and clients need no changes.thread.unarchivedgives it a freshsettledAt. The thread gets a new full window, and any auto-archive queued with the old value fails the guard.docs/user/thread-sidebar.md.Providers are unaffected.
Screenshots (2880×1800)
Testing
thread.auto-archive: archives when still settled at the observed time; rejects un-settled, activity-cleared, re-settled, and already-archived threads.isAutoArchiveDuepolicy tests, plus a reactor test covering off-by-default, the threshold, and a project override that disables it.storage cleanupcases inThreadSettlementReactor.test.tsfail the same way on untouchedmainin my environment.Model: Claude Opus 5.5 (1M context) · Harness: Claude Code in T3 Code
🤖 Generated with Claude Code
Summary by CodeRabbit