Skip to content

fix: align session sidebar recency with file updates#193

Open
Arshgill01 wants to merge 6 commits intomatt1398:mainfrom
Arshgill01:fix/session-sidebar-updated-at
Open

fix: align session sidebar recency with file updates#193
Arshgill01 wants to merge 6 commits intomatt1398:mainfrom
Arshgill01:fix/session-sidebar-updated-at

Conversation

@Arshgill01
Copy link
Copy Markdown
Contributor

@Arshgill01 Arshgill01 commented May 6, 2026

Summary

Fixes #181 by aligning sidebar session recency with the actual JSONL file update time.

Previously, project recency and sidebar session recency used different timestamps:

  • Project recency used the latest .jsonl file mtime.
  • Sidebar session rows/grouping used createdAt, which represents the session’s first prompt / creation time.

That meant a long-lived session started weeks ago but updated today could make the project appear fresh while the session still appeared old in the sidebar.

Changes

  • Added Session.updatedAt while preserving createdAt.
  • Populated updatedAt from the session JSONL file mtime.
  • Updated sidebar date grouping to prefer updatedAt ?? createdAt.
  • Updated session row “time ago” display to prefer updatedAt ?? createdAt.
  • Updated legacy session sorting to prefer updatedAt ?? createdAt.
  • Refreshed the selected project’s sidebar session list when an existing top-level session JSONL file changes.

Validation

  • pnpm typecheck — pass
  • pnpm test — pass, 49 files / 696 tests
  • pnpm lint — pass
  • pnpm build — pass

Notes

This intentionally avoids cache-clearing logic. The bug was caused by a timestamp mismatch between project recency and sidebar session recency, not by stale parsed session caches. Sidebar refreshes are still coalesced through the existing project refresh scheduler, so repeated JSONL writes do not trigger immediate one-refresh-per-event behavior.

Summary by CodeRabbit

  • New Features

    • Sessions now display a last-updated time when available for clearer recency.
  • Improvements

    • Sessions are sorted and grouped by last-updated time (falling back to creation time).
    • Sidebar refresh logic broadened for more responsive updates when sessions change.
  • Bug Fixes

    • Metadata parsing refined to avoid treating metadata entries as user content.
  • Tests

    • Added tests and a debug helper validating updatedAt behavior and date-grouping.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an updatedAt field to sessions, enabling the sidebar to sort and group sessions by their most recent activity. It also updates the notification listener to refresh the sidebar on any session change or addition. Review feedback recommends marking updatedAt as optional in the Session interface to accommodate legacy data and ensuring that test helpers provide numeric timestamps instead of strings to avoid runtime errors during sorting.

I am having trouble creating individual review comments. Click here to see my feedback.

src/main/types/domain.ts (93)

medium

Since the PR notes mention avoiding cache-clearing logic and the renderer code uses nullish coalescing (updatedAt ?? createdAt) to handle potentially missing data, it would be safer to mark updatedAt as optional in the interface. This accurately reflects that sessions loaded from older persistent caches may not have this field yet, preventing potential type-safety issues if other parts of the code assume it is always present.

  updatedAt?: number;

test/renderer/utils/dateGrouping.test.ts (13-14)

medium

The Session type (defined in src/main/types/domain.ts) expects createdAt and updatedAt to be numbers (Unix timestamps in milliseconds), but this test helper is providing ISO strings. While new Date() in the grouping utility can handle both, the sorting logic in sessionSlice.ts performs subtraction, which will result in NaN at runtime if strings are passed. The mock data should use numbers to match the domain model and ensure test reliability.

    createdAt: createdAt.getTime(),
    updatedAt: (updatedAt ?? createdAt).getTime(),

@coderabbitai coderabbitai Bot added the bug Something isn't working label May 6, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 17c5c15e-eb3f-4b7c-bfa5-e9d6ee7f9cc4

📥 Commits

Reviewing files that changed from the base of the PR and between f411b34 and 0178a9e.

📒 Files selected for processing (1)
  • src/renderer/utils/dateGrouping.ts

📝 Walkthrough

Walkthrough

Adds an optional session-level updatedAt timestamp (from session file mtime) and wires it into scanner output, UI display, ordering, date grouping, sidebar refresh logic, and tests; also refines session-file metadata parsing to ignore meta entries when deriving first-user-message.

Changes

Session Update Timestamp

