@agentshouse/mdmodel 0.1.0-c83456e1cebfb → 0.1.0-cabd61587647f

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 (295) hide show
  1. package/API.md +242 -181
  2. package/README.md +17 -18
  3. package/dist/blocks.d.ts.map +1 -1
  4. package/dist/blocks.js +33 -26
  5. package/dist/condition.d.ts +149 -0
  6. package/dist/condition.d.ts.map +1 -0
  7. package/dist/condition.js +500 -0
  8. package/dist/definition.d.ts +62 -24
  9. package/dist/definition.d.ts.map +1 -1
  10. package/dist/definition.js +703 -138
  11. package/dist/divide.d.ts.map +1 -1
  12. package/dist/divide.js +18 -8
  13. package/dist/document.d.ts +10 -2
  14. package/dist/document.d.ts.map +1 -1
  15. package/dist/document.js +370 -114
  16. package/dist/fields.d.ts +2 -0
  17. package/dist/fields.d.ts.map +1 -1
  18. package/dist/fields.js +7 -0
  19. package/dist/index.d.ts +14 -6
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +9 -4
  22. package/dist/links.d.ts +2 -0
  23. package/dist/links.d.ts.map +1 -1
  24. package/dist/links.js +23 -12
  25. package/dist/paths.d.ts +4 -0
  26. package/dist/paths.d.ts.map +1 -1
  27. package/dist/paths.js +110 -10
  28. package/dist/project.d.ts +1 -0
  29. package/dist/project.d.ts.map +1 -1
  30. package/dist/project.js +52 -30
  31. package/dist/references.d.ts +4 -0
  32. package/dist/references.d.ts.map +1 -0
  33. package/dist/references.js +25 -0
  34. package/dist/schema.d.ts +7 -6
  35. package/dist/schema.d.ts.map +1 -1
  36. package/dist/schema.js +157 -31
  37. package/dist/types.d.ts +43 -1
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/validate.d.ts +6 -1
  40. package/dist/validate.d.ts.map +1 -1
  41. package/dist/validate.js +167 -144
  42. package/dist/yaml.d.ts +8 -3
  43. package/dist/yaml.d.ts.map +1 -1
  44. package/dist/yaml.js +133 -43
  45. package/fixtures/README.md +49 -38
  46. package/fixtures/cases/absent-link-dangles/context.json +1 -0
  47. package/fixtures/cases/absent-link-dangles/expected.json +1 -0
  48. package/fixtures/cases/absent-link-dangles/library/item.md +8 -0
  49. package/fixtures/cases/absent-link-dangles/schema.yaml +6 -0
  50. package/fixtures/cases/absent-optional-field/context.json +1 -0
  51. package/fixtures/cases/absent-optional-field/expected.json +1 -0
  52. package/fixtures/cases/absent-optional-field/library/companies/acme.md +4 -0
  53. package/fixtures/cases/absent-optional-field/library/deals/lead.md +6 -0
  54. package/fixtures/cases/absent-optional-field/schema.yaml +56 -0
  55. package/fixtures/cases/absolute-link/context.json +1 -0
  56. package/fixtures/cases/{missing-binary-image → absolute-link}/expected.json +1 -1
  57. package/fixtures/cases/absolute-link/library/item.md +8 -0
  58. package/fixtures/cases/absolute-link/schema.yaml +6 -0
  59. package/fixtures/cases/attachment-reference-any-file/context.json +1 -0
  60. package/fixtures/cases/attachment-reference-any-file/expected.json +1 -0
  61. package/fixtures/cases/attachment-reference-any-file/library/companies/acme.md +4 -0
  62. package/fixtures/cases/attachment-reference-any-file/library/deals/renewal.md +15 -0
  63. package/fixtures/cases/attachment-reference-any-file/library/places/depot.md +4 -0
  64. package/fixtures/cases/attachment-reference-any-file/library/products/seats.md +4 -0
  65. package/fixtures/cases/attachment-reference-any-file/library/products/support.md +4 -0
  66. package/fixtures/cases/attachment-reference-any-file/schema.yaml +32 -0
  67. package/fixtures/cases/attachment-reference-dangles/context.json +1 -0
  68. package/fixtures/cases/attachment-reference-dangles/expected.json +1 -0
  69. package/fixtures/cases/attachment-reference-dangles/library/companies/acme.md +4 -0
  70. package/fixtures/cases/attachment-reference-dangles/library/deals/renewal.md +15 -0
  71. package/fixtures/cases/attachment-reference-dangles/library/places/depot.md +4 -0
  72. package/fixtures/cases/attachment-reference-dangles/library/products/seats.md +4 -0
  73. package/fixtures/cases/attachment-reference-dangles/library/products/support.md +4 -0
  74. package/fixtures/cases/attachment-reference-dangles/schema.yaml +32 -0
  75. package/fixtures/cases/attachment-reference-outside/context.json +1 -0
  76. package/fixtures/cases/attachment-reference-outside/expected.json +6 -0
  77. package/fixtures/cases/attachment-reference-outside/library/companies/acme.md +4 -0
  78. package/fixtures/cases/attachment-reference-outside/library/deals/renewal.md +15 -0
  79. package/fixtures/cases/attachment-reference-outside/library/places/depot.md +4 -0
  80. package/fixtures/cases/attachment-reference-outside/library/products/seats.md +4 -0
  81. package/fixtures/cases/attachment-reference-outside/library/products/support.md +4 -0
  82. package/fixtures/cases/attachment-reference-outside/schema.yaml +32 -0
  83. package/fixtures/cases/binary-any-reference/expected.json +1 -1
  84. package/fixtures/cases/binary-any-reference/schema.yaml +4 -4
  85. package/fixtures/cases/binary-document-collision/schema.yaml +1 -2
  86. package/fixtures/cases/binary-image-dangles/expected.json +1 -0
  87. package/fixtures/cases/binary-image-dangles/schema.yaml +1 -0
  88. package/fixtures/cases/binary-link-dangles/expected.json +1 -0
  89. package/fixtures/cases/binary-link-dangles/schema.yaml +1 -0
  90. package/fixtures/cases/binary-link-outside-collection/schema.yaml +1 -2
  91. package/fixtures/cases/binary-prototype-reference/expected.json +1 -1
  92. package/fixtures/cases/binary-prototype-reference/schema.yaml +4 -4
  93. package/fixtures/cases/binary-typed-reference/expected.json +1 -1
  94. package/fixtures/cases/binary-typed-reference/schema.yaml +5 -5
  95. package/fixtures/cases/boolean-field/context.json +1 -0
  96. package/fixtures/cases/boolean-field/expected.json +6 -0
  97. package/fixtures/cases/boolean-field/library/companies/acme.md +4 -0
  98. package/fixtures/cases/boolean-field/library/deals/renewal.md +31 -0
  99. package/fixtures/cases/boolean-field/schema.yaml +56 -0
  100. package/fixtures/cases/bracketed-link-definition/schema.yaml +6 -6
  101. package/fixtures/cases/closed-nested-object/context.json +1 -0
  102. package/fixtures/cases/closed-nested-object/expected.json +6 -0
  103. package/fixtures/cases/closed-nested-object/library/companies/acme.md +4 -0
  104. package/fixtures/cases/closed-nested-object/library/deals/renewal.md +32 -0
  105. package/fixtures/cases/closed-nested-object/schema.yaml +56 -0
  106. package/fixtures/cases/composed-root-reference/context.json +1 -0
  107. package/fixtures/cases/composed-root-reference/expected.json +6 -0
  108. package/fixtures/cases/composed-root-reference/library/a.md +5 -0
  109. package/fixtures/cases/composed-root-reference/schema.yaml +13 -0
  110. package/fixtures/cases/date-time-format/context.json +1 -0
  111. package/fixtures/cases/date-time-format/expected.json +6 -0
  112. package/fixtures/cases/date-time-format/library/companies/acme.md +4 -0
  113. package/fixtures/cases/date-time-format/library/deals/renewal.md +31 -0
  114. package/fixtures/cases/date-time-format/schema.yaml +56 -0
  115. package/fixtures/cases/declared-binary-links/schema.yaml +1 -2
  116. package/fixtures/cases/default-unfilled/context.json +1 -0
  117. package/fixtures/cases/default-unfilled/expected.json +6 -0
  118. package/fixtures/cases/default-unfilled/library/companies/acme.md +4 -0
  119. package/fixtures/cases/default-unfilled/library/deals/renewal.md +29 -0
  120. package/fixtures/cases/default-unfilled/schema.yaml +56 -0
  121. package/fixtures/cases/defs-pattern/context.json +1 -0
  122. package/fixtures/cases/defs-pattern/expected.json +6 -0
  123. package/fixtures/cases/defs-pattern/library/companies/acme.md +4 -0
  124. package/fixtures/cases/defs-pattern/library/deals/renewal.md +31 -0
  125. package/fixtures/cases/defs-pattern/schema.yaml +56 -0
  126. package/fixtures/cases/dependent-rule/context.json +1 -0
  127. package/fixtures/cases/dependent-rule/expected.json +6 -0
  128. package/fixtures/cases/dependent-rule/library/companies/acme.md +4 -0
  129. package/fixtures/cases/dependent-rule/library/deals/renewal.md +30 -0
  130. package/fixtures/cases/dependent-rule/schema.yaml +56 -0
  131. package/fixtures/cases/duplicate-link-definition/schema.yaml +6 -6
  132. package/fixtures/cases/email-format/context.json +1 -0
  133. package/fixtures/cases/email-format/expected.json +6 -0
  134. package/fixtures/cases/email-format/library/companies/acme.md +4 -0
  135. package/fixtures/cases/email-format/library/deals/renewal.md +31 -0
  136. package/fixtures/cases/email-format/schema.yaml +56 -0
  137. package/fixtures/cases/fenced-link-definition/schema.yaml +6 -6
  138. package/fixtures/cases/field-enum/expected.json +2 -2
  139. package/fixtures/cases/field-enum/schema.yaml +7 -7
  140. package/fixtures/cases/frontmatter-schema/schema.yaml +3 -4
  141. package/fixtures/cases/integer-field/context.json +1 -0
  142. package/fixtures/cases/integer-field/expected.json +6 -0
  143. package/fixtures/cases/integer-field/library/companies/acme.md +4 -0
  144. package/fixtures/cases/integer-field/library/deals/renewal.md +31 -0
  145. package/fixtures/cases/integer-field/schema.yaml +56 -0
  146. package/fixtures/cases/interrupted-link-definition/schema.yaml +1 -2
  147. package/fixtures/cases/json-schema-constructs/context.json +1 -0
  148. package/fixtures/cases/json-schema-constructs/expected.json +1 -0
  149. package/fixtures/cases/json-schema-constructs/library/companies/acme.md +4 -0
  150. package/fixtures/cases/json-schema-constructs/library/deals/renewal.md +31 -0
  151. package/fixtures/cases/json-schema-constructs/schema.yaml +56 -0
  152. package/fixtures/cases/list-of-objects-closed/context.json +1 -0
  153. package/fixtures/cases/list-of-objects-closed/expected.json +6 -0
  154. package/fixtures/cases/list-of-objects-closed/library/companies/acme.md +4 -0
  155. package/fixtures/cases/list-of-objects-closed/library/deals/renewal.md +32 -0
  156. package/fixtures/cases/list-of-objects-closed/schema.yaml +56 -0
  157. package/fixtures/cases/list-of-objects-item/context.json +1 -0
  158. package/fixtures/cases/list-of-objects-item/expected.json +6 -0
  159. package/fixtures/cases/list-of-objects-item/library/companies/acme.md +4 -0
  160. package/fixtures/cases/list-of-objects-item/library/deals/renewal.md +31 -0
  161. package/fixtures/cases/list-of-objects-item/schema.yaml +56 -0
  162. package/fixtures/cases/list-of-objects-reference/context.json +1 -0
  163. package/fixtures/cases/list-of-objects-reference/expected.json +6 -0
  164. package/fixtures/cases/list-of-objects-reference/library/companies/acme.md +4 -0
  165. package/fixtures/cases/list-of-objects-reference/library/deals/renewal.md +14 -0
  166. package/fixtures/cases/list-of-objects-reference/library/places/depot.md +4 -0
  167. package/fixtures/cases/list-of-objects-reference/library/products/seats.md +4 -0
  168. package/fixtures/cases/list-of-objects-reference/library/products/support.md +4 -0
  169. package/fixtures/cases/list-of-objects-reference/schema.yaml +32 -0
  170. package/fixtures/cases/list-size/context.json +1 -0
  171. package/fixtures/cases/list-size/expected.json +6 -0
  172. package/fixtures/cases/list-size/library/companies/acme.md +4 -0
  173. package/fixtures/cases/list-size/library/deals/renewal.md +31 -0
  174. package/fixtures/cases/list-size/schema.yaml +56 -0
  175. package/fixtures/cases/long-fence-link-definition/schema.yaml +1 -2
  176. package/fixtures/cases/malformed-definition/expected.json +2 -2
  177. package/fixtures/cases/malformed-definition/schema.yaml +3 -4
  178. package/fixtures/cases/member-document/schema.yaml +5 -5
  179. package/fixtures/cases/missing-required-field/expected.json +2 -2
  180. package/fixtures/cases/missing-required-field/schema.yaml +7 -7
  181. package/fixtures/cases/missing-section-item-kind/expected.json +2 -2
  182. package/fixtures/cases/missing-section-item-kind/schema.yaml +6 -6
  183. package/fixtures/cases/misspelled-key/context.json +1 -0
  184. package/fixtures/cases/misspelled-key/expected.json +6 -0
  185. package/fixtures/cases/misspelled-key/library/companies/acme.md +4 -0
  186. package/fixtures/cases/misspelled-key/library/deals/renewal.md +32 -0
  187. package/fixtures/cases/misspelled-key/schema.yaml +56 -0
  188. package/fixtures/cases/nested-defs/context.json +1 -0
  189. package/fixtures/cases/nested-defs/expected.json +6 -0
  190. package/fixtures/cases/nested-defs/library/deal.md +6 -0
  191. package/fixtures/cases/nested-defs/schema.yaml +11 -0
  192. package/fixtures/cases/nested-object-reference/context.json +1 -0
  193. package/fixtures/cases/nested-object-reference/expected.json +6 -0
  194. package/fixtures/cases/nested-object-reference/library/companies/acme.md +4 -0
  195. package/fixtures/cases/nested-object-reference/library/deals/renewal.md +14 -0
  196. package/fixtures/cases/nested-object-reference/library/places/depot.md +4 -0
  197. package/fixtures/cases/nested-object-reference/library/products/seats.md +4 -0
  198. package/fixtures/cases/nested-object-reference/library/products/support.md +4 -0
  199. package/fixtures/cases/nested-object-reference/schema.yaml +32 -0
  200. package/fixtures/cases/nested-reference/context.json +1 -0
  201. package/fixtures/cases/nested-reference/expected.json +1 -0
  202. package/fixtures/cases/nested-reference/library/companies/acme.md +4 -0
  203. package/fixtures/cases/nested-reference/library/deals/renewal.md +15 -0
  204. package/fixtures/cases/nested-reference/library/places/depot.md +4 -0
  205. package/fixtures/cases/nested-reference/library/products/seats.md +4 -0
  206. package/fixtures/cases/nested-reference/library/products/support.md +4 -0
  207. package/fixtures/cases/nested-reference/schema.yaml +32 -0
  208. package/fixtures/cases/nested-required-field/context.json +1 -0
  209. package/fixtures/cases/nested-required-field/expected.json +6 -0
  210. package/fixtures/cases/nested-required-field/library/companies/acme.md +4 -0
  211. package/fixtures/cases/nested-required-field/library/deals/renewal.md +30 -0
  212. package/fixtures/cases/nested-required-field/schema.yaml +56 -0
  213. package/fixtures/cases/null-refused/context.json +1 -0
  214. package/fixtures/cases/null-refused/expected.json +6 -0
  215. package/fixtures/cases/null-refused/library/companies/acme.md +4 -0
  216. package/fixtures/cases/null-refused/library/deals/renewal.md +31 -0
  217. package/fixtures/cases/null-refused/schema.yaml +56 -0
  218. package/fixtures/cases/numeric-range/context.json +1 -0
  219. package/fixtures/cases/numeric-range/expected.json +6 -0
  220. package/fixtures/cases/numeric-range/library/companies/acme.md +4 -0
  221. package/fixtures/cases/numeric-range/library/deals/renewal.md +31 -0
  222. package/fixtures/cases/numeric-range/schema.yaml +56 -0
  223. package/fixtures/cases/one-of-variant/context.json +1 -0
  224. package/fixtures/cases/one-of-variant/expected.json +6 -0
  225. package/fixtures/cases/one-of-variant/library/companies/acme.md +4 -0
  226. package/fixtures/cases/one-of-variant/library/deals/renewal.md +31 -0
  227. package/fixtures/cases/one-of-variant/schema.yaml +56 -0
  228. package/fixtures/cases/open-map-value/context.json +1 -0
  229. package/fixtures/cases/open-map-value/expected.json +6 -0
  230. package/fixtures/cases/open-map-value/library/companies/acme.md +4 -0
  231. package/fixtures/cases/open-map-value/library/deals/renewal.md +31 -0
  232. package/fixtures/cases/open-map-value/schema.yaml +56 -0
  233. package/fixtures/cases/other-room-reference/context.json +1 -0
  234. package/fixtures/cases/other-room-reference/expected.json +6 -0
  235. package/fixtures/cases/other-room-reference/library/companies/acme.md +4 -0
  236. package/fixtures/cases/other-room-reference/library/deals/renewal.md +14 -0
  237. package/fixtures/cases/other-room-reference/library/places/depot.md +4 -0
  238. package/fixtures/cases/other-room-reference/library/products/seats.md +4 -0
  239. package/fixtures/cases/other-room-reference/library/products/support.md +4 -0
  240. package/fixtures/cases/other-room-reference/schema.yaml +32 -0
  241. package/fixtures/cases/paragraph-link-definition/schema.yaml +1 -2
  242. package/fixtures/cases/prototype-field/expected.json +1 -1
  243. package/fixtures/cases/prototype-field/schema.yaml +6 -6
  244. package/fixtures/cases/quoted-link-definition/library/notes/draft.md +1 -1
  245. package/fixtures/cases/quoted-link-definition/schema.yaml +1 -2
  246. package/fixtures/cases/referenced-missing-file/schema.yaml +11 -10
  247. package/fixtures/cases/remote-ref/context.json +1 -0
  248. package/fixtures/cases/remote-ref/expected.json +5 -0
  249. package/fixtures/cases/remote-ref/schema.yaml +3 -0
  250. package/fixtures/cases/second-member-document/expected.json +2 -2
  251. package/fixtures/cases/second-member-document/schema.yaml +4 -5
  252. package/fixtures/cases/section-item-enum/schema.yaml +3 -4
  253. package/fixtures/cases/section-item-kind/schema.yaml +3 -4
  254. package/fixtures/cases/section-items/library/page.md +14 -0
  255. package/fixtures/cases/section-items/schema.yaml +10 -8
  256. package/fixtures/cases/section-reference-path/schema.yaml +3 -4
  257. package/fixtures/cases/section-reference-type/schema.yaml +3 -4
  258. package/fixtures/cases/shortcut-reference-link/library/item.md +1 -1
  259. package/fixtures/cases/shortcut-reference-link/schema.yaml +6 -6
  260. package/fixtures/cases/string-length/context.json +1 -0
  261. package/fixtures/cases/string-length/expected.json +6 -0
  262. package/fixtures/cases/string-length/library/companies/acme.md +4 -0
  263. package/fixtures/cases/string-length/library/deals/renewal.md +31 -0
  264. package/fixtures/cases/string-length/schema.yaml +56 -0
  265. package/fixtures/cases/structured-section/schema.yaml +7 -7
  266. package/fixtures/cases/submission-keys/schema.yaml +4 -4
  267. package/fixtures/cases/text-field-kind/expected.json +2 -2
  268. package/fixtures/cases/text-field-kind/schema.yaml +4 -4
  269. package/fixtures/cases/truncated-link-definition/library/notes/draft.md +1 -1
  270. package/fixtures/cases/truncated-link-definition/schema.yaml +1 -2
  271. package/fixtures/cases/types-folder-content/schema.yaml +4 -4
  272. package/fixtures/cases/undeclared-field/expected.json +1 -1
  273. package/fixtures/cases/undeclared-field/schema.yaml +6 -6
  274. package/fixtures/cases/unevaluated-items-closed/context.json +1 -0
  275. package/fixtures/cases/unevaluated-items-closed/expected.json +6 -0
  276. package/fixtures/cases/unevaluated-items-closed/library/trip.md +6 -0
  277. package/fixtures/cases/unevaluated-items-closed/schema.yaml +10 -0
  278. package/fixtures/cases/unknown-type/expected.json +1 -1
  279. package/fixtures/cases/unknown-type/schema.yaml +3 -4
  280. package/fixtures/cases/unlisted-reference-type/expected.json +2 -2
  281. package/fixtures/cases/unlisted-reference-type/schema.yaml +3 -4
  282. package/fixtures/cases/unresolved-link/library/item.md +1 -1
  283. package/fixtures/cases/unresolved-link/schema.yaml +6 -6
  284. package/fixtures/cases/valid-typed-document/schema.yaml +16 -15
  285. package/fixtures/cases/wide-item-fence-link/schema.yaml +1 -2
  286. package/fixtures/division.json +1 -1
  287. package/fixtures/projection.json +33 -1
  288. package/package.json +4 -2
  289. package/fixtures/cases/missing-binary-image/schema.yaml +0 -2
  290. package/fixtures/cases/missing-binary-link/expected.json +0 -5
  291. package/fixtures/cases/missing-binary-link/schema.yaml +0 -2
  292. /package/fixtures/cases/{missing-binary-image → binary-image-dangles}/context.json +0 -0
  293. /package/fixtures/cases/{missing-binary-image → binary-image-dangles}/library/notes/draft.md +0 -0
  294. /package/fixtures/cases/{missing-binary-link → binary-link-dangles}/context.json +0 -0
  295. /package/fixtures/cases/{missing-binary-link → binary-link-dangles}/library/notes/draft.md +0 -0
@@ -27,7 +27,7 @@ validation Libraries. It carries `schema`, one schema text, and `cases`. Each
27
27
  case carries `name`, the `file` the Document sits at, exact `source`, the
28
28
  `documentTargets` the collection holds as Markdown documents, the `definition`
29
29
  type name or `null`, an optional `move`, an optional `links` inventory, an
30
- optional `relabel`, and `expected`.
30
+ optional `relabel`, an optional `filtered`, and `expected`.
31
31
  A case carrying a `move` lists both the Path its target sits at and the Path the
32
32
  move takes it to, because the collection holds that target either way.
33
33
 
@@ -41,7 +41,11 @@ moved Path rewrites destinations and leaves the projection alone. Where
41
41
  `relabel` is present, split the source at its `from`, which the source carries
42
42
  exactly once, join the pieces with its `to`, parse the result, and confirm its
43
43
  projection is exactly the relabel's own `expected` and differs from the case's:
44
- a changed visible label changes the projection.
44
+ a changed visible label changes the projection. Where `filtered` is present,
45
+ apply `{ kind: 'field', name: field, value, prior }` with its `field` and
46
+ `value` and the Document's current value as `prior`, confirm the serialized
47
+ Document changed, and confirm its projection is still exactly `expected`: a
48
+ change to a value that is not prose leaves the projection alone.
45
49
 
46
50
  ## Division
47
51
 
@@ -75,56 +79,63 @@ Refusal:
75
79
  {
76
80
  "verdict": "refuse",
77
81
  "file": "<library path>",
78
- "location": "<field or section name>",
82
+ "location": "<JSON Pointer or section name>",
79
83
  "rule": "<rule id>",
80
84
  "referrers": ["<library path>"]
81
85
  }
82
86
  ```
83
87
 
84
- `location` is omitted when the rule is not about a field or section.
85
- `referrers` is present only for `referenced-missing-file`. A schema refusal
86
- carries no `file`; its `location`, when present, is the dotted path of the
87
- schema part it concerns, such as `types.task.fields.title`, or `line <n>` for
88
- `schema-yaml`.
88
+ `location` is the JSON Pointer of the frontmatter value a rule concerns, such
89
+ as `/shipping/city`, or the name of the section it concerns, and is omitted when
90
+ the rule concerns neither. `referrers` is present only for
91
+ `referenced-missing-file`. A schema refusal carries no `file`; its `location`
92
+ is the JSON Pointer of the schema part it concerns, such as
93
+ `/task/properties/title/type`, or `line <n>` for `schema-yaml`.
89
94
 
90
95
  ## Rule ids
91
96
 
92
- | Rule | When |
93
- | ------------------------- | -------------------------------------------------------------------------------- |
94
- | `binary-target-document` | A path is declared as both a text Document and a binary target |
95
- | `frontmatter-fence` | A present frontmatter fence does not parse as the accepted YAML subset |
96
- | `schema-yaml` | A schema text is not a mapping in the accepted YAML subset |
97
- | `schema-shape` | A schema is not a mapping of exactly `types` to a mapping of non-empty names |
98
- | `schema-member-document` | A second type is marked `member_document: true` |
99
- | `definition-shape` | A type is not a mapping of `fields`, `sections`, and a boolean `member_document` |
100
- | `definition-fields` | `fields` is not a mapping |
101
- | `definition-field` | A field spec is not an object of the accepted keys |
102
- | `definition-field-kind` | A field kind is not text, string, number, date, enum, reference, or list |
103
- | `definition-enum-values` | An enum field has no non-empty string `values` |
104
- | `definition-reference-to` | A reference has no `to` naming `any` or a type of the same schema |
105
- | `definition-list-of` | A list field or list section has no `of` that is one scalar kind |
106
- | `definition-sections` | `sections` is not a mapping |
107
- | `definition-section` | A section spec is not an object of the accepted keys |
108
- | `definition-section-kind` | A section kind is not `text` or `list` |
109
- | `unknown-type` | A file declares a type absent from the governing schema |
110
- | `required-field` | A required field is missing |
111
- | `required-section` | A required section heading is missing |
112
- | `field-kind` | A field value fails its kind, including date |
113
- | `field-enum` | A field value is not one of the declared enum values |
114
- | `undeclared-field` | A typed file carries a frontmatter field its type does not declare |
115
- | `unresolved-reference` | A reference field or item resolves to no current file of the required type |
116
- | `unresolved-link` | A relative body link does not resolve to a current path |
117
- | `structured-section` | A declared list section is not a list of its declared item kind |
118
- | `referenced-missing-file` | Remaining files still reference an absent path |
119
- | `unwritable-link` | No Markdown destination form can carry a new link destination |
120
- | `division-budget` | A division budget is not a whole number of at least 2 |
97
+ A frontmatter value that fails a JSON Schema keyword is refused under that
98
+ keyword's name, such as `required`, `type`, `enum`, `format`, `pattern`,
99
+ `minimum`, `maxLength`, `maxItems` or `oneOf`, at the value's JSON Pointer; a
100
+ missing required key is named by the Pointer it would sit at. A malformed
101
+ schema keyword is refused under that keyword's name at its Pointer in the
102
+ schema text. The model's own rules:
103
+
104
+ | Rule | When |
105
+ | ------------------------- | --------------------------------------------------------------------------------- |
106
+ | `binary-target-document` | A path is declared as both a text Document and a binary target |
107
+ | `frontmatter-fence` | A present frontmatter fence does not parse as the accepted YAML subset |
108
+ | `schema-yaml` | A schema text is not a mapping in the accepted YAML subset |
109
+ | `schema-type-name` | A type name is empty, starts with `$`, or is `any` or `attachment` |
110
+ | `schema` | A type or subschema is neither a mapping nor a boolean |
111
+ | `schema-keyword` | A schema carries a key that is no JSON Schema 2020-12 keyword the model admits |
112
+ | `$defs` | `$defs` is not a mapping |
113
+ | `$ref` | A `$ref` reaches no subschema under `#/$defs/` of the same file |
114
+ | `reference` | `reference` is not on a string or names something but a type, `any`, `attachment` |
115
+ | `sections` | A section is not `{ kind: text }` or `{ kind: list, items }` over one scalar |
116
+ | `member_document` | The mark is not a boolean, or a second type carries it |
117
+ | `unknown-type` | A file declares a type absent from the governing schema |
118
+ | `undeclared-field` | A closed object carries a key it does not declare |
119
+ | `required-section` | A required section heading is missing |
120
+ | `unresolved-reference` | A reference at any depth or a section item reaches no member it admits |
121
+ | `unresolved-link` | A body link is an absolute path or leaves the collection |
122
+ | `structured-section` | A declared list section is not a list of values of its item schema |
123
+ | `referenced-missing-file` | Remaining files still reference an absent path |
124
+ | `unwritable-link` | No Markdown destination form can carry a new link destination |
125
+ | `division-budget` | A division budget is not a whole number of at least 2 |
121
126
 
122
127
  `unwritable-link` is refused by `apply` and `division-budget` by `divide`, not
123
128
  by `validate`, so no case under `cases/` carries either.
124
129
 
130
+ A reference that admits `attachment` reaches any path in the same Library, so
131
+ neither `unresolved-reference` for an absent target nor
132
+ `referenced-missing-file` ever names it. A body link to an absent path in the
133
+ Library is accepted too, so `unresolved-link` never names it and
134
+ `referenced-missing-file` never counts it.
135
+
125
136
  ## YAML subset
126
137
 
127
138
  Frontmatter and a schema text are each a mapping in a closed YAML subset: block and flow mappings,
128
- block and flow sequences, plain and quoted scalars, `true`, `false`, `null`,
139
+ block and flow sequences, a block sequence item that opens a mapping, plain and quoted scalars (a single-quoted scalar doubles its apostrophe, a double-quoted one takes JSON's escapes), `true`, `false`, `null`,
129
140
  and decimal numbers. It does not take YAML 1.1 boolean or timestamp aliases,
130
141
  octal numbers, anchors, tags, or block scalars. A mapping carries each key once.
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1,8 @@
1
+ ---
2
+ type: task
3
+ title: Ship
4
+ ---
5
+
6
+ ## Description
7
+
8
+ See [plan](missing.md).
@@ -0,0 +1,6 @@
1
+ task:
2
+ properties:
3
+ title: { type: string }
4
+ required: [title]
5
+ sections:
6
+ Description: { kind: text, required: true }
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: company
3
+ name: Acme
4
+ ---
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: deal
3
+ title: Lead
4
+ company: ../companies/acme.md
5
+ stage: lead
6
+ ---
@@ -0,0 +1,56 @@
1
+ $defs:
2
+ address:
3
+ type: object
4
+ properties:
5
+ city: { type: string }
6
+ country: { type: string, pattern: '^[A-Z]{2}$' }
7
+ required: [city]
8
+ company:
9
+ properties:
10
+ name: { type: string }
11
+ deal:
12
+ type: object
13
+ properties:
14
+ title: { type: string, minLength: 1, maxLength: 40 }
15
+ company: { type: string, reference: company }
16
+ stage: { enum: [lead, proposal, won, lost], default: lead }
17
+ amount: { type: integer, minimum: 0 }
18
+ probability: { type: number, minimum: 0, maximum: 1 }
19
+ open: { type: boolean }
20
+ closes_at: { type: string, format: date-time }
21
+ contact_email: { type: string, format: email }
22
+ note: { type: [string, 'null'] }
23
+ shipping: { $ref: '#/$defs/address' }
24
+ tags: { type: array, items: { type: string }, maxItems: 3 }
25
+ lines:
26
+ type: array
27
+ items:
28
+ type: object
29
+ properties:
30
+ product: { type: string }
31
+ quantity: { type: integer, minimum: 1 }
32
+ required: [product, quantity]
33
+ blocks:
34
+ type: array
35
+ items:
36
+ oneOf:
37
+ - properties:
38
+ kind: { const: paragraph }
39
+ text: { type: string }
40
+ required: [kind, text]
41
+ - properties:
42
+ kind: { const: quiz }
43
+ question: { type: string }
44
+ required: [kind, question]
45
+ attributes:
46
+ type: object
47
+ additionalProperties: { type: string }
48
+ required: [title, company, stage]
49
+ if:
50
+ properties:
51
+ stage: { const: won }
52
+ required: [stage]
53
+ then:
54
+ required: [amount]
55
+ sections:
56
+ Description: { kind: text }
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "verdict": "refuse",
3
- "file": "notes/draft.md",
3
+ "file": "item.md",
4
4
  "rule": "unresolved-link"
5
5
  }
@@ -0,0 +1,8 @@
1
+ ---
2
+ type: task
3
+ title: Ship
4
+ ---
5
+
6
+ ## Description
7
+
8
+ See [plan](/notes/plan.md).
@@ -0,0 +1,6 @@
1
+ task:
2
+ properties:
3
+ title: { type: string }
4
+ required: [title]
5
+ sections:
6
+ Description: { kind: text, required: true }
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: company
3
+ name: Acme
4
+ ---
@@ -0,0 +1,15 @@
1
+ ---
2
+ type: deal
3
+ title: Renewal
4
+ company: ../companies/acme.md
5
+ shipping:
6
+ city: Paris
7
+ depot: ../places/depot.md
8
+ lines:
9
+ - product: ../products/seats.md
10
+ quantity: 10
11
+ - { product: ../products/support.md, quantity: 1 }
12
+ contract: ../products/seats.md
13
+ ---
14
+
15
+ The yearly renewal.
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: place
3
+ name: Depot
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: product
3
+ name: Seats
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: product
3
+ name: Support
4
+ ---
@@ -0,0 +1,32 @@
1
+ $defs:
2
+ address:
3
+ type: object
4
+ properties:
5
+ city: { type: string }
6
+ depot: { type: string, reference: place }
7
+ required: [city]
8
+ company:
9
+ properties:
10
+ name: { type: string }
11
+ product:
12
+ properties:
13
+ name: { type: string }
14
+ place:
15
+ properties:
16
+ name: { type: string }
17
+ deal:
18
+ type: object
19
+ properties:
20
+ title: { type: string }
21
+ company: { type: string, reference: company }
22
+ shipping: { $ref: '#/$defs/address' }
23
+ lines:
24
+ type: array
25
+ items:
26
+ type: object
27
+ properties:
28
+ product: { type: string, reference: product }
29
+ quantity: { type: integer, minimum: 1 }
30
+ required: [product, quantity]
31
+ contract: { type: string, reference: attachment }
32
+ required: [title, company]
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: company
3
+ name: Acme
4
+ ---
@@ -0,0 +1,15 @@
1
+ ---
2
+ type: deal
3
+ title: Renewal
4
+ company: ../companies/acme.md
5
+ shipping:
6
+ city: Paris
7
+ depot: ../places/depot.md
8
+ lines:
9
+ - product: ../products/seats.md
10
+ quantity: 10
11
+ - { product: ../products/support.md, quantity: 1 }
12
+ contract: ../assets/contract.pdf
13
+ ---
14
+
15
+ The yearly renewal.
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: place
3
+ name: Depot
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: product
3
+ name: Seats
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: product
3
+ name: Support
4
+ ---
@@ -0,0 +1,32 @@
1
+ $defs:
2
+ address:
3
+ type: object
4
+ properties:
5
+ city: { type: string }
6
+ depot: { type: string, reference: place }
7
+ required: [city]
8
+ company:
9
+ properties:
10
+ name: { type: string }
11
+ product:
12
+ properties:
13
+ name: { type: string }
14
+ place:
15
+ properties:
16
+ name: { type: string }
17
+ deal:
18
+ type: object
19
+ properties:
20
+ title: { type: string }
21
+ company: { type: string, reference: company }
22
+ shipping: { $ref: '#/$defs/address' }
23
+ lines:
24
+ type: array
25
+ items:
26
+ type: object
27
+ properties:
28
+ product: { type: string, reference: product }
29
+ quantity: { type: integer, minimum: 1 }
30
+ required: [product, quantity]
31
+ contract: { type: string, reference: attachment }
32
+ required: [title, company]
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1,6 @@
1
+ {
2
+ "verdict": "refuse",
3
+ "file": "deals/renewal.md",
4
+ "location": "/contract",
5
+ "rule": "unresolved-reference"
6
+ }
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: company
3
+ name: Acme
4
+ ---
@@ -0,0 +1,15 @@
1
+ ---
2
+ type: deal
3
+ title: Renewal
4
+ company: ../companies/acme.md
5
+ shipping:
6
+ city: Paris
7
+ depot: ../places/depot.md
8
+ lines:
9
+ - product: ../products/seats.md
10
+ quantity: 10
11
+ - { product: ../products/support.md, quantity: 1 }
12
+ contract: /rooms/other/assets/contract.pdf
13
+ ---
14
+
15
+ The yearly renewal.
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: place
3
+ name: Depot
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: product
3
+ name: Seats
4
+ ---
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: product
3
+ name: Support
4
+ ---
@@ -0,0 +1,32 @@
1
+ $defs:
2
+ address:
3
+ type: object
4
+ properties:
5
+ city: { type: string }
6
+ depot: { type: string, reference: place }
7
+ required: [city]
8
+ company:
9
+ properties:
10
+ name: { type: string }
11
+ product:
12
+ properties:
13
+ name: { type: string }
14
+ place:
15
+ properties:
16
+ name: { type: string }
17
+ deal:
18
+ type: object
19
+ properties:
20
+ title: { type: string }
21
+ company: { type: string, reference: company }
22
+ shipping: { $ref: '#/$defs/address' }
23
+ lines:
24
+ type: array
25
+ items:
26
+ type: object
27
+ properties:
28
+ product: { type: string, reference: product }
29
+ quantity: { type: integer, minimum: 1 }
30
+ required: [product, quantity]
31
+ contract: { type: string, reference: attachment }
32
+ required: [title, company]
@@ -2,5 +2,5 @@
2
2
  "verdict": "refuse",
3
3
  "file": "notes/draft.md",
4
4
  "rule": "unresolved-reference",
5
- "location": "subject"
5
+ "location": "/subject"
6
6
  }
@@ -1,4 +1,4 @@
1
- types:
2
- note:
3
- fields:
4
- subject: { kind: reference, to: any, required: true }
1
+ note:
2
+ properties:
3
+ subject: { type: string, reference: any }
4
+ required: [subject]
@@ -1,2 +1 @@
1
- types:
2
- note: {}
1
+ note: {}
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1 @@
1
+ note: {}
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1 @@
1
+ note: {}
@@ -1,2 +1 @@
1
- types:
2
- note: {}
1
+ note: {}
@@ -2,5 +2,5 @@
2
2
  "verdict": "refuse",
3
3
  "file": "notes/draft.md",
4
4
  "rule": "unresolved-reference",
5
- "location": "subject"
5
+ "location": "/subject"
6
6
  }
@@ -1,4 +1,4 @@
1
- types:
2
- note:
3
- fields:
4
- subject: { kind: reference, to: any, required: true }
1
+ note:
2
+ properties:
3
+ subject: { type: string, reference: any }
4
+ required: [subject]
@@ -2,5 +2,5 @@
2
2
  "verdict": "refuse",
3
3
  "file": "notes/draft.md",
