Skip to content

fix: make memory sync cursor paging lossless#2

Closed
krusty-agent wants to merge 273 commits intomainfrom
feat/mc-all-consolidated
Closed

fix: make memory sync cursor paging lossless#2
krusty-agent wants to merge 273 commits intomainfrom
feat/mc-all-consolidated

Conversation

@krusty-agent
Copy link
Owner

@krusty-agent krusty-agent commented Mar 3, 2026

Summary

  • fix /api/v1/memory/sync change selection to be lossless under since+limit paging
  • add convex/lib/memorySync.ts helper to return oldest→newest changes and advance cursor to newest delivered update
  • wire convex/memories.ts to use shared helper
  • document cursor semantics in API.md
  • add unit tests for cursor behavior and no-gap paging

Validation

  • bun test convex/lib/memorySync.test.ts
  • bun test convex/lib/artifactRetention.test.ts convex/lib/presenceSessions.test.ts convex/lib/memorySync.test.ts

Why

Previously listMemoryChangesSince returned newest-first slices and set cursor to the first (newest) entry. With limits, that could skip intermediate updates forever. This change makes pagination monotonic and gap-free.

brianorwhatever and others added 30 commits February 7, 2026 07:10
When a recurring item is checked off, automatically creates a new unchecked
copy with the next due date calculated based on the recurrence frequency
(daily/weekly/monthly) and interval.

- Updated checkItem mutation to detect recurrence and create next occurrence
- Updated batchCheckItems for consistency
- New item inherits all properties (name, description, priority, tags, etc.)
- New item placed at top of list with next calculated due date
- Attachments are not copied (belong to original item)
Vite's content hashing already handles browser caching for these assets.
Caching them in the service worker causes issues when deployments have
interdependent bundles (e.g., ListView-ABC.js references ItemDetailsModal-XYZ.js
but the new deployment only has ItemDetailsModal-NEW.js).

