docs/design/2026-07-17-workspace-session-info.md
session-info aggregate endpointGET /workspace/:id/sessions is cursor-paginated and does not return a total.
GET /daemon/status exposes live in-memory sessionCount only. Workspaces with
many persisted sessions (for example from scheduled tasks) cannot learn the
local store size without paging every session.
Add:
GET /workspace/:id/session-info
GET /workspaces/:workspace/session-info
Response (illustrative):
{
"active": 450,
"archived": 30,
"total": 480,
"live": 2,
"expensive": true,
"cost": "disk_scan"
}
live is omitted for an untrusted secondary workspace because those catalog
reads must not query the live bridge. If the scan reaches its safety limit or
cannot classify a candidate JSONL file, the response includes
"truncated": true; persisted counts are then lower bounds.
Persisted counts reuse the existing full-directory scan pattern already used by
session title search (SessionService.findSessionsByTitle /
findSessionTitlesByPrefix):
readdir the project chats dir (and archive twin)*.jsonlNo title/prompt hydration. This is O(n) on disk and must not be polled. The
response always sets expensive: true and cost: "disk_scan" so clients can
fail closed on hot paths. Docs call this out explicitly.
Default list pagination stays unchanged and does not compute totals. Do not
reuse organized-view listAllPersistedSummaries for counts — that path hydrates
full list metadata up to 50k sessions.
Always-on session_info on /capabilities, next to session_list.
total into every list page