@agentshouse/mdmodel 0.1.0-cd90851746292 → 0.1.0-cdbd463e01dc2

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 (95) hide show
  1. package/API.md +90 -81
  2. package/README.md +6 -4
  3. package/dist/definition.d.ts +1 -1
  4. package/dist/definition.d.ts.map +1 -1
  5. package/dist/definition.js +13 -9
  6. package/dist/event.d.ts +78 -0
  7. package/dist/event.d.ts.map +1 -0
  8. package/dist/event.js +230 -0
  9. package/dist/facts.d.ts +15 -0
  10. package/dist/facts.d.ts.map +1 -0
  11. package/dist/facts.js +39 -0
  12. package/dist/index.d.ts +17 -5
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +10 -3
  15. package/dist/kinds.d.ts +19 -0
  16. package/dist/kinds.d.ts.map +1 -0
  17. package/dist/kinds.js +161 -0
  18. package/dist/query/language.d.ts +223 -0
  19. package/dist/query/language.d.ts.map +1 -0
  20. package/dist/query/language.js +565 -0
  21. package/dist/query/match.d.ts +14 -0
  22. package/dist/query/match.d.ts.map +1 -0
  23. package/dist/query/match.js +121 -0
  24. package/dist/query/rows.d.ts +32 -0
  25. package/dist/query/rows.d.ts.map +1 -0
  26. package/dist/query/rows.js +161 -0
  27. package/dist/query/sql.d.ts +39 -0
  28. package/dist/query/sql.d.ts.map +1 -0
  29. package/dist/query/sql.js +279 -0
  30. package/dist/reserved.d.ts +5 -0
  31. package/dist/reserved.d.ts.map +1 -0
  32. package/dist/reserved.js +20 -0
  33. package/dist/types.d.ts +7 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/validate.d.ts +4 -3
  36. package/dist/validate.d.ts.map +1 -1
  37. package/dist/validate.js +103 -36
  38. package/fixtures/README.md +17 -2
  39. package/fixtures/cases/link-into-a-reserved-name/context.json +1 -0
  40. package/fixtures/cases/link-into-a-reserved-name/expected.json +5 -0
  41. package/fixtures/cases/link-into-a-reserved-name/library/notes/a.md +6 -0
  42. package/fixtures/cases/link-into-a-reserved-name/schema.yaml +3 -0
  43. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/context.json +1 -0
  44. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/expected.json +5 -0
  45. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/library/notes/b.md +5 -0
  46. package/fixtures/cases/member-on-an-untyped-document/context.json +1 -0
  47. package/fixtures/cases/member-on-an-untyped-document/expected.json +6 -0
  48. package/fixtures/cases/member-on-an-untyped-document/library/note.md +4 -0
  49. package/fixtures/cases/member-on-another-type/context.json +1 -0
  50. package/fixtures/cases/member-on-another-type/expected.json +6 -0
  51. package/fixtures/cases/member-on-another-type/library/note.md +4 -0
  52. package/fixtures/cases/member-on-another-type/schema.yaml +7 -0
  53. package/fixtures/cases/reference-into-a-reserved-name/context.json +1 -0
  54. package/fixtures/cases/reference-into-a-reserved-name/expected.json +6 -0
  55. package/fixtures/cases/reference-into-a-reserved-name/library/notes/a.md +4 -0
  56. package/fixtures/cases/reference-into-a-reserved-name/library/settings/brief.md +1 -0
  57. package/fixtures/cases/reference-into-a-reserved-name/schema.yaml +3 -0
  58. package/fixtures/cases/room-md-declares-a-type/context.json +1 -0
  59. package/fixtures/cases/room-md-declares-a-type/expected.json +6 -0
  60. package/fixtures/cases/room-md-declares-a-type/library/ROOM.md +5 -0
  61. package/fixtures/cases/typed-path-names-another-type/context.json +11 -0
  62. package/fixtures/cases/typed-path-names-another-type/expected.json +6 -0
  63. package/fixtures/cases/typed-path-names-another-type/library/settings/prefs/one.md +3 -0
  64. package/fixtures/cases/typed-path-names-another-type/schema.yaml +6 -0
  65. package/fixtures/cases/typed-path-names-its-type/context.json +11 -0
  66. package/fixtures/cases/typed-path-names-its-type/expected.json +3 -0
  67. package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/deeper/two.md +1 -0
  68. package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/one.md +4 -0
  69. package/fixtures/cases/typed-path-names-its-type/schema.yaml +6 -0
  70. package/fixtures/cases/typed-path-names-no-type/context.json +11 -0
  71. package/fixtures/cases/typed-path-names-no-type/expected.json +6 -0
  72. package/fixtures/cases/typed-path-names-no-type/library/settings/prefs/one.md +1 -0
  73. package/fixtures/cases/typed-path-names-no-type/schema.yaml +6 -0
  74. package/fixtures/cases/unnamed-typed-path-checks-its-fields/context.json +11 -0
  75. package/fixtures/cases/unnamed-typed-path-checks-its-fields/expected.json +6 -0
  76. package/fixtures/cases/unnamed-typed-path-checks-its-fields/library/rooms/team/tasks/plan.md +4 -0
  77. package/fixtures/cases/unnamed-typed-path-checks-its-fields/schema.yaml +5 -0
  78. package/fixtures/cases/unnamed-typed-path-names-a-type/context.json +11 -0
  79. package/fixtures/cases/unnamed-typed-path-names-a-type/expected.json +6 -0
  80. package/fixtures/cases/unnamed-typed-path-names-a-type/library/rooms/team/tasks/plan.md +6 -0
  81. package/fixtures/cases/unnamed-typed-path-names-a-type/schema.yaml +5 -0
  82. package/fixtures/cases/unnamed-typed-path-reads-its-type/context.json +11 -0
  83. package/fixtures/cases/unnamed-typed-path-reads-its-type/expected.json +3 -0
  84. package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/plan.md +1 -0
  85. package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/tasks/plan.md +5 -0
  86. package/fixtures/cases/unnamed-typed-path-reads-its-type/schema.yaml +5 -0
  87. package/fixtures/cases/unnamed-typed-path-without-a-body/context.json +11 -0
  88. package/fixtures/cases/unnamed-typed-path-without-a-body/expected.json +5 -0
  89. package/fixtures/cases/unnamed-typed-path-without-a-body/library/rooms/team/tasks/plan.md +5 -0
  90. package/fixtures/cases/unnamed-typed-path-without-a-body/schema.yaml +5 -0
  91. package/fixtures/queries.json +913 -0
  92. package/package.json +1 -1
  93. package/dist/condition.d.ts +0 -180
  94. package/dist/condition.d.ts.map +0 -1
  95. package/dist/condition.js +0 -633
