POST /tasks now accepts `parentId` and creates a subtask via
TaskService.addSubTaskTo (inheriting the parent's projectId). Invalid
parent references return 404 PARENT_NOT_FOUND; nested parents return
400 INVALID_PARENT. `subTaskIds` on POST and `parentId`/`subTaskIds`
on PATCH are now rejected with 400 UNSUPPORTED_FIELD instead of being
silently dropped.
Fixes#7346
Show "Week N · start – end" in week view and "Month YYYY" in month view,
right-aligned in the schedule nav bar. Move the week/month view toggle
out of main-header into the left of the schedule bar. Replace the "Now"
text button with a circle icon next to the chevrons, and disable prev
navigation when today is already in the displayed range.
- ISO 8601 week numbers via existing getWeekNumber util
- Parse day strings via parseDbDateStr to avoid UTC-midnight TZ skew
- Reuse existing T.F.WORKLOG.CMP.WEEK_NR / T.F.TODAY_TAG_TITLE keys
- Drop the duplicate month-title inside schedule-month; the shared nav
now owns the label for both views
Trace the root cause to Electron's init order: Ozone platform selection
fires in C++ PreEarlyInitialization() and the chosen platform is
memoized in ui/ozone/platform_selection.cc's g_selected_platform
static. Any app.commandLine.appendSwitch() from main.js runs in
PostEarlyInitialization() — after the memoization, so the write is
correct but the read has already happened. Primary source: electron
PR #48301 diff + Chromium ui/ozone/platform_selection.cc.
This confirms the argv wrapper is structurally the only fix available
from outside the Electron binary. Also documents why the two
lower-friction alternatives don't work:
- ELECTRON_OZONE_PLATFORM_HINT env var was removed as dead code in
Electron 39 (PR #47983).
- Setting XDG_SESSION_TYPE=x11 via snapcraft.yaml environment: would
work for Ozone but would fool IdleTimeHandler, silently breaking
GNOME Wayland idle detection.
Confidence in the mechanism hypothesis is raised from ~40% to ~85%.
Residual unknown: whether GPU child-process CommandLine inheritance
exposes a late appendSwitch to subsystems other than Ozone. Not
verified from source; does not change the shipping recommendation.
Related: issue #7270.
Address findings from code-reviewer + debugger-assistant +
refactor-specialist multi-review on 8e1c47ebc2:
- afterPack: read wrapper source before rename; on writeFile failure,
roll the rename back so a broken intermediate state can't ship a
package with no launcher. Strengthen idempotency check to require a
shebang at binPath (both files alone no longer counts as "installed").
- wrapper: gate the X11 injection on \$SNAP_NAME = "superproductivity",
not just \$SNAP set. An xdg-open from a sibling snap (e.g. Firefox)
leaks \$SNAP into the child env, which previously would have silently
forced XWayland on .deb/.rpm users. Derive BIN_DIR from \$SNAP
directly when we are our snap, avoiding fragile \$0 resolution
through snapd's wrapper chain. Stop argv scanning at -- so positional
args that resemble --ozone-platform aren't misread as a user override.
- app-control: point app.relaunch() execPath at the sibling shell
wrapper instead of the default process.execPath (which is the renamed
ELF and would bypass the flag injection on a relaunched Snap+Wayland
instance).
- Move build/snap-wrapper.sh -> build/linux/snap-wrapper.sh to match
the existing build/linux/ layout convention.
- Update research doc §18 to reflect the tightened predicate and the
relaunch fix.
Field reports on issue #7270 (v18.2.4 / v18.2.5) show that
app.commandLine.appendSwitch('ozone-platform','x11') is not equivalent
to the CLI flag on Snap+Wayland: Chromium's Ozone init dlopens
libEGL/libgbm on the core22 Mesa path before the switch is honored and
segfaults under host-vs-snap Mesa ABI drift, while the same flag on
argv consistently works.
Install an afterPack hook that renames the Electron binary and drops a
shell wrapper at the original name. The wrapper injects the flag into
argv only when \$SNAP is set AND the session is Wayland — non-Snap
targets (AppImage, .deb, .rpm) and X11 sessions pass through untouched.
Matches the mechanism used by snapcrafters/signal-desktop and
snapcrafters/mattermost-desktop.
See docs/research/snap-wayland-gpu-fix-research.md §18 for the full
evidence trail, drawbacks, validation plan, and removal conditions.
7-reviewer multi-review (6 Claude focus-agents + Codex CLI) over the
cherry-picked PR #7273 diff, plus 5 parallel research agents on Mesa
mechanism, Chromium flag behavior, peer-app field data, core22→core24
cost, and marker-timing semantics.
§17 captures: findings that changed the PR (now shipped in the
previous commit), disagreements worth noting (Codex W-C1 vs. three
independent flag-pair sources), validated decisions (APP_READY signal,
Snap config shape, novelty of the crash-loop mechanism), deferred
scope (pre-flight probe, core24 migration, forensic listener,
TOCTOU hardening), and confidence deltas.
Adds 14 new references (Mesa commit, libgbm ABI instability,
peer-app issues on Ubuntu 25.10, Canonical core24 migration docs,
electron-builder#8548, Obsidian launcher) tying each to the §17
claim it supports.
The "PR #7273 was closed" paragraph predates the two post-v18.2.4
field reports in §16. Updated to acknowledge the revisit condition
explicitly: reopen only if a real report came in that X11 widening
didn't rescue. §16 documents two such reports (Intel/Ubuntu 24.04 and
AMD/Ubuntu 25.10), both showing #7266's guard firing correctly and
still not rescuing the user. PR #7273's mechanism is no longer
speculative — it rescues the population #7266 provably does not.
Also wrap DISPLAY_COMPOSITOR in backticks on line 846 to prevent
prettier from parsing underscores as an italic span across lines.
Second post-v18.2.4 field report (Ubuntu 25.10 + AMD Raphael) replicates
DerEchteKoschi's failure pattern (Ubuntu 24.04 + Intel Arrow Lake-P):
#7266's guard fires, MESA-LOADER fails on gbm/dri_gbm.so, GPU process
segfaults in a loop regardless of ozone platform. Confirms the tail is
driven by host-Mesa/core22-runtime drift, not GPU vendor or generation.
Changes in §16:
- Intro + Environments: switch to n=2 framing with per-reporter blocks.
- What the log proves: clarify shared pattern; flag nekufa's
`--ozon-platform` typo (short-circuit in start-app.ts:73-75 only
matches `--ozone-platform`, so the log reflects the programmatic path).
- Scope table: drop "Arrow Lake, newer" parenthetical — generic
drift row covers any Ubuntu ≥ 24.04 with core22 mismatch.
- PR #7273 framing + core24 urgency cite n=2 evidence.
- Open question: note nekufa's typo disqualifies from CLI vs
appendSwitch question.
- Actionable outcomes split reply-to-thread per reporter; add
item 6 for separate Ctrl+Shift+X issue.
- Confidence: arch-specificity upgraded Medium → High.
- References: add both comment permalinks.
Prettier formatting applied.
The base body{} block was re-declaring --transition-duration-s (180ms)
and --transition-duration-l (400ms), shadowing the :root defaults
(150ms/375ms) for every element in the app regardless of theme
(body.isDarkTheme did not re-override them). That made the recent
token sweep silently drift some callers from 150ms to 180ms (+20%)
instead of the intended 1:1 swap, and left the light/dark experience
identical despite looking theme-specific.
Remove the three overrides — durations are now consistently the :root
defaults in both themes. Visible effect: task hover/select, done-toggle
SVG, and onboarding animations run about 30ms faster.
Update styling-guide.md to drop the obsolete "light theme overrides"
note and keep the bucket-rounding guidance.
Introduce coherent scales that replace ad-hoc hardcoded values and give
future components documented tokens to adopt.
Typography (src/styles/_css-variables.scss + src/styles/page.scss via
body styles in the sweep commit):
- --font-size-xs..3xl (11–28px) with --font-size-md as the body base.
- --font-weight-medium/semibold/bold (400 is the browser default, not
declared).
- --line-height-tight/snug/normal (unitless so they scale with size).
- --letter-spacing-tighter/tight/normal/wide.
- --font-mono-stack for code/kbd/pre/samp.
- --font-primary-stack reordered to lead with native OS UI fonts
(-apple-system, Segoe UI Variable Text, Roboto) with Inter/Open Sans
as graceful fallbacks.
Radius scale:
- --radius-xs/sm/md/lg/xl and --radius-pill.
- --card-border-radius retargets to var(--radius-md) (4px → 8px) and
--task-border-radius retargets to var(--radius-sm) (4px → 6px) for a
softer surface treatment; both legacy aliases stay so 30+ consumers
don't need touching.
Focus ring (keyboard accessibility):
- --focus-ring-width / -offset / -color tokens.
- .focus-ring opt-in utility class in src/styles/util.scss using
outline on :focus-visible — Material components keep their own focus
treatment.
Font stack dedup: src/styles/_fonts.scss is the single source of truth
for the stack. _css-variables.scss interpolates it into
--font-primary-stack; themes.scss passes the same list (as a literal
string, which is all mat.m2-define-typography-config accepts) — no more
"keep in sync" drift trap.
Also fix the inherited --transition-duration--leave (double dash) typo
on the light-theme body block so the override actually matches its
intended name.
docs/styling-guide.md documents all the new tokens, correct the
transition-duration values to match _css-variables.scss (-s 150ms,
-m 225ms), and adds a Focus Ring section with adoption guidance.
First post-release report on PR #7266 (v18.2.4): X11 widening fires
but doesn't rescue user on Ubuntu 24.04 + Intel Arrow Lake-P. Mesa
DRI still fails, GPU process segfaults in a loop. Lowers the 95%
estimate, promotes --disable-software-rasterizer to must-ship, and
upgrades core24/gpu-2404 migration urgency to 18.3.
* 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)
Follow-up to issue #7270 and the now-closed PR #7273. Extends the
existing research doc with four new sections based on multi-agent
research, verification passes, and empirical reporter confirmation.
- §12: PR #7273 GPU startup guard framing and mechanism analysis.
- §13: Deepened research on Chromium/Electron/Mesa correctness, prior
art for crash-loop startup markers (Firefox recent_crashes, Chromium
in-process GpuMode stack, BugSnag/Sentry patterns), testing strategy
with concrete spec proposal, edge cases, and long-term strategy.
- §14: Verification pass findings (four parallel agents) — corrections
applied to §12 (v18.2.3 timeline, --disable-gpu wording), rejected
claims with evidence, outstanding attribution fixes.
- §15: Final PR re-evaluation — including why PR #7273 was closed in
favor of #7266 after the reporter empirically confirmed that
--ozone-platform=x11 resolves their launch failure on Ubuntu 22.04.
Keeps the research available for the next time this class of failure
surfaces (future Chromium bumps, Mesa ABI drift on core24/gpu-2404,
Flatpak packaging, etc.).
* docs(research): add Snap + Wayland GPU init failure research
Synthesizes root cause (Mesa ABI drift in gnome-42-2204), scope,
peer-app consensus, and ranked options. Recommends widening the
existing Snap-gated --ozone-platform=x11 guard in start-app.ts to
cover Snap + Wayland sessions, with core24 + gpu-2404 migration
as the long-term fix.
https://claude.ai/code/session_01Hu6EP7Xux9JRvGGGKpBfwm
* docs(research): correct electron timing and soften unverified peer claims
* fix(electron): force X11 on Snap Wayland to avoid Mesa ABI drift
The existing Snap-only X11 fallback triggered only when $SNAP/gnome-platform
was empty. In practice gnome-platform is populated but its Mesa can drift
out of ABI sync with Electron's bundled libgbm, producing
"Failed to get system egl display" and a GPU process respawn loop on
Wayland sessions. Widen the guard to also fire when the session is
Wayland (XDG_SESSION_TYPE=wayland or WAYLAND_DISPLAY set). X11/GLX
avoids the failing Wayland EGL init path entirely while preserving
hardware acceleration.
Refs: electron-builder#9452, super-productivity#5672,
forum.snapcraft.io #40975, #49173https://claude.ai/code/session_01JNxazJmDhpMp9UYV6SqnBG
* refactor(electron): address review feedback on Snap X11 force
- Handle space-separated `--ozone-platform wayland` override in addition
to the `=` form; tighten the argv scan to reject accidental substring
matches (e.g., arg values that happen to contain `--ozone-platform=`).
- Enrich the log line with raw XDG_SESSION_TYPE and WAYLAND_DISPLAY
values to make user-reported triage faster.
- Tighten comment: correct "X11/GLX" to "X11 ozone backend" (modern
Chromium uses EGL on X11), clarify the root cause as Mesa version
drift rather than bundled-library ABI drift, broaden the loss list
beyond fractional scaling, and move issue references to the commit
body per CLAUDE.md guidance.
Follow-ups flagged but not addressed here: possible interaction with
`allowNativeWayland: true` in electron-builder.yaml, GPU cache keyed
by effective ozone platform, and the longer-term core24 migration
already in docs/long-term-plans/electron-upgrade-to-v40.md.
Refs: electron-builder#9452, super-productivity#5672,
forum.snapcraft.io #40975, #49173https://claude.ai/code/session_01JNxazJmDhpMp9UYV6SqnBG
* docs(research): verify peer-app claims, correct SP electron timing
---------
Co-authored-by: Claude <noreply@anthropic.com>
- 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)
* docs(wiki): refactor download page
Rework and improve download page in preparation for README updates.
* chore(ci): simplify the initial release text
Centralizing all links to one place will make maintenance of docs
easier.
* chore(docs): Update meta docs and templates
Aligning issue templates and other docs to support the use of the wiki
and to encourage additions from others.
* chore(docs): align README with new download page
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
* feat(electron): add Local REST API for desktop automation
Add a local HTTP server (port 3876) that allows external scripts and
tools to interact with a running Super Productivity desktop app.
Features:
- Task CRUD operations (create, read, update, delete)
- Task control (start, stop, set current)
- Task archive/restore operations
- Query filters for tasks (by title, project, tag, done status)
- Read-only project and tag listing
The API is disabled by default and can be enabled in Settings > Misc.
Only accepts connections from localhost (127.0.0.1) for security.
* fix: resolve lint errors for local REST API
* fix: use lazy injection for LocalRestApiHandlerService
Fixes StartupService tests by using Injector.get() instead of direct
injection, preventing LocalRestApiHandlerService from being instantiated
when StartupService tests don't have NgRx providers.
* fix: resolve markdown lint errors in API docs
* fix: add security warning to Local REST API hint
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>
Root cause: electron-builder auto-published unsigned files via implicit
tag-based publishing (despite release:false), and spaces in NSIS
artifact names caused naming mismatches — electron-builder sanitized
spaces to hyphens while softprops/action-gh-release converted them
to dots, resulting in three sets of exe files per architecture.
Changes:
- Hardcode NSIS artifactName with hyphens to eliminate spaces
- Add --publish never to explicitly prevent auto-publishing
- Update latest.yml with signed file hashes (preserving EB fields)
- Use lockfile-pinned app-builder-bin for blockmap regeneration
- Scope blockmap publishing to NSIS setup files only
- Fail hard if latest.yml references missing files
Extract styling rules, CSS variable reference, and design token
patterns into docs/styling-guide.md for a consistent design language.
CLAUDE.md now points to the guide for all styling changes.
Add deadline support for tasks with date-only and time-specific deadlines.
Core:
- Add deadlineDay, deadlineWithTime, deadlineRemindAt fields to task model
- Add NgRx actions (setDeadline, removeDeadline, clearDeadlineReminder)
- Add meta-reducer with mutual exclusivity and input validation
- Register deadline actions in ActionType enum and op-log codes
UI:
- Create deadline dialog with calendar, time input, and reminder options
- Add deadline badge to task list row with overdue warning color
- Add deadline item to task detail panel with flag icon
- Add deadline options to task context menu
- Show deadlines in scheduled list page
Reminders:
- Add deadline reminder effects and selectors
- Show reminder dialog with grouped deadline/schedule sections
- Handle deadline reminder clearing on dismiss, done, add-to-today
- Cancel Android native deadline notifications on delete/archive
Planner:
- Show deadline tasks in planner day view and overdue section
- Create dedicated planner-deadline-task component
- Optimize deadline grouping with O(N) single-pass selector
Other:
- Add deadline-today banner effect for unplanned deadline tasks
- Add translation keys for all deadline UI strings
- Add E2E tests for deadline reminder flows
- Add unit tests for deadline reducer and overdue utility
- Extract shared isDeadlineOverdue utility function
- Guard app-state selectors against undefined during teardown
Design document for GitHub issue #4328. Covers data model (deadlineDay,
deadlineWithTime, deadlineRemindAt), UI placement in detail panel and
task list rows, NgRx actions/reducers, and reminder integration.
The action-electron-builder omits --publish when release=false, causing
electron-builder to default to onTag on CI and publish unsigned files.
The signed files were then published separately, creating duplicates.
- Add --publish never to explicitly prevent auto-publishing
- Hardcode NSIS artifactName with hyphens to avoid SignPath converting
spaces to dots (Super.Productivity → Super-Productivity)
- Skip blockmap regeneration for portable targets, fail loudly if an
NSIS blockmap is unexpectedly missing
- Update normalization comment and docs filename reference
- 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.
Parallel to the SuperSync flowchart, covering the file-based sync
decision tree: gap detection, snapshot hydration, rev-based upload
retry, and error handling. Verified against source code with matching
abstraction level to the SuperSync chart.
Correct the flowchart to match actual codebase behavior:
- Move fresh-client dialogs under the "has remote ops" branch (was incorrectly under "no remote ops")
- Split single password dialog into two distinct decrypt error dialogs (DecryptNoPasswordError vs DecryptError)
- Route SYNC_IMPORT conflicts to ImportConflictDialog (was incorrectly using SyncConflictDialog)
- Add encryption-only change bypass for password-change SYNC_IMPORTs
- Add LWW tie-breaking details (remote wins on tie, archive ops always win)
- Add retry limit note on re-download, correct "Cancel" to "Disable SuperSync"
- Show silent server migration path for fresh clients with local data on empty server
Rename generic "Conflict dialog" labels to SyncConflictDialog and
ImportConflictDialog to reflect the two distinct components. Add orange
action styling for key state-changing nodes (apply, force upload/download,
enable encryption, upload).
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.
* feat: add label to heatmap for repeat task
* style(e2e): fix prettier formatting in planner spec
* fix(focus-mode): clear stale _isResumingBreak flag when isPauseTrackingDuringBreak is enabled (#6534)
When both isSyncSessionWithTracking and isPauseTrackingDuringBreak are
enabled, pausing and resuming a break left _isResumingBreak stale,
causing the next manual tracking start to dispatch clearResumingBreakFlag
instead of skipBreak. Refactor syncSessionResumeToTracking$ to explicitly
dispatch clearResumingBreakFlag in this case.
* refactor(sync): unify JWT expiry to 365 days for all auth methods
Replace separate JWT_EXPIRY_MAGIC_LINK (365d) and JWT_EXPIRY_PASSKEY (7d)
constants with a single JWT_EXPIRY (365d). The auth method only matters
during login — once a JWT is issued, it represents a verified session
regardless of how the user authenticated.
* feat(start-of-next-day): respect startOfNextDayDiff offset in today view
Thread startOfNextDayDiffMs through AppState, selectors, meta-reducers,
and task component so that "today" membership correctly accounts for the
user's configured day-start offset. When startOfNextDay=4 (4 AM), at
2:30 AM the app now correctly treats the previous calendar day as "today".
- Add isTodayWithOffset utility for offset-aware date comparison
- Store startOfNextDayDiffMs in AppState alongside todayStr
- Update all selectors (work-context, planner, task, overdue) to use offset
- Update meta-reducers with defensive fallbacks for state access
- Fix task component computed signals (isOverdue, isScheduledToday, etc.)
- Add 48 new tests covering offset boundary conditions
* style(planner): remove unused eslint-disable directive
* fix(start-of-next-day): use offset-aware date in ensureTasksDueTodayInTodayTag effect
Replace raw getDbDateStr() and getDateRangeForDay(Date.now()) with
store-derived todayStr and offset-adjusted range in task-due.effects.ts.
Without this, the effect would use the wrong day between midnight and
the configured startOfNextDay hour.
Also add selectOverdueTasks offset boundary tests.
* refactor(start-of-next-day): use DateService for offset-aware today checks
Add DateService.isToday() method that encapsulates the startOfNextDayDiff
offset logic, replacing scattered isToday()/getDbDateStr() calls across
effects, services, and components.
- Add isToday(date) to DateService for DRY offset-aware checks
- Fix task-repeat-cfg.effects.ts: 6 isToday/getDbDateStr calls
- Fix task-repeat-cfg.service.ts: isToday call
- Fix task-context-menu-inner.component.ts: 6 isToday/getDbDateStr calls
- Fix task-related-model.effects.ts: getDbDateStr call
- Fix work-context.service.ts: getDbDateStr call
- Remove duplicate planTaskForDay handler from tag.reducer.ts
(already handled by planner-shared meta-reducer with offset)
* refactor(start-of-next-day): migrate remaining isToday() calls to offset-aware DateService
Replace 6 call sites still using the non-offset isToday()/isYesterday()
with DateService methods that respect startOfNextDayDiff. Also adds
isYesterday() to DateService and uses isTodayWithOffset in legacy backup
migration. Behavior is identical at offset=0 (default).
* fix(start-of-next-day): fix offset bugs, sync regression, and code quality issues
- Fix wrong config path in legacy backup migration (misc.startOfNextDay)
- Restore sync readiness check (filter+first instead of take(1))
- Restore SYNC_AFTER_ENABLE in setInitialSyncDone conditions
- Use offset-aware dates in addAllDueToday/addAllDueTomorrow
- Make isSameDay offset-aware and pass offset through planner selectors
- Fix TagSettingsPageComponent selector from 'project-settings' to 'tag-settings'
- Hide settings link for virtual TODAY tag
- Revert direct ru.json edits (only en.json should be edited)
- Add standalone:true and use takeUntilDestroyed in settings components
- Restore Math.max(duration,1) for zero-duration overlap detection
- Remove dead code, stale CSS, and commented-out HTML
- Add input validation clamping in DateService.setStartOfNextDayDiff
* fix(start-of-next-day): fix offset bugs in overdue detection, planner display, and LWW sync
- Fix isOverdue ignoring offset for dueWithTime tasks in task.component
- Remove duplicate moveBeforeTask handler from tag.reducer (handled by meta-reducer)
- Add skip(1) and hydration guard to setTodayStr$ effect to prevent race condition
- Move side effects from map() to tap() in global-config.effects
- Fix isSameDay double-offset bug in planner.selectors for scheduled tasks/events
- Replace unsafe `as any` casts with proper PlannerState types
- Use safe optional chaining for todayStr access in meta-reducers
- Refactor handlePlanTaskForDay to use helper functions with hasChanges optimization
- Extend syncTodayTagTaskIds in LWW meta-reducer to handle dueWithTime changes
- Fix absolute import path in global-config.effects
- Add @deprecated to isToday() in favor of offset-aware alternatives
* fix(config): migrate task dueDays when startOfNextDay offset changes
When the "start of next day" offset changes and causes todayStr to shift,
existing tasks with dueDay matching the old todayStr are now migrated to
the new todayStr so they remain classified as "today" tasks.
* refactor(config): use switchMap and document archive task exclusion
Replace mergeMap with switchMap in setStartOfNextDayDiffOnChange
effect to better communicate intent (only latest emission matters).
Add comment clarifying archived tasks are intentionally excluded
from dueDay migration.
* test(sync): add LWW tests for dueWithTime → TODAY_TAG sync
Cover the dueWithTime path in syncTodayTagTaskIds that was added
but had no test coverage. Tests verify TODAY_TAG membership updates
when dueWithTime changes via LWW sync.
* docs(wiki): add new Quickstart to help with using Sync
There is a slew of notes that try to explain or show this so a
Quickstart can help bring everything into one place.
* docs(wiki): combine "First Steps" into single note with relevant links
* docs(wiki): update index notes
* docs(wiki): fix remaining broken external links
* docs(wiki): add core developer How-To guides to orient first-time devs
The majority of the documentation is currently spread across several
files ins "docs/" and READMEs. Over time these can be consolidated into
the wiki while retaining the common CONTRIBUTING.md as a valid entry
point.
* docs(wiki): add basic guides for plugins and issue integration
As with the core development docs, there is too much to add here right
now. These notes will serve as a simple entry to other resources.
* docs(wiki): add basic reference note for theming
* docs(wiki): add basic Translation guide
* docs(wiki): rename Theming and linting to clean up headings
* docs(wiki): add heading lint exception for GH-specific nav pages; rework sidebar and index pages
Sidebar should be a quick-access for the more common topics grouped
thematically with the X.00 notes simply enumerating all the notes where
appropriate.