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,1127 @@
1
+ [
2
+ {
3
+ "id": "link.0001",
4
+ "section": "§11.3",
5
+ "profile": "extended",
6
+ "operation": "link.parse",
7
+ "assertion": "envelope_equals",
8
+ "requires": [
9
+ "links"
10
+ ],
11
+ "input": {
12
+ "raw": "[[task-001]]"
13
+ },
14
+ "expect": {
15
+ "ok": true,
16
+ "result": {
17
+ "raw": "[[task-001]]",
18
+ "format": {
19
+ "$oneOf": [
20
+ "wikilink",
21
+ "markdown",
22
+ "path"
23
+ ]
24
+ },
25
+ "target": {
26
+ "$regex": ".+"
27
+ }
28
+ }
29
+ }
30
+ },
31
+ {
32
+ "id": "link.0002",
33
+ "section": "§11.3",
34
+ "profile": "extended",
35
+ "operation": "link.parse",
36
+ "assertion": "envelope_equals",
37
+ "requires": [
38
+ "links"
39
+ ],
40
+ "input": {
41
+ "raw": "[[task-001|My Task]]"
42
+ },
43
+ "expect": {
44
+ "ok": true,
45
+ "result": {
46
+ "raw": "[[task-001|My Task]]",
47
+ "format": {
48
+ "$oneOf": [
49
+ "wikilink",
50
+ "markdown",
51
+ "path"
52
+ ]
53
+ },
54
+ "target": {
55
+ "$regex": ".+"
56
+ }
57
+ }
58
+ }
59
+ },
60
+ {
61
+ "id": "link.0003",
62
+ "section": "§11.3",
63
+ "profile": "extended",
64
+ "operation": "link.parse",
65
+ "assertion": "envelope_equals",
66
+ "requires": [
67
+ "links"
68
+ ],
69
+ "input": {
70
+ "raw": "[[task-001#anchor]]"
71
+ },
72
+ "expect": {
73
+ "ok": true,
74
+ "result": {
75
+ "raw": "[[task-001#anchor]]",
76
+ "format": {
77
+ "$oneOf": [
78
+ "wikilink",
79
+ "markdown",
80
+ "path"
81
+ ]
82
+ },
83
+ "target": {
84
+ "$regex": ".+"
85
+ }
86
+ }
87
+ }
88
+ },
89
+ {
90
+ "id": "link.0004",
91
+ "section": "§11.3",
92
+ "profile": "extended",
93
+ "operation": "link.parse",
94
+ "assertion": "envelope_equals",
95
+ "requires": [
96
+ "links"
97
+ ],
98
+ "input": {
99
+ "raw": "[[task-001#anchor|Alias]]"
100
+ },
101
+ "expect": {
102
+ "ok": true,
103
+ "result": {
104
+ "raw": "[[task-001#anchor|Alias]]",
105
+ "format": {
106
+ "$oneOf": [
107
+ "wikilink",
108
+ "markdown",
109
+ "path"
110
+ ]
111
+ },
112
+ "target": {
113
+ "$regex": ".+"
114
+ }
115
+ }
116
+ }
117
+ },
118
+ {
119
+ "id": "link.0005",
120
+ "section": "§11.3",
121
+ "profile": "extended",
122
+ "operation": "link.parse",
123
+ "assertion": "envelope_equals",
124
+ "requires": [
125
+ "links"
126
+ ],
127
+ "input": {
128
+ "raw": "[[docs/api#auth]]"
129
+ },
130
+ "expect": {
131
+ "ok": true,
132
+ "result": {
133
+ "raw": "[[docs/api#auth]]",
134
+ "format": {
135
+ "$oneOf": [
136
+ "wikilink",
137
+ "markdown",
138
+ "path"
139
+ ]
140
+ },
141
+ "target": {
142
+ "$regex": ".+"
143
+ }
144
+ }
145
+ }
146
+ },
147
+ {
148
+ "id": "link.0006",
149
+ "section": "§11.3",
150
+ "profile": "extended",
151
+ "operation": "link.parse",
152
+ "assertion": "envelope_equals",
153
+ "requires": [
154
+ "links"
155
+ ],
156
+ "input": {
157
+ "raw": "[[./relative/path]]"
158
+ },
159
+ "expect": {
160
+ "ok": true,
161
+ "result": {
162
+ "raw": "[[./relative/path]]",
163
+ "format": {
164
+ "$oneOf": [
165
+ "wikilink",
166
+ "markdown",
167
+ "path"
168
+ ]
169
+ },
170
+ "target": {
171
+ "$regex": ".+"
172
+ }
173
+ }
174
+ }
175
+ },
176
+ {
177
+ "id": "link.0007",
178
+ "section": "§11.3",
179
+ "profile": "extended",
180
+ "operation": "link.parse",
181
+ "assertion": "envelope_equals",
182
+ "requires": [
183
+ "links"
184
+ ],
185
+ "input": {
186
+ "raw": "[[../parent/path]]"
187
+ },
188
+ "expect": {
189
+ "ok": true,
190
+ "result": {
191
+ "raw": "[[../parent/path]]",
192
+ "format": {
193
+ "$oneOf": [
194
+ "wikilink",
195
+ "markdown",
196
+ "path"
197
+ ]
198
+ },
199
+ "target": {
200
+ "$regex": ".+"
201
+ }
202
+ }
203
+ }
204
+ },
205
+ {
206
+ "id": "link.0008",
207
+ "section": "§11.3",
208
+ "profile": "extended",
209
+ "operation": "link.parse",
210
+ "assertion": "envelope_equals",
211
+ "requires": [
212
+ "links"
213
+ ],
214
+ "input": {
215
+ "raw": "[[folder/target]]"
216
+ },
217
+ "expect": {
218
+ "ok": true,
219
+ "result": {
220
+ "raw": "[[folder/target]]",
221
+ "format": {
222
+ "$oneOf": [
223
+ "wikilink",
224
+ "markdown",
225
+ "path"
226
+ ]
227
+ },
228
+ "target": {
229
+ "$regex": ".+"
230
+ }
231
+ }
232
+ }
233
+ },
234
+ {
235
+ "id": "link.0009",
236
+ "section": "§11.3",
237
+ "profile": "extended",
238
+ "operation": "link.parse",
239
+ "assertion": "envelope_equals",
240
+ "requires": [
241
+ "links"
242
+ ],
243
+ "input": {
244
+ "raw": "[[folder/target|Alias]]"
245
+ },
246
+ "expect": {
247
+ "ok": true,
248
+ "result": {
249
+ "raw": "[[folder/target|Alias]]",
250
+ "format": {
251
+ "$oneOf": [
252
+ "wikilink",
253
+ "markdown",
254
+ "path"
255
+ ]
256
+ },
257
+ "target": {
258
+ "$regex": ".+"
259
+ }
260
+ }
261
+ }
262
+ },
263
+ {
264
+ "id": "link.0010",
265
+ "section": "§11.3",
266
+ "profile": "extended",
267
+ "operation": "link.parse",
268
+ "assertion": "envelope_equals",
269
+ "requires": [
270
+ "links"
271
+ ],
272
+ "input": {
273
+ "raw": "[Label](file.md)"
274
+ },
275
+ "expect": {
276
+ "ok": true,
277
+ "result": {
278
+ "raw": "[Label](file.md)",
279
+ "format": {
280
+ "$oneOf": [
281
+ "wikilink",
282
+ "markdown",
283
+ "path"
284
+ ]
285
+ },
286
+ "target": {
287
+ "$regex": ".+"
288
+ }
289
+ }
290
+ }
291
+ },
292
+ {
293
+ "id": "link.0011",
294
+ "section": "§11.3",
295
+ "profile": "extended",
296
+ "operation": "link.parse",
297
+ "assertion": "envelope_equals",
298
+ "requires": [
299
+ "links"
300
+ ],
301
+ "input": {
302
+ "raw": "[Label](./relative.md)"
303
+ },
304
+ "expect": {
305
+ "ok": true,
306
+ "result": {
307
+ "raw": "[Label](./relative.md)",
308
+ "format": {
309
+ "$oneOf": [
310
+ "wikilink",
311
+ "markdown",
312
+ "path"
313
+ ]
314
+ },
315
+ "target": {
316
+ "$regex": ".+"
317
+ }
318
+ }
319
+ }
320
+ },
321
+ {
322
+ "id": "link.0012",
323
+ "section": "§11.3",
324
+ "profile": "extended",
325
+ "operation": "link.parse",
326
+ "assertion": "envelope_equals",
327
+ "requires": [
328
+ "links"
329
+ ],
330
+ "input": {
331
+ "raw": "[Label](../relative.md#heading)"
332
+ },
333
+ "expect": {
334
+ "ok": true,
335
+ "result": {
336
+ "raw": "[Label](../relative.md#heading)",
337
+ "format": {
338
+ "$oneOf": [
339
+ "wikilink",
340
+ "markdown",
341
+ "path"
342
+ ]
343
+ },
344
+ "target": {
345
+ "$regex": ".+"
346
+ }
347
+ }
348
+ }
349
+ },
350
+ {
351
+ "id": "link.0013",
352
+ "section": "§11.3",
353
+ "profile": "extended",
354
+ "operation": "link.parse",
355
+ "assertion": "envelope_equals",
356
+ "requires": [
357
+ "links"
358
+ ],
359
+ "input": {
360
+ "raw": "[Another](folder/child.md)"
361
+ },
362
+ "expect": {
363
+ "ok": true,
364
+ "result": {
365
+ "raw": "[Another](folder/child.md)",
366
+ "format": {
367
+ "$oneOf": [
368
+ "wikilink",
369
+ "markdown",
370
+ "path"
371
+ ]
372
+ },
373
+ "target": {
374
+ "$regex": ".+"
375
+ }
376
+ }
377
+ }
378
+ },
379
+ {
380
+ "id": "link.0014",
381
+ "section": "§11.3",
382
+ "profile": "extended",
383
+ "operation": "link.parse",
384
+ "assertion": "envelope_equals",
385
+ "requires": [
386
+ "links"
387
+ ],
388
+ "input": {
389
+ "raw": "./other.md"
390
+ },
391
+ "expect": {
392
+ "ok": true,
393
+ "result": {
394
+ "raw": "./other.md",
395
+ "format": {
396
+ "$oneOf": [
397
+ "wikilink",
398
+ "markdown",
399
+ "path"
400
+ ]
401
+ },
402
+ "target": {
403
+ "$regex": ".+"
404
+ }
405
+ }
406
+ }
407
+ },
408
+ {
409
+ "id": "link.0015",
410
+ "section": "§11.3",
411
+ "profile": "extended",
412
+ "operation": "link.parse",
413
+ "assertion": "envelope_equals",
414
+ "requires": [
415
+ "links"
416
+ ],
417
+ "input": {
418
+ "raw": "../parent/task.md"
419
+ },
420
+ "expect": {
421
+ "ok": true,
422
+ "result": {
423
+ "raw": "../parent/task.md",
424
+ "format": {
425
+ "$oneOf": [
426
+ "wikilink",
427
+ "markdown",
428
+ "path"
429
+ ]
430
+ },
431
+ "target": {
432
+ "$regex": ".+"
433
+ }
434
+ }
435
+ }
436
+ },
437
+ {
438
+ "id": "link.0016",
439
+ "section": "§11.3",
440
+ "profile": "extended",
441
+ "operation": "link.parse",
442
+ "assertion": "envelope_equals",
443
+ "requires": [
444
+ "links"
445
+ ],
446
+ "input": {
447
+ "raw": "/root/task.md"
448
+ },
449
+ "expect": {
450
+ "ok": true,
451
+ "result": {
452
+ "raw": "/root/task.md",
453
+ "format": {
454
+ "$oneOf": [
455
+ "wikilink",
456
+ "markdown",
457
+ "path"
458
+ ]
459
+ },
460
+ "target": {
461
+ "$regex": ".+"
462
+ }
463
+ }
464
+ }
465
+ },
466
+ {
467
+ "id": "link.0017",
468
+ "section": "§11.3",
469
+ "profile": "extended",
470
+ "operation": "link.parse",
471
+ "assertion": "envelope_equals",
472
+ "requires": [
473
+ "links"
474
+ ],
475
+ "input": {
476
+ "raw": "folder/task.md"
477
+ },
478
+ "expect": {
479
+ "ok": true,
480
+ "result": {
481
+ "raw": "folder/task.md",
482
+ "format": {
483
+ "$oneOf": [
484
+ "wikilink",
485
+ "markdown",
486
+ "path"
487
+ ]
488
+ },
489
+ "target": {
490
+ "$regex": ".+"
491
+ }
492
+ }
493
+ }
494
+ },
495
+ {
496
+ "id": "link.0018",
497
+ "section": "§11.3",
498
+ "profile": "extended",
499
+ "operation": "link.parse",
500
+ "assertion": "envelope_equals",
501
+ "requires": [
502
+ "links"
503
+ ],
504
+ "input": {
505
+ "raw": "nested/folder/task.md"
506
+ },
507
+ "expect": {
508
+ "ok": true,
509
+ "result": {
510
+ "raw": "nested/folder/task.md",
511
+ "format": {
512
+ "$oneOf": [
513
+ "wikilink",
514
+ "markdown",
515
+ "path"
516
+ ]
517
+ },
518
+ "target": {
519
+ "$regex": ".+"
520
+ }
521
+ }
522
+ }
523
+ },
524
+ {
525
+ "id": "link.0019",
526
+ "section": "§11.3",
527
+ "profile": "extended",
528
+ "operation": "link.parse",
529
+ "assertion": "envelope_error",
530
+ "requires": [
531
+ "links"
532
+ ],
533
+ "input": {
534
+ "raw": "task-plain"
535
+ },
536
+ "expect": {
537
+ "error": {
538
+ "$regex": "invalid_link_format|link"
539
+ }
540
+ }
541
+ },
542
+ {
543
+ "id": "link.0020",
544
+ "section": "§11.3",
545
+ "profile": "extended",
546
+ "operation": "link.parse",
547
+ "assertion": "envelope_error",
548
+ "requires": [
549
+ "links"
550
+ ],
551
+ "input": {
552
+ "raw": "[broken](missing"
553
+ },
554
+ "expect": {
555
+ "error": {
556
+ "$regex": "invalid_link_format|link"
557
+ }
558
+ }
559
+ },
560
+ {
561
+ "id": "link.0021",
562
+ "section": "§11.3",
563
+ "profile": "extended",
564
+ "operation": "link.parse",
565
+ "assertion": "envelope_error",
566
+ "requires": [
567
+ "links"
568
+ ],
569
+ "input": {
570
+ "raw": "[[broken"
571
+ },
572
+ "expect": {
573
+ "error": {
574
+ "$regex": "invalid_link_format|link"
575
+ }
576
+ }
577
+ },
578
+ {
579
+ "id": "link.0022",
580
+ "section": "§11.3",
581
+ "profile": "extended",
582
+ "operation": "link.parse",
583
+ "assertion": "envelope_error",
584
+ "requires": [
585
+ "links"
586
+ ],
587
+ "input": {
588
+ "raw": "http://example.com"
589
+ },
590
+ "expect": {
591
+ "error": {
592
+ "$regex": "invalid_link_format|link"
593
+ }
594
+ }
595
+ },
596
+ {
597
+ "id": "link.0023",
598
+ "section": "§11.3",
599
+ "profile": "extended",
600
+ "operation": "link.parse",
601
+ "assertion": "envelope_error",
602
+ "requires": [
603
+ "links"
604
+ ],
605
+ "input": {
606
+ "raw": ""
607
+ },
608
+ "expect": {
609
+ "error": {
610
+ "$regex": "invalid_link_format|link"
611
+ }
612
+ }
613
+ },
614
+ {
615
+ "id": "link.0024",
616
+ "section": "§11.3",
617
+ "profile": "extended",
618
+ "operation": "link.parse",
619
+ "assertion": "envelope_error",
620
+ "requires": [
621
+ "links"
622
+ ],
623
+ "input": {
624
+ "raw": "not a link"
625
+ },
626
+ "expect": {
627
+ "error": {
628
+ "$regex": "invalid_link_format|link"
629
+ }
630
+ }
631
+ },
632
+ {
633
+ "id": "link.0025",
634
+ "section": "§11",
635
+ "profile": "extended",
636
+ "operation": "link.resolve",
637
+ "assertion": "envelope_equals",
638
+ "requires": [
639
+ "links"
640
+ ],
641
+ "input": {
642
+ "raw": "[[task-001]]",
643
+ "sourcePath": "tasks/sub/task-002.md",
644
+ "collectionRoot": "/vault",
645
+ "candidates": [
646
+ "tasks/task-001.md"
647
+ ],
648
+ "expectedPath": "tasks/task-001.md"
649
+ },
650
+ "expect": {
651
+ "ok": true,
652
+ "result": {
653
+ "path": "tasks/task-001.md"
654
+ }
655
+ }
656
+ },
657
+ {
658
+ "id": "link.0026",
659
+ "section": "§11",
660
+ "profile": "extended",
661
+ "operation": "link.resolve",
662
+ "assertion": "envelope_equals",
663
+ "requires": [
664
+ "links"
665
+ ],
666
+ "input": {
667
+ "raw": "[[../task-001]]",
668
+ "sourcePath": "tasks/sub/task-002.md",
669
+ "collectionRoot": "/vault",
670
+ "candidates": [],
671
+ "expectedPath": "tasks/task-001.md"
672
+ },
673
+ "expect": {
674
+ "ok": true,
675
+ "result": {
676
+ "path": "tasks/task-001.md"
677
+ }
678
+ }
679
+ },
680
+ {
681
+ "id": "link.0027",
682
+ "section": "§11",
683
+ "profile": "extended",
684
+ "operation": "link.resolve",
685
+ "assertion": "envelope_equals",
686
+ "requires": [
687
+ "links"
688
+ ],
689
+ "input": {
690
+ "raw": "[Doc](../../notes/doc.md)",
691
+ "sourcePath": "tasks/sub/task-002.md",
692
+ "collectionRoot": "/vault",
693
+ "candidates": [],
694
+ "expectedPath": "notes/doc.md"
695
+ },
696
+ "expect": {
697
+ "ok": true,
698
+ "result": {
699
+ "path": "notes/doc.md"
700
+ }
701
+ }
702
+ },
703
+ {
704
+ "id": "link.0028",
705
+ "section": "§11",
706
+ "profile": "extended",
707
+ "operation": "link.resolve",
708
+ "assertion": "envelope_equals",
709
+ "requires": [
710
+ "links"
711
+ ],
712
+ "input": {
713
+ "raw": "[[ambiguous]]",
714
+ "sourcePath": "tasks/sub/task-002.md",
715
+ "collectionRoot": "/vault",
716
+ "candidates": [
717
+ "tasks/ambiguous.md",
718
+ "notes/ambiguous.md"
719
+ ],
720
+ "expectedPath": "notes/ambiguous.md"
721
+ },
722
+ "expect": {
723
+ "ok": true,
724
+ "result": {
725
+ "path": "notes/ambiguous.md"
726
+ }
727
+ }
728
+ },
729
+ {
730
+ "id": "link.0029",
731
+ "section": "§11.5",
732
+ "profile": "extended",
733
+ "operation": "link.resolve",
734
+ "assertion": "envelope_error",
735
+ "requires": [
736
+ "links"
737
+ ],
738
+ "input": {
739
+ "raw": "[[../../escape]]",
740
+ "sourcePath": "tasks/sub/task-002.md",
741
+ "collectionRoot": "/vault",
742
+ "candidates": [],
743
+ "errorRegex": "path_traversal|escape"
744
+ },
745
+ "expect": {
746
+ "error": {
747
+ "$regex": "path_traversal|escape"
748
+ }
749
+ }
750
+ },
751
+ {
752
+ "id": "link.0030",
753
+ "section": "§11.5",
754
+ "profile": "extended",
755
+ "operation": "link.resolve",
756
+ "assertion": "envelope_error",
757
+ "requires": [
758
+ "links"
759
+ ],
760
+ "input": {
761
+ "raw": "[Doc](../../../escape.md)",
762
+ "sourcePath": "tasks/sub/task-002.md",
763
+ "collectionRoot": "/vault",
764
+ "candidates": [],
765
+ "errorRegex": "path_traversal|escape"
766
+ },
767
+ "expect": {
768
+ "error": {
769
+ "$regex": "path_traversal|escape"
770
+ }
771
+ }
772
+ },
773
+ {
774
+ "id": "link.0031",
775
+ "section": "§11.5",
776
+ "profile": "extended",
777
+ "operation": "link.resolve",
778
+ "assertion": "envelope_error",
779
+ "requires": [
780
+ "links"
781
+ ],
782
+ "input": {
783
+ "raw": "../../../escape.md",
784
+ "sourcePath": "tasks/sub/task-002.md",
785
+ "collectionRoot": "/vault",
786
+ "candidates": [],
787
+ "errorRegex": "path_traversal|escape"
788
+ },
789
+ "expect": {
790
+ "error": {
791
+ "$regex": "path_traversal|escape"
792
+ }
793
+ }
794
+ },
795
+ {
796
+ "id": "link.0032",
797
+ "section": "§11.5",
798
+ "profile": "extended",
799
+ "operation": "link.resolve",
800
+ "assertion": "envelope_error",
801
+ "requires": [
802
+ "links"
803
+ ],
804
+ "input": {
805
+ "raw": "[[../../../outside/secret]]",
806
+ "sourcePath": "deep/nested/path/task.md",
807
+ "collectionRoot": "/vault",
808
+ "candidates": [],
809
+ "errorRegex": "path_traversal|escape"
810
+ },
811
+ "expect": {
812
+ "error": {
813
+ "$regex": "path_traversal|escape"
814
+ }
815
+ }
816
+ },
817
+ {
818
+ "id": "link.0033",
819
+ "section": "§11",
820
+ "profile": "extended",
821
+ "operation": "link.resolve",
822
+ "assertion": "envelope_equals",
823
+ "requires": [
824
+ "links"
825
+ ],
826
+ "input": {
827
+ "raw": "[[meeting-notes]]",
828
+ "sourcePath": "tasks/sub/task-002.md",
829
+ "collectionRoot": "/vault",
830
+ "candidates": [
831
+ "notes/meeting-notes.markdown",
832
+ "notes/meeting-notes.md"
833
+ ],
834
+ "extensions": [
835
+ ".md",
836
+ ".markdown"
837
+ ],
838
+ "expectedPath": "notes/meeting-notes.md"
839
+ },
840
+ "expect": {
841
+ "ok": true,
842
+ "result": {
843
+ "path": "notes/meeting-notes.md"
844
+ }
845
+ }
846
+ },
847
+ {
848
+ "id": "link.0034",
849
+ "section": "§11",
850
+ "profile": "extended",
851
+ "operation": "link.resolve",
852
+ "assertion": "envelope_error",
853
+ "requires": [
854
+ "links"
855
+ ],
856
+ "input": {
857
+ "raw": "[[meeting-notes]]",
858
+ "sourcePath": "tasks/sub/task-002.md",
859
+ "collectionRoot": "/vault",
860
+ "candidates": [],
861
+ "extensions": [
862
+ ".md",
863
+ ".markdown"
864
+ ],
865
+ "errorRegex": "unresolved|link"
866
+ },
867
+ "expect": {
868
+ "error": {
869
+ "$regex": "unresolved|link"
870
+ }
871
+ }
872
+ },
873
+ {
874
+ "id": "link.0035",
875
+ "section": "§11",
876
+ "profile": "extended",
877
+ "operation": "link.resolve",
878
+ "assertion": "envelope_equals",
879
+ "requires": [
880
+ "links"
881
+ ],
882
+ "input": {
883
+ "raw": "[[my-task-id]]",
884
+ "sourcePath": "tasks/task-001.md",
885
+ "collectionRoot": "/vault",
886
+ "candidates": [
887
+ "tasks/task-002.md"
888
+ ],
889
+ "idIndex": {
890
+ "tasks/task-002.md": "my-task-id"
891
+ },
892
+ "expectedPath": "tasks/task-002.md"
893
+ },
894
+ "expect": {
895
+ "ok": true,
896
+ "result": {
897
+ "path": "tasks/task-002.md"
898
+ }
899
+ }
900
+ },
901
+ {
902
+ "id": "link.0036",
903
+ "section": "§11",
904
+ "profile": "extended",
905
+ "operation": "link.resolve",
906
+ "assertion": "envelope_error",
907
+ "requires": [
908
+ "links"
909
+ ],
910
+ "input": {
911
+ "raw": "[[shared]]",
912
+ "sourcePath": "tasks/sub/task-001.md",
913
+ "collectionRoot": "/vault",
914
+ "candidates": [
915
+ "notes/shared.md",
916
+ "tasks/sub/shared.md"
917
+ ],
918
+ "errorRegex": "ambiguous_link"
919
+ },
920
+ "expect": {
921
+ "error": {
922
+ "$regex": "ambiguous_link"
923
+ }
924
+ }
925
+ },
926
+ {
927
+ "id": "link.0037",
928
+ "section": "§11",
929
+ "profile": "extended",
930
+ "operation": "link.resolve",
931
+ "assertion": "envelope_error",
932
+ "requires": [
933
+ "links"
934
+ ],
935
+ "input": {
936
+ "raw": "[[util]]",
937
+ "sourcePath": "archive/old/task.md",
938
+ "collectionRoot": "/vault",
939
+ "candidates": [
940
+ "lib/util.md",
941
+ "lib/nested/extra/util.md"
942
+ ],
943
+ "errorRegex": "ambiguous_link"
944
+ },
945
+ "expect": {
946
+ "error": {
947
+ "$regex": "ambiguous_link"
948
+ }
949
+ }
950
+ },
951
+ {
952
+ "id": "link.0038",
953
+ "section": "§11",
954
+ "profile": "extended",
955
+ "operation": "link.resolve",
956
+ "assertion": "envelope_equals",
957
+ "requires": [
958
+ "links"
959
+ ],
960
+ "input": {
961
+ "raw": "[[notes/meeting]]",
962
+ "sourcePath": "tasks/sub/task-002.md",
963
+ "collectionRoot": "/vault",
964
+ "candidates": [
965
+ "notes/meeting.md"
966
+ ],
967
+ "expectedPath": "notes/meeting.md"
968
+ },
969
+ "expect": {
970
+ "ok": true,
971
+ "result": {
972
+ "path": "notes/meeting.md"
973
+ }
974
+ }
975
+ },
976
+ {
977
+ "id": "link.0039",
978
+ "section": "§11.6",
979
+ "profile": "extended",
980
+ "operation": "link.update_references_on_rename",
981
+ "assertion": "envelope_equals",
982
+ "requires": [
983
+ "links",
984
+ "rename"
985
+ ],
986
+ "input": {
987
+ "oldPath": "tasks/task-001.md",
988
+ "newPath": "tasks/task-001-renamed.md",
989
+ "references": [
990
+ "[[task-001]]",
991
+ "[[task-001|Alias]]",
992
+ "[Label](../tasks/task-001.md#anchor)"
993
+ ]
994
+ },
995
+ "expect": {
996
+ "ok": true,
997
+ "result": {
998
+ "updated": {
999
+ "$contains": [
1000
+ "[[task-001-renamed]]",
1001
+ "[[task-001-renamed|Alias]]"
1002
+ ]
1003
+ }
1004
+ }
1005
+ }
1006
+ },
1007
+ {
1008
+ "id": "link.0040",
1009
+ "section": "§11.6",
1010
+ "profile": "extended",
1011
+ "operation": "link.update_references_on_rename",
1012
+ "assertion": "envelope_equals",
1013
+ "requires": [
1014
+ "links",
1015
+ "rename"
1016
+ ],
1017
+ "input": {
1018
+ "oldPath": "tasks/task-001.md",
1019
+ "newPath": "tasks/task-001-renamed.md",
1020
+ "references": [
1021
+ "[[task-001]]",
1022
+ "[[task-999]]",
1023
+ "[[other-note]]"
1024
+ ]
1025
+ },
1026
+ "expect": {
1027
+ "ok": true,
1028
+ "result": {
1029
+ "updated": {
1030
+ "$contains": [
1031
+ "[[task-001-renamed]]",
1032
+ "[[task-999]]",
1033
+ "[[other-note]]"
1034
+ ]
1035
+ }
1036
+ }
1037
+ }
1038
+ },
1039
+ {
1040
+ "id": "link.0041",
1041
+ "section": "§11.6",
1042
+ "profile": "extended",
1043
+ "operation": "link.update_references_on_rename",
1044
+ "assertion": "envelope_equals",
1045
+ "requires": [
1046
+ "links",
1047
+ "rename"
1048
+ ],
1049
+ "input": {
1050
+ "oldPath": "tasks/task-001.md",
1051
+ "newPath": "tasks/task-001-v2.md",
1052
+ "references": [
1053
+ "[Task](tasks/task-001.md)",
1054
+ "[Task](tasks/task-001.md#details)",
1055
+ "[Task](tasks/task-777.md#other)"
1056
+ ]
1057
+ },
1058
+ "expect": {
1059
+ "ok": true,
1060
+ "result": {
1061
+ "updated": {
1062
+ "$contains": [
1063
+ "[Task](tasks/task-001-v2.md)",
1064
+ "[Task](tasks/task-001-v2.md#details)",
1065
+ "[Task](tasks/task-777.md#other)"
1066
+ ]
1067
+ }
1068
+ }
1069
+ }
1070
+ },
1071
+ {
1072
+ "id": "link.0042",
1073
+ "section": "§11.6",
1074
+ "profile": "extended",
1075
+ "operation": "link.update_references_on_rename",
1076
+ "assertion": "envelope_equals",
1077
+ "requires": [
1078
+ "links",
1079
+ "rename"
1080
+ ],
1081
+ "input": {
1082
+ "oldPath": "tasks/task-001.md",
1083
+ "newPath": "tasks/task-001-v3.md",
1084
+ "references": [
1085
+ "[[task-001#anchor|Alias]]",
1086
+ "[[task-001]]",
1087
+ "[[task-abc]]"
1088
+ ]
1089
+ },
1090
+ "expect": {
1091
+ "ok": true,
1092
+ "result": {
1093
+ "updated": {
1094
+ "$contains": [
1095
+ "[[task-001-v3#anchor|Alias]]",
1096
+ "[[task-001-v3]]",
1097
+ "[[task-abc]]"
1098
+ ]
1099
+ }
1100
+ }
1101
+ }
1102
+ },
1103
+ {
1104
+ "id": "link.0043",
1105
+ "section": "§11.3",
1106
+ "profile": "extended",
1107
+ "operation": "link.parse",
1108
+ "assertion": "envelope_equals",
1109
+ "requires": [
1110
+ "links"
1111
+ ],
1112
+ "input": {
1113
+ "raw": "[[docs/api#auth|API Reference]]"
1114
+ },
1115
+ "expect": {
1116
+ "ok": true,
1117
+ "result": {
1118
+ "raw": "[[docs/api#auth|API Reference]]",
1119
+ "target": "docs/api",
1120
+ "alias": "API Reference",
1121
+ "anchor": "auth",
1122
+ "format": "wikilink",
1123
+ "is_relative": false
1124
+ }
1125
+ }
1126
+ }
1127
+ ]