4
4
  "rule": "unresolved-reference",
5
- "location": "subject"
5
+ "location": "/subject"
6
6
  }
@@ -1,5 +1,5 @@
1
- types:
2
- note:
3
- fields:
4
- subject: { kind: reference, to: person, required: true }
5
- person: {}
1
+ note:
2
+ properties:
3
+ subject: { type: string, reference: person }
4
+ required: [subject]
5
+ person: {}
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1,6 @@
1
+ {
2
+ "verdict": "refuse",
3
+ "file": "deals/renewal.md",
4
+ "location": "/open",
5
+ "rule": "type"
6
+ }
@@ -0,0 +1,4 @@
1
+ ---
2
+ type: company
3
+ name: Acme
4
+ ---
@@ -0,0 +1,31 @@
1
+ ---
2
+ type: deal
3
+ title: Renewal
4
+ company: ../companies/acme.md
5
+ stage: won
6
+ amount: 1200
7
+ probability: 0.5
8
+ open: "no"
9
+ closes_at: 2026-10-10T09:30:00Z
10
+ contact_email: ana@example.com
11
+ note: null
12
+ shipping:
13
+ city: Paris
14
+ country: FR
15
+ tags: [renewal, priority]
16
+ lines:
17
+ - product: seats
18
+ quantity: 10
19
+ - product: support
20
+ quantity: 1
21
+ blocks:
22
+ - kind: paragraph
23
+ text: Signed.
24
+ - { kind: quiz, question: Renew next year? }
25
+ attributes:
26
+ region: emea
27
+ ---
28
+
29
+ ## Description
30
+
31
+ The yearly renewal.