- Bump cache version to invalidate old caches
- Skip caching /assets/*.js and *.css files with content hashes
- Let browser HTTP caching handle these (immutable, long-lived)
- Connect TagSelector to useQuery for fetching list tags
- Add useMutation for createTag, addTagToItem, removeTagFromItem
- Implement tag toggle functionality (click to add/remove)
- Auto-add newly created tags to the current item
- Add visual feedback (checkmark) for selected tags

The component was previously stubbed out with TODO comments
and an empty tags array. Now it actually works.
- Add Attachments component with upload/view/delete functionality
- Integrate Convex file storage (backend already exists)
- Show attachment indicator (📎 count) on list items
- Support images, PDFs, and text files (max 10MB)
- Add to ItemDetailsModal alongside other item properties
🔔 Notifications Feature:
- Service worker push notification handling with click-to-open
- useNotifications hook for subscription management
- Notification settings in Settings modal (toggle + reminder time)
- Local notification scheduling for items with due dates
- Reminder notifications (15m, 30m, 1h, 2h, 1d before due)
- Permission handling and graceful fallbacks

Implementation:
- src/workers/service-worker.ts: Push event handler, notification click
- src/lib/notifications.ts: Push subscription, local notifications
- src/hooks/useNotifications.tsx: React hook for notification state
- src/lib/storage.ts: Notification preferences storage
- src/components/Settings.tsx: Notification settings UI
- src/pages/ListView.tsx: Schedule notifications when viewing list
- Make SubItems.tsx fully functional with real Convex mutations
- Add sub-item creation, checking, unchecking, and removal
- Show progress bar in modal (e.g., 2/5 sub-items done)
- Add sub-item progress indicator on ListItem (📦 2/5 badge)
- Follow existing haptic feedback patterns
- Respect canEdit permissions throughout
- Sort unchecked sub-items first, checked at bottom
- Add list/calendar view toggle buttons in list header
- Integrate CalendarView component into ListView
- Click items in calendar to open ItemDetailsModal
- Calendar shows items grouped by due date
- Smooth transitions between view modes
- Add multi-select mode to ListView with select/deselect all
- Integrate BatchOperations component with check/uncheck/delete actions
- Add long-press to enter select mode on list items
- Show selection checkboxes and highlight when items selected
- Hide drag handles and remove buttons in select mode
- Count of selected items displayed in header bar
- Add built-in templates (Grocery, Packing, Weekly Tasks, Project Kickoff, Moving, Party Planning)
- Create TemplatePickerModal for selecting templates when creating new lists
- Update Home page to show template picker before blank list creation
- Create SaveAsTemplateModal for saving existing lists as templates
- Add 'Save as Template' button to ListView
- Connect Templates page with actual API and built-in templates
- Templates pre-populate lists with common items including priorities
Implement keyboard navigation and shortcuts for ListView:
- n or /: Focus add item input
- j/k or arrow keys: Navigate up/down items
- x or space: Toggle check on focused item
- e or Enter: Edit focused item
- d, Delete, or Backspace: Delete focused item
- Escape: Clear focus / close modals
- ?: Show keyboard shortcuts help modal

Features:
- Visual focus indicator (blue ring) on keyboard-navigated items
- Keyboard shortcuts help modal accessible via ? key or header button
- Existing useKeyboardShortcuts hook wired up with ListView
- AddItemInput now accepts ref for programmatic focus
- Shortcuts disabled in input fields (only Escape works)
- Focus automatically adjusts when items change
Bug: Tags couldn't be removed and appeared on every item.

Root cause: ItemDetailsModal received stale item snapshots stored in
React state. When tags were updated on the server, the modal still
showed the old data because it was using a snapshot instead of the
live query data.

Fix:
- Store only item IDs in state (editingItemId, selectedCalendarItemId)
- Look up live items from the reactive items array using useMemo
- This ensures tag changes are immediately reflected in the modal UI

The modal now receives real-time updates from Convex queries, so
tag additions/removals are properly reflected in the UI.
The previous fix (PR aviarytech#23) stopped caching hashed assets, but the root
issue remained: cached index.html still references old asset hashes.

When user visits with stale cached HTML:
1. Cached HTML references old hashes (e.g., index-abc123.js)
2. New deploy has different hashes (e.g., index-xyz456.js)
3. Browser loads old HTML → requests old JS → 404 → HTML response
4. Browser fails with 'text/html is not a valid JavaScript MIME type'

Changes:
- Network-first for navigation requests (HTML always fresh from server)
- Fallback to cache only when offline
- Cache version bump to lisa-v3 to clear old caches
- Add stale asset detection that auto-refreshes on MIME errors
- Add updateViaCache: 'none' to force SW update checks
- Periodic SW update checks every 5 minutes
- Handle controllerchange to auto-reload on SW update

This ensures users always get fresh HTML with correct asset references,
while still supporting offline access as a fallback.
- Add flex-wrap to header container to allow wrapping on small screens
- Group view toggle and action buttons together with flex-shrink-0 to prevent squishing
- Make Publish and Share buttons show only icons on mobile (text on desktop)
- Ensure buttons don't overlap or get crowded on narrow viewports

Fixes the 'buttons at the top' bug report.
…rror

The getSubItems query was being called with temporary optimistic IDs
(like 'temp-1770491397213') before items were persisted to the database.
This caused ArgumentValidationError since Convex validators require real
Id<'items'> values.

Fix:
- Add isTempId() helper to detect temporary optimistic IDs
- Skip the getSubItems query in useSubItemProgress hook when itemId is temp
- Skip the query in SubItems component when parentId is temp
- Update SubItemsProps to accept string type for parentId

This allows optimistic UI to work correctly without triggering validation
errors from queries that can't find the not-yet-persisted items.
The parentId prop accepts both Id<"items"> and string (for temp optimistic IDs),
but the addItem mutation only accepts Id<"items"> | undefined.

Added a guard to return early if parentId is a temp ID (can't add sub-items to
a non-persisted parent), and cast parentId as Id<"items"> since we've verified
it's not a temp ID at that point.

Fixes TypeScript build error TS2322.
Krusty added 28 commits March 2, 2026 23:19
@krusty-agent
Copy link
Owner Author

Superseded by aviarytech consolidated PR aviarytech#167: aviarytech#167

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants