Repository navigation
Conversation
FiredKeyStore and NotificationIds each computed the retention cutoff as dayLabelOf(now.subtract(Duration(days: 14))). That is 14 x 24 h: across a DST change one day is 23 or 25 h, so in the hour either side of local midnight the cutoff landed one label early or late (AGENTS.md: day arithmetic must not assume 86400 s). One shared FiredKeyStore.cutoffLabel([now]) now does it with the existing calendar helpers, dayLabelBefore(todayLabel(now), 14), and NotificationIds uses it instead of its own copy. The effect was only a day more or less of notification bookkeeping kept twice a year, but the two copies could also have drifted apart.
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
Reviewer's GuideAPIExpose a shared calendar-day cutoff helper so notification retention no longer depends on elapsed 24-hour periods.
Uses of the APIUse the shared cutoff for fired-key database and preferences pruning, and for notification-slot pruning, removing the duplicated date-label dependency.
TestsVerify the shared cutoff stays at 14 calendar days across DST transitions and on an ordinary day.
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="test/notify_retention_dst_test.dart" line_range="30" />
<code_context>
+ lib.lookupFunction<_UnsetenvNative, _UnsetenvDart>('unsetenv')(key);
+ } else {
+ final value = tz.toNativeUtf8();
+ lib.lookupFunction<_SetenvNative, _SetenvDart>('setenv')(key, value, 1);
+ calloc.free(value);
+ }
</code_context>
<issue_to_address>
**Windows test setup fails**
When the Flutter test suite runs on Windows, `_setProcessTz` looks up POSIX `setenv`/`tzset` symbols that Windows does not provide, so `setUpAll` throws before assertions run and the test file fails.
Use a Windows-compatible way to set and restore the process time zone, or skip this setup on Windows.
Also at `test/notify_retention_dst_test.dart:42`.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 1 finding to address first, and the new calendar-day cutoff is used to prune both fired-key and notification-slot claims. If it removes a claim too soon, a later event can send a duplicate notification; reverting does not restore claims already deleted.
Blocking findings: test/notify_retention_dst_test.dart:30
| lib.lookupFunction<_UnsetenvNative, _UnsetenvDart>('unsetenv')(key); | ||
| } else { | ||
| final value = tz.toNativeUtf8(); | ||
| lib.lookupFunction<_SetenvNative, _SetenvDart>('setenv')(key, value, 1); |
There was a problem hiding this comment.
🟡 Medium · Windows test setup fails
When the Flutter test suite runs on Windows, _setProcessTz looks up POSIX setenv/tzset symbols that Windows does not provide, so setUpAll throws before assertions run and the test file fails.
Use a Windows-compatible way to set and restore the process time zone, or skip this setup on Windows.
Also at test/notify_retention_dst_test.dart:42.
Prompt for AI agents
In `test/notify_retention_dst_test.dart` at line 30:
**Windows test setup fails**
When the Flutter test suite runs on Windows, `_setProcessTz` looks up POSIX `setenv`/`tzset` symbols that Windows does not provide, so `setUpAll` throws before assertions run and the test file fails.
Use a Windows-compatible way to set and restore the process time zone, or skip this setup on Windows.
Also at `test/notify_retention_dst_test.dart:42`.
Why
FiredKeyStore._cutoffLabel()andNotificationIds._pruneeach computed the 14-day retention cutoff asdayLabelOf(DateTime.now().subtract(const Duration(days: 14))). That is 336 hours, not 14 calendar days: across a DST change one of those days is 23 or 25 h, so in the hour either side of local midnight the cutoff lands one label early or late. AGENTS.md §3.7 calls this out ("Day-length arithmetic must not assume 86400 s"), andday_label.dartalready hasdayLabelBeforefor exactly this.Impact is small, to be upfront: twice a year, dated fired-key / slot bookkeeping is kept a day longer or shorter. The dedupe only needs today's keys. The other reason to fix it is that the same cutoff was written out twice and could drift.
What changes
FiredKeyStore.cutoffLabel([DateTime? now])(was private_cutoffLabel()):dayLabelBefore(todayLabel(now), retentionDays)!. Both of its callers (the DB prune and the prefs-mirror prune) use it.NotificationIds._pruneusesFiredKeyStore.cutoffLabel()instead of its own copy (NotificationIds.retentionDaysis already defined asFiredKeyStore.retentionDays). Its now-unusedday_label.dartimport is dropped.Tests
test/notify_retention_dst_test.dartmoves the process timezone to America/New_York (libcsetenv/tzset, asday_window_dst_testdoes) and checks the cutoff at 00:30 the day after the 23 h day (2026-02-23, the old code gave2026-02-22), at 23:30 the day after the 25 h day (2026-10-19, old:2026-10-20), and on an ordinary day. A first test asserts the zone really has DST, so the others can't pass vacuously. With the old formula, the two DST cases fail.FiredKeyStore/NotificationIds: 86 passed.flutter analyze: no issues.🤖 Generated with Claude Code
Summary by Sourcery
Use calendar-day retention cutoffs consistently across notification bookkeeping and verify them across daylight-saving transitions.
Bug Fixes:
Enhancements:
Tests:
Summary by CodeRabbit