Add recency sorting to project/list (#41223)

## What changed

- Include `recencyAt`, derived from the newest non-archived assigned thread, in project responses.
- Let `project/list` sort by `position` or `recencyAt` in either direction, with recency as the default descending order for that key and projects without activity placed last.
- Encode the sort key, direction, and millisecond-precision anchor in new cursors while retaining existing ascending-position cursors.
- Add an index for project recency lookups and document the API's sorting and pagination behavior.

## Testing

- Cover recency updates when threads are assigned, archived, unarchived, or deleted.
- Cover ordering, null handling, tie-breaking, cursor pagination, invalid sort combinations, and cursor mismatches.

GitOrigin-RevId: 6165e2b9976b0b45cfa16bcd42978b67811f6df5
This commit is contained in:
Anton Panasenko authored and copyberry committed 2026-08-27 23:43:46 +00:00
1 parent 2d929eb7c3
commit f6726e8986
22 files changed
+796 -122

No files matched your search

+11 -1
View File
@@ -5,6 +5,7 @@ use crate::DeletedProject;
use crate::ListProjectsParams;
use crate::MoveProjectParams;
use crate::ProjectMoveOutcome;
use crate::SortDirection;
use crate::StoredProject;
use crate::StoredProjectRoot;
use crate::StoredProjectsPage;
@@ -20,7 +21,15 @@ pub(super) async fn list_projects(
let state = state(store)?;
let has_cursor = params.cursor.is_some();
let page = state
.list_projects(params.cursor.as_deref(), params.limit)
.list_projects(
params.cursor.as_deref(),
params.limit,
params.sort_key,
match params.sort_direction {
SortDirection::Asc => codex_state::SortDirection::Asc,
SortDirection::Desc => codex_state::SortDirection::Desc,
},
)
.await
.map_err(|error| {
if has_cursor && error.to_string().starts_with("invalid project cursor:") {
@@ -178,5 +187,6 @@ fn stored_project(project: codex_state::Project) -> StoredProject {
position: project.position,
created_at_ms: project.created_at_ms,
updated_at_ms: project.updated_at_ms,
recency_at_ms: project.recency_at_ms,
}
}