Layer / File(s) Summary
Data Shape
src/main/types/domain.ts
Session interface gains an optional updatedAt?: number field adjacent to createdAt.
Data Production
src/main/services/discovery/ProjectScanner.ts
buildSessionMetadata and buildLightSessionMetadata populate updatedAt using the floored effective modification time of the session file.
Metadata Parsing Guard
src/main/utils/jsonl.ts
analyzeSessionFileMetadata now excludes entries with isMeta === true when deriving firstUserMessage.
Display
src/renderer/components/sidebar/SessionItem.tsx
Session item display time uses Math.max(updatedAt ?? createdAt, createdAt) (effectively updatedAt ?? createdAt) when formatting the session time.
Sorting / Fetching
src/renderer/store/slices/sessionSlice.ts
fetchSessions sorts sessions by Math.max(updatedAt ?? createdAt, createdAt) (descending), replacing the prior createdAt-only sort.
Date Grouping
src/renderer/utils/dateGrouping.ts
groupSessionsByDate computes sessionDate from Math.max(updatedAt, createdAt) to avoid regressions and group by the most recent timestamp.
Sidebar Refresh Logic
src/renderer/store/index.ts
Introduces shouldRefreshSidebar to refresh the sidebar for top-level session events when the session is unknown or the event is change/add, replacing the previous narrower condition.
Tests / Tools
test/main/services/discovery/ProjectScanner.updatedAt.test.ts, test/renderer/utils/dateGrouping.test.ts, test-debug.ts
Adds scanner test asserting createdAt from first-user message and updatedAt near file mtime; extends date-grouping tests and helpers to cover updatedAt; adds a debug script exercising ProjectScanner and session listing.

Possibly related PRs

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed PR implements all requirements from issue #181: adds Session.updatedAt field populated from JSONL file mtime, updates sidebar grouping/display/sorting to use updatedAt, and refreshes sidebar when files change.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #181. Modifications to ProjectScanner, Session type, sidebar components, sorting, date grouping, and store logic all serve the core objective without unrelated additions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/renderer/utils/dateGrouping.test.ts (1)

16-16: ⚡ Quick win

createSession always populates updatedAt, leaving the undefined fallback in dateGrouping.ts untested.

(updatedAt ?? createdAt).getTime() means session.updatedAt is always a number — the real Session.updatedAt is optional. As a result, dateGrouping.ts's updatedAt ?? createdAt branch is only exercised via equal values, never with updatedAt === undefined.

Changing to updatedAt?.getTime() is backward-compatible: all existing call-sites omit updatedAt, so they'd get undefined and fall through to createdAt in the grouping logic — same bucket, same assertions. The new test explicitly passes updatedToday, so it still produces a defined updatedAt and continues to assert Today.

♻️ Proposed fix
-    updatedAt: (updatedAt ?? createdAt).getTime(),
+    updatedAt: updatedAt?.getTime(),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/renderer/utils/dateGrouping.test.ts` at line 16, The test helper
createSession currently sets updatedAt to (updatedAt ?? createdAt).getTime(),
which always produces a numeric updatedAt and prevents exercising the
dateGrouping.ts branch where updatedAt is undefined; change the helper to use
updatedAt?.getTime() so updatedAt remains undefined when not passed, allowing
dateGrouping's (updatedAt ?? createdAt) fallback to be tested; keep any tests
that need a defined updatedAt (e.g., passing updatedToday) unchanged so they
still assert "Today".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/renderer/utils/dateGrouping.test.ts`:
- Line 16: The test helper createSession currently sets updatedAt to (updatedAt
?? createdAt).getTime(), which always produces a numeric updatedAt and prevents
exercising the dateGrouping.ts branch where updatedAt is undefined; change the
helper to use updatedAt?.getTime() so updatedAt remains undefined when not
passed, allowing dateGrouping's (updatedAt ?? createdAt) fallback to be tested;
keep any tests that need a defined updatedAt (e.g., passing updatedToday)
unchanged so they still assert "Today".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fcfb942c-e6b0-4f0f-9b25-6f65c9bed073

📥 Commits

Reviewing files that changed from the base of the PR and between 627a16e and 417c0e9.

📒 Files selected for processing (4)
  • src/main/types/domain.ts
  • src/main/utils/jsonl.ts
  • test/main/services/discovery/ProjectScanner.updatedAt.test.ts
  • test/renderer/utils/dateGrouping.test.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/renderer/utils/dateGrouping.test.ts (1)

