Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 00-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The tasknotes plugin is the primary reference for how this spec was derived, but

## 0.1 Status and authority

This document is part of `tasknotes-spec` version `0.3.0-rc.5`.
This document is part of `tasknotes-spec` version `0.3.0-rc.6`.

This specification is normative for implementations that claim conformance.
No single implementation is normative; implementations are expected to conform to the specification.
Expand Down
67 changes: 45 additions & 22 deletions 12-mdbase-v0.3-binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

**Status:** Draft

**Record contract:** `tasknotes.task` `0.3.0-rc.5`
**Record contract:** `tasknotes.task` `0.3.0-rc.6`

This revision adds optional `assignees`: links to records implementing
`mdbase.person`, resolved by ordinary mdbase link resolution. Unresolved links
survive person deletion or membership removal. Assignment and editable person
identity associations never grant collection access. See
[the contract](mdbase/tasknotes.task.md).

rc.6 moves app behaviour out of the binding into the collection's TaskNotes
settings record (§12.8.1): natural-language triggers, templating, archive moves,
time-tracking auto-stop, body-checkbox reset on recurrence, the link write
format, and each status's next status, cycle exclusion and auto-archive. The
binding keeps what gives task records their meaning.

**Event contract:** `tasknotes.task.completed` `1.0.0`

**Target:** mdbase `0.3.x`
Expand Down Expand Up @@ -50,7 +56,7 @@ can implement and several applications can consume.

```text
personal_task ─┐
work_task ─────┼─ implements tasknotes.task 0.3.0-rc.5 ── TaskNotes
work_task ─────┼─ implements tasknotes.task 0.3.0-rc.6 ── TaskNotes
issue_task ────┘ ├─ automation
└─ another task app
```
Expand Down Expand Up @@ -94,7 +100,7 @@ An mdbase TaskNotes type declares one implementation:
```yaml
implements:
- contract: tasknotes.task
version: 0.3.0-rc.5
version: 0.3.0-rc.6
fields:
title: summary
status: state
Expand Down Expand Up @@ -227,8 +233,9 @@ The following consistency rules apply:
and
- definition semantics MUST agree with completed/skipped membership.

Status and priority labels, colors, and icons are presentation hints. Status
cycle, completion, skipping, auto-archive, and priority weight are semantic.
Status and priority labels, colors, and icons are presentation hints.
Completion, skipping, order and priority weight are semantic. Status cycling
and auto-archive are app behaviour and live in the settings record (§12.8.1).

## 12.8 Title, recurrence, links, and operations

Expand All @@ -237,16 +244,13 @@ defined elsewhere in this specification:

- `title` follows §9.13 and MUST agree with `collection.display` and
`collection.path`;
- `recurrence` follows §4;
- `recurrence` follows §4 (`syntax` and `maintain_due_date_offset`);
- `occurrences` follows §2.6.6, §4.18, §5.20, and §9.17;
- `links` follows §11;
- `links` follows §11 (`accepted_formats`);
- attachment membership is the portable `attachments` contract field; binary
MIME type, digest, byte size, revision, and timestamps remain authoritative
in mdbase file descriptors and are not projected into task frontmatter;
- `archive` follows §5.12;
- `time_tracking` follows §5.19 and §9.16;
- `templating` follows §5.3.5 and §9.14; and
- optional `nlp` triggers follow §9.18.
in mdbase file descriptors and are not projected into task frontmatter; and
- `archive` follows §5.12 (`archived_tag`).

Archive always operates on the portable `tags` contract field, so the binding
does not repeat a record-specific `tags_field`. The implementation's `fields`
Expand All @@ -255,10 +259,37 @@ map determines the actual frontmatter property.
Application-local notification preferences and generator bookkeeping MUST NOT
be placed in the binding.

### 12.8.1 App settings record

App behaviour that every TaskNotes client honours, but that does not change what
a task record means, lives in one record at `_settings/dev.tasknotes.md`. The
record implements `mdbase.app-settings` 1.0.0 and `tasknotes.settings` 1.0.0
(both published in mdbase-contracts) with `app: dev.tasknotes`,
`scope: collection` and `settings_version: 1`. Its flat frontmatter holds:

| Field | Was in the rc.5 binding |
| --- | --- |
| `nlp_triggers` | `nlp.triggers` |
| `template_enabled`, `template_path` | `templating.enabled`, `templating.template_path` |
| `occurrence_template_enabled`, `occurrence_template_path` | `templating.occurrence_enabled`, `templating.occurrence_template_path` |
| `template_failure_mode`, `template_unknown_variable_policy` | `templating.failure_mode`, `templating.unknown_variable_policy` |
| `move_on_archive`, `archive_folder` | `archive.move_on_archive`, `archive.folder` |
| `auto_stop_time_tracking_on_complete` | `time_tracking.auto_stop_on_complete` |
| `reset_body_checkboxes_on_recurrence` | `recurrence.reset_body_checkboxes` |
| `link_write_format` | `links.write_format` |
| `status_behavior.<value>` | `status.definitions[].next_status`, `exclude_from_cycle`, `auto_archive`, `auto_archive_delay_minutes` |

Clients MUST read each setting from the record first, then from an
implementation of an earlier contract version that still carries it in its
binding, then use the default. A missing record means defaults; clients MUST
NOT create or rewrite the record on read. A status without a
`status_behavior` entry has no next status, no auto-archive (delay 5 minutes),
and is excluded from the cycle exactly when it is a skipped status.

## 12.9 Multiple implementations

A collection may contain any number of types implementing
`tasknotes.task 0.3.0-rc.5`. TaskNotes-aware readers MUST:
`tasknotes.task 0.3.0-rc.6`. TaskNotes-aware readers MUST:

1. resolve the exact local contract;
2. enumerate every implementation in canonical type-name order;
Expand Down Expand Up @@ -362,7 +393,7 @@ lifecycle:
created_at: { now: true }
implements:
- contract: tasknotes.task
version: 0.3.0-rc.5
version: 0.3.0-rc.6
fields:
title: summary
status: state
Expand All @@ -389,21 +420,13 @@ implements:
recurrence:
syntax: tasknotes
maintain_due_date_offset: false
reset_body_checkboxes: false
occurrences:
identity_roles: [recurrenceParent, occurrenceDate]
default_materialization: manual
default_next_trigger: completion
links:
accepted_formats: [wikilink, markdown]
write_format: wikilink
archive:
archived_tag: archived
move_on_archive: false
time_tracking:
auto_stop_on_complete: true
templating:
enabled: false
occurrence_enabled: false
---
```
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 0.3.0-rc.6 - Unreleased

- Move app behaviour out of the `tasknotes.task` binding into the collection's
TaskNotes settings record (`_settings/dev.tasknotes.md`, contract
`tasknotes.settings` 1.0.0): `nlp`, `templating`, `time_tracking`,
`archive.move_on_archive`, `archive.folder`, `recurrence.reset_body_checkboxes`,
`links.write_format`, and each status definition's `next_status`,
`exclude_from_cycle`, `auto_archive` and `auto_archive_delay_minutes`.
- Readers take each moved setting from the record, then from an rc.5 binding,
then its default, so a collection still on rc.5 keeps its behaviour.

## 0.3.0-rc.5 - Unreleased

- Make `assignees` links to `mdbase.person` records, declared in
Expand Down
23 changes: 17 additions & 6 deletions conformance/tests/mdbase-data-contract.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ test("publishes valid JSON Schemas for the portable task view, binding, and comp
recurrence: {
syntax: "tasknotes",
maintain_due_date_offset: false,
reset_body_checkboxes: false,
},
occurrences: {
identity_roles: ["recurrenceParent", "occurrenceDate"],
Expand All @@ -100,16 +99,28 @@ test("publishes valid JSON Schemas for the portable task view, binding, and comp
},
links: {
accepted_formats: ["wikilink", "markdown"],
write_format: "wikilink",
},
archive: {
archived_tag: "archived",
move_on_archive: false,
},
time_tracking: { auto_stop_on_complete: true },
templating: { enabled: false, occurrence_enabled: false },
};
assert.equal(validateBinding(binding), true, validateBinding.errors);
assert.equal(
validateBinding({
...binding,
time_tracking: { auto_stop_on_complete: true },
}),
false,
"app behaviour lives in the tasknotes.settings record, not the binding"
);
assert.equal(
validateBinding({
...binding,
archive: { archived_tag: "archived", move_on_archive: false },
}),
false,
"archive moves are app behaviour"
);
assert.equal(
validateBinding({ ...binding, contract: "tasknotes.task" }),
false,
Expand Down Expand Up @@ -137,7 +148,7 @@ test("the published contract uses one exact identity and the canonical schemas",
assert.match(contract, /^kind: mdbase\.contract$/m);
assert.match(contract, /^id: tasknotes\.task$/m);
assert.match(contract, /^contract_type: record$/m);
assert.match(contract, /^version: 0\.3\.0-rc\.3$/m);
assert.match(contract, /^version: 0\.3\.0-rc\.6$/m);
assert.match(contract, /^record_schema:$/m);
assert.match(contract, /ref: \.\.\/schemas\/tasknotes-task\.schema\.json/);
assert.match(
Expand Down
9 changes: 6 additions & 3 deletions mdbase/tasknotes.task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
kind: mdbase.contract
contract_type: record
id: tasknotes.task
version: 0.3.0-rc.5
version: 0.3.0-rc.6
name: TaskNotes task
description: Portable task data and behavior defined by tasknotes-spec 0.3.0-rc.5.
description: Portable task data and behavior defined by tasknotes-spec 0.3.0-rc.6.
record_schema:
dialect: json-schema-2020-12
ref: ../schemas/tasknotes-task.schema.json
Expand All @@ -17,7 +17,10 @@ binding_schema:

Types implement this contract with an `implements` entry in their mdbase type
file. The `fields` map adapts custom frontmatter names to this portable view;
the `binding` object supplies TaskNotes behavior.
the `binding` object supplies what task records mean, such as status and
priority vocabularies. App behaviour that does not change that meaning, such as
templates, archive moves and status cycling, lives in the collection's
`tasknotes.settings` record at `_settings/dev.tasknotes.md`.

`assignees` is an optional unique list of links to records implementing
`mdbase.person`, for example `"[[Alex Rivera]]"` or `"[[people/alex-rivera]]"`.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tasknotes-spec",
"version": "0.3.0-rc.5",
"version": "0.3.0-rc.6",
"description": "Specification and conformance fixtures for TaskNotes-compatible markdown task files.",
"license": "MIT",
"type": "module",
Expand Down
Loading