@@ -0,0 +1,913 @@
1
+ {
2
+ "schema": "task:\n type: object\n properties:\n title: { type: string }\n status: { enum: [open, done] }\n due: { type: string, format: date }\n at: { type: string, format: date-time }\n ends: { type: [string, \"null\"], format: date-time }\n place:\n type: object\n properties:\n city: { type: string }\n starts: { type: string, format: time }\n points: { type: number }\n count: { type: integer }\n done: { type: boolean }\n priority: { type: integer, enum: [1, 2, 3] }\n flagged: { enum: [true, false] }\n tier: { enum: [1, 2, null] }\n rank: { enum: [1, high] }\n owner: { type: string, reference: person }\n labels: { type: array, items: { type: string } }\n times: { type: array, items: { type: string, format: date-time } }\n steps:\n type: array\n items:\n type: object\n properties:\n name: { type: string }\n at: { type: string, format: date-time }\nperson:\n type: object\n properties:\n name: { type: string }\n",
3
+ "documents": {
4
+ "task": {
5
+ "path": "tasks/one.md",
6
+ "type": "task",
7
+ "fileId": "file-one",
8
+ "text": "# One\n\nShip the release on Friday.\n",
9
+ "fields": {
10
+ "title": "Ship the release",
11
+ "status": "open",
12
+ "due": "2026-10-30",
13
+ "at": "2026-10-30T10:00:00+02:00",
14
+ "starts": "09:30:00Z",
15
+ "points": 3,
16
+ "count": 2,
17
+ "done": false,
18
+ "owner": "../people/ada.md",
19
+ "labels": [
20
+ "urgent",
21
+ "home"
22
+ ],
23
+ "times": [
24
+ "2026-10-30T07:00:00Z",
25
+ "2026-10-31T09:00:00+01:00"
26
+ ],
27
+ "steps": [
28
+ {
29
+ "name": "draft",
30
+ "at": "2026-10-29T23:30:00-01:00"
31
+ }
32
+ ]
33
+ }
34
+ },
35
+ "bare-task": {
36
+ "path": "tasks/two.md",
37
+ "type": "task",
38
+ "fileId": "file-two",
39
+ "text": null,
40
+ "fields": {
41
+ "title": "Two",
42
+ "status": "done",
43
+ "ends": null,
44
+ "labels": []
45
+ }
46
+ },
47
+ "spaced-task": {
48
+ "path": "tasks/three.md",
49
+ "type": "task",
50
+ "fileId": "file-three",
51
+ "text": null,
52
+ "fields": {
53
+ "title": "Three",
54
+ "status": "open",
55
+ "at": "2026-10-30 08:00:00Z",
56
+ "times": [
57
+ "2026-10-30T09:00:00+0100",
58
+ "2026-10-30T12:00:00+02",
59
+ "2026-12-31T23:59:60Z"
60
+ ]
61
+ }
62
+ },
63
+ "note": {
64
+ "path": "notes/loose.md",
65
+ "type": "any",
66
+ "fileId": null,
67
+ "text": "Loose note\n",
68
+ "fields": {
69
+ "at": "2026-10-30T10:00:00+02:00",
70
+ "title": "Loose"
71
+ }
72
+ },
73
+ "export": {
74
+ "path": "data/export.csv",
75
+ "type": null,
76
+ "fileId": null,
77
+ "text": "path,status\n",
78
+ "fields": {}
79
+ }
80
+ },
81
+ "cases": [
82
+ {
83
+ "name": "a type names its Documents",
84
+ "query": {
85
+ "types": [
86
+ "task"
87
+ ]
88
+ },
89
+ "document": "task",
90
+ "matches": true
91
+ },
92
+ {
93
+ "name": "a type leaves an untyped Document out",
94
+ "query": {
95
+ "types": [
96
+ "task"
97
+ ]
98
+ },
99
+ "document": "note",
100
+ "matches": false
101
+ },
102
+ {
103
+ "name": "any names an untyped Markdown Document",
104
+ "query": {
105
+ "types": [
106
+ "any"
107
+ ]
108
+ },
109
+ "document": "note",
110
+ "matches": true
111
+ },
112
+ {
113
+ "name": "any leaves a non-Markdown Document out",
114
+ "query": {
115
+ "types": [
116
+ "any"
117
+ ]
118
+ },
119
+ "document": "export",
120
+ "matches": false
121
+ },
122
+ {
123
+ "name": "a string equals itself",
124
+ "query": {
125
+ "where": {
126
+ "/title": "Ship the release"
127
+ }
128
+ },
129
+ "document": "task",
130
+ "matches": true
131
+ },
132
+ {
133
+ "name": "a string never equals its own prefix",
134
+ "query": {
135
+ "where": {
136
+ "/title": "Ship"
137
+ }
138
+ },
139
+ "document": "task",
140
+ "matches": false
141
+ },
142
+ {
143
+ "name": "a date-time equals the same instant in another offset",
144
+ "query": {
145
+ "where": {
146
+ "/at": "2026-10-30T08:00:00Z"
147
+ }
148
+ },
149
+ "document": "task",
150
+ "matches": true
151
+ },
152
+ {
153
+ "name": "an untyped value equals text, not an instant",
154
+ "query": {
155
+ "where": {
156
+ "/at": "2026-10-30T08:00:00Z"
157
+ }
158
+ },
159
+ "document": "note",
160
+ "matches": false
161
+ },
162
+ {
163
+ "name": "an untyped value equals its own text",
164
+ "query": {
165
+ "where": {
166
+ "/at": "2026-10-30T10:00:00+02:00"
167
+ }
168
+ },
169
+ "document": "note",
170
+ "matches": true
171
+ },
172
+ {
173
+ "name": "a date-time written with a space equals the same instant",
174
+ "query": {
175
+ "where": {
176
+ "/at": "2026-10-30T10:00:00+02:00"
177
+ }
178
+ },
179
+ "document": "spaced-task",
180
+ "matches": true
181
+ },
182
+ {
183
+ "name": "a date-time with a space orders as an instant, not as its text",
184
+ "query": {
185
+ "where": {
186
+ "/at": {
187
+ "$gt": "2026-10-30T09:59:00+02:00"
188
+ }
189
+ }
190
+ },
191
+ "document": "spaced-task",
192
+ "matches": true
193
+ },
194
+ {
195
+ "name": "a date-time whose offset has no colon equals the same instant",
196
+ "query": {
197
+ "where": {
198
+ "/times": "2026-10-30T08:00:00Z"
199
+ }
200
+ },
201
+ "document": "spaced-task",
202
+ "matches": true
203
+ },
204
+ {
205
+ "name": "a date-time whose offset is hours alone equals the same instant",
206
+ "query": {
207
+ "where": {
208
+ "/times": "2026-10-30T10:00:00Z"
209
+ }
210
+ },
211
+ "document": "spaced-task",
212
+ "matches": true
213
+ },
214
+ {
215
+ "name": "a query may write the instant with a space",
216
+ "query": {
217
+ "where": {
218
+ "/at": "2026-10-30 08:00:00Z"
219
+ }
220
+ },
221
+ "document": "task",
222
+ "matches": true
223
+ },
224
+ {
225
+ "name": "a query may write the offset with no colon",
226
+ "query": {
227
+ "where": {
228
+ "/at": "2026-10-30T09:00:00+0100"
229
+ }
230
+ },
231
+ "document": "task",
232
+ "matches": true
233
+ },
234
+ {
235
+ "name": "a query may write the offset as hours alone",
236
+ "query": {
237
+ "where": {
238
+ "/at": "2026-10-30T09:00:00+01"
239
+ }
240
+ },
241
+ "document": "task",
242
+ "matches": true
243
+ },
244
+ {
245
+ "name": "a leap second is the instant after it",
246
+ "query": {
247
+ "where": {
248
+ "/times": "2027-01-01T00:00:00Z"
249
+ }
250
+ },
251
+ "document": "spaced-task",
252
+ "matches": true
253
+ },
254
+ {
255
+ "name": "an explicit null equals null",
256
+ "query": {
257
+ "where": {
258
+ "/ends": null
259
+ }
260
+ },
261
+ "document": "bare-task",
262
+ "matches": true
263
+ },
264
+ {
265
+ "name": "a missing value does not equal null",
266
+ "query": {
267
+ "where": {
268
+ "/ends": null
269
+ }
270
+ },
271
+ "document": "task",
272
+ "matches": false
273
+ },
274
+ {
275
+ "name": "an explicit null exists",
276
+ "query": {
277
+ "where": {
278
+ "/ends": {
279
+ "$exists": true
280
+ }
281
+ }
282
+ },
283
+ "document": "bare-task",
284
+ "matches": true
285
+ },
286
+ {
287
+ "name": "an explicit null fails not-equal to null",
288
+ "query": {
289
+ "where": {
290
+ "/ends": {
291
+ "$ne": null
292
+ }
293
+ }
294
+ },
295
+ "document": "bare-task",
296
+ "matches": false
297
+ },
298
+ {
299
+ "name": "a missing value passes not-equal to null",
300
+ "query": {
301
+ "where": {
302
+ "/ends": {
303
+ "$ne": null
304
+ }
305
+ }
306
+ },
307
+ "document": "task",
308
+ "matches": true
309
+ },
310
+ {
311
+ "name": "an explicit null passes not-equal to a value",
312
+ "query": {
313
+ "where": {
314
+ "/ends": {
315
+ "$ne": "2026-10-30T08:00:00Z"
316
+ }
317
+ }
318
+ },
319
+ "document": "bare-task",
320
+ "matches": true
321
+ },
322
+ {
323
+ "name": "an explicit null fails a range",
324
+ "query": {
325
+ "where": {
326
+ "/ends": {
327
+ "$gte": "2026-01-01T00:00:00Z"
328
+ }
329
+ }
330
+ },
331
+ "document": "bare-task",
332
+ "matches": false
333
+ },
334
+ {
335
+ "name": "an explicit null is in a list naming null",
336
+ "query": {
337
+ "where": {
338
+ "/ends": {
339
+ "$in": [
340
+ null,
341
+ "2026-10-30T08:00:00Z"
342
+ ]
343
+ }
344
+ }
345
+ },
346
+ "document": "bare-task",
347
+ "matches": true
348
+ },
349
+ {
350
+ "name": "a date-time one nanosecond later is another instant",
351
+ "query": {
352
+ "where": {
353
+ "/at": "2026-10-30T08:00:00.000000001Z"
354
+ }
355
+ },
356
+ "document": "task",
357
+ "matches": false
358
+ },
359
+ {
360
+ "name": "a date-time orders as an instant, not as its text",
361
+ "query": {
362
+ "where": {
363
+ "/at": {
364
+ "$lt": "2026-10-30T09:00:00Z"
365
+ }
366
+ }
367
+ },
368
+ "document": "task",
369
+ "matches": true
370
+ },
371
+ {
372
+ "name": "an untyped value orders as text",
373
+ "query": {
374
+ "where": {
375
+ "/at": {
376
+ "$lt": "2026-10-30T09:00:00Z"
377
+ }
378
+ }
379
+ },
380
+ "document": "note",
381
+ "matches": false
382
+ },
383
+ {
384
+ "name": "a later instant written earlier as text is later",
385
+ "query": {
386
+ "where": {
387
+ "/at": {
388
+ "$gt": "2026-10-30T07:59:59-00:30"
389
+ }
390
+ }
391
+ },
392
+ "document": "task",
393
+ "matches": false
394
+ },
395
+ {
396
+ "name": "a closed range holds its one instant",
397
+ "query": {
398
+ "where": {
399
+ "/at": {
400
+ "$gte": "2026-10-30T08:00:00Z",
401
+ "$lte": "2026-10-30T08:00:00Z"
402
+ }
403
+ }
404
+ },
405
+ "document": "task",
406
+ "matches": true
407
+ },
408
+ {
409
+ "name": "a list of date-times holds an item at the same instant",
410
+ "query": {
411
+ "where": {
412
+ "/times": "2026-10-31T08:00:00Z"
413
+ }
414
+ },
415
+ "document": "task",
416
+ "matches": true
417
+ },
418
+ {
419
+ "name": "a list of date-times holds every instant named",
420
+ "query": {
421
+ "where": {
422
+ "/times": {
423
+ "$all": [
424
+ "2026-10-30T07:00:00Z",
425
+ "2026-10-31T08:00:00Z"
426
+ ]
427
+ }
428
+ }
429
+ },
430
+ "document": "task",
431
+ "matches": true
432
+ },
433
+ {
434
+ "name": "a date-time reached through a list orders as an instant",
435
+ "query": {
436
+ "where": {
437
+ "/steps/at": {
438
+ "$gt": "2026-10-30T00:00:00Z"
439
+ }
440
+ }
441
+ },
442
+ "document": "task",
443
+ "matches": true
444
+ },
445
+ {
446
+ "name": "a date orders within its month",
447
+ "query": {
448
+ "where": {
449
+ "/due": {
450
+ "$gte": "2026-10-01",
451
+ "$lt": "2026-11-01"
452
+ }
453
+ }
454
+ },
455
+ "document": "task",
456
+ "matches": true
457
+ },
458
+ {
459
+ "name": "a missing value does not exist",
460
+ "query": {
461
+ "where": {
462
+ "/due": {
463
+ "$exists": false
464
+ }
465
+ }
466
+ },
467
+ "document": "bare-task",
468
+ "matches": true
469
+ },
470
+ {
471
+ "name": "a missing value fails exists",
472
+ "query": {
473
+ "where": {
474
+ "/due": {
475
+ "$exists": true
476
+ }
477
+ }
478
+ },
479
+ "document": "bare-task",
480
+ "matches": false
481
+ },
482
+ {
483
+ "name": "a missing value fails equality",
484
+ "query": {
485
+ "where": {
486
+ "/due": "2026-10-30"
487
+ }
488
+ },
489
+ "document": "bare-task",
490
+ "matches": false
491
+ },
492
+ {
493
+ "name": "a missing value passes not-equal",
494
+ "query": {
495
+ "where": {
496
+ "/due": {
497
+ "$ne": "2026-10-30"
498
+ }
499
+ }
500
+ },
501
+ "document": "bare-task",
502
+ "matches": true
503
+ },
504
+ {
505
+ "name": "a missing value passes not-in",
506
+ "query": {
507
+ "where": {
508
+ "/due": {
509
+ "$nin": [
510
+ "2026-10-30"
511
+ ]
512
+ }
513
+ }
514
+ },
515
+ "document": "bare-task",
516
+ "matches": true
517
+ },
518
+ {
519
+ "name": "a missing value fails a range",
520
+ "query": {
521
+ "where": {
522
+ "/at": {
523
+ "$lt": "2027-01-01T00:00:00Z"
524
+ }
525
+ }
526
+ },
527
+ "document": "bare-task",
528
+ "matches": false
529
+ },
530
+ {
531
+ "name": "a missing value fails a prefix",
532
+ "query": {
533
+ "where": {
534
+ "/owner": {
535
+ "$prefix": "people/"
536
+ }
537
+ }
538
+ },
539
+ "document": "bare-task",
540
+ "matches": false
541
+ },
542
+ {
543
+ "name": "a present value fails not-equal to itself",
544
+ "query": {
545
+ "where": {
546
+ "/status": {
547
+ "$ne": "open"
548
+ }
549
+ }
550
+ },
551
+ "document": "task",
552
+ "matches": false
553
+ },
554
+ {
555
+ "name": "a present value passes not-equal to another",
556
+ "query": {
557
+ "where": {
558
+ "/status": {
559
+ "$ne": "open"
560
+ }
561
+ }
562
+ },
563
+ "document": "bare-task",
564
+ "matches": true
565
+ },
566
+ {
567
+ "name": "a date-time fails not-equal to the same instant",
568
+ "query": {
569
+ "where": {
570
+ "/at": {
571
+ "$ne": "2026-10-30T08:00:00Z"
572
+ }
573
+ }
574
+ },
575
+ "document": "task",
576
+ "matches": false
577
+ },
578
+ {
579
+ "name": "a list holds one of the values named",
580
+ "query": {
581
+ "where": {
582
+ "/labels": {
583
+ "$in": [
584
+ "home",
585
+ "away"
586
+ ]
587
+ }
588
+ }
589
+ },
590
+ "document": "task",
591
+ "matches": true
592
+ },
593
+ {
594
+ "name": "a list holding a value fails not-in it",
595
+ "query": {
596
+ "where": {
597
+ "/labels": {
598
+ "$nin": [
599
+ "home"
600
+ ]
601
+ }
602
+ }
603
+ },
604
+ "document": "task",
605
+ "matches": false
606
+ },
607
+ {
608
+ "name": "a list lacking a value passes not-in it",
609
+ "query": {
610
+ "where": {
611
+ "/labels": {
612
+ "$nin": [
613
+ "away"
614
+ ]
615
+ }
616
+ }
617
+ },
618
+ "document": "task",
619
+ "matches": true
620
+ },
621
+ {
622
+ "name": "a list must hold every value of all",
623
+ "query": {
624
+ "where": {
625
+ "/labels": {
626
+ "$all": [
627
+ "urgent",
628
+ "away"
629
+ ]
630
+ }
631
+ }
632
+ },
633
+ "document": "task",
634
+ "matches": false
635
+ },
636
+ {
637
+ "name": "an empty list has size zero",
638
+ "query": {
639
+ "where": {
640
+ "/labels": {
641
+ "$size": 0
642
+ }
643
+ }
644
+ },
645
+ "document": "bare-task",
646
+ "matches": true
647
+ },
648
+ {
649
+ "name": "a list of two has no size zero",
650
+ "query": {
651
+ "where": {
652
+ "/labels": {
653
+ "$size": 0
654
+ }
655
+ }
656
+ },
657
+ "document": "task",
658
+ "matches": false
659
+ },
660
+ {
661
+ "name": "a number orders against a fraction",
662
+ "query": {
663
+ "where": {
664
+ "/points": {
665
+ "$gt": 2.5
666
+ }
667
+ }
668
+ },
669
+ "document": "task",
670
+ "matches": true
671
+ },
672
+ {
673
+ "name": "an integer equals itself",
674
+ "query": {
675
+ "where": {
676
+ "/count": 2
677
+ }
678
+ },
679
+ "document": "task",
680
+ "matches": true
681
+ },
682
+ {
683
+ "name": "a boolean equals itself",
684
+ "query": {
685
+ "where": {
686
+ "/done": false
687
+ }
688
+ },
689
+ "document": "task",
690
+ "matches": true
691
+ },
692
+ {
693
+ "name": "a string starts with its prefix",
694
+ "query": {
695
+ "where": {
696
+ "/title": {
697
+ "$prefix": "Ship"
698
+ }
699
+ }
700
+ },
701
+ "document": "task",
702
+ "matches": true
703
+ },
704
+ {
705
+ "name": "a prefix compares case",
706
+ "query": {
707
+ "where": {
708
+ "/title": {
709
+ "$prefix": "ship"
710
+ }
711
+ }
712
+ },
713
+ "document": "task",
714
+ "matches": false
715
+ },
716
+ {
717
+ "name": "a list item starts with a prefix",
718
+ "query": {
719
+ "where": {
720
+ "/labels": {
721
+ "$prefix": "urg"
722
+ }
723
+ }
724
+ },
725
+ "document": "task",
726
+ "matches": true
727
+ },
728
+ {
729
+ "name": "a reference starts with the folder of its target",
730
+ "query": {
731
+ "where": {
732
+ "/owner": {
733
+ "$prefix": "people/"
734
+ }
735
+ }
736
+ },
737
+ "document": "task",
738
+ "matches": true
739
+ },
740
+ {
741
+ "name": "a date starts with its month",
742
+ "query": {
743
+ "where": {
744
+ "/due": {
745
+ "$prefix": "2026-10"
746
+ }
747
+ }
748
+ },
749
+ "document": "task",
750
+ "matches": true
751
+ },
752
+ {
753
+ "name": "a reference equals the Path of its target",
754
+ "query": {
755
+ "where": {
756
+ "/owner": "people/ada.md"
757
+ }
758
+ },
759
+ "document": "task",
760
+ "matches": true
761
+ },
762
+ {
763
+ "name": "a time equals its text",
764
+ "query": {
765
+ "where": {
766
+ "/starts": "09:30:00Z"
767
+ }
768
+ },
769
+ "document": "task",
770
+ "matches": true
771
+ },
772
+ {
773
+ "name": "a file ID names its Document",
774
+ "query": {
775
+ "fileIds": [
776
+ "file-one"
777
+ ]
778
+ },
779
+ "document": "task",
780
+ "matches": true
781
+ },
782
+ {
783
+ "name": "a file ID names no other Document",
784
+ "query": {
785
+ "fileIds": [
786
+ "file-one"
787
+ ]
788
+ },
789
+ "document": "bare-task",
790
+ "matches": false
791
+ },
792
+ {
793
+ "name": "a file ID names no Document without one",
794
+ "query": {
795
+ "fileIds": [
796
+ "file-one"
797
+ ]
798
+ },
799
+ "document": "note",
800
+ "matches": false
801
+ },
802
+ {
803
+ "name": "a named Path is read",
804
+ "query": {
805
+ "paths": [
806
+ "tasks/one.md"
807
+ ]
808
+ },
809
+ "document": "task",
810
+ "matches": true
811
+ },
812
+ {
813
+ "name": "a folder holds its own Documents",
814
+ "query": {
815
+ "folder": "tasks"
816
+ },
817
+ "document": "task",
818
+ "matches": true
819
+ },
820
+ {
821
+ "name": "a folder holds no other folder's Documents",
822
+ "query": {
823
+ "folder": "tasks"
824
+ },
825
+ "document": "note",
826
+ "matches": false
827
+ },
828
+ {
829
+ "name": "a Path prefix holds what lies beneath it",
830
+ "query": {
831
+ "pathPrefix": "tasks"
832
+ },
833
+ "document": "task",
834
+ "matches": true
835
+ },
836
+ {
837
+ "name": "a Path prefix is a whole directory",
838
+ "query": {
839
+ "pathPrefix": "task"
840
+ },
841
+ "document": "task",
842
+ "matches": false
843
+ },
844
+ {
845
+ "name": "a phrase is found ignoring case",
846
+ "query": {
847
+ "text": "FRIDAY"
848
+ },
849
+ "document": "task",
850
+ "matches": true
851
+ },
852
+ {
853
+ "name": "a phrase is never found in a document holding no text",
854
+ "query": {
855
+ "text": "friday"
856
+ },
857
+ "document": "bare-task",
858
+ "matches": false
859
+ },
860
+ {
861
+ "name": "or holds when one part holds",
862
+ "query": {
863
+ "where": {
864
+ "$or": [
865
+ {
866
+ "/status": "done"
867
+ },
868
+ {
869
+ "/points": {
870
+ "$gt": 2
871
+ }
872
+ }
873
+ ]
874
+ }
875
+ },
876
+ "document": "task",
877
+ "matches": true
878
+ },
879
+ {
880
+ "name": "and fails when one part fails",
881
+ "query": {
882
+ "where": {
883
+ "$and": [
884
+ {
885
+ "/status": "open"
886
+ },
887
+ {
888
+ "/due": {
889
+ "$exists": false
890
+ }
891
+ }
892
+ ]
893
+ }
894
+ },
895
+ "document": "task",
896
+ "matches": false
897
+ },
898
+ {
899
+ "name": "a type, a Path prefix and a field test hold together",
900
+ "query": {
901
+ "types": [
902
+ "task"
903
+ ],
904
+ "pathPrefix": "tasks",
905
+ "where": {
906
+ "/status": "done"
907
+ }
908
+ },
909
+ "document": "bare-task",
910
+ "matches": true
911
+ }
912
+ ]
913
+ }