2. Model and Field Mapping
2.1 Task record model
A task record consists of:
- frontmatter object (structured fields),
- markdown body (freeform text),
- file metadata (path, created/modified time) where available.
Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features.
2.2 Required semantic roles
Conforming implementations MUST support these semantic roles:
| Semantic role | Type | Required |
|---|---|---|
title |
string | support required (value required via configured title source, see §2.2.2) |
status |
string/enum | yes |
completed_date |
date | support required (conditionally required, see §2.2.1) |
date_created |
datetime | yes |
date_modified |
datetime | yes |
If storage omits a role marked yes, validation MUST report an error (see §6).
For operation-required roles, validation and operation rules in §5 and §6 apply.
2.2.1 Conditional requiredness (completed_date)
completed_date support is mandatory, but presence is conditional:
- For non-recurring tasks with
statusin configuredstatus.completed_values,completed_dateMUST be present. - For non-recurring tasks with non-completed status,
completed_dateMAY be absent. - For recurring tasks,
completed_dateis not required by recurrence completion semantics and MAY be absent.
Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required.
2.2.2 Conditional requiredness (title)
Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior:
- Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13):
- when
title.storage=frontmatter: mappedtitlekey when present and non-empty, then file basename fallback; - when
title.storage=filename: file basename first, then mappedtitlefallback when basename is unavailable.
- when
- If mapped title and filename-derived title both exist and differ, the source authoritative for active
title.storageMUST win and implementations SHOULD emittitle_source_conflict. - When
title.storage=filename, implementations MAY keep mappedtitleas a synchronized compatibility mirror, but filename-derived title remains authoritative. - Title storage mode controls canonical writes (§9.13):
frontmatterfavors mapped-key writes;filenamefavors filename-derived title with rename-on-title-change behavior.
Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone.
2.3 Common semantic roles
Implementations conforming beyond minimal scope SHOULD support:
| Semantic role | Type | Notes |
|---|---|---|
id |
string | stable task identity token; see §2.6.5 |
priority |
string/enum | configurable values |
due |
date or datetime | see §3 |
scheduled |
date or datetime | see §3 |
tags |
list |
free tags |
contexts |
list |
commonly prefixed with @ |
projects |
list |
project references, see §11 |
time_estimate |
integer >= 0 | minutes |
time_entries |
list | see §2.6 |
recurrence |
string | tasknotes recurrence string; see §4 |
recurrence_anchor |
enum | scheduled or completion |
complete_instances |
list |
recurring completion state |
skipped_instances |
list |
recurring skip state |
recurrence_parent |
link-or-string | parent recurring task reference for materialized occurrence notes; see §4.18 |
occurrence_date |
date | target date represented by a materialized occurrence note |
occurrence_materialization |
enum | parent task materialization mode: manual, on_completion, or rolling |
occurrence_next_trigger |
enum | parent task next-note trigger: completion or completion_or_skip |
occurrence_template |
link-or-string | optional template used when creating materialized occurrence notes |
occurrence_past_horizon |
duration | optional rolling materialization lookbehind bound |
occurrence_future_horizon |
duration | optional rolling materialization lookahead bound |
blocked_by |
list | dependency records, see §10 and §11 |
reminders |
list | reminder records, see §10 |
Optional extended roles are defined in §7 profiles.
2.4 Field mapping requirements
2.4.1 Mapping presence
An implementation MUST have an effective mapping from each supported semantic role to a canonical write key.
Mapping configuration is defined in §9.
If semantic role id is supported, it MUST also have a canonical write key.
2.4.2 Read behavior
Readers MUST:
- Read the canonical mapped key if present.
- Support configured aliases where enabled.
- Resolve conflicts deterministically when canonical and alias keys coexist.
- When canonical and alias keys both exist for the same semantic role, canonical key value MUST win.
- When canonical key wins over alias, validator/loader SHOULD emit warning
alias_conflict_ignored.
2.4.3 Write behavior
Writers MUST:
- write only canonical keys,
- avoid introducing alias keys in new writes,
- preserve unknown fields unless the operation explicitly opts into normalization.
2.5 Legacy alias compatibility
Implementations SHOULD accept these aliases on read for interoperability:
| Semantic role | Canonical example | Alias examples |
|---|---|---|
recurrence_anchor |
recurrence_anchor |
recurrenceAnchor |
complete_instances |
complete_instances |
completeInstances |
skipped_instances |
skipped_instances |
skippedInstances |
recurrence_parent |
recurrence_parent |
recurrenceParent |
occurrence_date |
occurrence_date |
occurrenceDate |
occurrence_materialization |
occurrence_materialization |
occurrenceMaterialization |
occurrence_next_trigger |
occurrence_next_trigger |
occurrenceNextTrigger |
occurrence_template |
occurrence_template |
occurrenceTemplate |
occurrence_past_horizon |
occurrence_past_horizon |
occurrencePastHorizon |
occurrence_future_horizon |
occurrence_future_horizon |
occurrenceFutureHorizon |
date_created |
dateCreated |
date_created |
date_modified |
dateModified |
date_modified |
completed_date |
completedDate |
completed_date |
time_entries |
timeEntries |
time_entries |
time_estimate |
timeEstimate |
time_estimate |
blocked_by |
blockedBy |
blocked_by |
This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical.
2.6 Structured role schemas
2.6.1 time_entries
time_entries items MUST be objects with:
startTimedatetime (required)endTimedatetime (optional)descriptionstring (optional)
Additional constraints:
- a task MUST NOT contain more than one active time entry (entry with
startTimeand noendTime) at commit time. - an entry with missing
endTimeis interpreted as an active/running session. - an implementation MAY accept
durationon read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes.
Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping.
2.6.2 projects
projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted.
When interpreted as links, parsing and resolution MUST follow §11.
2.6.3 blocked_by
blocked_by items MUST be objects with:
uidlink-or-string task reference (required)reltypeenum (required; default allowed by §10 when omitted)gapISO 8601 duration string (optional)
Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11.
2.6.4 reminders
reminders items MUST be objects with:
idstring (required)typeenumabsolute|relative(required)- relative-only fields:
relatedTo,offset - absolute-only fields:
absoluteTime descriptionstring (optional)
Detailed semantics are defined in §10.
2.6.5 id (stable task identity)
When semantic role id is present:
- value MUST be a non-empty string.
- value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations.
- readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3).
- implementations SHOULD keep
idunique within a collection; duplicate IDs SHOULD produce a validation issue.
2.6.6 Materialized occurrence roles
The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4).
Parent recurring task roles:
occurrence_materialization: enummanual|on_completion|rolling; controls when occurrence notes are created (§4.18.5).occurrence_next_trigger: enumcompletion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6).occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported.occurrence_past_horizonandoccurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7).
Materialized occurrence note roles:
recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections.occurrence_date: date value identifying the target date this occurrence note represents.
Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key.
Within a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4).
Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content.
For dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3.
2.7 Unknown fields
Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations.
Unknown fields MAY be removed only when:
- explicit normalization/migration is requested, or
- strict schema replacement is explicitly requested.
2.8 Example mapping
Example effective mapping:
mapping:
id: id
title: title
status: status
date_created: dateCreated
date_modified: dateModified
completed_date: completedDate
recurrence: recurrence
recurrence_anchor: recurrence_anchor
complete_instances: complete_instances
skipped_instances: skipped_instances
recurrence_parent: recurrence_parent
occurrence_date: occurrence_date
occurrence_materialization: occurrence_materialization
occurrence_next_trigger: occurrence_next_trigger
occurrence_template: occurrence_template
occurrence_past_horizon: occurrence_past_horizon
occurrence_future_horizon: occurrence_future_horizon
time_estimate: timeEstimate
time_entries: timeEntries
blocked_by: blockedBy
reminders: reminders
2.9 Example task record
---
id: task-2026-01-10-weekly-review
title: Weekly review
status: open
priority: high
scheduled: 2026-02-20
recurrence: FREQ=WEEKLY;BYDAY=FR
recurrence_anchor: scheduled
complete_instances: [2026-02-13]
skipped_instances: []
blockedBy:
- uid: "[[prepare-metrics]]"
reltype: FINISHTOSTART
gap: P1D
reminders:
- id: rem_day_before
type: relative
relatedTo: due
offset: -P1D
- id: rem_start
type: absolute
absoluteTime: 2026-02-20T09:00:00Z
dateCreated: 2026-01-10T09:30:00Z
dateModified: 2026-02-20T08:02:11Z
---
Review completed work and plan next week.
2.10 Deterministic load example
Given frontmatter:
recurrence_anchor: scheduled
recurrenceAnchor: completion
If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning.