From 598315dd9ee6647c7c09bd019d77cb3c37e2745d Mon Sep 17 00:00:00 2001 From: callumalpass Date: Sun, 31 May 2026 21:48:10 +1000 Subject: [PATCH] Document materialized occurrences --- README.md | 11 +++- docs/features.md | 2 +- docs/features/recurring-tasks.md | 61 ++++++++++++++++++++++- docs/features/task-management.md | 2 +- docs/releases/unreleased.md | 2 + docs/settings/features.md | 2 + docs/settings/property-types-reference.md | 55 ++++++++++++++++++++ docs/settings/task-properties.md | 6 +++ docs/spec | 2 +- docs/spec.md | 8 +-- docs/webhooks.md | 2 + docs/workflows.md | 2 + 12 files changed, 145 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9ca96759..68762051 100644 --- a/README.md +++ b/README.md @@ -65,11 +65,20 @@ recurrence: "FREQ=WEEKLY;BYDAY=MO" complete_instances: ["2024-01-08"] ``` +When an individual recurrence needs its own note, TaskNotes can materialize that occurrence as a normal task: + +```yaml +title: "Weekly meeting" +recurrence_parent: "[[Tasks/Weekly meeting]]" +occurrence_date: "2024-01-15" +scheduled: "2024-01-15" +``` + All property names are configurable. If you already use `deadline` instead of `due`, remap it in settings. ## Other features -Calendar sync with Google and Microsoft (OAuth) or any ICS feed. Time tracking with start/stop per task, Pomodoro timer, and session history. Recurring tasks with fixed or flexible schedules and per-instance completion tracking. Dependencies between tasks. Natural language parsing for task creation. Custom statuses, priorities, and user-defined fields. +Calendar sync with Google and Microsoft (OAuth) or any ICS feed. Time tracking with start/stop per task, Pomodoro timer, and session history. Recurring tasks with fixed or flexible schedules, per-instance completion tracking, and optional materialized occurrence notes. Dependencies between tasks. Natural language parsing for task creation. Custom statuses, priorities, and user-defined fields. ## Integrations diff --git a/docs/features.md b/docs/features.md index 2965eec6..73898e74 100644 --- a/docs/features.md +++ b/docs/features.md @@ -6,7 +6,7 @@ TaskNotes includes task organization, time tracking, and calendar integration fe TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases. -Reminders can be relative (for example, "3 days before due") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. +Reminders can be relative (for example, "3 days before due") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. See [Task Management](features/task-management.md) for details. For recurrence behavior, see [Recurring Tasks](features/recurring-tasks.md). diff --git a/docs/features/recurring-tasks.md b/docs/features/recurring-tasks.md index 0ca2a613..53cff39a 100644 --- a/docs/features/recurring-tasks.md +++ b/docs/features/recurring-tasks.md @@ -1,7 +1,7 @@ # Recurring Tasks -TaskNotes recurring tasks use RFC 5545 RRule strings with `DTSTART` support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance. +TaskNotes recurring tasks use RFC 5545 RRule strings with `DTSTART` support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content. If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the `scheduled` field as the next concrete commitment. Most day-to-day editing affects `scheduled`, while recurrence editing changes the plan itself. @@ -11,6 +11,7 @@ Recurring tasks operate on two independent levels: 1. **Recurring Pattern**: Defines when pattern instances appear (controlled by `DTSTART` in the recurrence rule) 2. **Next Occurrence**: The specific date/time when you plan to work on the next instance (controlled by the `scheduled` field) +3. **Materialized Occurrence Notes**: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content This separation lets you reschedule the next occurrence without changing the pattern. @@ -33,6 +34,11 @@ Recurring tasks require: - **Recurrence Rule**: RRule string with `DTSTART` - **Scheduled Date**: Next occurrence date (independent from the pattern) +Materialized occurrence notes add two system fields to the occurrence note: + +- `recurrence_parent`: link/path back to the recurring parent task +- `occurrence_date`: the occurrence date represented by the note + ### DTSTART Integration `DTSTART` is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances. @@ -86,6 +92,57 @@ The `scheduled` field automatically tracks the next uncompleted occurrence: This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities. +## Materialized Occurrence Notes + +Most recurring tasks can remain virtual: the parent task stores `complete_instances` and `skipped_instances`, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note. + +Good uses include: + +- A weekly review where each week needs a separate agenda and notes +- A maintenance task where each visit needs photos, links, or a checklist +- A recurring meeting where every occurrence should have its own time entries and completion state + +To create one manually, right-click a recurring task card or calendar occurrence and choose **Open or create occurrence note**. The Task Action Palette also exposes **Open or create occurrence note** for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate. + +An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. Its frontmatter includes: + +```yaml +recurrence_parent: "[[Tasks/Weekly review]]" +occurrence_date: "2026-06-01" +scheduled: "2026-06-01" +``` + +The parent task remains the source of the recurrence rule. The occurrence note owns date-specific state such as `status`, `completedDate`, body content, checklists, time entries, reminders, contexts, projects, and other per-instance fields. + +### Occurrence Note Policies + +Each recurring parent has an **Occurrence notes** submenu under its recurrence menu: + +- **Create manually**: occurrence notes are only created by explicit action. +- **Create next after completion**: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note. +- **Rolling window**: defined by the TaskNotes spec, but not automated in the plugin yet. + +When **Create next after completion** is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence. + +The same submenu also controls the next-note trigger: + +- **Completion only**: create the next occurrence note only when the current occurrence is completed. +- **Completion or skip**: create the next occurrence note when the current occurrence is completed or skipped. + +Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent `skipped_instances` list. + +### Completion Reconciliation + +When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship: + +- The occurrence note is completed like a normal task. +- The parent adds the occurrence date to `complete_instances`. +- The parent removes that date from `skipped_instances` if needed. +- The parent recalculates `scheduled` to the next uncompleted occurrence. +- If the parent policy is **Create next after completion**, TaskNotes creates the next occurrence note idempotently. + +Uncompleting an occurrence note removes the date from the parent's `complete_instances` list, but it does not delete later occurrence notes that were already created. + ### Example Behavior ```yaml @@ -126,7 +183,7 @@ Completed instances are stored in: complete_instances: ["2025-08-04", "2025-08-06", "2025-08-08"] ``` -When completion changes, `scheduled` updates to the next uncompleted instance. +When completion changes, `scheduled` updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions. This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks. diff --git a/docs/features/task-management.md b/docs/features/task-management.md index 650a9395..3a21b5ff 100644 --- a/docs/features/task-management.md +++ b/docs/features/task-management.md @@ -180,7 +180,7 @@ For template variables, see [Template Variables Reference](template-variables.md ## Recurring Tasks -TaskNotes recurring tasks use RFC 5545 RRule syntax with `DTSTART`, separate pattern definition from next occurrence scheduling, and support independent instance completion. +TaskNotes recurring tasks use RFC 5545 RRule syntax with `DTSTART`, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu. For full behavior, examples, and edge cases, see [Recurring Tasks](recurring-tasks.md). diff --git a/docs/releases/unreleased.md b/docs/releases/unreleased.md index 44202db3..6a220902 100644 --- a/docs/releases/unreleased.md +++ b/docs/releases/unreleased.md @@ -26,12 +26,14 @@ Example: ## Added +- Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. - (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request. - (#1510, #1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Kickdak and @Glint-Eye for the requests, @inigourrestarazu for identifying the project-linked parent edge case, and @stanley-910 and @Spencerduran for the earlier PRs. ## Changed - Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling. +- Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode. ## Fixed diff --git a/docs/settings/features.md b/docs/settings/features.md index f893838c..c553edcf 100644 --- a/docs/settings/features.md +++ b/docs/settings/features.md @@ -39,6 +39,8 @@ Time tracking options handle completion behavior. You can automatically stop run Use **Maintain due date offset in recurring tasks** to keep due/scheduled spacing consistent when recurring tasks roll forward. +Occurrence note behavior is configured per recurring task from the task context menu: open **Recurrence → Occurrence notes** to choose manual creation or automatic creation of the next materialized occurrence after completion. See [Recurring Tasks](../features/recurring-tasks.md#materialized-occurrence-notes) for the workflow and storage model. + ## Timeblocking Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views. diff --git a/docs/settings/property-types-reference.md b/docs/settings/property-types-reference.md index 912d16d0..9990f43c 100644 --- a/docs/settings/property-types-reference.md +++ b/docs/settings/property-types-reference.md @@ -26,6 +26,13 @@ This reference documents the expected data types for each frontmatter property t | reminders | list (objects) | See [Reminders](#reminders) | | complete_instances | list | `["2025-01-08", "2025-01-15"]` | | skipped_instances | list | `["2025-01-22"]` | +| recurrence_parent | text (link/path) | `"[[Tasks/Weekly review]]"` | +| occurrence_date | text (date) | `"2025-01-15"` | +| occurrence_materialization | text | `"manual"` or `"on_completion"` | +| occurrence_next_trigger | text | `"completion"` or `"completion_or_skip"` | +| occurrence_template | text (link/path) | `"[[Templates/Occurrence]]"` | +| occurrence_past_horizon | text (duration) | `"P7D"` | +| occurrence_future_horizon | text (duration) | `"P14D"` | | icsEventId | list | `["event-abc123"]` | Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values. @@ -213,6 +220,54 @@ Single-item arrays may look verbose, but they prevent edge cases when filters an - "2025-01-22" ``` +### Materialized Occurrence Properties + +Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments. + +#### recurrence_parent + +- **Type:** text (link or path string) +- **Description:** Parent recurring task for a materialized occurrence note +- **Example:** `recurrence_parent: "[[Tasks/Weekly review]]"` + +#### occurrence_date + +- **Type:** text (date string) +- **Format:** `YYYY-MM-DD` +- **Description:** Target recurrence date represented by a materialized occurrence note +- **Example:** `occurrence_date: "2025-01-15"` + +#### occurrence_materialization + +- **Type:** text (string) +- **Valid values:** `"manual"`, `"on_completion"`, `"rolling"` +- **Description:** Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet. +- **Example:** `occurrence_materialization: "on_completion"` + +#### occurrence_next_trigger + +- **Type:** text (string) +- **Valid values:** `"completion"` or `"completion_or_skip"` +- **Description:** Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to `on_completion` +- **Example:** `occurrence_next_trigger: "completion_or_skip"` + +#### occurrence_template + +- **Type:** text (link or path string) +- **Description:** Optional template reference used when creating materialized occurrence notes +- **Example:** `occurrence_template: "[[Templates/Weekly occurrence]]"` + +#### occurrence_past_horizon and occurrence_future_horizon + +- **Type:** text (ISO 8601 duration string) +- **Description:** Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin. +- **Examples:** + + ```yaml + occurrence_past_horizon: "P7D" + occurrence_future_horizon: "P14D" + ``` + --- ### Complex Properties diff --git a/docs/settings/task-properties.md b/docs/settings/task-properties.md index bfe5868b..368f5f04 100644 --- a/docs/settings/task-properties.md +++ b/docs/settings/task-properties.md @@ -179,6 +179,8 @@ Pattern for repeating tasks. Configuration options: - **Property key**: Frontmatter field name (default: `recurrence`) - **Default**: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly) +Recurring tasks also use the **Recurrence anchor** metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under **Recurrence → Occurrence notes** rather than as a global default. + ### Reminders Notifications before task deadlines. Configuration options: @@ -211,8 +213,12 @@ These properties are system-managed and typically only require property key conf - **Archive Tag**: Tag used to mark archived tasks - **Time Entries**: Time tracking entries for the task - **Complete Instances**: Completion history for recurring tasks +- **Skipped Instances**: Skip history for recurring tasks +- **Recurrence Anchor**: Whether recurring progression is based on scheduled date or completion date - **Blocked By**: Tasks that must be completed first +Materialized occurrence notes also use system-managed frontmatter fields such as `recurrence_parent`, `occurrence_date`, `occurrence_materialization`, `occurrence_next_trigger`, and optional occurrence template/horizon fields. These fields are documented in the [Property Types Reference](property-types-reference.md#materialized-occurrence-properties) and are normally changed through recurrence and occurrence-note controls instead of by hand. + ## Feature Properties These properties are used by specific TaskNotes features and are not stored in task frontmatter: diff --git a/docs/spec b/docs/spec index c61895f8..e96d00cb 160000 --- a/docs/spec +++ b/docs/spec @@ -1 +1 @@ -Subproject commit c61895f80ff9b315a558d45607c497a6ec2343ed +Subproject commit e96d00cbe202a389bb7aa93c16b3a29a94334db5 diff --git a/docs/spec.md b/docs/spec.md index 3d1ae701..213d906c 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -2,9 +2,9 @@ The TaskNotes specification defines how tools should read, write, and reason about task data stored as markdown files with YAML frontmatter. -It exists so that multiple implementations — the Obsidian plugin, the terminal UI, CLI tools, and anything else that touches the same vault — can agree on what a task looks like, how dates and recurrence work, and what happens when a task is completed, skipped, or archived. +It exists so that multiple implementations — the Obsidian plugin, the terminal UI, CLI tools, and anything else that touches the same vault — can agree on what a task looks like, how dates and recurrence work, and what happens when a task is completed, skipped, archived, or materialized from a recurring parent. -The spec is maintained separately from any single implementation. The canonical source is [callumalpass/tasknotes-spec](https://github.com/callumalpass/tasknotes-spec). +The spec is maintained separately from any single implementation. The canonical source is [callumalpass/tasknotes-spec](https://github.com/callumalpass/tasknotes-spec). The embedded docs currently track the 0.2.0 materialized-occurrences update, including the optional `materialized-occurrences` conformance profile. ## Sections @@ -14,7 +14,7 @@ The spec is maintained separately from any single implementation. The canonical | [Terminology](spec/01-terminology.md) | Normative definitions used throughout | | [Model & Mapping](spec/02-model-and-mapping.md) | Task data model, semantic roles, and field mapping | | [Temporal Semantics](spec/03-temporal-semantics.md) | Date, datetime, and timezone rules | -| [Recurrence](spec/04-recurrence.md) | RRULE semantics and per-instance state | +| [Recurrence](spec/04-recurrence.md) | RRULE semantics, per-instance state, and materialized occurrence semantics | | [Operations](spec/05-operations.md) | Create, update, complete, skip, delete behaviors | | [Validation](spec/06-validation.md) | Validation rules and the issue model | | [Conformance](spec/07-conformance.md) | Conformance profiles and how to claim them | @@ -25,7 +25,7 @@ The spec is maintained separately from any single implementation. The canonical ## Conformance -The spec includes an executable conformance suite — a set of JSON test fixtures that any implementation can run against via a simple adapter interface. The suite covers date handling, recurrence, field mapping, configuration, operations, validation, and more. +The spec includes an executable conformance suite — a set of JSON test fixtures that any implementation can run against via a simple adapter interface. The suite covers date handling, recurrence, materialized occurrence operations, field mapping, configuration, operations, validation, and more. Implementations claim conformance to one or more profiles (core-lite, recurrence, extended, templating) and must declare their spec version and any known deviations. diff --git a/docs/webhooks.md b/docs/webhooks.md index 4da94056..7716ffad 100644 --- a/docs/webhooks.md +++ b/docs/webhooks.md @@ -35,6 +35,8 @@ Recurring events: - `recurring.instance.completed` - `recurring.instance.skipped` +Completing a materialized occurrence note emits `recurring.instance.completed` with the reconciled parent task plus the completed `occurrence` and `date` in the event data. Skipping virtual recurring instances emits `recurring.instance.skipped`; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook. + Reminder events: - `reminder.triggered` diff --git a/docs/workflows.md b/docs/workflows.md index 2f45aaae..d6c71483 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -22,6 +22,8 @@ complete_instances: Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view. +For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card or calendar view and choose **Open or create occurrence note**. The occurrence note keeps the date-specific checklist and completion state while the parent recurring task keeps the long-term rule. + ## Project-Centered Planning Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation.