tasknotes-spec 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/00-overview.md +172 -0
  2. package/01-terminology.md +156 -0
  3. package/02-model-and-mapping.md +288 -0
  4. package/03-temporal-semantics.md +290 -0
  5. package/04-recurrence.md +398 -0
  6. package/05-operations.md +968 -0
  7. package/06-validation.md +267 -0
  8. package/07-conformance.md +292 -0
  9. package/08-compatibility-and-migrations.md +188 -0
  10. package/09-configuration.md +837 -0
  11. package/10-dependencies-and-reminders.md +266 -0
  12. package/11-links.md +373 -0
  13. package/CHANGELOG.md +25 -0
  14. package/README.md +80 -0
  15. package/conformance/README.md +31 -0
  16. package/conformance/adapters/mdbase-tasknotes.adapter.mjs +141 -0
  17. package/conformance/adapters/tasknotes-core/conformance.ts +2498 -0
  18. package/conformance/adapters/tasknotes-core/create-compat.ts +1 -0
  19. package/conformance/adapters/tasknotes-core/date.ts +12 -0
  20. package/conformance/adapters/tasknotes-core/field-mapping.ts +14 -0
  21. package/conformance/adapters/tasknotes-core/recurrence.ts +10 -0
  22. package/conformance/adapters/tasknotes-date-bridge.ts +20 -0
  23. package/conformance/adapters/tasknotes-runtime-bridge.ts +1107 -0
  24. package/conformance/adapters/tasknotes-runtime-obsidian-shim.ts +84 -0
  25. package/conformance/adapters/tasknotes-templating-bridge.ts +13 -0
  26. package/conformance/adapters/tasknotes.adapter.mjs +485 -0
  27. package/conformance/docs/ADAPTER_CONTRACT.md +245 -0
  28. package/conformance/docs/FIXTURE_FORMAT.md +247 -0
  29. package/conformance/docs/RUNNER_GUIDE.md +393 -0
  30. package/conformance/fixtures/config-schema.json +634 -0
  31. package/conformance/fixtures/config.json +18984 -0
  32. package/conformance/fixtures/conformance.json +444 -0
  33. package/conformance/fixtures/create-compat.json +18639 -0
  34. package/conformance/fixtures/date.json +25612 -0
  35. package/conformance/fixtures/dependencies.json +8647 -0
  36. package/conformance/fixtures/field-mapping.json +5406 -0
  37. package/conformance/fixtures/links.json +1127 -0
  38. package/conformance/fixtures/migrations.json +668 -0
  39. package/conformance/fixtures/operations.json +2761 -0
  40. package/conformance/fixtures/recurrence.json +22958 -0
  41. package/conformance/fixtures/reminders.json +13333 -0
  42. package/conformance/fixtures/templating.json +497 -0
  43. package/conformance/fixtures/validation.json +5308 -0
  44. package/conformance/lib/adapter-loader.mjs +23 -0
  45. package/conformance/lib/load-fixtures.mjs +43 -0
  46. package/conformance/lib/matchers.mjs +200 -0
  47. package/conformance/manifest.json +232 -0
  48. package/conformance/scripts/generate-fixtures.mjs +5239 -0
  49. package/conformance/scripts/package-fixtures.mjs +101 -0
  50. package/conformance/tests/coverage.test.mjs +213 -0
  51. package/conformance/tests/runner.test.mjs +102 -0
  52. package/conformance/tests/tasknotes-runtime-routing.test.mjs +64 -0
  53. package/package.json +49 -0
@@ -0,0 +1,497 @@
1
+ [
2
+ {
3
+ "id": "templating.0001",
4
+ "section": "§5.3.5",
5
+ "profile": "templating",
6
+ "operation": "templating.parse_sections",
7
+ "assertion": "envelope_equals",
8
+ "requires": [
9
+ "templating"
10
+ ],
11
+ "input": {
12
+ "templateText": "---\ntitle: {{title}}\nstatus: {{status}}\n---\nBody {{details}}",
13
+ "expected": {
14
+ "frontmatterRaw": "title: {{title}}\nstatus: {{status}}",
15
+ "body": "Body {{details}}"
16
+ }
17
+ },
18
+ "expect": {
19
+ "ok": true,
20
+ "result": {
21
+ "$contains": {
22
+ "frontmatterRaw": "title: {{title}}\nstatus: {{status}}",
23
+ "body": "Body {{details}}"
24
+ }
25
+ }
26
+ }
27
+ },
28
+ {
29
+ "id": "templating.0002",
30
+ "section": "§5.3.5",
31
+ "profile": "templating",
32
+ "operation": "templating.parse_sections",
33
+ "assertion": "envelope_equals",
34
+ "requires": [
35
+ "templating"
36
+ ],
37
+ "input": {
38
+ "templateText": "No frontmatter here",
39
+ "expected": {
40
+ "frontmatterRaw": "",
41
+ "body": "No frontmatter here"
42
+ }
43
+ },
44
+ "expect": {
45
+ "ok": true,
46
+ "result": {
47
+ "$contains": {
48
+ "frontmatterRaw": "",
49
+ "body": "No frontmatter here"
50
+ }
51
+ }
52
+ }
53
+ },
54
+ {
55
+ "id": "templating.0003",
56
+ "section": "§5.3.5",
57
+ "profile": "templating",
58
+ "operation": "templating.expand_variables",
59
+ "assertion": "envelope_equals",
60
+ "requires": [
61
+ "templating"
62
+ ],
63
+ "input": {
64
+ "template": "{{title}} - {{status}}",
65
+ "values": {
66
+ "title": "Pay bill",
67
+ "status": "open"
68
+ },
69
+ "expected": "Pay bill - open"
70
+ },
71
+ "expect": {
72
+ "ok": true,
73
+ "result": {
74
+ "value": "Pay bill - open"
75
+ }
76
+ }
77
+ },
78
+ {
79
+ "id": "templating.0004",
80
+ "section": "§5.3.5",
81
+ "profile": "templating",
82
+ "operation": "templating.expand_variables",
83
+ "assertion": "envelope_equals",
84
+ "requires": [
85
+ "templating"
86
+ ],
87
+ "input": {
88
+ "template": "{{title}} {{unknown}}",
89
+ "values": {
90
+ "title": "Pay bill"
91
+ },
92
+ "unknownVariablePolicy": "preserve",
93
+ "expected": "Pay bill {{unknown}}"
94
+ },
95
+ "expect": {
96
+ "ok": true,
97
+ "result": {
98
+ "value": "Pay bill {{unknown}}"
99
+ }
100
+ }
101
+ },
102
+ {
103
+ "id": "templating.0005",
104
+ "section": "§5.3.5",
105
+ "profile": "templating",
106
+ "operation": "templating.expand_variables",
107
+ "assertion": "envelope_equals",
108
+ "requires": [
109
+ "templating"
110
+ ],
111
+ "input": {
112
+ "template": "{{title}} {{unknown}}",
113
+ "values": {
114
+ "title": "Pay bill"
115
+ },
116
+ "unknownVariablePolicy": "empty",
117
+ "expected": "Pay bill "
118
+ },
119
+ "expect": {
120
+ "ok": true,
121
+ "result": {
122
+ "value": "Pay bill "
123
+ }
124
+ }
125
+ },
126
+ {
127
+ "id": "templating.0006",
128
+ "section": "§5.3.5",
129
+ "profile": "templating",
130
+ "operation": "templating.expand_variables",
131
+ "assertion": "envelope_equals",
132
+ "requires": [
133
+ "templating"
134
+ ],
135
+ "input": {
136
+ "template": "{{title}} {{priority}} {{dueDate}} {{scheduledDate}} {{details}} {{contexts}} {{tags}} {{timeEstimate}} {{date}} {{time}}",
137
+ "values": {
138
+ "title": "Pay bill",
139
+ "priority": "high",
140
+ "dueDate": "2026-02-20",
141
+ "scheduledDate": "2026-02-19",
142
+ "details": "foo",
143
+ "contexts": "@home",
144
+ "tags": "#task",
145
+ "timeEstimate": "60",
146
+ "date": "2026-02-20",
147
+ "time": "10:00"
148
+ },
149
+ "expected": "Pay bill high 2026-02-20 2026-02-19 foo @home #task 60 2026-02-20 10:00"
150
+ },
151
+ "expect": {
152
+ "ok": true,
153
+ "result": {
154
+ "value": "Pay bill high 2026-02-20 2026-02-19 foo @home #task 60 2026-02-20 10:00"
155
+ }
156
+ }
157
+ },
158
+ {
159
+ "id": "templating.0007",
160
+ "section": "§5.3.5",
161
+ "profile": "templating",
162
+ "operation": "templating.expand_variables",
163
+ "assertion": "envelope_equals",
164
+ "requires": [
165
+ "templating"
166
+ ],
167
+ "input": {
168
+ "template": "{{title}} {{status}} {{priority}} {{dueDate}} {{scheduledDate}} {{details}} {{contexts}} {{tags}} {{hashtags}} {{timeEstimate}} {{parentNote}} {{date}} {{time}} {{year}} {{month}} {{day}}",
169
+ "values": {
170
+ "title": "Write report",
171
+ "status": "open",
172
+ "priority": "normal",
173
+ "dueDate": "2026-02-20",
174
+ "scheduledDate": "2026-02-19",
175
+ "details": "ship weekly update",
176
+ "contexts": "work, home",
177
+ "tags": "task, writing",
178
+ "hashtags": "#task #writing",
179
+ "timeEstimate": "45",
180
+ "parentNote": "Projects/Alpha",
181
+ "date": "2026-02-20",
182
+ "time": "10:00",
183
+ "year": "2026",
184
+ "month": "02",
185
+ "day": "20"
186
+ },
187
+ "expected": "Write report open normal 2026-02-20 2026-02-19 ship weekly update work, home task, writing #task #writing 45 Projects/Alpha 2026-02-20 10:00 2026 02 20"
188
+ },
189
+ "expect": {
190
+ "ok": true,
191
+ "result": {
192
+ "value": "Write report open normal 2026-02-20 2026-02-19 ship weekly update work, home task, writing #task #writing 45 Projects/Alpha 2026-02-20 10:00 2026 02 20"
193
+ }
194
+ }
195
+ },
196
+ {
197
+ "id": "templating.0008",
198
+ "section": "§5.3.5",
199
+ "profile": "templating",
200
+ "operation": "templating.tokenize",
201
+ "assertion": "envelope_equals",
202
+ "requires": [
203
+ "templating"
204
+ ],
205
+ "input": {
206
+ "template": "{{title}} {{status}} {{priority}}",
207
+ "expectedTokens": [
208
+ "title",
209
+ "status",
210
+ "priority"
211
+ ]
212
+ },
213
+ "expect": {
214
+ "ok": true,
215
+ "result": {
216
+ "tokens": [
217
+ "title",
218
+ "status",
219
+ "priority"
220
+ ]
221
+ }
222
+ }
223
+ },
224
+ {
225
+ "id": "templating.0009",
226
+ "section": "§5.3.5",
227
+ "profile": "templating",
228
+ "operation": "templating.tokenize",
229
+ "assertion": "envelope_equals",
230
+ "requires": [
231
+ "templating"
232
+ ],
233
+ "input": {
234
+ "template": "prefix {{title}} mid {{unknown}} suffix",
235
+ "expectedTokens": [
236
+ "title",
237
+ "unknown"
238
+ ]
239
+ },
240
+ "expect": {
241
+ "ok": true,
242
+ "result": {
243
+ "tokens": [
244
+ "title",
245
+ "unknown"
246
+ ]
247
+ }
248
+ }
249
+ },
250
+ {
251
+ "id": "templating.0010",
252
+ "section": "§5.3.5",
253
+ "profile": "templating",
254
+ "operation": "templating.merge_frontmatter",
255
+ "assertion": "envelope_equals",
256
+ "requires": [
257
+ "templating"
258
+ ],
259
+ "input": {
260
+ "baseFrontmatter": {
261
+ "title": "A",
262
+ "status": "open",
263
+ "priority": "normal"
264
+ },
265
+ "templateFrontmatter": {
266
+ "title": "B",
267
+ "status": "done",
268
+ "project": "X"
269
+ },
270
+ "expected": {
271
+ "title": "A",
272
+ "status": "open",
273
+ "priority": "normal",
274
+ "project": "X"
275
+ }
276
+ },
277
+ "expect": {
278
+ "ok": true,
279
+ "result": {
280
+ "value": {
281
+ "title": "A",
282
+ "status": "open",
283
+ "priority": "normal",
284
+ "project": "X"
285
+ }
286
+ }
287
+ }
288
+ },
289
+ {
290
+ "id": "templating.0011",
291
+ "section": "§5.3.5",
292
+ "profile": "templating",
293
+ "operation": "templating.merge_frontmatter",
294
+ "assertion": "envelope_equals",
295
+ "requires": [
296
+ "templating"
297
+ ],
298
+ "input": {
299
+ "baseFrontmatter": {
300
+ "title": "A",
301
+ "tags": [
302
+ "one"
303
+ ]
304
+ },
305
+ "templateFrontmatter": {
306
+ "tags": [
307
+ "two"
308
+ ],
309
+ "extra": true
310
+ },
311
+ "expected": {
312
+ "title": "A",
313
+ "tags": [
314
+ "one"
315
+ ],
316
+ "extra": true
317
+ }
318
+ },
319
+ "expect": {
320
+ "ok": true,
321
+ "result": {
322
+ "value": {
323
+ "title": "A",
324
+ "tags": [
325
+ "one"
326
+ ],
327
+ "extra": true
328
+ }
329
+ }
330
+ }
331
+ },
332
+ {
333
+ "id": "templating.0012",
334
+ "section": "§5.3.5",
335
+ "profile": "templating",
336
+ "operation": "templating.create_pipeline",
337
+ "assertion": "envelope_equals",
338
+ "requires": [
339
+ "templating"
340
+ ],
341
+ "input": {
342
+ "baseFrontmatter": {
343
+ "title": "Base title",
344
+ "status": "open",
345
+ "priority": "normal"
346
+ },
347
+ "templateFrontmatter": {
348
+ "title": "Template title",
349
+ "status": "done",
350
+ "project": "A"
351
+ },
352
+ "callerBody": "Caller body",
353
+ "templateBody": "Template body",
354
+ "expectedFrontmatter": {
355
+ "title": "Base title",
356
+ "status": "open",
357
+ "priority": "normal",
358
+ "project": "A"
359
+ },
360
+ "expectedBody": "Template body"
361
+ },
362
+ "expect": {
363
+ "ok": true,
364
+ "result": {
365
+ "frontmatter": {
366
+ "title": "Base title",
367
+ "status": "open",
368
+ "priority": "normal",
369
+ "project": "A"
370
+ },
371
+ "body": "Template body"
372
+ }
373
+ }
374
+ },
375
+ {
376
+ "id": "templating.0013",
377
+ "section": "§5.3.5",
378
+ "profile": "templating",
379
+ "operation": "templating.create_pipeline",
380
+ "assertion": "envelope_equals",
381
+ "requires": [
382
+ "templating"
383
+ ],
384
+ "input": {
385
+ "baseFrontmatter": {
386
+ "title": "Base title",
387
+ "status": "open"
388
+ },
389
+ "templateFrontmatter": {
390
+ "status": "done",
391
+ "project": "A"
392
+ },
393
+ "callerBody": "Caller body",
394
+ "templateBody": "",
395
+ "expectedFrontmatter": {
396
+ "title": "Base title",
397
+ "status": "open",
398
+ "project": "A"
399
+ },
400
+ "expectedBody": "Caller body"
401
+ },
402
+ "expect": {
403
+ "ok": true,
404
+ "result": {
405
+ "frontmatter": {
406
+ "title": "Base title",
407
+ "status": "open",
408
+ "project": "A"
409
+ },
410
+ "body": "Caller body"
411
+ }
412
+ }
413
+ },
414
+ {
415
+ "id": "templating.0014",
416
+ "section": "§5.3.5",
417
+ "profile": "templating",
418
+ "operation": "templating.handle_failure",
419
+ "assertion": "envelope_error",
420
+ "requires": [
421
+ "templating"
422
+ ],
423
+ "input": {
424
+ "failureMode": "error",
425
+ "errorCode": "template_missing",
426
+ "shouldError": true
427
+ },
428
+ "expect": {
429
+ "error": {
430
+ "$regex": "template_missing|template_parse_failed|template"
431
+ }
432
+ }
433
+ },
434
+ {
435
+ "id": "templating.0015",
436
+ "section": "§5.3.5",
437
+ "profile": "templating",
438
+ "operation": "templating.handle_failure",
439
+ "assertion": "envelope_equals",
440
+ "requires": [
441
+ "templating"
442
+ ],
443
+ "input": {
444
+ "failureMode": "warning_fallback",
445
+ "errorCode": "template_parse_failed",
446
+ "shouldError": false
447
+ },
448
+ "expect": {
449
+ "ok": true,
450
+ "result": {
451
+ "mode": "fallback"
452
+ }
453
+ }
454
+ },
455
+ {
456
+ "id": "templating.0016",
457
+ "section": "§9.14",
458
+ "profile": "templating",
459
+ "operation": "templating.config_defaults",
460
+ "assertion": "envelope_equals",
461
+ "requires": [
462
+ "templating"
463
+ ],
464
+ "input": {
465
+ "enabled": true,
466
+ "template_path": "Templates/Task.md"
467
+ },
468
+ "expect": {
469
+ "ok": true,
470
+ "result": {
471
+ "failure_mode": "warning_fallback",
472
+ "unknown_variable_policy": "preserve"
473
+ }
474
+ }
475
+ },
476
+ {
477
+ "id": "templating.0017",
478
+ "section": "§7.3.3",
479
+ "profile": "templating",
480
+ "operation": "templating.profile_claim_requirements",
481
+ "assertion": "envelope_equals",
482
+ "requires": [
483
+ "templating"
484
+ ],
485
+ "input": {
486
+ "supports_create_time_templating": true,
487
+ "supports_failure_mode": true,
488
+ "supports_variable_set": true
489
+ },
490
+ "expect": {
491
+ "ok": true,
492
+ "result": {
493
+ "value": "claim_valid"
494
+ }
495
+ }
496
+ }
497
+ ]