* 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>
Make `:ref/default-open-blocks-level 0` collapse references by default
in the DB version, matching the previous file-graph behavior. The
section fold is scoped to the page-bottom "Linked References" panel
only — the inline "Open block references" popup rendered next to
blocks always shows its references uncollapsed.
1. Collapse the "Linked References" section when the configured level
is 0, gated on a new `:linked-refs-section?` config flag set only
by the page-bottom call site in page.cljs. The inline popup at
block.cljs:3366 passes `{}` and is unaffected.
2. Propagate `:block.temp/has-children?` on the top-level fetched
block in `get-block-and-children`. The list-view loads linked-
reference blocks with `:children? false`, so `(:block/_parent ...)`
is always nil in the client DB and the collapse check in
`block-default-collapsed?` could never fire. Use a lightweight
`d/datoms :avet :block/parent` scan that stops at the first match,
rather than the reverse-ref `(:block/_parent block)` which
materializes the full child set. Includes a regression test.
3. Fall back to `:block.temp/has-children?` when computing `has-child?`
in `block-container-inner-aux`. This renders the collapse arrow for
blocks whose children exist in the worker DB but haven't been
lazily loaded into the client DB yet (e.g. linked-reference blocks).
Clicking the arrow calls `expand-block!` which loads them.
The `:ref/default-open-blocks-level 0 → (int? ...)` state.cljs fix
from PR #12228 is already present on this branch.
Move the Logseq Markdown Mirror syntax/export work out of the two-way sync branch while leaving file-to-DB sync behavior behind.
Details:\n- add docs/logseq-markdown-syntax.md and update ADR 0016 with the one-way mirror syntax contract\n- export mirror files with page id markers, property list items, nested default property values, node page refs, task status markers, and datetime values with time\n- preserve block refs as uuid links where needed while keeping page/node refs readable\n- update focused export and markdown mirror tests
Validation:\n- bb dev:lint-and-test
cdc1bc1d32 made it such that two classes
had to enable bidirectional properties when only one class should be
needed. Using the example from #12296, the bug was requiring the user
to enable bidirectional on #Person and #Book when #Book is all that
should be needed
* chore(deps): upgrade Clojure version to 1.12.4 across multiple dependency files
* chore: bump shadow-cljs to 3.3.6
* chore: bump org.clojure/clojurescript to 1.12.134
* chore(deps): upgrade Clojure version to 1.12.4 in workflow files
* chore(deps): upgrade Java version to 21 in workflow files
* chore(deps): upgrade Node.js version to 24 in workflow files
* chore(deps): upgrade Node.js version to 24 in Dockerfile
* feat(updater): migrate electron-forge to electron-builder
* fix wrong android app version
* fix workflow
* feat(dependency-upgrade): add max-update-interval option for dependency audits
* chore(deps): upgrade electron-builder and electron-updater
* fix: update manual verification instructions for Electron shim cache
* chore: update shadow-cljs version to 3.4.4 across all dependencies
* chore: upgrade electron version to 41.2.1
* chore: update metosin/malli dependency to latest
* chore: upgrade cider-nrepl version to 0.59.0 in dependencies
* chore: upgrade clj-kondo version to 2026.04.15 and fix warning
* chore: move Electron windows build configuration from yml to ci
* chore: update Electron signing configuration to extend from base config
* fix: replace icon file for NSIS compatibility
* chore: resolve metosin/malli version conflicts
* chore: upgrade jdk to 21 in e2e workflow
---------
Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
it shouldn't be able to. Somes of these bugs are caused by same incorrect
definition of built-in? as found in
22c7736751. --content and --pos could modify all
built-in nodes. *properties and *tags options could modify private
built-in nodes which the app is not able to do and the CLI should be
disallowed from doing as well