* fix(issue): prevent crash from orphan issueProviderId (#7135)
The Jira image-headers effect in task-detail-panel subscribed to
selectIssueProviderById without an error handler, so a task with an
issueProviderId pointing at a deleted provider (e.g. after sync
convergence where taskIdsToUnlink didn't cover all local tasks)
propagated the selector throw to Zone.js as a crash dialog. Wrap the
inner selector observable in catchError that logs and falls back to
of(null); the downstream jiraCfg?.isEnabled guard handles the fallback.
Also drop IssueLog.log(issueProviderKey, issueProvider) from the
throwing variant of the selector: providers may carry credentials
(host, token, apiKey) and IssueLog history is exportable.
* fix(focus-mode): sync tray countdown with in-app timer during breaks
Tray title was rebuilt from a cached currentFocusSessionTime that only
refreshed when CURRENT_TASK_UPDATED fired. addTimeSpent is gated on an
active current task, so during focus-mode breaks or task-less focus
sessions the cache froze while the in-app timer kept ticking.
Add the tick action to taskChangeElectron$ so the cache refreshes every
second whenever the focus timer is running.
Fixes#7278
* fix(ci): restore GitHub Actions SHA pins undone by 0e9218bd68
Commit 0e9218bd68 silently reverted PR #7212 (github-actions-minor group
bump) along with its stated sync/client-id work. This restores the 15
workflow files to their pre-revert state.
Actions restored to newer pinned SHAs:
- actions/upload-artifact v7.0.0 -> v7.0.1
- step-security/harden-runner v2.16.1 -> v2.17.0
- softprops/action-gh-release v2.6.1 -> v3.0.0
- signpath/github-action-submit-signing-request v2.0 -> v2.1
- anthropics/claude-code-action v1.0.89 -> v1.0.93
- docker/build-push-action v7.0.0 -> v7.1.0
- easingthemes/ssh-deploy v5.1.1 -> v6.0.3
* fix: restore i18n, UI, and docs work undone by 0e9218bd68
Commit 0e9218bd68 silently reverted the following work alongside its stated
sync/client-id changes. Files where later master commits (fec7b25f23, etc.)
already re-applied the reverted work are intentionally left untouched.
Restored:
- #7232 docs/long-term-plans/location-based-reminders.md (513 lines)
- #7199 Romanian i18n phase 3 (ro.json + ro-md.json, ~1168 lines)
- #7049 Polish translation improvements
- #7143 planner component styling (4 scss files)
- #7211 add-task-bar preserve time estimate when typing title
- #7208 task.reducer roll-up estimates for added subtasks
- #6767 focus-mode pomodoro reset button
- #7205 plugin-dev github-issue-provider TOKEN description
- #7231 mobile-bottom-nav FAB fix
- a4fe03272 iOS keyboard accessory bar (global-theme + dialog-fullscreen-markdown)
- 309670db3 ShortSyntaxEffects undefined guard
- 667a7986f Dropbox PKCE auth comment/behavior
* fix(electron): restore electron + e2e work undone by 0e9218bd68
Commit 0e9218bd68 silently reverted the following electron/e2e work.
Files already re-fixed by later master commits are left as-is:
- e2e/tests/sync/supersync-archive-conflict.spec.ts (de33234976 + 191d129ff3)
Restored:
- e8a3e156eb fix(electron): Linux autostart IDB backing-store recovery
(re-adds electron/clear-stale-idb-locks.ts + start-app.ts wiring)
- 5ce78a5b63 fix(electron): macOS Cmd+Q / Dock > Quit hang
(setIsQuiting + before-quit delegate to close-handler)
- 46e0fa2d01 fix(sync): FILE_SYNC_LIST_FILES IPC contract
(electronAPI.d.ts + local-file-sync + preload + ipc-events)
- ea1ef16307 fix(android): session-only SAF permissions on OEM devices
- 8865dc0a50 test(e2e): supersync parallel-worker stampede guard
(SUPERSYNC_SERVER_HEALTHY env-var fallback + goto retry loop)
- af7c7687e2 test(e2e): block WS-triggered downloads in non-WS specs
- 265b44db5d test(e2e): premature waitForURL on daily-summary
(this is literally the fix the bad commit's message claimed to add)
Conflict resolutions:
- e2e/utils/supersync-helpers.ts: kept the refined getDoneTaskElement
checks from d64014d086 (later than c558bcab5e) while restoring the
goto retry loop from 8865dc0a50.
- electron/start-app.ts: unioned imports (setIsQuiting +
clearStaleLevelDbLocks from theirs, fs from ours).
* fix(sync): restore sync-core work undone by 0e9218bd68
Commit 0e9218bd68 silently reverted parts of several sync fixes. Most
sync-core reverts have already been re-addressed differently on master
by later commits (1f5184f6e7, 05cd875dd6, 09f5ced2c9, 7df43358ab,
d9158d6adb, 32dbc95ed9, 8c3b08e016, f89fe1ebc3) — those files are
intentionally left untouched to avoid reverting master's newer work.
This PR restores only the pieces that are genuinely still missing:
- e8a3e156eb fix(electron): IDB backing-store autoreload (in-app piece)
operation-log-hydrator.service.ts + .spec.ts (the electron/clear-
stale-idb-locks.ts piece was restored in the prior commit)
Plus three low-risk documentation/cleanup restorations:
- operation-sync.util.ts — add "Nextcloud" to isFileBasedProvider JSDoc
- dropbox.ts — restore improved _getRedirectUri JSDoc (667a7986fb)
- dialog-get-and-enter-auth-code.component.ts — restore isNativePlatform
comment explaining why manual code entry flow is used (667a7986fb)
- file-adapter.interface.ts — remove stray "// NEW" comment (46e0fa2d01)
Intentionally NOT restored (master's newer work covers or supersedes):
- sync-trigger.service.ts / sync.effects.ts (05cd875dd6)
- sync-wrapper.service.ts (1f5184f6e7)
- sync-errors.ts (1f5184f6e7 re-added LegacySyncFormatDetectedError)
- file-based-sync-adapter.service.ts + spec (1f5184f6e7 + d9158d6adb)
- file-based-sync.types.ts (1f5184f6e7)
- operation-log.const.ts (32dbc95ed9 bumped IDB_OPEN_RETRIES to 5)
- dialog-sync-initial-cfg.component.ts (f89fe1ebc3)
- Separate JsonParseError and SyncDataCorruptedError handlers in sync wrapper
- Handle corrupted remote data gracefully instead of throwing
- Add getOrGenerateClientId() as unified entry point, eliminating dual injection
of ClientIdService + CLIENT_ID_PROVIDER in snapshot-upload, file-based-encryption,
and sync-hydration services
- Use crypto.getRandomValues() instead of Math.random() for client ID generation
- Warn user when stored client ID is invalid and must be regenerated
- Fix flaky e2e supersync tests (premature waitForURL match on daily-summary URL)
Add Google Calendar as a plugin-based calendar provider with OAuth 2.0
authentication, multi-calendar support, and event management.
- Plugin fetches events from selected read calendars, merged into the
existing calendar integration pipeline
- Context menus on planner and schedule views for calendar events:
open link, reschedule, create as task, hide forever, delete
- Reschedule opens date/time picker and updates event via plugin API,
handling both timed and all-day events correctly
- Delete with confirmation dialog
- CalendarEventActionsService extracts shared event action logic
- HiddenCalendarEventsService for permanent event hiding
- triggerRefresh() for immediate UI updates after mutations
- Multi-select config fields for choosing calendars to display
- Fix change detection for plugin select fields in provider dialog
- Electron-safe URL opening with scheme validation
Replace the accent-colored block + checkmark icon on swipe-right with
a dynamic strikethrough line that follows the touch position. The line
extends from left to right tracking the finger, transitions at the
trigger threshold, and snaps to full width on completion.
For undo (swiping on done tasks), the native text-decoration
line-through fades out via text-decoration-color animation, task
opacity increases from dimmed to full, and the checkmark unchecks.
Key implementation details:
- Strikethrough Y position adapts to task title center, with
even-line-count offset for multi-line titles
- Undo uses text-decoration-color animation on .display-value
- showUndoneAnimation input on done-toggle removes is-done class
- Left swipe (context menu) behavior is unchanged
- Zero performance impact on desktop (IS_TOUCH_PRIMARY guard)
- Update target version from 40.6.1 to 40.8.3 (E37 is EOL since Jan 2026)
- Replace Snap X11-only strategy with gnome-42-2204 plug override (Tidal HiFi
pattern) to fix the root cause while preserving Wayland support
- Fix fatal infinite recursion bug in planned protocol.handle migration code
- Add Flathub manifest upgrade section (runtime 25.08, Wayland re-enablement,
wrapper script following Signal Desktop pattern)
- Add breaking changes audit across Electron 38-40 (Node.js 22→24 is safe)
- Clarify macOS Tahoe situation (fix already in 37.6.0+, ongoing freezes are
Apple system-level memory management issues)
- Add Flathub linter-valid socket configuration
- Update ecosystem comparison table with March 2026 data
* docs: add plan for Android background sync via WorkManager
Outlines the implementation plan for using WorkManager to periodically
sync with SuperSync server in the background, cancelling stale reminders
for tasks that were completed/deleted on other devices.
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* docs: refine plan based on multi-agent architecture review
- Pin frontend hook to SyncProviderManager.currentProviderPrivateCfg$
- Add skipWhileApplyingRemoteOps() guard for selector-based effect
- Add HRX (dismiss reminder) and deadlineRemindAt to parser
- Add batch operation ds field handling
- Add ProGuard rules step for release builds
- Add error handling note for BootReceiver WorkManager enqueue
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* docs: improve plan after second review round
Key changes:
- Remove Step 5 (ReminderAlarmStore lookup) - hash-based cancellation is
sufficient, no store lookup needed
- Add BackgroundSyncProvider interface for extensibility to Dropbox/WebDAV
- Per-account lastServerSeq keyed by baseUrl hash
- Add SyncReminderScheduler helper to deduplicate scheduling logic
- Document edge cases: account switching, token expiry, force-kill,
gapDetected, notification race conditions
- Add extensibility section explaining Dropbox feasibility and architecture
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* feat(android): add background sync to cancel stale reminders via WorkManager
When a task is completed/deleted on desktop, Android reminders for that task
would still fire because the mobile app didn't know about the change. This adds
a WorkManager periodic job (every 15 min) that fetches operations from the
SuperSync server and cancels AlarmManager alarms + notifications for tasks that
are done, deleted, archived, or had their reminders dismissed.
Architecture:
- BackgroundSyncProvider interface for extensibility (Dropbox/WebDAV possible later)
- SuperSyncBackgroundProvider: lightweight HTTP client + operation parser
- SyncReminderWorker: CoroutineWorker that fetches ops and cancels reminders
- SyncReminderScheduler: helper to schedule/cancel the WorkManager job
- AndroidSyncBridgeEffects: mirrors SuperSync credentials to native SharedPreferences
- Per-account lastServerSeq prevents account-switching bugs
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* chore: update package-lock.json after npm install
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* fix(android): address review issues and add tests for background sync
Fixes from code review:
- Fix distinctUntilChanged to properly handle provider switching
(non-SuperSync emissions now treated as equal to prevent repeated clears)
- Add null-safe ops array parsing in SuperSyncBackgroundProvider
- Add write/call timeouts to OkHttpClient (30s write, 60s call)
- Remove no-op `hash and hash` line in Kotlin hash function
Tests:
- Add cross-platform parity tests for notification ID hash function
(pinned expected values that must match Kotlin implementation)
- Add AndroidSyncBridgeEffects unit tests covering:
- distinctUntilChanged comparator behavior
- credential set/clear decision logic
- observable filtering integration (dedup, null filtering)
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* fix(android): fix hash overflow and operation parser payload paths
Two critical bugs found during final review:
1. Hash function abs(Int.MIN_VALUE) bug: In Kotlin, abs(Int.MIN_VALUE)
returns Int.MIN_VALUE (still negative) due to 32-bit overflow.
Fixed by converting to Long before abs(), matching JS behavior where
Math.abs works on 64-bit floats.
2. Operation parser payload structure: The parser was looking at
p.isDone and p.task.changes directly, but the actual compact
operation format wraps everything in p.entityChanges[] and
p.actionPayload. Rewrote to use p.entityChanges as primary source
(consistent structure with entityType, entityId, changes fields)
and p.actionPayload.task.changes as secondary source.
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* docs: add long-term plan for Android background sync improvements
Covers three phases: fast app startup via cached sync seq,
push-based notification cancellation via FCM, and extending
background sync to Dropbox/WebDAV providers.
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
* fix(android): address review feedback for background reminder sync
- Remove PLAN.md from repo root (C1)
- Use EncryptedSharedPreferences for access token storage with
fallback to standard SharedPreferences on broken KeyStore (C2)
- Reset lastServerSeq when access token changes to prevent stale
seq on account switch with same server URL (I1)
- Add max iteration guard (100) to pagination loop to prevent
infinite loops from server bugs (I2)
- Use type predicate filter instead of non-null assertions (I3)
- Add exponential backoff (5min) to WorkManager schedule (S1)
- Add comments linking action type codes to frontend source (S2)
- Extract distinctUntilChanged comparator to named function with
JSDoc explaining the suppression semantics (S3)
https://claude.ai/code/session_01RkrVBB492k8RBA8zt5swwe
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Remove outdated feature requests from .github/CONTRIBUTING.md (GitLab
support already exists) and add commit message format section
- Improve PR template with type-of-change checkboxes and checklist
- Update commit guideline links in README and CONTRIBUTING.md to
reference the project's own format instead of external angular.js docs
- Add "only edit en.json" rule to TRANSLATING.md and clarify workflow
- Update add-new-integration.md provider list to match codebase (add
Trello, ClickUp, Linear, Azure DevOps, Nextcloud Deck; note GitHub
plugin migration; fix type name to BuiltInIssueProviderKey)
- Add cross-references between mac certificate docs and remove 240-line
duplicate section from update-mac-certificates.md
- Clean up update-android-app.md (specify npm version args, collapse
deprecated workflow, translate German UI labels to English)
- Add context to howto-refresh-snap-credentials.md
- Fix fine-grained token note in github-access-token-instructions.md
- Fix absolute URL to relative path in gitlab-access-token-instructions.md
- Fix grammar in i18n-script-usage.md
- Add status headers to all 19 long-term plan files (Planned, Completed,
Archived with reason, Investigation Complete)
- Fix broken relative link in hybrid-manifest-architecture.md
- Delete supersync-scenarios-simplified.md (duplicate of
supersync-scenarios.md; known issues already covered there)
- Rename vector-clock-pruning-research.md to
vector-clock-history-and-alternatives.md for clarity
Design for extending the existing CalDAV provider with VEVENT (calendar
event) support alongside existing VTODO sync. Serves privacy-focused
self-hosted calendar users with no new auth infrastructure needed.
Complements the Google Calendar provider design.
Evaluates authentication approaches for cross-platform Google Calendar
integration and documents decisions: hybrid auth proxy with user-provided
credentials option, REST API v3, and phased two-way sync rollout.
Document findings from attempted Electron upgrade including the
upstream blocker (electron-builder#9452) for Snap packaging and
a phased implementation plan for when it's resolved.
When encryption was enabled, forceUploadLocalState (triggered by "Use local"
in conflict dialog) caused double-encryption: the upload service encrypted the
state payload, then the file adapter encrypted the entire file. On download,
only the outer layer was decrypted, leaving the state as an opaque string that
couldn't be hydrated — making "Use remote" silently fail and forcing a
ping-pong loop between clients.
Fix: _uploadSnapshot now uses getStateSnapshot() (matching _buildMergedSyncData)
instead of the passed state parameter, since file-level encryption already
handles security.
Also: clean up dead return values in _buildMergedSyncData, reset
_lastSyncTimestamps in _uploadSnapshot for consistency, and update stale
piggybacking doc reference.
Remove duplicate LegacySyncProvider enum and use SyncProviderId everywhere.
The two enums had identical values but were separate types for historical
reasons, making the "Legacy" name misleading since providers are actively used.
- Add deterministic tie-breaking test for vector clock pruning with
equal counters (shared-schema)
- Remove last isLikelyPruningArtifact reference from entity versioning doc
Lower the cap to leave headroom for future increases and surface
size-related edge cases earlier. All pruning logic is MAX-agnostic
so this is a safe constant change with documentation updates.
- Remove dead test:shard:pfapi script from package.json
- Update AGENTS.md persistence layer path to op-log and sync
- Update documentation file paths in secure-storage.md,
vector-clocks.md, and quick-reference.md