mirror of
https://github.com/logseq/logseq.git
synced 2026-06-01 19:01:22 +00:00
fix: honor documented repeater cookie semantics (#12523)
* fix: honor the three documented repeater cookie semantics
Logseq's documented repeater semantics (per docs.logseq.com and
`logseq/docs` `Tasks.md`) define three org-mode-style cookies for
recurring tasks:
`.+`: repeats from the last completion date
`++`: advances from scheduled, skipping in whole intervals to future
`+`: advances from scheduled by the declared interval (can stack)
The scheduler in `worker/commands.cljs` has been ignoring the cookie
entirely and applying a single, `++`-like semantic for every
recurring task. A user who wrote `.+1w` in markdown — expecting "a
week from when I actually finished" — silently got `++1w` behavior
("a week from the original scheduled date, skipped to future"),
which for a weekly task scheduled 2026-04-01 and completed on
2026-04-05 returns the next occurrence on 2026-04-08 rather than
the documented 2026-04-12.
This change:
* Adds a closed-values `:logseq.property.repeat/repeat-type` property
with values `:dotted-plus` / `:plus` / `:double-plus`. Default is
`:double-plus` so existing recurring tasks see no behavior change
on upgrade.
* Rewrites the scheduler to branch on repeat-type and implement each
semantic: `.+` anchors on now; `+` advances from original once (can
stack overdue, per org-mode); `++` iterates in whole intervals
until strictly after now. The `++` path is mathematically
equivalent to the previous scheduler, so default-path behavior is
preserved.
* Guards against frequency <= 0 — the old code would silently produce
nonsense and, under the new `++` loop, would spin forever. The
guard short-circuits to `nil`.
* Extracts `resolve-recur-frequency` and fixes the previous
`(or [A B] [C D])` pattern in `compute-reschedule-property-tx` —
any 2-vector is truthy in Clojure, so the default-value branch
was unreachable and entities without an explicit
`:recur-frequency` silently fell through to `frequency = nil`.
`if-let` makes both branches reachable so default-to-1 actually
works at migration time.
* Restores the cookie-type selector that was removed from the
date-time popover in `0a5b88467` (Nov 2020) — in-code support for
all three cookies has been present but not user-pickable for the
last ~5.5 years.
* Adds `docs/recurring-tasks.md` — a technical spec for contributors
and users that restates and augments the upstream `Tasks.md` text,
adds decision guidance, and documents the implementation surface.
* Extends the file-graph → DB-graph migration (built on top of
`44d6bd49c4` "fix: preserve repeated schedule import") to also
carry the cookie kind via a new `repeat-types` map in
`graph-parser/exporter.cljs`, so an imported `.+1w` task lands in
the DB-graph with `:repeat-type.dotted-plus` rather than picking
up the `:double-plus` default. Test updated to assert this.
* Adds deftests covering each cookie's distinctive behavior plus
boundary cases (non-positive frequency, unknown unit, frequency > 1
variants, `++` at month/year units, and both branches of
`resolve-recur-frequency`).
The preexisting `get-next-time-test` passes unchanged under the
`:double-plus` default, preserving the existing regression contract.
Tests pin `t/now` via `with-redefs` for determinism.
Refs #7731, #11260, #6715, #8531. Folds in the small remaining delta
from #12532 (now closed as superseded by `44d6bd49c4`).
* fix: harden recurring task repeat type
* fix: contain repeat type selector
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: handle clamped monthly repeats
---------
Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1434,6 +1434,7 @@
|
||||
:property.built-in/repeat-checked-property "Repeating Checked Property"
|
||||
:property.built-in/repeat-recur-frequency "Repeating recur frequency"
|
||||
:property.built-in/repeat-recur-unit "Repeating recur unit"
|
||||
:property.built-in/repeat-repeat-type "Repeating type"
|
||||
:property.built-in/repeat-repeated "Node Repeats?"
|
||||
:property.built-in/repeat-temporal-property "Repeating Temporal Property"
|
||||
:property.built-in/scalar-default-value "Non ref type default value"
|
||||
@@ -1484,6 +1485,7 @@
|
||||
:property.repeat/datetime "Repeat datetime"
|
||||
:property.repeat/every "Every"
|
||||
:property.repeat/is-label "is:"
|
||||
:property.repeat/next-date "Next date"
|
||||
:property.repeat/task "Repeat task"
|
||||
:property.repeat/when "When"
|
||||
|
||||
@@ -1494,6 +1496,10 @@
|
||||
:property.repeat-recur-unit/week "Week"
|
||||
:property.repeat-recur-unit/year "Year"
|
||||
|
||||
:property.repeat-repeat-type/dotted-plus "Advance from completion"
|
||||
:property.repeat-repeat-type/double-plus "Advance from scheduled, skip to future"
|
||||
:property.repeat-repeat-type/plus "Advance from scheduled"
|
||||
|
||||
:property.status/backlog "Backlog"
|
||||
:property.status/canceled "Canceled"
|
||||
:property.status/doing "Doing"
|
||||
|
||||
@@ -1423,6 +1423,7 @@
|
||||
:property.built-in/repeat-checked-property "重复的选中属性"
|
||||
:property.built-in/repeat-recur-frequency "重复频率"
|
||||
:property.built-in/repeat-recur-unit "重复单位"
|
||||
:property.built-in/repeat-repeat-type "重复类型"
|
||||
:property.built-in/repeat-repeated "节点是否重复?"
|
||||
:property.built-in/repeat-temporal-property "重复的时间属性"
|
||||
:property.built-in/scalar-default-value "非引用类型默认值"
|
||||
@@ -1473,6 +1474,7 @@
|
||||
:property.repeat/datetime "重复日期时间"
|
||||
:property.repeat/every "每"
|
||||
:property.repeat/is-label "是:"
|
||||
:property.repeat/next-date "下次日期"
|
||||
:property.repeat/task "重复任务"
|
||||
:property.repeat/when "当"
|
||||
|
||||
@@ -1483,6 +1485,10 @@
|
||||
:property.repeat-recur-unit/week "周"
|
||||
:property.repeat-recur-unit/year "年"
|
||||
|
||||
:property.repeat-repeat-type/dotted-plus "从完成时间推进"
|
||||
:property.repeat-repeat-type/double-plus "从计划时间推进,跳到未来"
|
||||
:property.repeat-repeat-type/plus "从计划时间推进"
|
||||
|
||||
:property.status/backlog "待办列表"
|
||||
:property.status/canceled "已取消"
|
||||
:property.status/doing "进行中"
|
||||
|
||||
Reference in New Issue
Block a user