super-productivity/docs/wiki/4.13-Repeating-Tasks.md
Johannes Millan 7f604f68f7
feat(task-repeat): default skip-overdue for new everyday recurring tasks (#8861)
* feat(task-repeat): default skip-overdue for new everyday recurring tasks

New recurring configs now default skipOverdue ("Don't let overdue instances
pile up") to ON only for a plain everyday schedule — the "Daily" preset or a
CUSTOM every-single-day cycle. That is the one case where the option is both
useful and provably safe: everyday tasks are the only schedule that actually
piles up (one empty overdue copy per missed day), and today is always
scheduled so a missed instance regenerates the same day and can never
silently vanish (it cannot even drop to zero).

Every other schedule stays OFF — workday/weekly/monthly/yearly and every-N-day
custom cycles keep their one missed occurrence visible, so a real obligation
(pay rent on the 1st, renew the domain) never disappears until its next
occurrence. Deriving the default purely from the effective schedule means the
"Daily" preset and a CUSTOM every-day cycle (the same schedule entered two
ways) get the same default — no "same schedule, different default" surprise.

The default is seeded from the chosen schedule in both config-creation paths:
the repeat dialog (re-derived from the final schedule on save, and skipped
when the user explicitly toggled the Advanced checkbox) and the inline
add-task-bar recurrence. Existing configs and DEFAULT_TASK_REPEAT_CFG
(skipOverdue: false) are unchanged; only newly created configs are affected.

Supersedes the broader daily+Mon-Fri variant, dropping the schedule-change
checkbox re-sync machinery: an Advanced checkbox opened on a Daily config and
then switched may briefly show a stale ON, but save always persists the safe
re-derived value.

* docs(task-repeat): clarify custom every-day default; signpost baseline

Multi-review follow-ups (no behavior change):
- Wiki 2.06 + 4.13: a CUSTOM every-single-day cycle also defaults skipOverdue
  ON (it is the same schedule as the Daily preset); "off" now reads "custom
  cycles longer than a day" so the docs match getDefaultSkipOverdue.
- Comment on DEFAULT_TASK_REPEAT_CFG.skipOverdue pointing to the schedule-aware
  creation default, so the model's `false` baseline is not mistaken for the
  effective default.
- Tighten the save() display-gap comment: the cosmetic seeded-ON/persist-OFF
  gap applies to any new non-Daily config whose Advanced panel is opened
  untouched, not only a Daily→switch.

* refactor(task-repeat): use type-only import in skip-overdue predicate

TaskRepeatCfgCopy is used only in type position; match the codebase's import type convention (58 other files). No behavior change.
2026-07-08 19:55:37 +02:00

12 KiB
Raw Permalink Blame History

Repeating Tasks

Repeating tasks in Super Productivity are tasks that recur on a schedule—daily, weekly, monthly, or yearly—so you dont have to create the same task over and over. The app stores a repeat configuration that defines the pattern, then automatically creates new task instances when they are due. Understanding how repeating tasks are defined, when the next instance is created, and how the app avoids duplicates and handles skipped dates helps you use them reliably in the Planner, Schedule, and Today View.

For how to create, edit, and manage repeating tasks in the UI, see 2.06-Manage-Repeating-Tasks. For how the repeat configuration fits into the task model, see 4.09-Task-Attributes. Repeating tasks cannot be made into subtasks; see 4.11-Subtasks.

How Repeating Tasks Are Defined and Stored

A repeating task is defined by a repeat configuration linked to the task. The configuration is stored separately and describes the pattern. Key options you can set include:

  • Repeat cycle — How often the task recurs: daily, weekly, monthly, or yearly.
  • Repeat interval — How many units between instances (for example “every 2 weeks” or “every 3 months”).
  • Start date — When the pattern begins; the app does not create instances before this date.
  • Last created instance — The app tracks the most recent date for which a task instance was created so it knows what to create next.
  • Skipped dates — You can mark specific dates as “skipped” so no instance is created on those days; the pattern continues before and after. That lets you skip a holiday, a day off, or a one-off exception without changing the rule.
  • Start time and reminder — Optional: a default time (and reminder) for each instance, so recurring work appears at a fixed time on the Schedule.
  • Subtask templates — Optional: a set of subtasks that are added to each new instance so you dont have to recreate the same checklist every time.

The app also offers quick settings that map to common patterns—for example “daily,” “weekly on this weekday,” “monthly on this date,” “weekdays only” (MondayFriday), “yearly on this date,” or “custom” for full control. These are shortcuts that fill in the underlying cycle, interval, and (for weekly) which weekdays.

When you make a task repeatable, it keeps its project, tags, and other attributes; the repeat configuration is added and the app uses it to generate future instances.

What Triggers the Next Instance Creation

The app creates the next task instance when it detects that an instance is due and does not yet exist. It does this by:

  1. Looking at the pattern — From the repeat configuration (cycle, interval, start date, last created instance), the app works out the most recent date when a task should have been created, working backwards from today (or from a chosen “up to” date). That determines which dates are “missing” and need an instance.
  2. Checking each candidate date — For each such date, the app checks that no instance already exists for that date (and that the date is not in your skipped-dates list). If an instance is missing, it creates one.
  3. Updating the configuration — After creating an instance, the app updates “last created instance” so it doesnt create another one for the same date. That keeps the pattern in sync and avoids duplicates.

When you first make a task repeatable, the app computes the first occurrence date from the pattern and start date. It may set the tasks due date to that first occurrence and, if the first occurrence is not today, remove the task from the Today list so it appears on the correct day instead. That way the first instance aligns with the repeat rule from the start.

Instance creation runs as part of normal app use (for example when you open the app or switch context), so overdue instances are created when the app catches up. You dont have to trigger creation manually unless your workflow exposes a “create next instance” action.

How the App Prevents Duplicates and Handles Exceptions

The app uses several mechanisms so you dont get duplicate instances and so sync and skipped dates behave correctly.

Deterministic Task IDs

Each repeat instance is created with a predictable ID derived from the repeat configuration and the date. That means the same configuration and the same date always produce the same task ID on every device. When you sync (for example via WebDAV or Dropbox), two devices that both run the “create instance for this date” logic will create tasks with the same ID, so sync sees one task, not two. That prevents duplicates across devices.

Duplicate Checks Before Creating

Before creating an instance for a given date, the app:

  1. Checks for an existing instance — It looks for a task that either has the expected deterministic ID or has that date as its due date. If one exists (for example created on another device and already synced, or an older “legacy” task with a different ID but the same date), it does not create another. That covers both new and legacy data.
  2. Checks skipped dates — If the date is in your list of skipped (deleted) instances, the app does not create a task for that date. The pattern continues; that date is simply omitted.
  3. Updates “last created” — After a successful create, the app updates the configurations “last created instance” so the next run knows not to create again for that date.

Together, these steps keep at most one instance per date per repeat configuration, locally and when synced.

Skipped Dates (Exceptions)

You can skip specific occurrences without changing the repeat rule. Those dates are stored in the configurations exception list. The app never creates an instance for those dates, but it does create instances for all other dates that match the pattern. So you can skip a single day (or several) and the rest of the schedule stays the same.

Repeating Tasks in the Schedule and Planner

The Schedule view can show projected instances of repeating tasks (with a start time set) even before the actual task instance is created. That gives you a forward-looking timeline: you see when the next “standup” or “review” will occur according to the pattern. Once the instance is created, it appears as a normal task on the Schedule. See 4.04-Schedule-View.

The Planner view also shows recurring task projections on the days they will occur, so you can see how repeating work fits into the week or month. See 4.03-Planner-View.

Date calculations for repeat patterns use a consistent reference time (noon) internally to avoid timezone and daylight-saving issues, so the “next occurrence” stays correct across timezones and DST changes.

Summary

  • Repeating tasks are defined by a repeat configuration (cycle, interval, start date, skipped dates, optional time and subtask templates).
  • The app creates the next instance when it detects a due date with no instance yet, then updates “last created” so it doesnt duplicate.
  • Deterministic IDs (config + date) prevent duplicate instances when syncing across devices.
  • Skipped dates let you omit specific occurrences without breaking the pattern.
  • The Schedule (and Planner) can show projected repeat instances; actual instances appear once created.

Wait for Completion Option

When you enable "Wait for completion" on a repeating task, the app will not create the next instance until you complete the current one. This is useful for tasks that must be done in sequence—for example, a weekly review that should only appear after you finish the previous week's review, or a recurring chore that shouldn't pile up if you fall behind.

How It Works

  • Normal behavior: The app creates the next instance based on the schedule (e.g., every Monday), regardless of whether you completed the previous instance.
  • With "Wait for completion": The app checks if any uncompleted instance exists (including archived tasks). If one does, it will not create the next instance. Once you mark the current instance as done, the next due instance appears immediately if its scheduled occurrence is already due.

Key Behaviors

  • Immediate creation after completion: When you complete the gating task and the next scheduled occurrence is already due, the next instance is created right away—you don't have to wait until the next day or restart the app.
  • Archived instances count: If you archive an uncompleted instance, it still blocks creation of the next one. This prevents the pattern from advancing when old work is left unfinished.
  • Completed blockers are rechecked: Completing any unfinished live or archived instance rechecks whether the next due task can be created. If other unfinished instances still exist, creation stays blocked.

Use Cases

  • Sequential reviews: Weekly or monthly reviews that should only appear after the previous one is done
  • Chores that shouldn't pile up: Recurring maintenance tasks where you want to finish one before the next appears
  • Habit tracking: Tasks where you want to ensure completion before moving to the next occurrence

This option works independently from "Repeat from completion date" (which re-anchors the schedule to the completion day). You can enable both if you want the task to repeat N days after completion AND wait for completion before creating the next instance.

Don't Let Overdue Instances Pile Up Option

When you enable "Don't let overdue instances pile up" on a repeating task, missed occurrences don't accumulate as a stack of duplicate overdue tasks—you keep a single, up-to-date instance instead. An empty missed instance is removed once a newer one exists; any instance where you tracked time, completed subtasks, or made edits is always kept.

Default Behavior

  • On by default for the Every day preset (or an equivalent custom every-single-day cycle). An everyday task is the only schedule that actually piles up (one empty overdue copy per day if you fall behind), and today is always a scheduled day, so a missed instance reliably comes back the same day—it can never silently vanish. You get one current instance instead of a growing stack.
  • Off by default for every other schedule (workday, weekly, monthly, yearly, and custom cycles longer than a day). These have at most one missed occurrence, so nothing piles up—and an overdue "pay rent on the 1st" or "renew the domain" should stay visible as a reminder rather than quietly disappear until its next occurrence.

This only sets the default for newly created repeating tasks. Existing tasks keep whatever they were configured with, and you can turn the option on or off for any task under the repeat dialog's Advanced section.

When to Use It

  • Daily habits and routines: Water the plants, daily standup, inbox zero—skip the guilt-pile of stale duplicates and just see today's.
  • Keep it off for bills and renewals: Leave it off (the default) for monthly or yearly obligations so a missed one stays on your list until you handle it.