Repository navigation
Description
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 (sidebar presentation), with the read-state mutation in apps/server.
Steps to reproduce
- Use a thread whose latest run has finished successfully.
- Snooze the thread for a short duration, for example Custom → 1 minute.
- Let the snooze timer expire. The thread returns with the Woke badge in the sidebar.
- Click Dismiss Woke notification. The badge disappears.
- From the thread's context menu, choose Mark unread.
No new run or new snooze occurs between steps 4 and 5.
Expected behavior
The thread shows Done, reflecting its unread completion. A wake notification that was already dismissed should stay dismissed until another snooze/wake cycle.
Actual behavior
The old Woke badge reappears instead of Done. Marking the completion unread also makes the previously acknowledged wake look unseen again.
Impact
Minor bug or occasional failure: the sidebar displays a stale wake notification and obscures the intended unread-completion status.
Version or commit
Observed with the official backend release 0.1.2-nightly.20261022.3541, built from 044f07257c9684ae4543bd1e1ebf9c394e9e3830.
Environment
Ubuntu 20.04.6 LTS, Linux x86_64 backend, connected T3 client using the web/desktop sidebar. This appears independent of the model/provider.
Investigation
Source references are pinned to the affected release commit:
- Dismissing Woke sends a thread visit at
wokeAt, acknowledging the notification throughlastVisitedAt. - Mark unread rewinds
lastVisitedAtto one millisecond before the latest run's completion, while the mutation retains the expired snooze fields. - The sidebar then sees
lastVisitedAt < wokeAtagain and prioritizes Woke over Done.
For example: completion at 10:00, snooze expiry and dismissal at 10:05, then Mark unread moves the read timestamp to 09:59:59.999. The same 10:05 wake is classified as unseen again.
Workaround / locally verified fix
A local patch to the same release commit retires an expired snooze when handling thread.mark-unread: clear snoozedUntil and snoozedAt, retaining the expiry timestamp in lastSnoozeWakeAt for auto-settlement. Future snoozes are preserved and updatedAt is unchanged.
The reporter confirmed that the original sidebar sequence works after installing this patched backend.
Regression coverage checks the read timestamp rewind, expired versus future snoozes, the retained wake timestamp, and replaying the mark-unread command after snoozing again. These focused suites passed on the release source: 54 tests.
vp test run \
apps/server/src/orchestration-v2/Orchestrator.control-reads.test.ts \
apps/server/src/orchestration-v2/ThreadSettlementService.test.ts \
packages/client-runtime/src/state/threadSnoozed.test.tsThe compiled executable was also smoke-tested with an isolated data directory. The sidebar confirmation was manual; no automated browser test was run. This is a local workaround, not an upstream fix or a claim about newer releases.
Activity
juliusmarminge commentedon Oct 24, 2026
Reproduced on current main eea9895, using the web dev app on Linux with fresh isolated state and a successfully completed Codex run. Custom snooze for 1 minute → timer expires → Dismiss Woke notification removes the badge → context menu Mark unread restores Woke instead of Done. Repeated dismissal and Mark unread gives the same result. Existing fix PR #24080 covers this report.