Specification
8. Compatibility and Migrations
This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.
8.1 Purpose#
This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.
8.2 Compatibility modes#
Implementations MAY support compatibility modes for legacy behavior.
If supported, compatibility modes MUST:
- be explicitly enabled or disabled,
- be discoverable through configuration or capability metadata,
- not be silently enabled by default in new collections.
8.3 Migration expectations#
When canonical behavior differs from historical behavior, implementations SHOULD provide:
- deterministic migration rules,
- dry-run preview support,
- rollback-safe workflow guidance.
8.4 Alias normalization migration#
For legacy key aliases, a migration SHOULD:
- read both canonical and alias keys,
- choose canonical value deterministically (recommended: canonical key precedence),
- rewrite persisted file using canonical keys,
- preserve unrelated unknown fields.
8.4.1 Example#
Before:
recurrenceAnchor: scheduled
recurrence_anchor: completion
After normalization:
recurrenceAnchor: scheduled
With warning:
alias_conflict_ignored: alias value ignored because canonical key present.
8.5 Temporal normalization migration#
If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates.
Example:
Before:
dateCreated: 2026-02-20 10:00:00+00:00
After:
dateCreated: 2026-02-20T10:00:00Z
8.6 Recurrence state migration#
If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically.
Recommended resolution policy:
- if overlap exists, prefer most recent user action where recoverable,
- otherwise prefer
complete_instancesand remove overlapping skip entries, - emit migration report for affected dates.
Policy choice MUST be documented.
8.7 Materialized occurrence migration#
When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation. Recommended migration behavior:
- do not materialize historical or future occurrence notes unless explicitly requested;
- preserve existing parent
complete_instancesandskipped_instances; - when importing existing per-occurrence task files, require deterministic parent/date matching before adding
recurrence_parentandoccurrence_date; - when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report
occurrence_state_conflict; - provide a dry-run report before converting existing task files into materialized occurrence notes.
Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks.
8.8 Dependency migration#
When migrating legacy dependency data, implementations SHOULD:
- normalize dependency key names to mapped canonical key,
- ensure each entry has
uidand canonicalreltype, - normalize legacy string/path references into configured canonical reference style,
- remove duplicate dependency entries by policy.
If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values.
8.9 Reminder migration#
When migrating legacy reminder data, implementations SHOULD:
- normalize reminder key names,
- normalize
typevalues to canonical enum (absoluteorrelative), - normalize
relatedTovalues to canonical enum (dueorscheduled), - normalize
absoluteTimeto canonical UTC ISOZ, - validate and normalize offsets to ISO 8601 duration syntax.
If reminder id values are missing, migration MAY generate IDs and MUST report generated count.
8.10 Link migration#
When migrating legacy link values, implementations SHOULD:
- normalize supported link syntaxes according to §11 parsing rules,
- preserve alias and anchor components where possible,
- normalize resolved targets into canonical write format by policy,
- detect and report ambiguous links instead of silently choosing non-deterministically.
8.11 Divergence register#
Implementations SHOULD maintain a divergence register with columns:
- section
- current behavior
- target canonical behavior
- migration strategy
- deprecation timeline
8.12 Deprecation policy#
For any behavior deprecated by the specification:
- announce deprecation in release notes,
- provide warning period,
- provide migration tooling where feasible,
- remove deprecated behavior only in a version aligned with compatibility commitments.
8.13 Data safety requirements#
Migrations MUST NOT:
- silently drop unknown fields,
- silently convert valid date-only fields to datetime,
- silently rewrite recurrence semantics without explicit policy,
- silently materialize occurrence notes outside explicit user/configured materialization policy,
- silently delete materialized occurrence notes during recurrence edits,
- silently drop unresolved dependency entries,
- silently rewrite link targets to different destinations without explicit policy,
- silently delete reminders unless explicitly requested.
8.14 Suggested migration report format#
spec_version_from: 0.1.0-draft
spec_version_to: 0.3.0-rc.3
files_scanned: 214
files_changed: 67
warnings:
alias_conflict_ignored: 3
instance_state_overlap_resolved: 2
occurrence_state_conflict: 1
unresolved_dependency_target: 4
changes:
normalized_datetime_fields: 41
alias_keys_removed: 29
instance_overlaps_fixed: 2
occurrence_state_conflicts: 1
inferred_dependency_reltype: 5
generated_reminder_ids: 8
normalized_link_targets: 14
8.15 Compatibility statement example#
Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true
Planned removal: v2.0.0
Migration command: tasknotes migrate --normalize-frontmatter