feat(web): optional activity-ordered sidebar - #10
Open
Antisophy wants to merge 1 commit into
Open
Conversation
Adds sidebar_sort_by_recency, off by default. With it enabled the sidebar is ordered by activity rather than creation: the most recently worked-on task sits at the top and the order updates as tasks are used. A parent rises with its most recently active descendant at any depth, so a task does not sit stale above or below work happening beneath it. Siblings re-sort among themselves and nothing is reparented, leaving the tree structure untouched. Archive and Import move below the live tasks, and New Task moves to the top. Ordering needs a timestamp for when a task was last worked on, and neither existing signal answers that. last_active is cleared when a session starts, for crash recovery, and recovered from the transcript's mtime; the startup sweep resumes every in-flight session and each resume appends to its transcript, so a single restart rewrites every mtime and collapses all tasks onto one timestamp. A resume writes session and meta records rather than a conversation turn, so the newest user/assistant record in the transcript is unaffected by it. last_turn_at holds that value, read from the tail of the file rather than the whole thing since transcripts can reach tens of megabytes and this runs per task at startup. The scan window grows if the tail holds no turn, so a repeatedly-resumed but unused session still resolves. Claude and Codex transcript shapes are both recognized; an unrecognized shape yields no value and the task falls back to its creation time. last_turn_at is persisted but treated as a cache, recomputed from the transcript at every startup so a stale value cannot persist until the task is next used. Between startups touchTask maintains it, which fires on message-send and turn-completion and never on session lifecycle. Default-off means the creation-ordered list, the Archive and Import placement and the New Task position are all unchanged unless the option is set.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a
sidebar_sort_by_recencyoption, off by default. Enabling it orders the sidebar by activity rather than creation: the most recently worked-on task sits at the top and the order updates as tasks are used.Why a new timestamp
Ordering needs to know when a task was last worked on, and neither existing signal answers that.
last_activeis cleared when a session starts, for crash recovery, and recovered from the transcript's mtime. The startup sweep resumes every in-flight session and each resume appends to its transcript, so one restart rewrites every mtime and collapses all tasks onto a single timestamp. Ordering on it produces essentially the order the sweep happened to touch things.A resume writes session and meta records rather than a conversation turn, so the newest user/assistant record in the transcript is unaffected by it.
last_turn_atholds that value.Reading it
ae.workflow.history.last_turnscans the tail of the transcript rather than the whole file, since transcripts reach tens of megabytes and this runs per task at startup. The window grows if the tail contains no turn, so a repeatedly-resumed but unused session still resolves instead of reporting nothing.Claude and Codex record shapes are both recognized. An unrecognized shape yields no value and that task falls back to its creation time, which is also what happens for a task that has never run, so a fresh draft sorts near the top rather than the floor.
The value is persisted but treated as a cache: recomputed from the transcript at every startup, so a stale entry cannot survive until the task is next used. Between startups
touchTaskmaintains it, which fires on message-send and turn-completion and never on session lifecycle.Default off
With the option unset, the creation-ordered list, the Archive and Import placement, and the New Task position are all exactly as before. The sort, the group placement and the New Task move are each gated on it.
Tests
Sidebar.test.tscovers both modes: unchanged order when off, recency order when on, a parent raised by a deep descendant, siblings re-sorting without reparenting, and the group placement in each mode.last_turn.dunit tests cover a transcript whose newest records are the meta ones a resume writes, a transcript with no turns at all, malformed lines, a missing file, the Codex shape, and a turn buried past the first scan window.The hand-rolled scan was also checked against 9,599 real transcript lines across several Claude sessions and a Codex rollout, agreeing with a full JSON parse on every line, including that it reads each record's own timestamp rather than one nested in a payload.
nix flake check: full check set built. Five integration checks failed under parallel load and passed when re-run serially; a previous run of the same set failed a disjoint five, so they look load-related rather than related to this change.