120-129: ⚡ Quick win

Consider adding a test for when updatedAt is older than createdAt.

The new test validates the primary happy path (updatedAt is newer). However, there's no test covering the inverse — when updatedAt is provided but is older than createdAt. Given the implementation uses updatedAt ?? createdAt, a stale/incorrect mtime would silently move a session to an older group. A test like the one below would document whether that behavior is intentional:

📝 Suggested additional test case
+    it('should use updatedAt even when it is older than createdAt', () => {
+      const createdToday = new Date('2024-01-15T10:00:00Z'); // Today
+      const updatedOld = new Date('2024-01-01T10:00:00Z');   // Older
+      const sessions = [createSession('1', createdToday, updatedOld)];
+
+      const result = groupSessionsByDate(sessions);
+
+      // Documents that updatedAt is unconditionally preferred when present
+      expect(result.Today).toHaveLength(0);
+      expect(result.Older).toHaveLength(1);
+    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/renderer/utils/dateGrouping.test.ts` around lines 120 - 129, Add a test
to cover the case where updatedAt is present but older than createdAt to
document and verify behavior of groupSessionsByDate; specifically, using
createSession to build a session with createdAt newer than updatedAt, call
groupSessionsByDate(sessions) and assert the session falls into the group
determined by createdAt (e.g., Today) and not moved to Older, so we can ensure
updatedAt being older doesn't incorrectly override createdAt.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/renderer/utils/dateGrouping.test.ts`:
- Around line 120-129: Add a test to cover the case where updatedAt is present
but older than createdAt to document and verify behavior of groupSessionsByDate;
specifically, using createSession to build a session with createdAt newer than
updatedAt, call groupSessionsByDate(sessions) and assert the session falls into
the group determined by createdAt (e.g., Today) and not moved to Older, so we
can ensure updatedAt being older doesn't incorrectly override createdAt.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fba6d9db-c5b2-4ae0-9b73-a19e211cb905

📥 Commits

Reviewing files that changed from the base of the PR and between 417c0e9 and e326e52.

📒 Files selected for processing (1)
  • test/renderer/utils/dateGrouping.test.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/renderer/utils/dateGrouping.ts (1)

31-33: ⚡ Quick win

Update the function JSDoc to match updatedAt-aware grouping.

The implementation now groups by the most recent timestamp (max(updatedAt, createdAt)), but the comment still says grouping is based on createdAt only.

Proposed doc patch
- * Sessions are categorized based on their createdAt timestamp:
- * - Today: Sessions created today
- * - Yesterday: Sessions created yesterday
- * - Previous 7 Days: Sessions created 2-7 days ago
- * - Older: Sessions created more than 7 days ago
+ * Sessions are categorized based on their most recent timestamp
+ * (max(updatedAt, createdAt), with createdAt fallback):
+ * - Today: Sessions updated/created today
+ * - Yesterday: Sessions updated/created yesterday
+ * - Previous 7 Days: Sessions updated/created 2-7 days ago
+ * - Older: Sessions updated/created more than 7 days ago
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/utils/dateGrouping.ts` around lines 31 - 33, Update the function
JSDoc to reflect that grouping now uses the most recent timestamp between
updatedAt and createdAt (i.e., timestamp is computed via
Math.max(session.updatedAt ?? session.createdAt, session.createdAt)), rather
than only createdAt; mention that the variable timestamp and resulting
sessionDate are derived from the later of updatedAt and createdAt so groups
won't move backwards in time.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/renderer/utils/dateGrouping.ts`:
- Around line 31-33: Update the function JSDoc to reflect that grouping now uses
the most recent timestamp between updatedAt and createdAt (i.e., timestamp is
computed via Math.max(session.updatedAt ?? session.createdAt,
session.createdAt)), rather than only createdAt; mention that the variable
timestamp and resulting sessionDate are derived from the later of updatedAt and
createdAt so groups won't move backwards in time.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 90950b2c-77f6-49e3-821f-a310c6b8c3c7

📥 Commits

Reviewing files that changed from the base of the PR and between e326e52 and f411b34.

📒 Files selected for processing (5)
  • src/renderer/components/sidebar/SessionItem.tsx
  • src/renderer/store/slices/sessionSlice.ts
  • src/renderer/utils/dateGrouping.ts
  • test-debug.ts
  • test/renderer/utils/dateGrouping.test.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Sessions displayed not in synch with the latest date of update

1 participant