Sidebar can miss unread Completed status for newly finished threads
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
With a newly completed background thread, when completed, the sidebar entry switched to the already-viewed/idle state instead of showing the unread Completed dot/status.
My agent claims to have tracked it down to visit-state seeding:
New thread UI state can be seeded from the thread activity timestamp:
seedVisitedAt: thread.updatedAt ?? thread.createdAt
For a just-completed thread, updatedAt can be equal to or later than latestTurn.completedAt. The sidebar's unread-completion check uses a strict comparison:
latestTurn.completedAt > lastVisitedAt
That means if lastVisitedAt is seeded to completedAt or later, the completed thread is treated as already viewed even when the user has not opened it.
Minimal bad state:
latestTurn: {
state: "completed",
completedAt: "2026-04-13T00:05:00.000Z",
},
updatedAt: "2026-04-13T00:05:00.000Z",
threadLastVisitedAtById: {
[threadKey]: "2026-04-13T00:05:00.000Z",
}
Agent's suggested fix: for first-observed completed threads after initial bootstrap, seed visit state before latestTurn.completedAt so they appear unread. Initial bootstrap history should still seed as read, so old completed threads do not all show as newly completed.
And suggested regression coverage:
- first-seen completed
thread-upsertedshows unreadCompleted - same case with
updatedAt > completedAt - post-bootstrap snapshot introducing a completed thread shows unread
Completed - initial bootstrap historical completed threads stay read
- non-
completedsettled turns do not showCompleted
Hope that's helpful! Thanks for the great work on t3 code ❤️
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the visit-state seeding path for new thread UI state and the sidebar unread-completion check using latestTurn.completedAt and lastVisitedAt. Add regression coverage for first-seen completed thread-upserted events, updatedAt later than completedAt, post-bootstrap snapshots, historical bootstrap threads, and non-completed settled turns. Done means new completed threads show unread Completed while initial history remains read.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100