# ReKnock Recurring Tasks: Research

*Short comparison of how five popular task apps handle repeating tasks, and what ReKnock should copy. Written from product knowledge, not re-verified against live apps today. Details change, so treat each cell as "what I believe", not gospel.*

## The three questions that matter

1. **Fixed vs after-completion.** Does the next one come from the calendar ("every 28th") or from when you actually did it ("30 days after I last did it")?
2. **How do you enter it?** Pickers only, or plain English ("every last Friday")?
3. **Can you skip one?** Or stop the series cleanly?

## Comparison

| | Fixed schedule | After completion | Plain-English input | Skip one | End condition | Lead time |
|---|---|---|---|---|---|---|
| **Todoist** | Yes: `every 28th` | Yes: `every! 30 days` | Excellent, the benchmark | No dedicated skip; workaround is complete or reschedule | `until`, `for N weeks` | No |
| **TickTick** | Yes (default) | Yes: "repeat from completion date" | Good, parses it from the title | Has a skip action | End date or count | Reminder offsets only |
| **Things 3** | Yes: "repeat on a schedule" | Yes: "repeat after completion" | Little or none | No skip. You can delete one or stop repeating | Optional end | **Yes**: "add N days before deadline" |
| **Google Tasks** | Yes | No | No | No | Date or count | No |
| **Apple Reminders** | Yes, with custom N units and "last Friday" style monthly | No | Via Siri | No ("delete this and future" only) | End date | No |

## What they do on completion

- All five keep **one live task** and move it forward (or create the next copy). None build a backlog of missed ones for daily or weekly tasks.
- Todoist and TickTick, when you complete an **overdue** fixed task, jump to the **next future** occurrence. That is the behavior people expect and the one ReKnock wants.
- Things and TickTick show the next item early (Things hides it until the lead window). Matches ReKnock's `start_date`: quiet until it is time.

## Lessons

- **Both modes are needed.** Card minimums and smoke alarms are fixed. "Oil change every 6 months" and "30 days after I did it" are after-completion. Only Todoist, TickTick and Things offer both, and Rob has examples of each.
- **Lead time is a real feature.** Things proves the value ("show it 3 days before the deadline"). ReKnock already has `start_date`, so lead time falls out for free.
- **Plain English wins on voice.** ReKnock is used through MCP and voice. A deterministic parser for common phrases, backed by a structured form, fits that.
- **Skip is underserved and cheap.** Everyone gets this wrong. Nagging apps need it more than others, because an un-skippable occurrence keeps knocking.
- **Month-end handling is rarely documented.** Calendar RFC 5545 *skips* months that lack a 31st. People find that surprising. Clamping to the last day matches expectation for "pay on the 31st".

## Recommendation

1. **One live task row per series.** On completion, log a done-history snapshot and push `start_date` (and `due_date`) to the next occurrence. Same id, text, contexts, nag times, quadrant. Reuses ReKnock's existing "quiet until start_date" mechanism, so almost no new nagging logic.
2. **Store the rule as an RFC 5545 RRULE subset** (`FREQ`, `INTERVAL`, `BYDAY` incl. ordinals like `-1FR`, `BYMONTHDAY`, `BYMONTH`, `UNTIL`, `COUNT`), plus ReKnock fields for `mode` and `lead_days`. Interoperable and well specified. Deviate in one place: clamp short months instead of skipping.
3. **Two modes:** `fixed` (default) and `after_completion`.
4. **Always jump to the next future occurrence.** Never create a backlog.
5. **Skip + stop** as first-class actions (`skip_occurrence` tool, `stop_series` on done, `repeat: none` on update).
6. **Input:** structured `repeat` object (canonical) and a `repeat_text` plain-English helper, parsed by a small deterministic grammar that echoes back its interpretation so a voice user can confirm.
7. **Lead time** as `lead_days`, mapped to `start_date = occurrence - lead_days`.
8. **Do not use an LLM to parse repeat text server-side.** The calling assistant already is one. Keep the server deterministic and testable.
