@formicoidea/labre-core 0.31.0 → 0.33.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 (637) hide show
  1. package/dist/_pkgs/affine-block-attachment/attachment-block.js +1 -1
  2. package/dist/_pkgs/affine-block-callout/callout-block.d.ts +6 -0
  3. package/dist/_pkgs/affine-block-callout/callout-block.js +26 -4
  4. package/dist/_pkgs/affine-block-callout/callout-keymap.js +59 -19
  5. package/dist/_pkgs/affine-block-callout/commands/callout-to-paragraph.d.ts +20 -0
  6. package/dist/_pkgs/affine-block-callout/commands/callout-to-paragraph.js +60 -0
  7. package/dist/_pkgs/affine-block-callout/commands/split-callout.d.ts +17 -0
  8. package/dist/_pkgs/affine-block-callout/commands/split-callout.js +42 -0
  9. package/dist/_pkgs/affine-block-callout/configs/slash-menu.js +9 -6
  10. package/dist/_pkgs/affine-block-callout/emoji-margin.d.ts +9 -0
  11. package/dist/_pkgs/affine-block-callout/emoji-margin.js +36 -0
  12. package/dist/_pkgs/affine-block-callout/emoji-menu.d.ts +5 -1
  13. package/dist/_pkgs/affine-block-callout/emoji-menu.js +5 -0
  14. package/dist/_pkgs/affine-block-code/code-block-inline.js +1 -1
  15. package/dist/_pkgs/affine-block-code/code-block.d.ts +14 -0
  16. package/dist/_pkgs/affine-block-code/code-block.js +44 -6
  17. package/dist/_pkgs/affine-block-code/code-toolbar/components/code-toolbar.d.ts +2 -0
  18. package/dist/_pkgs/affine-block-code/code-toolbar/components/code-toolbar.js +23 -14
  19. package/dist/_pkgs/affine-block-code/code-toolbar/components/more-menu.d.ts +16 -0
  20. package/dist/_pkgs/affine-block-code/code-toolbar/components/more-menu.js +93 -0
  21. package/dist/_pkgs/affine-block-code/code-toolbar/config.js +54 -5
  22. package/dist/_pkgs/affine-block-code/code-toolbar/index.js +1 -1
  23. package/dist/_pkgs/affine-block-code/effects.d.ts +2 -0
  24. package/dist/_pkgs/affine-block-code/effects.js +2 -0
  25. package/dist/_pkgs/affine-block-code/highlight/affine-code-unit.js +6 -1
  26. package/dist/_pkgs/affine-block-code/index.d.ts +1 -0
  27. package/dist/_pkgs/affine-block-code/index.js +1 -0
  28. package/dist/_pkgs/affine-block-code/line-numbers.d.ts +25 -0
  29. package/dist/_pkgs/affine-block-code/line-numbers.js +27 -0
  30. package/dist/_pkgs/affine-block-code/styles.js +31 -0
  31. package/dist/_pkgs/affine-block-data-view/data-view-block.js +1 -0
  32. package/dist/_pkgs/affine-block-database/components/title/index.js +4 -1
  33. package/dist/_pkgs/affine-block-database/configs/slash-menu.js +28 -1
  34. package/dist/_pkgs/affine-block-database/data-source.js +1 -2
  35. package/dist/_pkgs/affine-block-database/database-block.js +13 -0
  36. package/dist/_pkgs/affine-block-database/external-data-source.js +1 -1
  37. package/dist/_pkgs/affine-block-database/properties/paste-url.d.ts +24 -0
  38. package/dist/_pkgs/affine-block-database/properties/paste-url.js +98 -0
  39. package/dist/_pkgs/affine-block-database/properties/rich-text/cell-renderer.js +9 -19
  40. package/dist/_pkgs/affine-block-database/properties/title/text.js +20 -25
  41. package/dist/_pkgs/affine-block-database/views/index.js +1 -0
  42. package/dist/_pkgs/affine-block-edgeless-text/edgeless-text-block.js +11 -1
  43. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.d.ts +3 -0
  44. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.js +48 -1
  45. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/font-size.d.ts +17 -0
  46. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/font-size.js +24 -0
  47. package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-service.js +1 -1
  48. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +2 -2
  49. package/dist/_pkgs/affine-block-embed-doc/common/doc-trashed.d.ts +9 -0
  50. package/dist/_pkgs/affine-block-embed-doc/common/doc-trashed.js +10 -0
  51. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/toolbar.js +1 -1
  52. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.js +8 -4
  53. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/utils.js +1 -1
  54. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +1 -1
  55. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.d.ts +4 -0
  56. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.js +23 -4
  57. package/dist/_pkgs/affine-block-frame/frame-manager.d.ts +13 -0
  58. package/dist/_pkgs/affine-block-frame/frame-manager.js +34 -2
  59. package/dist/_pkgs/affine-block-frame/frame-tool.js +1 -1
  60. package/dist/_pkgs/affine-block-image/components/page-image-block.js +1 -1
  61. package/dist/_pkgs/affine-block-image/image-edgeless-block.js +1 -1
  62. package/dist/_pkgs/affine-block-latex/styles.js +6 -1
  63. package/dist/_pkgs/affine-block-list/utils/forward-delete.js +1 -1
  64. package/dist/_pkgs/affine-block-note/commands/select-block.js +1 -1
  65. package/dist/_pkgs/affine-block-note/commands/select-blocks-between.js +1 -1
  66. package/dist/_pkgs/affine-block-note/move-block.js +1 -1
  67. package/dist/_pkgs/affine-block-note/note-edgeless-block.d.ts +9 -0
  68. package/dist/_pkgs/affine-block-note/note-edgeless-block.js +29 -1
  69. package/dist/_pkgs/affine-block-paragraph/utils/forward-delete.js +2 -2
  70. package/dist/_pkgs/affine-block-paragraph/utils/merge-with-prev.js +1 -1
  71. package/dist/_pkgs/affine-block-root/commands/pivot-commands.d.ts +37 -0
  72. package/dist/_pkgs/affine-block-root/commands/pivot-commands.js +168 -0
  73. package/dist/_pkgs/affine-block-root/commands/reading-commands.d.ts +23 -0
  74. package/dist/_pkgs/affine-block-root/commands/reading-commands.js +107 -0
  75. package/dist/_pkgs/affine-block-root/commands/tag-commands.d.ts +47 -0
  76. package/dist/_pkgs/affine-block-root/commands/tag-commands.js +159 -0
  77. package/dist/_pkgs/affine-block-root/configs/toolbar.d.ts +1 -0
  78. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.js +10 -3
  79. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/render-linked-doc.js +1 -1
  80. package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +27 -2
  81. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +11 -2
  82. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-service.js +14 -0
  83. package/dist/_pkgs/affine-block-root/edgeless/index.d.ts +1 -0
  84. package/dist/_pkgs/affine-block-root/edgeless/index.js +1 -0
  85. package/dist/_pkgs/affine-block-root/edgeless/reserved-keys.d.ts +21 -0
  86. package/dist/_pkgs/affine-block-root/edgeless/reserved-keys.js +34 -0
  87. package/dist/_pkgs/affine-block-root/edgeless/utils/clipboard-utils.js +1 -1
  88. package/dist/_pkgs/affine-block-root/edgeless/utils/clone-utils.d.ts +7 -1
  89. package/dist/_pkgs/affine-block-root/edgeless/utils/clone-utils.js +11 -2
  90. package/dist/_pkgs/affine-block-root/index.d.ts +4 -1
  91. package/dist/_pkgs/affine-block-root/index.js +4 -1
  92. package/dist/_pkgs/affine-block-root/keyboard/commands.d.ts +2 -0
  93. package/dist/_pkgs/affine-block-root/keyboard/commands.js +147 -0
  94. package/dist/_pkgs/affine-block-root/view.js +13 -4
  95. package/dist/_pkgs/affine-block-surface/adapters/markdown/element-adapter/type.js +1 -1
  96. package/dist/_pkgs/affine-block-surface/adapters/plain-text/element-adapter/type.js +1 -1
  97. package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.js +0 -1
  98. package/dist/_pkgs/affine-block-surface/effects.js +6 -0
  99. package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +21 -3
  100. package/dist/_pkgs/affine-block-surface/element-model/index.js +14 -2
  101. package/dist/_pkgs/affine-block-surface/extensions/audit.d.ts +107 -0
  102. package/dist/_pkgs/affine-block-surface/extensions/audit.js +489 -0
  103. package/dist/_pkgs/affine-block-surface/extensions/crud-extension.d.ts +14 -0
  104. package/dist/_pkgs/affine-block-surface/extensions/crud-extension.js +37 -5
  105. package/dist/_pkgs/affine-block-surface/extensions/editor-anchored-panel.d.ts +133 -0
  106. package/dist/_pkgs/affine-block-surface/extensions/editor-anchored-panel.js +327 -0
  107. package/dist/_pkgs/affine-block-surface/extensions/element-renderer.js +1 -1
  108. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +1 -1
  109. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +17 -0
  110. package/dist/_pkgs/affine-block-surface/extensions/index.js +17 -0
  111. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.d.ts +172 -0
  112. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +393 -0
  113. package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +306 -0
  114. package/dist/_pkgs/affine-block-surface/extensions/interchange.js +64 -0
  115. package/dist/_pkgs/affine-block-surface/extensions/map-quality-widget.d.ts +146 -0
  116. package/dist/_pkgs/affine-block-surface/extensions/map-quality-widget.js +528 -0
  117. package/dist/_pkgs/affine-block-surface/extensions/map-quality.d.ts +109 -0
  118. package/dist/_pkgs/affine-block-surface/extensions/map-quality.js +84 -0
  119. package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.d.ts +248 -0
  120. package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.js +248 -0
  121. package/dist/_pkgs/affine-block-surface/extensions/reading-toolbar.d.ts +15 -0
  122. package/dist/_pkgs/affine-block-surface/extensions/reading-toolbar.js +158 -0
  123. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +145 -0
  124. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +588 -0
  125. package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +494 -0
  126. package/dist/_pkgs/affine-block-surface/extensions/reading.js +767 -0
  127. package/dist/_pkgs/affine-block-surface/extensions/spotlight.d.ts +45 -0
  128. package/dist/_pkgs/affine-block-surface/extensions/spotlight.js +177 -0
  129. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +107 -0
  130. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +958 -0
  131. package/dist/_pkgs/affine-block-surface/extensions/tags-toolbar.d.ts +10 -0
  132. package/dist/_pkgs/affine-block-surface/extensions/tags-toolbar.js +295 -0
  133. package/dist/_pkgs/affine-block-surface/extensions/validation-toolbar.d.ts +27 -0
  134. package/dist/_pkgs/affine-block-surface/extensions/validation-toolbar.js +361 -0
  135. package/dist/_pkgs/affine-block-surface/extensions/validation.d.ts +2129 -0
  136. package/dist/_pkgs/affine-block-surface/extensions/validation.js +4620 -0
  137. package/dist/_pkgs/affine-block-surface/extensions/violation-detail-widget.d.ts +330 -0
  138. package/dist/_pkgs/affine-block-surface/extensions/violation-detail-widget.js +1004 -0
  139. package/dist/_pkgs/affine-block-surface/extensions/violation-timeline.d.ts +80 -0
  140. package/dist/_pkgs/affine-block-surface/extensions/violation-timeline.js +123 -0
  141. package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +610 -0
  142. package/dist/_pkgs/affine-block-surface/framework-background/def.js +206 -0
  143. package/dist/_pkgs/affine-block-surface/framework-background/facts.d.ts +188 -0
  144. package/dist/_pkgs/affine-block-surface/framework-background/facts.js +284 -0
  145. package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +5 -0
  146. package/dist/_pkgs/affine-block-surface/framework-background/index.js +5 -0
  147. package/dist/_pkgs/affine-block-surface/framework-background/interaction.d.ts +12 -0
  148. package/dist/_pkgs/affine-block-surface/framework-background/interaction.js +24 -0
  149. package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +99 -0
  150. package/dist/_pkgs/affine-block-surface/framework-background/labels.js +193 -0
  151. package/dist/_pkgs/affine-block-surface/framework-background/renderer.d.ts +8 -0
  152. package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +399 -0
  153. package/dist/_pkgs/affine-block-surface/index.d.ts +1 -0
  154. package/dist/_pkgs/affine-block-surface/index.js +1 -0
  155. package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.d.ts +69 -3
  156. package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.js +333 -44
  157. package/dist/_pkgs/affine-block-surface/renderer/dom-renderer.js +18 -2
  158. package/dist/_pkgs/affine-block-surface/renderer/overlay.js +1 -1
  159. package/dist/_pkgs/affine-block-surface/tool/default-tool.js +8 -0
  160. package/dist/_pkgs/affine-block-surface/utils/font.js +9 -3
  161. package/dist/_pkgs/affine-block-surface/view.d.ts +17 -0
  162. package/dist/_pkgs/affine-block-surface/view.js +57 -2
  163. package/dist/_pkgs/affine-block-surface-ref/portal/note.js +2 -2
  164. package/dist/_pkgs/affine-block-table/commands.js +1 -1
  165. package/dist/_pkgs/affine-block-table/selection-controller.d.ts +6 -0
  166. package/dist/_pkgs/affine-block-table/selection-controller.js +24 -1
  167. package/dist/_pkgs/affine-block-table/table-block.js +8 -2
  168. package/dist/_pkgs/affine-block-table/table-cell.js +5 -6
  169. package/dist/_pkgs/affine-block-table/table-keymap.d.ts +18 -0
  170. package/dist/_pkgs/affine-block-table/table-keymap.js +41 -0
  171. package/dist/_pkgs/affine-block-table/utils.d.ts +7 -0
  172. package/dist/_pkgs/affine-block-table/utils.js +12 -0
  173. package/dist/_pkgs/affine-block-table/view.js +2 -0
  174. package/dist/_pkgs/affine-components/caption/captioned-block-component.js +2 -1
  175. package/dist/_pkgs/affine-components/context-menu/button.d.ts +7 -0
  176. package/dist/_pkgs/affine-components/context-menu/button.js +7 -2
  177. package/dist/_pkgs/affine-components/context-menu/input.d.ts +4 -0
  178. package/dist/_pkgs/affine-components/context-menu/input.js +12 -0
  179. package/dist/_pkgs/affine-components/context-menu/menu-all.d.ts +2 -0
  180. package/dist/_pkgs/affine-components/context-menu/menu-renderer.js +8 -1
  181. package/dist/_pkgs/affine-components/context-menu/sub-menu.js +3 -0
  182. package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.js +1 -1
  183. package/dist/_pkgs/affine-components/embed-card-modal/embed-card-edit-modal.js +1 -1
  184. package/dist/_pkgs/affine-components/filterable-list/styles.js +1 -1
  185. package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
  186. package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
  187. package/dist/_pkgs/affine-components/icon-picker/affine-icon-picker-panel.d.ts +28 -0
  188. package/dist/_pkgs/affine-components/icon-picker/affine-icon-picker-panel.js +231 -0
  189. package/dist/_pkgs/affine-components/icon-picker/emoji-data.d.ts +40 -0
  190. package/dist/_pkgs/affine-components/icon-picker/emoji-data.js +99 -0
  191. package/dist/_pkgs/affine-components/icon-picker/emoji-picker-panel.d.ts +32 -0
  192. package/dist/_pkgs/affine-components/icon-picker/emoji-picker-panel.js +276 -0
  193. package/dist/_pkgs/affine-components/icon-picker/icon-data.d.ts +34 -0
  194. package/dist/_pkgs/affine-components/icon-picker/icon-data.js +83 -0
  195. package/dist/_pkgs/affine-components/icon-picker/icon-picker.d.ts +39 -0
  196. package/dist/_pkgs/affine-components/icon-picker/icon-picker.js +233 -0
  197. package/dist/_pkgs/affine-components/icon-picker/index.d.ts +8 -0
  198. package/dist/_pkgs/affine-components/icon-picker/index.js +15 -0
  199. package/dist/_pkgs/affine-components/icon-picker/recent-store.d.ts +8 -0
  200. package/dist/_pkgs/affine-components/icon-picker/recent-store.js +41 -0
  201. package/dist/_pkgs/affine-components/icon-picker/styles.d.ts +5 -0
  202. package/dist/_pkgs/affine-components/icon-picker/styles.js +166 -0
  203. package/dist/_pkgs/affine-components/icon-picker/types.d.ts +22 -0
  204. package/dist/_pkgs/affine-components/icon-picker/types.js +10 -0
  205. package/dist/_pkgs/affine-components/icons/text.js +426 -426
  206. package/dist/_pkgs/affine-components/open-doc-dropdown-menu/dropdown-menu.d.ts +1 -0
  207. package/dist/_pkgs/affine-components/peek/peekable.js +1 -1
  208. package/dist/_pkgs/affine-components/portal/portal.d.ts +1 -1
  209. package/dist/_pkgs/affine-components/toolbar/index.d.ts +1 -0
  210. package/dist/_pkgs/affine-components/toolbar/index.js +1 -0
  211. package/dist/_pkgs/affine-components/toolbar/menu-button.js +2 -1
  212. package/dist/_pkgs/affine-components/toolbar/picker-menu.d.ts +55 -0
  213. package/dist/_pkgs/affine-components/toolbar/picker-menu.js +47 -0
  214. package/dist/_pkgs/affine-components/toolbar/toolbar.js +11 -10
  215. package/dist/_pkgs/affine-foundation/view.js +11 -2
  216. package/dist/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.js +2 -2
  217. package/dist/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.js +2 -2
  218. package/dist/_pkgs/affine-fragment-frame-panel/header/frames-setting-menu.js +1 -1
  219. package/dist/_pkgs/affine-fragment-outline/mobile-outline-panel.js +1 -1
  220. package/dist/_pkgs/affine-gfx-brush/index.d.ts +1 -0
  221. package/dist/_pkgs/affine-gfx-brush/index.js +1 -0
  222. package/dist/_pkgs/affine-gfx-brush/renderer/dom/brush.d.ts +1 -0
  223. package/dist/_pkgs/affine-gfx-brush/renderer/dom/brush.js +11 -0
  224. package/dist/_pkgs/affine-gfx-brush/renderer/dom/highlighter.d.ts +1 -0
  225. package/dist/_pkgs/affine-gfx-brush/renderer/dom/highlighter.js +11 -0
  226. package/dist/_pkgs/affine-gfx-brush/renderer/dom/index.d.ts +2 -0
  227. package/dist/_pkgs/affine-gfx-brush/renderer/dom/index.js +2 -0
  228. package/dist/_pkgs/affine-gfx-brush/renderer/dom/shared.d.ts +14 -0
  229. package/dist/_pkgs/affine-gfx-brush/renderer/dom/shared.js +54 -0
  230. package/dist/_pkgs/affine-gfx-brush/renderer/index.d.ts +1 -0
  231. package/dist/_pkgs/affine-gfx-brush/renderer/index.js +4 -0
  232. package/dist/_pkgs/affine-gfx-brush/toolbar/components/pen/pen-tool-button.js +1 -1
  233. package/dist/_pkgs/affine-gfx-brush/view.d.ts +14 -0
  234. package/dist/_pkgs/affine-gfx-brush/view.js +29 -3
  235. package/dist/_pkgs/affine-gfx-connector/connector-manager.js +39 -16
  236. package/dist/_pkgs/affine-gfx-connector/connector-tool.d.ts +26 -1
  237. package/dist/_pkgs/affine-gfx-connector/connector-tool.js +12 -3
  238. package/dist/_pkgs/affine-gfx-connector/connector-watcher.js +1 -4
  239. package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.d.ts +123 -0
  240. package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.js +282 -0
  241. package/dist/_pkgs/affine-gfx-connector/direction/direction-widget.d.ts +65 -0
  242. package/dist/_pkgs/affine-gfx-connector/direction/direction-widget.js +395 -0
  243. package/dist/_pkgs/affine-gfx-connector/direction/index.d.ts +4 -0
  244. package/dist/_pkgs/affine-gfx-connector/direction/index.js +4 -0
  245. package/dist/_pkgs/affine-gfx-connector/direction/invert-direction.d.ts +72 -0
  246. package/dist/_pkgs/affine-gfx-connector/direction/invert-direction.js +185 -0
  247. package/dist/_pkgs/affine-gfx-connector/direction/typed-edge.d.ts +69 -0
  248. package/dist/_pkgs/affine-gfx-connector/direction/typed-edge.js +66 -0
  249. package/dist/_pkgs/affine-gfx-connector/effects.d.ts +2 -0
  250. package/dist/_pkgs/affine-gfx-connector/effects.js +2 -0
  251. package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.js +78 -41
  252. package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +1 -1
  253. package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.js +1 -1
  254. package/dist/_pkgs/affine-gfx-connector/index.d.ts +1 -0
  255. package/dist/_pkgs/affine-gfx-connector/index.js +1 -0
  256. package/dist/_pkgs/affine-gfx-connector/toolbar/config.d.ts +50 -0
  257. package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +68 -2
  258. package/dist/_pkgs/affine-gfx-connector/view.js +16 -0
  259. package/dist/_pkgs/affine-gfx-group/command/group-api.js +150 -62
  260. package/dist/_pkgs/affine-gfx-group/text/edgeless-group-title-editor.js +4 -1
  261. package/dist/_pkgs/affine-gfx-mindmap/adapter/markdown/index.js +1 -1
  262. package/dist/_pkgs/affine-gfx-mindmap/adapter/utils.js +1 -1
  263. package/dist/_pkgs/affine-gfx-mindmap/templates/index.js +583 -4
  264. package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-menu.js +23 -23
  265. package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.js +5 -1
  266. package/dist/_pkgs/affine-gfx-mindmap/view/utils.js +1 -1
  267. package/dist/_pkgs/affine-gfx-note/overlay/overlay.js +1 -1
  268. package/dist/_pkgs/affine-gfx-note/toolbar/note-senior-button.js +1 -1
  269. package/dist/_pkgs/affine-gfx-pointer/tools/pan-tool.d.ts +16 -0
  270. package/dist/_pkgs/affine-gfx-pointer/tools/pan-tool.js +102 -32
  271. package/dist/_pkgs/affine-gfx-shape/commands.d.ts +2 -0
  272. package/dist/_pkgs/affine-gfx-shape/commands.js +33 -0
  273. package/dist/_pkgs/affine-gfx-shape/consts.js +1 -1
  274. package/dist/_pkgs/affine-gfx-shape/draggable/shape-draggable.js +1 -1
  275. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape/polygon.js +17 -9
  276. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape/utils.js +8 -3
  277. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape-dom/index.js +48 -19
  278. package/dist/_pkgs/affine-gfx-shape/element-view.js +19 -12
  279. package/dist/_pkgs/affine-gfx-shape/index.d.ts +1 -1
  280. package/dist/_pkgs/affine-gfx-shape/index.js +1 -1
  281. package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.js +1 -1
  282. package/dist/_pkgs/affine-gfx-shape/overlay/polygon-vertex-editing-overlay.js +12 -7
  283. package/dist/_pkgs/affine-gfx-shape/overlay/shape-overlay.js +1 -1
  284. package/dist/_pkgs/affine-gfx-shape/polygon-tool.js +4 -2
  285. package/dist/_pkgs/affine-gfx-shape/shape-tool.js +1 -1
  286. package/dist/_pkgs/affine-gfx-shape/text/edgeless-shape-text-editor.d.ts +26 -0
  287. package/dist/_pkgs/affine-gfx-shape/text/edgeless-shape-text-editor.js +124 -15
  288. package/dist/_pkgs/affine-gfx-shape/view.js +3 -3
  289. package/dist/_pkgs/affine-gfx-template/builtin/other.js +66 -17
  290. package/dist/_pkgs/affine-gfx-template/toolbar/overlay-scrollbar.js +1 -1
  291. package/dist/_pkgs/affine-gfx-template/toolbar/template-panel.js +1 -1
  292. package/dist/_pkgs/affine-gfx-template/toolbar/template-tool-button.d.ts +2 -0
  293. package/dist/_pkgs/affine-gfx-template/toolbar/template-tool-button.js +18 -1
  294. package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +9 -5
  295. package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +1 -1
  296. package/dist/_pkgs/affine-inline-latex/command.js +46 -26
  297. package/dist/_pkgs/affine-inline-latex/latex-node/latex-node.d.ts +10 -0
  298. package/dist/_pkgs/affine-inline-latex/latex-node/latex-node.js +23 -0
  299. package/dist/_pkgs/affine-inline-link/command.js +1 -1
  300. package/dist/_pkgs/affine-inline-link/link-node/affine-link.js +4 -1
  301. package/dist/_pkgs/affine-inline-preset/adapters/html/html-inline.d.ts +3 -0
  302. package/dist/_pkgs/affine-inline-preset/adapters/html/html-inline.js +29 -1
  303. package/dist/_pkgs/affine-inline-preset/command/format-block.js +1 -1
  304. package/dist/_pkgs/affine-inline-preset/command/format-native.js +2 -2
  305. package/dist/_pkgs/affine-inline-preset/command/format-text.js +1 -1
  306. package/dist/_pkgs/affine-inline-preset/inline-spec.js +1 -1
  307. package/dist/_pkgs/affine-inline-reference/reference-node/reference-node.js +1 -1
  308. package/dist/_pkgs/affine-model/blocks/code/code-model.d.ts +1 -0
  309. package/dist/_pkgs/affine-model/blocks/code/code-model.js +1 -0
  310. package/dist/_pkgs/affine-model/elements/bpmn/node.d.ts +40 -7
  311. package/dist/_pkgs/affine-model/elements/bpmn/node.js +4 -2
  312. package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +74 -17
  313. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +55 -26
  314. package/dist/_pkgs/affine-model/elements/c4/board.d.ts +88 -0
  315. package/dist/_pkgs/affine-model/elements/c4/board.js +128 -0
  316. package/dist/_pkgs/affine-model/elements/c4/boundary.d.ts +63 -0
  317. package/dist/_pkgs/affine-model/elements/c4/boundary.js +134 -0
  318. package/dist/_pkgs/affine-model/elements/c4/index.d.ts +3 -0
  319. package/dist/_pkgs/affine-model/elements/c4/index.js +3 -0
  320. package/dist/_pkgs/affine-model/elements/c4/node.d.ts +97 -0
  321. package/dist/_pkgs/affine-model/elements/c4/node.js +130 -0
  322. package/dist/_pkgs/affine-model/elements/connector/connector.js +25 -1
  323. package/dist/_pkgs/affine-model/elements/context-map/context-map.d.ts +27 -0
  324. package/dist/_pkgs/affine-model/elements/context-map/context-map.js +94 -0
  325. package/dist/_pkgs/affine-model/elements/context-map/index.d.ts +1 -0
  326. package/dist/_pkgs/affine-model/elements/context-map/index.js +1 -0
  327. package/dist/_pkgs/affine-model/elements/core-domain/core-domain.d.ts +34 -17
  328. package/dist/_pkgs/affine-model/elements/core-domain/core-domain.js +28 -26
  329. package/dist/_pkgs/affine-model/elements/edgy/board.d.ts +32 -0
  330. package/dist/_pkgs/affine-model/elements/edgy/board.js +112 -0
  331. package/dist/_pkgs/affine-model/elements/edgy/facets.d.ts +12 -0
  332. package/dist/_pkgs/affine-model/elements/edgy/facets.js +25 -1
  333. package/dist/_pkgs/affine-model/elements/edgy/index.d.ts +1 -0
  334. package/dist/_pkgs/affine-model/elements/edgy/index.js +1 -0
  335. package/dist/_pkgs/affine-model/elements/event-storming/event-storming.d.ts +36 -0
  336. package/dist/_pkgs/affine-model/elements/event-storming/event-storming.js +103 -0
  337. package/dist/_pkgs/affine-model/elements/event-storming/index.d.ts +1 -0
  338. package/dist/_pkgs/affine-model/elements/event-storming/index.js +1 -0
  339. package/dist/_pkgs/affine-model/elements/framework-background/background.d.ts +42 -0
  340. package/dist/_pkgs/affine-model/elements/framework-background/background.js +42 -0
  341. package/dist/_pkgs/affine-model/elements/framework-background/index.d.ts +1 -0
  342. package/dist/_pkgs/affine-model/elements/framework-background/index.js +1 -0
  343. package/dist/_pkgs/affine-model/elements/index.d.ts +14 -1
  344. package/dist/_pkgs/affine-model/elements/index.js +4 -0
  345. package/dist/_pkgs/affine-model/elements/mindmap/mindmap.js +8 -3
  346. package/dist/_pkgs/affine-model/elements/mindmap/style.d.ts +10 -0
  347. package/dist/_pkgs/affine-model/elements/mindmap/style.js +8 -0
  348. package/dist/_pkgs/affine-model/elements/shape/api/polygon.js +2 -8
  349. package/dist/_pkgs/affine-model/elements/wardley/wardley.d.ts +21 -29
  350. package/dist/_pkgs/affine-model/elements/wardley/wardley.js +41 -48
  351. package/dist/_pkgs/affine-shared/adapters/html/block-adapter.js +1 -1
  352. package/dist/_pkgs/affine-shared/adapters/markdown/block-adapter.js +1 -1
  353. package/dist/_pkgs/affine-shared/adapters/markdown/delta-converter.d.ts +6 -1
  354. package/dist/_pkgs/affine-shared/adapters/markdown/delta-converter.js +161 -3
  355. package/dist/_pkgs/affine-shared/adapters/markdown/markdown.js +5 -1
  356. package/dist/_pkgs/affine-shared/adapters/notion-html/block-adapter.js +1 -1
  357. package/dist/_pkgs/affine-shared/adapters/notion-html/delta-converter.js +1 -1
  358. package/dist/_pkgs/affine-shared/adapters/plain-text/block-adapter.js +1 -1
  359. package/dist/_pkgs/affine-shared/adapters/plain-text/delta-converter.js +1 -1
  360. package/dist/_pkgs/affine-shared/adapters/types/delta-converter.d.ts +1 -0
  361. package/dist/_pkgs/affine-shared/adapters/utils/color.d.ts +24 -0
  362. package/dist/_pkgs/affine-shared/adapters/utils/color.js +283 -0
  363. package/dist/_pkgs/affine-shared/adapters/utils/index.d.ts +1 -0
  364. package/dist/_pkgs/affine-shared/adapters/utils/index.js +1 -0
  365. package/dist/_pkgs/affine-shared/commands/block-crud/get-selected-blocks.js +10 -2
  366. package/dist/_pkgs/affine-shared/commands/model-crud/draft-selected-models.js +1 -1
  367. package/dist/_pkgs/affine-shared/commands/selection/focus-block-end.js +1 -1
  368. package/dist/_pkgs/affine-shared/commands/selection/focus-block-start.js +1 -1
  369. package/dist/_pkgs/affine-shared/consts/index.d.ts +10 -0
  370. package/dist/_pkgs/affine-shared/consts/index.js +10 -0
  371. package/dist/_pkgs/affine-shared/services/artefact-catalogue-service.d.ts +55 -0
  372. package/dist/_pkgs/affine-shared/services/artefact-catalogue-service.js +35 -0
  373. package/dist/_pkgs/affine-shared/services/audit-service.d.ts +311 -0
  374. package/dist/_pkgs/affine-shared/services/audit-service.js +228 -0
  375. package/dist/_pkgs/affine-shared/services/command-usage-service.d.ts +31 -0
  376. package/dist/_pkgs/affine-shared/services/command-usage-service.js +109 -0
  377. package/dist/_pkgs/affine-shared/services/comment-service/block-comment-manager.js +1 -1
  378. package/dist/_pkgs/affine-shared/services/doc-display-meta-service.js +1 -1
  379. package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +7 -0
  380. package/dist/_pkgs/affine-shared/services/edit-props-store.js +11 -0
  381. package/dist/_pkgs/affine-shared/services/embed-iframe/embed-iframe-config.js +1 -1
  382. package/dist/_pkgs/affine-shared/services/font-loader/font-loader-service.d.ts +26 -1
  383. package/dist/_pkgs/affine-shared/services/font-loader/font-loader-service.js +124 -7
  384. package/dist/_pkgs/affine-shared/services/index.d.ts +7 -0
  385. package/dist/_pkgs/affine-shared/services/index.js +7 -0
  386. package/dist/_pkgs/affine-shared/services/pivot-materiality-publisher.d.ts +129 -0
  387. package/dist/_pkgs/affine-shared/services/pivot-materiality-publisher.js +312 -0
  388. package/dist/_pkgs/affine-shared/services/pivot-properties-service.d.ts +217 -0
  389. package/dist/_pkgs/affine-shared/services/pivot-properties-service.js +114 -0
  390. package/dist/_pkgs/affine-shared/services/telemetry-service/code-block.d.ts +1 -1
  391. package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +255 -1
  392. package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +2 -2
  393. package/dist/_pkgs/affine-shared/services/telemetry-service/types.d.ts +6 -1
  394. package/dist/_pkgs/affine-shared/services/toolbar-service/action.d.ts +10 -0
  395. package/dist/_pkgs/affine-shared/services/toolbar-service/index.d.ts +1 -0
  396. package/dist/_pkgs/affine-shared/services/toolbar-service/index.js +1 -0
  397. package/dist/_pkgs/affine-shared/services/toolbar-service/layout.d.ts +134 -0
  398. package/dist/_pkgs/affine-shared/services/toolbar-service/layout.js +146 -0
  399. package/dist/_pkgs/affine-shared/services/toolbar-service/registry.d.ts +44 -0
  400. package/dist/_pkgs/affine-shared/services/toolbar-service/registry.js +161 -3
  401. package/dist/_pkgs/affine-shared/services/translation-service/index.d.ts +68 -0
  402. package/dist/_pkgs/affine-shared/services/translation-service/index.js +39 -0
  403. package/dist/_pkgs/affine-shared/services/universe-tag-defs-service.d.ts +155 -0
  404. package/dist/_pkgs/affine-shared/services/universe-tag-defs-service.js +256 -0
  405. package/dist/_pkgs/affine-shared/test-utils/affine-template.js +1 -1
  406. package/dist/_pkgs/affine-shared/utils/dom/point-to-range.d.ts +4 -0
  407. package/dist/_pkgs/affine-shared/utils/dom/point-to-range.js +58 -2
  408. package/dist/_pkgs/affine-shared/utils/dom/viewport.d.ts +60 -0
  409. package/dist/_pkgs/affine-shared/utils/dom/viewport.js +58 -0
  410. package/dist/_pkgs/affine-shared/utils/edgeless.js +1 -1
  411. package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +34 -0
  412. package/dist/_pkgs/affine-shared/utils/file/filesys.js +48 -7
  413. package/dist/_pkgs/affine-shared/utils/print-to-pdf.d.ts +21 -0
  414. package/dist/_pkgs/affine-shared/utils/print-to-pdf.js +166 -32
  415. package/dist/_pkgs/affine-shared/utils/zod-schema.d.ts +7 -0
  416. package/dist/_pkgs/affine-shared/utils/zod-schema.js +25 -1
  417. package/dist/_pkgs/affine-widget-drag-handle/utils.js +1 -1
  418. package/dist/_pkgs/affine-widget-drag-handle/watchers/edgeless-watcher.d.ts +19 -10
  419. package/dist/_pkgs/affine-widget-drag-handle/watchers/edgeless-watcher.js +122 -23
  420. package/dist/_pkgs/affine-widget-drag-handle/watchers/pointer-event-watcher.d.ts +2 -0
  421. package/dist/_pkgs/affine-widget-drag-handle/watchers/pointer-event-watcher.js +25 -4
  422. package/dist/_pkgs/affine-widget-edgeless-auto-connect/index.js +1 -1
  423. package/dist/_pkgs/affine-widget-edgeless-dragging-area/edgeless-dragging-area-rect.js +1 -1
  424. package/dist/_pkgs/affine-widget-edgeless-selected-rect/auto-complete-panel.js +10 -5
  425. package/dist/_pkgs/affine-widget-edgeless-selected-rect/edgeless-auto-complete.d.ts +15 -1
  426. package/dist/_pkgs/affine-widget-edgeless-selected-rect/edgeless-auto-complete.js +37 -32
  427. package/dist/_pkgs/affine-widget-edgeless-selected-rect/edgeless-element-link.js +5 -4
  428. package/dist/_pkgs/affine-widget-edgeless-selected-rect/edgeless-selected-rect.js +19 -9
  429. package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.d.ts +16 -2
  430. package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.js +19 -2
  431. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-default.d.ts +14 -0
  432. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-default.js +40 -0
  433. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.d.ts +158 -0
  434. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +572 -0
  435. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/catalogue-groups.d.ts +46 -0
  436. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/catalogue-groups.js +66 -0
  437. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/chord-format.d.ts +13 -0
  438. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/chord-format.js +50 -0
  439. package/dist/_pkgs/affine-widget-edgeless-toolbar/edgeless-toolbar.d.ts +6 -0
  440. package/dist/_pkgs/affine-widget-edgeless-toolbar/edgeless-toolbar.js +15 -5
  441. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.d.ts +2 -0
  442. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.js +2 -0
  443. package/dist/_pkgs/affine-widget-edgeless-toolbar/extension/index.d.ts +7 -0
  444. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +5 -0
  445. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +5 -0
  446. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.d.ts +57 -0
  447. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.js +140 -0
  448. package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +9 -0
  449. package/dist/_pkgs/affine-widget-frame-title/edgeless-frame-title-editor.js +4 -1
  450. package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
  451. package/dist/_pkgs/affine-widget-keyboard-toolbar/keyboard-tool-panel.js +1 -1
  452. package/dist/_pkgs/affine-widget-linked-doc/import-doc/import-doc.js +1 -1
  453. package/dist/_pkgs/affine-widget-linked-doc/linked-doc-popover.js +2 -15
  454. package/dist/_pkgs/affine-widget-linked-doc/transformers/markdown.d.ts +10 -1
  455. package/dist/_pkgs/affine-widget-linked-doc/transformers/markdown.js +133 -6
  456. package/dist/_pkgs/affine-widget-linked-doc/transformers/utils.d.ts +10 -0
  457. package/dist/_pkgs/affine-widget-linked-doc/transformers/utils.js +120 -3
  458. package/dist/_pkgs/affine-widget-linked-doc/utils.d.ts +12 -0
  459. package/dist/_pkgs/affine-widget-linked-doc/utils.js +33 -0
  460. package/dist/_pkgs/affine-widget-page-dragging-area/index.js +1 -1
  461. package/dist/_pkgs/affine-widget-remote-selection/doc/doc-remote-selection.js +1 -1
  462. package/dist/_pkgs/affine-widget-remote-selection/edgeless/index.js +6 -4
  463. package/dist/_pkgs/affine-widget-slash-menu/slash-menu-popover.js +8 -4
  464. package/dist/_pkgs/affine-widget-slash-menu/utils.d.ts +9 -0
  465. package/dist/_pkgs/affine-widget-slash-menu/utils.js +24 -0
  466. package/dist/_pkgs/affine-widget-toolbar/toolbar.d.ts +6 -0
  467. package/dist/_pkgs/affine-widget-toolbar/toolbar.js +40 -8
  468. package/dist/_pkgs/affine-widget-toolbar/utils.d.ts +146 -3
  469. package/dist/_pkgs/affine-widget-toolbar/utils.js +744 -58
  470. package/dist/_pkgs/data-view/core/common/property-menu.js +3 -16
  471. package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.d.ts +4 -0
  472. package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.js +28 -1
  473. package/dist/_pkgs/data-view/core/data-view.d.ts +3 -1
  474. package/dist/_pkgs/data-view/core/data-view.js +25 -3
  475. package/dist/_pkgs/data-view/core/detail/field.js +2 -2
  476. package/dist/_pkgs/data-view/core/detail/selection.d.ts +4 -2
  477. package/dist/_pkgs/data-view/core/detail/selection.js +23 -7
  478. package/dist/_pkgs/data-view/core/effect.js +2 -0
  479. package/dist/_pkgs/data-view/core/filter/eval.js +36 -23
  480. package/dist/_pkgs/data-view/core/filter/filter-fn/matcher.d.ts +7 -0
  481. package/dist/_pkgs/data-view/core/filter/filter-fn/matcher.js +12 -0
  482. package/dist/_pkgs/data-view/core/group-by/compare-date-keys.d.ts +11 -0
  483. package/dist/_pkgs/data-view/core/group-by/compare-date-keys.js +55 -0
  484. package/dist/_pkgs/data-view/core/group-by/define.d.ts +6 -0
  485. package/dist/_pkgs/data-view/core/group-by/define.js +114 -0
  486. package/dist/_pkgs/data-view/core/group-by/matcher.d.ts +7 -0
  487. package/dist/_pkgs/data-view/core/group-by/matcher.js +13 -0
  488. package/dist/_pkgs/data-view/core/group-by/renderer/boolean-group.js +11 -11
  489. package/dist/_pkgs/data-view/core/group-by/renderer/date-group.d.ts +9 -0
  490. package/dist/_pkgs/data-view/core/group-by/renderer/date-group.js +97 -0
  491. package/dist/_pkgs/data-view/core/group-by/setting.js +86 -7
  492. package/dist/_pkgs/data-view/core/group-by/trait.d.ts +34 -0
  493. package/dist/_pkgs/data-view/core/group-by/trait.js +106 -10
  494. package/dist/_pkgs/data-view/core/utils/menu-title.js +17 -17
  495. package/dist/_pkgs/data-view/property-presets/multi-select/cell-renderer.js +3 -1
  496. package/dist/_pkgs/data-view/property-presets/number/define.js +2 -1
  497. package/dist/_pkgs/data-view/property-presets/select/cell-renderer.js +3 -1
  498. package/dist/_pkgs/data-view/view-presets/calendar/calendar-view-manager.d.ts +70 -0
  499. package/dist/_pkgs/data-view/view-presets/calendar/calendar-view-manager.js +449 -0
  500. package/dist/_pkgs/data-view/view-presets/calendar/define.d.ts +10 -0
  501. package/dist/_pkgs/data-view/view-presets/calendar/define.js +27 -0
  502. package/dist/_pkgs/data-view/view-presets/calendar/effect.d.ts +1 -0
  503. package/dist/_pkgs/data-view/view-presets/calendar/effect.js +4 -0
  504. package/dist/_pkgs/data-view/view-presets/calendar/index.d.ts +6 -0
  505. package/dist/_pkgs/data-view/view-presets/calendar/index.js +6 -0
  506. package/dist/_pkgs/data-view/view-presets/calendar/layout.d.ts +37 -0
  507. package/dist/_pkgs/data-view/view-presets/calendar/layout.js +138 -0
  508. package/dist/_pkgs/data-view/view-presets/calendar/pc/actions.d.ts +7 -0
  509. package/dist/_pkgs/data-view/view-presets/calendar/pc/actions.js +64 -0
  510. package/dist/_pkgs/data-view/view-presets/calendar/pc/dnd.d.ts +32 -0
  511. package/dist/_pkgs/data-view/view-presets/calendar/pc/dnd.js +159 -0
  512. package/dist/_pkgs/data-view/view-presets/calendar/pc/effect.d.ts +1 -0
  513. package/dist/_pkgs/data-view/view-presets/calendar/pc/effect.js +7 -0
  514. package/dist/_pkgs/data-view/view-presets/calendar/pc/hit-test.d.ts +1 -0
  515. package/dist/_pkgs/data-view/view-presets/calendar/pc/hit-test.js +28 -0
  516. package/dist/_pkgs/data-view/view-presets/calendar/pc/styles.d.ts +1 -0
  517. package/dist/_pkgs/data-view/view-presets/calendar/pc/styles.js +707 -0
  518. package/dist/_pkgs/data-view/view-presets/calendar/pc/view.d.ts +89 -0
  519. package/dist/_pkgs/data-view/view-presets/calendar/pc/view.js +849 -0
  520. package/dist/_pkgs/data-view/view-presets/calendar/renderer.d.ts +2 -0
  521. package/dist/_pkgs/data-view/view-presets/calendar/renderer.js +8 -0
  522. package/dist/_pkgs/data-view/view-presets/calendar/source.d.ts +8 -0
  523. package/dist/_pkgs/data-view/view-presets/calendar/source.js +3 -0
  524. package/dist/_pkgs/data-view/view-presets/calendar/types.d.ts +79 -0
  525. package/dist/_pkgs/data-view/view-presets/calendar/types.js +1 -0
  526. package/dist/_pkgs/data-view/view-presets/convert.js +28 -0
  527. package/dist/_pkgs/data-view/view-presets/effect.js +2 -0
  528. package/dist/_pkgs/data-view/view-presets/index.d.ts +2 -0
  529. package/dist/_pkgs/data-view/view-presets/index.js +3 -0
  530. package/dist/_pkgs/data-view/view-presets/kanban/kanban-view-manager.js +3 -1
  531. package/dist/_pkgs/data-view/view-presets/kanban/mobile/cell.js +2 -2
  532. package/dist/_pkgs/data-view/view-presets/table/collapsed-state.d.ts +18 -0
  533. package/dist/_pkgs/data-view/view-presets/table/collapsed-state.js +36 -0
  534. package/dist/_pkgs/data-view/view-presets/table/mobile/cell.js +2 -2
  535. package/dist/_pkgs/data-view/view-presets/table/mobile/group.d.ts +11 -0
  536. package/dist/_pkgs/data-view/view-presets/table/mobile/group.js +89 -4
  537. package/dist/_pkgs/data-view/view-presets/table/pc/cell.d.ts +3 -0
  538. package/dist/_pkgs/data-view/view-presets/table/pc/cell.js +11 -2
  539. package/dist/_pkgs/data-view/view-presets/table/pc/controller/hotkeys.d.ts +1 -0
  540. package/dist/_pkgs/data-view/view-presets/table/pc/controller/hotkeys.js +39 -33
  541. package/dist/_pkgs/data-view/view-presets/table/pc/group.d.ts +10 -0
  542. package/dist/_pkgs/data-view/view-presets/table/pc/group.js +86 -5
  543. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/hotkeys.d.ts +1 -0
  544. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/hotkeys.js +39 -33
  545. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/group-title.js +18 -18
  546. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/row/cell.d.ts +3 -0
  547. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/row/cell.js +8 -0
  548. package/dist/_pkgs/data-view/view-presets/table/table-view-manager.js +3 -1
  549. package/dist/_pkgs/data-view/view-presets/table/utils.d.ts +3 -0
  550. package/dist/_pkgs/data-view/view-presets/table/utils.js +16 -1
  551. package/dist/_pkgs/data-view/widget-presets/tools/presets/view-options/view-options.js +3 -1
  552. package/dist/_pkgs/global/gfx/curve.js +4 -3
  553. package/dist/_pkgs/std/clipboard/clipboard.js +13 -3
  554. package/dist/_pkgs/std/clipboard/utils.d.ts +5 -0
  555. package/dist/_pkgs/std/clipboard/utils.js +10 -0
  556. package/dist/_pkgs/std/event/dispatcher.js +27 -1
  557. package/dist/_pkgs/std/event/keymap.js +16 -6
  558. package/dist/_pkgs/std/extension/command-registry.d.ts +475 -0
  559. package/dist/_pkgs/std/extension/command-registry.js +431 -0
  560. package/dist/_pkgs/std/extension/dnd/index.d.ts +1 -1
  561. package/dist/_pkgs/std/extension/index.d.ts +2 -0
  562. package/dist/_pkgs/std/extension/index.js +2 -0
  563. package/dist/_pkgs/std/extension/shortcut.js +2 -1
  564. package/dist/_pkgs/std/extension/translation-manifest.d.ts +49 -0
  565. package/dist/_pkgs/std/extension/translation-manifest.js +71 -0
  566. package/dist/_pkgs/std/gfx/grid.js +1 -1
  567. package/dist/_pkgs/std/gfx/index.d.ts +7 -3
  568. package/dist/_pkgs/std/gfx/index.js +6 -2
  569. package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.js +6 -1
  570. package/dist/_pkgs/std/gfx/interactivity/manager.d.ts +8 -0
  571. package/dist/_pkgs/std/gfx/interactivity/manager.js +18 -0
  572. package/dist/_pkgs/std/gfx/layer.d.ts +1 -1
  573. package/dist/_pkgs/std/gfx/layer.js +1 -2
  574. package/dist/_pkgs/std/gfx/model/surface/decorators/field.js +9 -0
  575. package/dist/_pkgs/std/gfx/model/surface/decorators/index.d.ts +2 -2
  576. package/dist/_pkgs/std/gfx/model/surface/decorators/index.js +2 -2
  577. package/dist/_pkgs/std/gfx/model/surface/decorators/local.d.ts +14 -0
  578. package/dist/_pkgs/std/gfx/model/surface/decorators/local.js +22 -0
  579. package/dist/_pkgs/std/gfx/model/surface/decorators/observer.d.ts +2 -0
  580. package/dist/_pkgs/std/gfx/model/surface/decorators/observer.js +40 -1
  581. package/dist/_pkgs/std/gfx/model/surface/element-model.d.ts +442 -0
  582. package/dist/_pkgs/std/gfx/model/surface/element-model.js +510 -25
  583. package/dist/_pkgs/std/gfx/model/surface/pivot.d.ts +48 -0
  584. package/dist/_pkgs/std/gfx/model/surface/pivot.js +34 -0
  585. package/dist/_pkgs/std/gfx/model/surface/role.d.ts +153 -0
  586. package/dist/_pkgs/std/gfx/model/surface/role.js +117 -0
  587. package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +70 -0
  588. package/dist/_pkgs/std/gfx/model/surface/surface-model.js +305 -17
  589. package/dist/_pkgs/std/gfx/model/surface/tags.d.ts +77 -0
  590. package/dist/_pkgs/std/gfx/model/surface/tags.js +246 -0
  591. package/dist/_pkgs/std/gfx/perf.d.ts +10 -0
  592. package/dist/_pkgs/std/gfx/perf.js +30 -0
  593. package/dist/_pkgs/std/gfx/selection.js +1 -1
  594. package/dist/_pkgs/std/gfx/tool/tool-controller.d.ts +13 -0
  595. package/dist/_pkgs/std/gfx/tool/tool-controller.js +26 -0
  596. package/dist/_pkgs/std/gfx/viewport.d.ts +12 -0
  597. package/dist/_pkgs/std/gfx/viewport.js +20 -2
  598. package/dist/_pkgs/std/inline/extensions/inline-manager.js +1 -1
  599. package/dist/_pkgs/std/inline/extensions/markdown-matcher.js +1 -1
  600. package/dist/_pkgs/std/inline/services/event.d.ts +2 -0
  601. package/dist/_pkgs/std/inline/services/event.js +96 -21
  602. package/dist/_pkgs/std/utils/layer.js +2 -6
  603. package/dist/_pkgs/std/utils/tree.d.ts +14 -0
  604. package/dist/_pkgs/std/utils/tree.js +59 -8
  605. package/dist/_pkgs/std/view/element/gfx-block-component.js +23 -13
  606. package/dist/_pkgs/store/extension/workspace/workspace-meta.d.ts +10 -0
  607. package/dist/_pkgs/store/model/block/flat-sync-controller.js +2 -12
  608. package/dist/_pkgs/store/model/store/crud.js +10 -4
  609. package/dist/_pkgs/store/reactive/flat-native-y/index.d.ts +1 -1
  610. package/dist/_pkgs/store/reactive/flat-native-y/index.js +24 -2
  611. package/dist/commands.d.ts +58 -0
  612. package/dist/commands.js +66 -0
  613. package/dist/extensions/command-telemetry.d.ts +21 -0
  614. package/dist/extensions/command-telemetry.js +89 -0
  615. package/dist/extensions/command-usage.d.ts +23 -0
  616. package/dist/extensions/command-usage.js +37 -0
  617. package/dist/extensions/store.d.ts +9 -4
  618. package/dist/extensions/store.js +27 -24
  619. package/dist/extensions/view.d.ts +9 -4
  620. package/dist/extensions/view.js +35 -8
  621. package/dist/flags.d.ts +98 -21
  622. package/dist/flags.js +103 -22
  623. package/dist/frameworks.d.ts +45 -0
  624. package/dist/frameworks.js +186 -0
  625. package/dist/schemas.d.ts +8 -5
  626. package/dist/schemas.js +28 -32
  627. package/dist/shortcuts.d.ts +16 -16
  628. package/dist/shortcuts.js +8 -36
  629. package/dist/translations.d.ts +56 -0
  630. package/dist/translations.js +200 -0
  631. package/package.json +16 -4
  632. package/dist/_pkgs/affine-block-root/keyboard/shortcuts.d.ts +0 -8
  633. package/dist/_pkgs/affine-block-root/keyboard/shortcuts.js +0 -48
  634. package/dist/_pkgs/affine-gfx-shape/shortcuts.d.ts +0 -6
  635. package/dist/_pkgs/affine-gfx-shape/shortcuts.js +0 -28
  636. package/dist/_pkgs/data-view/core/utils/cache.d.ts +0 -5
  637. package/dist/_pkgs/data-view/core/utils/cache.js +0 -28
@@ -0,0 +1,2129 @@
1
+ import type { AuditFinding } from '../../affine-shared/services/index.js';
2
+ import { Bound } from '../../global/gfx/index.js';
3
+ import type { RoleDefs, RoleId, SurfaceBlockModel, ValidationException } from '../../std/gfx/index.js';
4
+ import { GfxPrimitiveElementModel, InteractivityExtension } from '../../std/gfx/index.js';
5
+ import type { ExtensionType } from '../../store/index.js';
6
+ import type { FrameworkBackgroundDef } from '../framework-background/def.js';
7
+ import type { CanvasRenderer } from '../renderer/canvas-renderer.js';
8
+ import { Overlay } from '../renderer/overlay.js';
9
+ import type { RoughCanvas } from '../utils/rough/canvas.js';
10
+ import { type QualityNudge } from './map-quality.js';
11
+ import { ViolationTimeline } from './violation-timeline.js';
12
+ /**
13
+ * Minimal validation engine (PF5, wave 1).
14
+ *
15
+ * A framework declares its rules as DATA and registers them; the engine walks
16
+ * the surface and produces VIOLATION OBJECTS. It renders no text, decides no
17
+ * wording and knows no concrete framework — it only knows roles (PF1) and
18
+ * geometry.
19
+ *
20
+ * Structural twin of `./spotlight.ts`: a generic mechanism living with the
21
+ * surface, opted into by a framework through a DI identifier.
22
+ *
23
+ * ## Gating (PF4 reversed flag contract)
24
+ *
25
+ * The engine registers **no rule of its own**. Rules are registered by the
26
+ * flag-gated `…ViewExtension` of their framework (validation is tooling, not
27
+ * content — see `docs/adr/0009`), so a disabled framework contributes no rule
28
+ * and {@link ValidationManager} short-circuits before touching a single
29
+ * element. Flag off costs exactly one empty-map check.
30
+ */
31
+ /**
32
+ * How severely a violation is meant to bite. The engine only carries the value
33
+ * through to the violation; acting on it is the host's decision.
34
+ *
35
+ * - `blocking-overridable` — the host may block, and must let the user override.
36
+ * - `warning` — surfaced, never blocking. The sketch always wins.
37
+ * - `audit` — collected for reporting, invisible to the drawing user.
38
+ */
39
+ export type ViolationSeverity = 'blocking-overridable' | 'warning' | 'audit';
40
+ /**
41
+ * What a PROFILE can say about a rule: one of the three severities, or `'off'`
42
+ * — the rule is not evaluated at all, and costs nothing.
43
+ */
44
+ export type ProfileSeverity = ViolationSeverity | 'off';
45
+ /**
46
+ * Rule families. One family = one evaluation function ({@link RULE_FAMILIES}).
47
+ * Adding one is adding an entry here and a function below, never a change to
48
+ * the shape of a rule.
49
+ *
50
+ * - `element-in-background` — the subject must sit inside the framework's frame.
51
+ * - `orientation-against-axis` — a DIRECTIONAL subject (an arrow, an edge) must
52
+ * not run against the declared sense of one of the frame's axes.
53
+ * - `attachment` — the subject must STRADDLE one of the frame's zone
54
+ * transitions, and optionally be posed ON a carrier element.
55
+ * - `no-overlap` — declared pairs of roles must not collide. The first family
56
+ * that is not element-local: it evaluates PAIRS.
57
+ * - `tone-convention` — the subject must be drawn in one of the tones the
58
+ * frame's own palette declares for it. On-demand only, in practice.
59
+ * - `majority-fact` — a remark about the MAP, raised when a declared fact holds
60
+ * for a majority of the subjects. Silent while nothing carries the fact.
61
+ * - `relative-order-along-axis` — the two elements a TYPED EDGE links must sit
62
+ * in the order that edge states, along one axis of the frame. The first
63
+ * family whose subject is a RELATION rather than an element or a proximity.
64
+ * - `relation-endpoints` — WHAT a typed edge is allowed to run between, and how
65
+ * many times. The grammar of a framework's relations, read off the roles at
66
+ * the two ends rather than off the geometry: the same relation between the
67
+ * same two artefacts is right or wrong wherever they happen to be drawn.
68
+ * - `element-in-zone` — the subject must sit inside (or outside) named ZONES of
69
+ * the frame it is on. `element-in-background` asks whether an artefact is on
70
+ * the map at all; this one asks whether it is in the right REGION of it.
71
+ * - `edge-degree` — how many typed edges of one role may arrive at, and leave,
72
+ * one node. The first family whose subject is a node but whose evidence is
73
+ * its RELATIONS: nothing about where it is drawn takes part.
74
+ * - `role-count` — how many subjects of one role one INSTANCE of the frame must
75
+ * carry. Existence and uniqueness, counted per frame and reported ON it.
76
+ * - `edge-locality` — a typed edge must stay inside one instance of the frame,
77
+ * or must cross between two. Where `relation-endpoints` asks what a relation
78
+ * runs between, this asks which FRAMES its two ends belong to.
79
+ * - `reachability` — every subject must be reachable from a declared root by
80
+ * following typed edges. The first family that builds a graph rather than
81
+ * walking elements, and the only one that is not local to one element or one
82
+ * relation.
83
+ * - `label-presence` — the subject must be NAMED. The first family that reads
84
+ * an element's words rather than its geometry, its role or its relations.
85
+ * - `view-admissibility` — which roles a frame ADMITS, read off a level the
86
+ * frame itself declares. The first family whose question is asked of the
87
+ * VIEW rather than of the artefact: every other one starts from a subject and
88
+ * looks around it, this one starts from the sheet and asks what has been
89
+ * drawn on it.
90
+ */
91
+ export type RuleFamily = 'element-in-background' | 'orientation-against-axis' | 'attachment' | 'no-overlap' | 'relative-order-along-axis' | 'relation-endpoints' | 'element-in-zone' | 'tone-convention' | 'majority-fact' | 'edge-degree' | 'role-count' | 'edge-locality' | 'reachability' | 'label-presence' | 'view-admissibility';
92
+ /**
93
+ * WHEN a rule is evaluated (PF5.14).
94
+ *
95
+ * - `realtime` — the default, and what every rule was before this existed:
96
+ * evaluated on the debounced path while the user draws, inside the 16 ms
97
+ * budget.
98
+ * - `on-demand` — evaluated ONLY when the user asks for a check-up, and never
99
+ * during a gesture. {@link evaluateRules} skips these before touching a
100
+ * single element, so a framework can ship a control that would not fit the
101
+ * frame — or that is simply not urgent — without spending a microsecond of
102
+ * the drawing budget on it.
103
+ *
104
+ * The split is a property of the RULE, not of the caller: a rule that must not
105
+ * interrupt says so once, in its own declaration, and no evaluation path has to
106
+ * remember. That is what makes "zero real-time cost" provable at the bench
107
+ * rather than promised in a comment.
108
+ */
109
+ export type ValidationMoment = 'realtime' | 'on-demand';
110
+ /** `orientation-against-axis` configuration. */
111
+ export interface AgainstAxisDef {
112
+ /** Id of the axis in the rule's {@link ValidationRule.background}. */
113
+ axis: string;
114
+ /**
115
+ * Dead zone, in degrees, around the perpendicular. A subject at exactly 90°
116
+ * to the axis runs neither with it nor against it, and a rule that indicted
117
+ * it would be indicting a drawing hand rather than a mistake — so the verdict
118
+ * only falls beyond `90 + toleranceDeg` away from the axis' forward sense.
119
+ */
120
+ toleranceDeg: number;
121
+ }
122
+ /**
123
+ * What a finding SAYS: an i18n key, plus the framework's own wording for a host
124
+ * that ships no catalogue for it, for the message and for the remediation hint.
125
+ *
126
+ * Split out of {@link ValidationRule} because a rule can have more than one way
127
+ * of failing, and a family that knows WHICH one failed must be able to say so.
128
+ * A single message covering two distinct mistakes is a message that describes
129
+ * neither: "not on a dependency at a phase transition" — the wording Wardley's
130
+ * W2 shipped with, before the PO reduced that rule to one condition — left the
131
+ * user to guess which half they had got wrong, on a symbol eight units wide.
132
+ */
133
+ export interface RuleMessage {
134
+ /** i18n key of the message; resolved by the host. The engine holds no prose. */
135
+ messageKey: string;
136
+ /**
137
+ * The FRAMEWORK's own wording, used when the host ships no catalogue for the
138
+ * key — exactly the `labelKey` + `fallback` pair a {@link ValidationProfile}
139
+ * and a background label already carry. The framework owns the word; the
140
+ * library still never invents one.
141
+ */
142
+ messageFallback?: string;
143
+ /** i18n key of an optional remediation hint. */
144
+ suggestionKey?: string;
145
+ /** The framework's own wording for {@link suggestionKey}. */
146
+ suggestionFallback?: string;
147
+ }
148
+ /** `attachment` configuration. */
149
+ export interface AttachmentDef {
150
+ /**
151
+ * OPTIONAL: the role of an element the subject must also be posed ON.
152
+ *
153
+ * It has to be an **edge** role: "posed on" is measured as a distance to a
154
+ * PATH, and a node has none. A rule naming a node role here matches nothing
155
+ * and warns once rather than failing silently — a rule that never fires and
156
+ * never says why is the worst thing declarative data can do.
157
+ *
158
+ * Absent means the subject is judged on {@link boundaryAxis} alone, which is
159
+ * the shape Wardley's W2 took the day the PO spelled the rule out: a bar
160
+ * straddling a phase divider is right whether or not a dependency happens to
161
+ * run under it (recette of 02/08/2026).
162
+ */
163
+ carrierRole?: RoleId;
164
+ /**
165
+ * How far, in model units, the subject may sit from its carrier. Read only
166
+ * when a {@link carrierRole} is declared, and absent means "on the path" —
167
+ * a boundary-only rule declares neither.
168
+ */
169
+ tolerance?: number;
170
+ /**
171
+ * The subject must STRADDLE one of the frame's declared transitions, measured
172
+ * across this axis. Absent means the position along the axis is not judged at
173
+ * all.
174
+ *
175
+ * ## "Straddling", as geometry
176
+ *
177
+ * The subject's own EXTENT along the axis must intersect the transition BAND
178
+ * — the frontier widened by the frame's declared
179
+ * {@link FrameworkBackgroundDef.transitionBandWidth}. One interval overlap,
180
+ * and it says both halves of what the practitioner means at once:
181
+ *
182
+ * - a subject WIDE enough to cover the frontier is superimposed on it, and is
183
+ * accepted whatever the band says — the line genuinely passes through it;
184
+ * - a subject too thin to cover anything (an inertia bar is eight units wide)
185
+ * is accepted while it is within the band, which is the frame's own
186
+ * declared tolerance for "on this frontier" and, on a Wardley map, Wardley's
187
+ * zone of punctuated equilibrium.
188
+ *
189
+ * Measured on the extent and never on the centre: "superimposed on the line"
190
+ * is a statement about the subject's ink, not about a point inside it. The
191
+ * band is a ratio of the plot, so the verdict holds when the map is resized.
192
+ * A rule asking for a boundary against a frame that declares no band warns
193
+ * once and drops the requirement rather than indicting every subject on the
194
+ * board.
195
+ */
196
+ boundaryAxis?: string;
197
+ /**
198
+ * The words for the boundary half, when a rule that ALSO declares a
199
+ * {@link carrierRole} wants to say something other than its own message —
200
+ * two requirements the user has two different ways of fixing are two
201
+ * sentences. A boundary-only rule needs none: its own message is the only
202
+ * thing it can be saying.
203
+ */
204
+ offBoundary?: RuleMessage;
205
+ }
206
+ /**
207
+ * One `no-overlap` combination: two roles that must not collide. Order carries
208
+ * no meaning — `[label, node]` and `[node, label]` are the same requirement.
209
+ *
210
+ * Which GEOMETRY each side is measured with is not declared here: it follows
211
+ * the role's own `kind` in {@link ValidationRule.roles}. An `edge` role is
212
+ * measured along its PATH, because the bounding box of a diagonal link covers
213
+ * half the map and would indict every label anywhere near it; a `text` role by
214
+ * the ink of its text, because a text box is created at a width that says
215
+ * nothing about what it reads; a `node` role by its bounds.
216
+ */
217
+ export type OverlapPair = readonly [RoleId, RoleId];
218
+ /**
219
+ * `tone-convention` configuration (PF13.8 / Q5).
220
+ *
221
+ * A framework's colour code is a CONVENTION, not a decoration: on a Wardley map
222
+ * the landscape is drawn in greys, red is reserved for what is changing and
223
+ * green for benefits. A component someone coloured red for emphasis is saying
224
+ * something the author did not mean.
225
+ *
226
+ * ## Why palette ENTRIES and not colours
227
+ *
228
+ * The sanctioned colours are named against the frame's own declared palette
229
+ * ({@link BackgroundChromeDef.palette}) — the same `@name` indirection every
230
+ * background label and wash already uses. A rule therefore never restates a hex
231
+ * the background already owns, and a host restyling the frame restyles the
232
+ * convention with it, in one place.
233
+ *
234
+ * ## Why TONES and not exact colours
235
+ *
236
+ * The convention is about tones, so the comparison is too: an element is judged
237
+ * on the tone family its colour falls into ({@link toneOf}), never on matching
238
+ * a palette entry byte for byte. Otherwise every legitimate shade of grey the
239
+ * shape toolbar can produce would be a finding, which is a rule nobody would
240
+ * keep switched on for five minutes.
241
+ *
242
+ * A colour the engine cannot classify — a CSS variable it has no theme to
243
+ * resolve, a gradient, `transparent` — yields SILENCE. Guessing would mean
244
+ * indicting a user over a colour nobody in this process can actually see.
245
+ */
246
+ export interface ToneConventionDef {
247
+ /**
248
+ * Names of the entries, in the rule's {@link ValidationRule.background}
249
+ * palette, whose tones the subject may be drawn in. A rule naming entries
250
+ * that resolve to no classifiable tone at all warns once and evaluates
251
+ * nothing, rather than indicting every element on the board.
252
+ */
253
+ palette: readonly string[];
254
+ }
255
+ /**
256
+ * `majority-fact` configuration (PF13.8 / Q6).
257
+ *
258
+ * "Most of what you have mapped is an activity — the phase names for activities
259
+ * would read better." A remark about the MAP, raised from a count over its
260
+ * elements, and deliberately never imposed.
261
+ *
262
+ * ## The gate, and why it is silence rather than a warning
263
+ *
264
+ * The fact is read off a declared element prop that may not exist yet — Wardley's
265
+ * `nature` is the type-3 classification, and nothing writes it today. A family
266
+ * that guessed would produce a remark about a majority it computed over an empty
267
+ * population, i.e. a sentence with no evidence behind it. So a surface where NO
268
+ * subject carries the fact raises nothing at all, silently: the rule is shipped,
269
+ * inert, and starts working by itself the day the fact lands. Nothing to
270
+ * remember, nothing to switch on.
271
+ */
272
+ export interface MajorityDef {
273
+ /**
274
+ * The element prop carrying the fact, read duck-typed: the engine must not
275
+ * import a framework's model to count something declared by data.
276
+ */
277
+ fact: string;
278
+ /** The value that must hold for a majority of the subjects. */
279
+ value: string;
280
+ }
281
+ /**
282
+ * `relative-order-along-axis` configuration — the family of `docs/adr/0010`'s
283
+ * W4, "a provider component may not be positioned higher than its consumer".
284
+ *
285
+ * The rule reads a RELATION: given a typed edge, it compares the two elements
286
+ * that edge links along one axis of the frame, in the order the edge states.
287
+ * That order comes from the persisted `source → target` pair and from nowhere
288
+ * else — deriving it from the geometry would make the rule compare the layout
289
+ * against itself, so it could never fire (ADR 0010 § 4a).
290
+ */
291
+ export interface RelativeOrderDef {
292
+ /**
293
+ * The EDGE role whose orientation is read. An element matching it (or
294
+ * specialising it) with both ends bound is one subject of the rule; every
295
+ * other edge on the board is none of its business — a Wardley change arrow is
296
+ * oriented too, and says nothing about who depends on whom.
297
+ */
298
+ edgeRole: RoleId;
299
+ /** Id of the axis in the rule's {@link ValidationRule.background}. */
300
+ axis: string;
301
+ /**
302
+ * Which end the edge states should be FURTHER ALONG the axis' forward sense
303
+ * (the direction of increasing value: up for a vertical axis, right for a
304
+ * horizontal one).
305
+ *
306
+ * `'source-ahead'` for `wardley:dependency`: the source is the consumer, so
307
+ * it sits higher on the visibility axis and the target is what it rests on.
308
+ * Needs descend from source to target; value flows back up.
309
+ */
310
+ expect: 'source-ahead' | 'target-ahead';
311
+ /**
312
+ * Slack before the verdict falls, as a RATIO of the frame's extent along that
313
+ * axis — never a number of model units.
314
+ *
315
+ * Same lesson the transition band learned on the PO recette of 01/08/2026: an
316
+ * absolute tolerance is four times as strict on a map four times as big, and
317
+ * nothing on screen explains why. Two components drawn level are not a
318
+ * mistake — an architect lines up a chain before spreading it out — so the
319
+ * rule only speaks when one is genuinely below the other.
320
+ *
321
+ * Absent means zero: any inversion at all, however small, is reported.
322
+ */
323
+ toleranceRatio?: number;
324
+ }
325
+ /**
326
+ * One sanctioned sentence of a framework's relation grammar: `source` _edge_
327
+ * `target`, all three named by ROLE.
328
+ *
329
+ * Read exactly the way `docs/adr/0010` says an edge is read — the source is the
330
+ * subject of the verb, the target its object — so a triplet is a sentence a
331
+ * practitioner would say out loud: an actor issues a command, a command lands on
332
+ * an aggregate, an aggregate raises an event. Each side matches by
333
+ * {@link roleIsA}, so a triplet written on a parent role covers every
334
+ * specialisation of it for free.
335
+ */
336
+ export interface EndpointTriplet {
337
+ source: RoleId;
338
+ edge: RoleId;
339
+ target: RoleId;
340
+ }
341
+ /**
342
+ * `relation-endpoints` configuration — the grammar of a framework's relations.
343
+ *
344
+ * Where `relative-order-along-axis` asks whether the two ends of a relation are
345
+ * in the right PLACE, this family asks whether they are the right THINGS. It
346
+ * reads the persisted `source → target` pair and the roles the two ends carry,
347
+ * and nothing else: no coordinate takes part, so the verdict survives every
348
+ * layout of the same document.
349
+ *
350
+ * ## Four ways of failing, four sentences
351
+ *
352
+ * A relation can be wrong in ways the user fixes with four different gestures —
353
+ * re-point an end, delete a loop, delete a copy, choose between two patterns —
354
+ * so each mode carries its own {@link RuleMessage} and falls back to the rule's
355
+ * own words when a framework declares none. Same precedent as
356
+ * {@link AttachmentDef.offBoundary}, for the same reason: one sentence covering
357
+ * four mistakes describes none of them.
358
+ */
359
+ export interface RelationEndpointsDef {
360
+ /**
361
+ * The EDGE role whose ends are read. An element matching it (or specialising
362
+ * it) is one subject of the rule; every other edge on the board is none of
363
+ * its business — a free connector somebody drew to point at something is not
364
+ * a claim about the model.
365
+ */
366
+ edgeRole: RoleId;
367
+ /**
368
+ * The sanctioned sentences. Absent means the shape of the relation is not
369
+ * judged at all, which is what a rule that only forbids loops or duplicates
370
+ * declares.
371
+ *
372
+ * ## The alphabet, and why an unknown end is SILENCE
373
+ *
374
+ * The roles cited by the triplets — every `source` and every `target` — form
375
+ * the alphabet this rule speaks. An edge with an end OUTSIDE that alphabet is
376
+ * not evaluated at all: not the matrix, not the loop, not the duplicate.
377
+ *
378
+ * A hard requirement, and the one that makes the family shippable. A flow
379
+ * drawn onto an Event Storming hotspot, or onto a plain rectangle somebody
380
+ * dropped on the board to think with, is a DRAFT — the user is saying "there
381
+ * is something here", and a tool that answered "that arc is forbidden" would
382
+ * be indicting the act of sketching. The frameworks' own grammars are written
383
+ * on a handful of artefacts each; everything else on the canvas has to stay
384
+ * outside the conversation (PRD principle 8).
385
+ */
386
+ allowed?: readonly EndpointTriplet[];
387
+ /**
388
+ * Pairs of edge roles that may not BOTH be drawn between the same two
389
+ * elements. The node pair is unordered — two contexts related twice are
390
+ * related twice whichever end each relation starts from — and so is the role
391
+ * pair: `[acl, conformist]` and `[conformist, acl]` are one requirement.
392
+ *
393
+ * The Context Mapping case: a downstream context protecting itself with an
394
+ * anti-corruption layer is not simultaneously conforming to its upstream. Both
395
+ * relations are legitimate on their own; together they are a contradiction,
396
+ * and only the pair can say so.
397
+ */
398
+ exclusivePairs?: readonly (readonly [RoleId, RoleId])[];
399
+ /**
400
+ * Whether an edge whose two ends are the SAME element is a finding.
401
+ *
402
+ * Absent, a self-loop is silence — total silence, even when the matrix says
403
+ * nothing about it. A loop is either a deliberate notation (a process that
404
+ * feeds itself) or a hand that dropped the second end on the first, and a
405
+ * framework that has not decided which has not asked to be told about it.
406
+ */
407
+ forbidSelfLoop?: boolean;
408
+ /** Whether the SAME relation drawn twice between the same ordered pair is a finding. */
409
+ forbidDuplicate?: boolean;
410
+ /** Words for an edge whose sentence is not in {@link allowed}. */
411
+ offMatrix?: RuleMessage;
412
+ /** Words for an edge that loops back onto its own source. */
413
+ selfLoop?: RuleMessage;
414
+ /** Words for the second copy of a relation that already exists. */
415
+ duplicate?: RuleMessage;
416
+ /** Words for two relations of {@link exclusivePairs} drawn between one pair. */
417
+ exclusive?: RuleMessage;
418
+ /**
419
+ * Words for a NEUTRAL connector drawn between two artefacts of this rule's
420
+ * own vocabulary — and, by being present at all, the request to look for one.
421
+ * Absent, a role-less link is invisible to this family, which is what every
422
+ * rule written before this field means.
423
+ *
424
+ * ## The gap this closes
425
+ *
426
+ * A framework's edge tool stamps a role. Quick-connect and auto-complete do
427
+ * not: releasing the canvas' own link gesture between two artefacts produces a
428
+ * connector carrying NO role, so it says nothing to any of the four verdicts
429
+ * above — the grammar reads it as absent, and the user reads it as drawn. A
430
+ * process whose steps are joined by such links looks connected and validates
431
+ * as if nobody had joined anything.
432
+ *
433
+ * ## Why BOTH ends must be artefacts this grammar could have related
434
+ *
435
+ * The same proportionality that makes {@link allowed}'s alphabet a hard
436
+ * requirement, applied one level up. A plain connector from an artefact to a
437
+ * sticky note, to a legend glyph, to a shape somebody dropped on the board, is
438
+ * an annotation and none of the framework's business — pointing at things is
439
+ * what a whiteboard is for. A plain connector between two artefacts this
440
+ * rule's own sentences run between is the only case where the user can be
441
+ * presumed to have meant a typed relation and reached for the wrong gesture.
442
+ *
443
+ * "Could have related" is read off {@link allowed}'s own ALPHABET when the
444
+ * rule declares a matrix: the roles its triplets name as a source or a target,
445
+ * matched with {@link roleIsA} so a specialisation counts. That is the
446
+ * tightest honest reading, and it excludes — with nothing for an author to
447
+ * remember — every role a framework declares for something that is not an
448
+ * endpoint of anything: the background role, a legend glyph, a lane. Presuming
449
+ * somebody meant to draw a typed relation onto a POOL is exactly the
450
+ * over-firing this test exists to prevent.
451
+ *
452
+ * A rule declaring NO matrix has no alphabet to read, so it falls back to
453
+ * membership in its own {@link ValidationRule.roles} — never to a prefix match
454
+ * on the `framework:` half of the role id. The namespace is a naming
455
+ * CONVENTION (`role.ts` says so, and types the id as a bare string); the
456
+ * vocabulary is DATA the framework hands the engine. Reading the data cannot
457
+ * be wrong about a framework that spells its own prefix differently, and it
458
+ * keeps this file free of string surgery on ids it does not own.
459
+ *
460
+ * `roles` stays purely the dictionary the inheritance walk reads either way.
461
+ * It is never overloaded into a filter, so an author never has to shrink the
462
+ * vocabulary a rule's other clauses depend on in order to change what this
463
+ * one flags.
464
+ */
465
+ flagNeutral?: RuleMessage;
466
+ }
467
+ /**
468
+ * `edge-degree` configuration — the CARDINALITY of a framework's relations, read
469
+ * at a node.
470
+ *
471
+ * "A start event has no incoming sequence flow"; "a task has at least one".
472
+ * Where {@link RelationEndpointsDef} judges one relation against the roles at
473
+ * its ends, this judges one NODE against how many relations reach it — the other
474
+ * half of a relation grammar, and the half no per-edge rule can express, because
475
+ * the mistake is a COUNT and nothing is wrong with any single link.
476
+ *
477
+ * ## Read off the persisted ends, never off the geometry
478
+ *
479
+ * Same reading as `docs/adr/0010`: an edge's `source` is the subject of its
480
+ * verb and its `target` the object, so "incoming" and "outgoing" are properties
481
+ * of the document and not of which way somebody dragged. Nothing here consults a
482
+ * coordinate, so the verdict survives every layout of the same process.
483
+ */
484
+ export interface EdgeDegreeDef {
485
+ /**
486
+ * The EDGE role being counted. An element matching it (or specialising it)
487
+ * counts; every other link on the board is none of this rule's business — a
488
+ * message flow arriving at a task says nothing about how many sequence flows
489
+ * do.
490
+ */
491
+ edgeRole: RoleId;
492
+ /** Fewest edges of that role that may ARRIVE at the subject. */
493
+ minIn?: number;
494
+ /** Most edges of that role that may ARRIVE at the subject. */
495
+ maxIn?: number;
496
+ /** Fewest edges of that role that may LEAVE the subject. */
497
+ minOut?: number;
498
+ /** Most edges of that role that may LEAVE the subject. */
499
+ maxOut?: number;
500
+ /**
501
+ * A DISJUNCTIVE floor: the subject must reach this count on at least ONE
502
+ * side. The finding falls only when BOTH the incoming and the outgoing count
503
+ * are short of it.
504
+ *
505
+ * ## Why a fifth bound rather than two of the four
506
+ *
507
+ * The four above are conjunctive — declare `minIn` and `minOut` together and
508
+ * the subject has to satisfy both — and there is a whole class of normative
509
+ * shape that says the opposite: an artefact must do one thing OR the other,
510
+ * and doing either is enough. A branching artefact that neither splits nor
511
+ * merges is the canonical one: it takes one thing in, puts one thing out and
512
+ * decides nothing, which is a node somebody drew and then never gave a job.
513
+ * `minIn: 2` would indict every split, `minOut: 2` every merge; the
514
+ * requirement is genuinely "at least one of the two", and no conjunction of
515
+ * per-direction bounds expresses it.
516
+ *
517
+ * ## Composition
518
+ *
519
+ * Orthogonal to the four, and evaluated after them: a rule may cap one side
520
+ * with `maxIn` and still ask for two on either side, and each bound keeps its
521
+ * own sentence. Absent — the case for every rule written before it existed —
522
+ * nothing is asked and nothing is counted.
523
+ */
524
+ eitherMin?: number;
525
+ /**
526
+ * A FORBIDDEN ZONE: the shape of degree a subject may not have, declared as
527
+ * the bounds it must NOT all satisfy at once.
528
+ *
529
+ * The inverse polarity of every bound above. `minIn`/`maxIn`/`minOut`/`maxOut`
530
+ * here read exactly as they do there — `minIn: 2` means "two or more arrive" —
531
+ * but the rule fires when the node matches ALL of the ones supplied, instead of
532
+ * when it misses one.
533
+ *
534
+ * ## Why the inverse cannot be written with the bounds
535
+ *
536
+ * Two shapes want it, and neither is expressible as a floor or a ceiling:
537
+ *
538
+ * - an artefact that MERGES and SPLITS at once — `{ minIn: 2, minOut: 2 }`.
539
+ * Both halves are individually fine and their conjunction is ambiguous, so
540
+ * the rule is about the pair and about nothing else;
541
+ * - an artefact that does NEITHER — `{ maxIn: 1, maxOut: 1 }`. A ceiling on
542
+ * each side alone forbids the legitimate split and the legitimate merge; only
543
+ * their conjunction describes the artefact that decides nothing.
544
+ *
545
+ * The second one is the same requirement {@link eitherMin} states from the
546
+ * other side, and a framework may write it either way — `eitherMin: 2` and
547
+ * `forbidPattern: { maxIn: 1, maxOut: 1 }` are the same set of nodes. Both are
548
+ * offered because a rule reads best when its data says what its sentence says,
549
+ * and the two sentences a notation actually writes are "a gateway must branch"
550
+ * and "a gateway that does nothing is superfluous".
551
+ *
552
+ * ## A pattern of ONE bound is legal, and always redundant
553
+ *
554
+ * `{ minIn: 2 }` fires on `in >= 2`, which is what `maxIn: 1` already says, and
555
+ * `{ maxIn: 1 }` alone is `minIn: 2`. Coherent under the rule above and left
556
+ * legal rather than warned about — the conjunction of one is still a
557
+ * conjunction, and a framework mid-edit should not be shouted at. But a
558
+ * one-bound pattern is never the reason to reach for this field: write the
559
+ * plain inverse bound, which carries a per-direction sentence naming the side
560
+ * the user has to act on.
561
+ *
562
+ * ## Words, and the empty pattern
563
+ *
564
+ * The pattern carries its OWN message rather than a slot beside the others: a
565
+ * forbidden zone is not a bound that failed, and its sentence never reads like
566
+ * one. `RuleMessage` is intersected rather than optional, so the type system
567
+ * requires that sentence — this is the one bound with no `?? rule` fallback,
568
+ * because it is the one that can never borrow the rule's own words honestly.
569
+ *
570
+ * A pattern supplying no bound at all is satisfied by every node, which would
571
+ * indict the whole board — it warns once and is not evaluated.
572
+ */
573
+ forbidPattern?: RuleMessage & {
574
+ minIn?: number;
575
+ maxIn?: number;
576
+ minOut?: number;
577
+ maxOut?: number;
578
+ };
579
+ /**
580
+ * Words for each bound, when a rule declaring more than one wants to say
581
+ * something other than its own message.
582
+ *
583
+ * The {@link AttachmentDef.offBoundary} precedent, for the same reason: "a
584
+ * start event begins the process" covers both "something points at it" and
585
+ * "nothing leaves it", and the two are fixed by opposite gestures. A rule
586
+ * declaring a single bound needs none — its own message is the only thing it
587
+ * can be saying.
588
+ */
589
+ tooFewIn?: RuleMessage;
590
+ /** Words for {@link maxIn}. */
591
+ tooManyIn?: RuleMessage;
592
+ /** Words for {@link minOut}. */
593
+ tooFewOut?: RuleMessage;
594
+ /** Words for {@link maxOut}. */
595
+ tooManyOut?: RuleMessage;
596
+ /**
597
+ * Words for {@link eitherMin} — the one bound whose sentence is genuinely
598
+ * about NEITHER side, and therefore the one a per-direction message could
599
+ * never carry.
600
+ */
601
+ neither?: RuleMessage;
602
+ }
603
+ /**
604
+ * `role-count` configuration — existence and uniqueness, counted per INSTANCE of
605
+ * the frame.
606
+ *
607
+ * "A pool holds exactly one start event." The subject of the finding is not any
608
+ * one element — no start event is wrong, there are simply none or three — so the
609
+ * finding is raised ON THE FRAME, exactly like {@link MajorityDef}'s remark
610
+ * about a map. That is what puts the bracket on the pool, and what makes the
611
+ * `map` exemption scope reach it: `raise` stamps the frame as the finding's own
612
+ * {@link Violation.backgroundId}, so an arbitration made on one pool covers that
613
+ * pool and no other on the board.
614
+ */
615
+ export interface RoleCountDef {
616
+ /**
617
+ * The role being counted, matched by {@link roleIsA} — a rule counting
618
+ * `bpmn:start-event` counts its message and timer variants too, which is the
619
+ * only reading under which "one start event" stays one requirement as the
620
+ * vocabulary grows.
621
+ */
622
+ subject: RoleId;
623
+ /**
624
+ * Count only the elements whose role IS {@link subject}, without descending
625
+ * into its specialisations.
626
+ *
627
+ * The default — `roleIsA`, the reading every other role test in this engine
628
+ * uses — is right whenever the requirement is about the FAMILY: "one
629
+ * beginning" means one beginning of any kind, and a vocabulary that grows a
630
+ * new variant inherits the rule for free.
631
+ *
632
+ * It is wrong when the requirement is about the PLAIN member of a family, as
633
+ * distinct from its qualified siblings: "at most one UNQUALIFIED beginning per
634
+ * frame" is a statement about the artefact that carries no qualifier, and
635
+ * several qualified ones beside it are exactly what the notation is for. Under
636
+ * the descending reading that rule cannot be written at all — every variant
637
+ * would count towards a bound meant for the plain one alone.
638
+ *
639
+ * Applies to the SUBJECT only. {@link ifPresent} keeps descending, and
640
+ * deliberately: a guard asks "is there one of these at all", which is a
641
+ * question about the family whatever the bound beside it counts. A framework
642
+ * needing the exact reading on both sides has not turned up yet, and inventing
643
+ * a second flag for it would be data nobody can read.
644
+ */
645
+ exact?: boolean;
646
+ /** Fewest subjects one instance of the frame must carry. */
647
+ min?: number;
648
+ /** Most subjects one instance of the frame may carry. */
649
+ max?: number;
650
+ /**
651
+ * A GUARD: the bounds apply to a frame only while that frame also holds at
652
+ * least one element whose role is (or specialises) this one. A frame holding
653
+ * none is not judged at all — not "judged and found compliant", not walked.
654
+ *
655
+ * ## Why a notation needs this, and why it is not `min` with a different face
656
+ *
657
+ * Whole families of artefact are OPTIONAL on their own and NORMATIVE in
658
+ * pairs. A sketch may legitimately show neither a beginning nor an end; what
659
+ * it may not show is one without the other, because a reader who sees where
660
+ * the work finishes will look for where it starts, and finding nothing is a
661
+ * question the drawing cannot answer.
662
+ *
663
+ * An unconditional `min: 1` would state the wrong thing twice over: it would
664
+ * indict the perfectly legitimate sketch that declares neither, and it would
665
+ * be doing so in the name of a requirement the notation does not make. The
666
+ * PAIRING is the requirement, and a pairing is exactly a bound plus a guard.
667
+ *
668
+ * Two rules, mirrored, then say the whole of it — "if there is an end there
669
+ * must be a start", "if there is a start there must be an end" — and each is
670
+ * one line of data. That is the shape this field is for.
671
+ *
672
+ * ## Same attribution as the subject
673
+ *
674
+ * The guard element must be IN the frame, on the same containment-only
675
+ * reading {@link evaluateRoleCount} uses for the subjects it counts: an
676
+ * artefact floating beside a pool no more arms a requirement about that pool
677
+ * than it satisfies one. Absent, the bounds apply to every instance, which is
678
+ * what every rule written before this field means.
679
+ */
680
+ ifPresent?: RoleId;
681
+ /** Words for {@link min} — see {@link EdgeDegreeDef.tooFewIn}. */
682
+ tooFew?: RuleMessage;
683
+ /** Words for {@link max}. */
684
+ tooMany?: RuleMessage;
685
+ }
686
+ /**
687
+ * `edge-locality` configuration — a relation constrained relative to the frame
688
+ * instances its two ends sit on.
689
+ *
690
+ * The canonical pair a swimlane notation is built on, and both halves of it are
691
+ * one declaration away from each other: a sequence flow stays inside one pool
692
+ * (`same-background`), a message flow only exists BETWEEN pools
693
+ * (`cross-background`). Neither is expressible by {@link RelationEndpointsDef}:
694
+ * the two ends carry exactly the same roles in the legal case and the illegal
695
+ * one, and the only thing that differs is which frame each of them is drawn on.
696
+ */
697
+ export interface EdgeLocalityDef {
698
+ /** The EDGE role being constrained, matched by {@link roleIsA}. */
699
+ edgeRole: RoleId;
700
+ /**
701
+ * `'same-background'` — the two ends must belong to ONE instance, and two
702
+ * different ones are the finding; `'cross-background'` — the two ends must
703
+ * belong to different instances, and one instance is the finding.
704
+ */
705
+ mode: 'same-background' | 'cross-background';
706
+ }
707
+ /**
708
+ * `reachability` configuration — every subject must be reachable from a declared
709
+ * ROOT by following typed edges.
710
+ *
711
+ * The orphan question, and the first one in this engine that no amount of
712
+ * looking at an element or at a relation can answer: a task with a perfectly
713
+ * good sequence flow on either side is still unreachable if the chain it belongs
714
+ * to never starts anywhere. Only the graph knows.
715
+ */
716
+ export interface ReachabilityDef {
717
+ /**
718
+ * Where the traversal STARTS. Every element whose role is (or specialises)
719
+ * this one is a root, and a board carrying none silences the rule whole — see
720
+ * {@link evaluateReachability}, and {@link implicitRoots} for the second kind
721
+ * of root a notation with an optional start marker needs.
722
+ */
723
+ rootRole: RoleId;
724
+ /** The role whose elements must be reachable. */
725
+ subjectRole: RoleId;
726
+ /** The edge role that is FOLLOWED, source → target, and only that way. */
727
+ edgeRole: RoleId;
728
+ /**
729
+ * Also treat every SUBJECT that nothing points at as a root — in-degree zero
730
+ * along {@link edgeRole}.
731
+ *
732
+ * ## What this changes, and what it is for
733
+ *
734
+ * A notation where the explicit start marker is OPTIONAL has a second, silent
735
+ * way of saying "the work begins here": draw the artefact and point nothing at
736
+ * it. Two branches of a process running side by side, only one of them given a
737
+ * start marker, are both perfectly well-formed — and a traversal that only
738
+ * left from the marker would report the whole of the second branch as
739
+ * unreachable, which is a wall of brackets over a drawing that is right.
740
+ *
741
+ * ## What is left, exactly
742
+ *
743
+ * A subject fires when it has an incoming counted edge — so it is not an
744
+ * implicit root — and no root ever reaches it. Two shapes satisfy that, and
745
+ * the second one is easy to forget:
746
+ *
747
+ * 1. a RING entered from nowhere: artefacts pointing round at each other, each
748
+ * with an incoming edge and none of them reachable from outside. The real
749
+ * defect, and the one this reading exists to keep visible — work that can
750
+ * never begin;
751
+ * 2. a subject fed ONLY by an edge the walk can never leave from: one whose
752
+ * `source` is a dangling id, or an element whose role is neither
753
+ * {@link rootRole} nor {@link subjectRole}. The edge disqualifies the
754
+ * subject as an implicit root, and its source is never enqueued, so nothing
755
+ * reaches it.
756
+ *
757
+ * The second shape is a BROKEN or FOREIGN edge, which is
758
+ * `relation-endpoints`' subject rather than this family's, and this family
759
+ * reports the consequence rather than the cause. It behaves identically with
760
+ * the flag off — it is inherited, not introduced here — so a framework that
761
+ * finds the report confusing wants a `relation-endpoints` rule beside this
762
+ * one, not a change to this flag.
763
+ *
764
+ * ## The zero-root gate still holds
765
+ *
766
+ * "No root on the board" becomes "no root of EITHER kind", and it is still
767
+ * total silence. In practice a board with any subject at all has an implicit
768
+ * root unless every subject is pointed at, so the gate stops being the thing
769
+ * that saves a blank sketch and becomes the thing that saves a board where the
770
+ * question genuinely does not arise.
771
+ *
772
+ * Absent or `false` is the original reading: only the declared role starts a
773
+ * traversal, and a board carrying no such element says nothing at all.
774
+ */
775
+ implicitRoots?: boolean;
776
+ }
777
+ /**
778
+ * `label-presence` configuration — the first brick of the PRD's *étiquetage*
779
+ * family, and the first family in this engine that reads an element's WORDS.
780
+ *
781
+ * "This step has no name." Every other family asks about geometry, roles or
782
+ * relations; this one asks whether the artefact says what it is. An unnamed box
783
+ * in the middle of a diagram is the one defect a reader cannot work around —
784
+ * they can infer a missing arrow from the layout, and they can infer nothing at
785
+ * all from an empty rectangle.
786
+ *
787
+ * ## Where the words come from
788
+ *
789
+ * The element's own `text`, read duck-typed exactly as {@link textInkBound}
790
+ * already reads it — the one property every artefact-bearing element model
791
+ * carries (a `Y.Text` on a shape, a connector label, a free text) and the only
792
+ * one the engine can read without importing a model. See {@link elementLabel}
793
+ * for what counts as empty.
794
+ *
795
+ * A framework whose artefacts are named by a SEPARATE element beside them — a
796
+ * text element sitting next to a node, the way a Wardley label does — is not
797
+ * asking this question, and this family cannot answer it: it reads the subject's
798
+ * own words and nothing else. That is a different family (a proximity between
799
+ * two roles), not a flag on this one.
800
+ */
801
+ export interface LabelPresenceDef {
802
+ /**
803
+ * The subject must carry a label. Written as a literal rather than a boolean
804
+ * because it is a DISCRIMINANT and not a switch: `present: false` would mean
805
+ * "this artefact must stay unnamed", which no notation asks for. The field
806
+ * exists so the questions this family grows next — a maximum length, a
807
+ * pattern, a name that must match the zone it sits in — arrive as siblings
808
+ * beside it rather than as a second family.
809
+ */
810
+ present: true;
811
+ }
812
+ /**
813
+ * `view-admissibility` configuration — WHICH ROLES the frame admits, given the
814
+ * level the frame itself declares.
815
+ *
816
+ * The engine names no framework and no level. It is handed the PROP the frame
817
+ * writes its level in, and a table keyed by the VALUES that prop can take: the
818
+ * same idiom `backgroundLabelText` and `backgroundInVariant` already use to read
819
+ * a declared prop off an instance, promoted to a rule so a verdict can turn on
820
+ * it. C4 is the first consumer — `levelProp: 'level'`, keyed by
821
+ * `context` / `container` / `component` — and nothing here knows that.
822
+ *
823
+ * ## Why the table is FORBIDDEN and not ADMITTED
824
+ *
825
+ * Because the honest default for a view is permissive. A C4 context diagram
826
+ * legitimately shows the people and the neighbouring systems around the one it
827
+ * is about; a container diagram legitimately shows the persons, the systems and
828
+ * the system boundary it zooms into. An allow-list would have to enumerate
829
+ * every one of those, and would indict every artefact the framework's author
830
+ * forgot — including the free rectangles, the notes and the legend glyphs a
831
+ * whiteboard is made of. A deny-list says only what the notation actually
832
+ * refuses, and everything it does not name is left alone (PRD principle 8).
833
+ *
834
+ * A level the table has no entry for — or whose entry is empty — is a level the
835
+ * rule has nothing to say about, and it evaluates NOTHING there. That is what
836
+ * lets a framework declare the two levels that forbid something and stay silent
837
+ * on the one that forbids nothing, rather than shipping a rule that can never
838
+ * fire.
839
+ */
840
+ export interface ViewAdmissibilityDef {
841
+ /**
842
+ * The prop the FRAME writes its level in, on the instance itself — `'level'`
843
+ * for a C4 board.
844
+ *
845
+ * A prop name and not a declared axis, a zone or a variant, because the level
846
+ * of a view is none of those: it is a fact the author states about the sheet,
847
+ * and the engine's job is to read it back where the framework says it is
848
+ * written. A frame whose prop holds nothing, or holds something that is not a
849
+ * non-empty string, has stated no level and is not judged.
850
+ */
851
+ levelProp: string;
852
+ /**
853
+ * Per level VALUE, the roles that view does not admit — matched by
854
+ * {@link roleIsA}, so naming a parent role covers its specialisations (C4's
855
+ * `c4:container` reaches `c4:database`, `c4:boundary` reaches both of its
856
+ * children).
857
+ *
858
+ * Own keys only when it is read: the table is an object literal shipped by a
859
+ * framework, so a frame whose level happened to say `'constructor'` must not
860
+ * resolve to something off the prototype.
861
+ */
862
+ forbidden: Readonly<Record<string, readonly RoleId[]>>;
863
+ }
864
+ /**
865
+ * `element-in-zone` configuration — the artefact is on the map, but is it in the
866
+ * right REGION of it?
867
+ *
868
+ * `element-in-background` frames a subject against the whole card; this frames
869
+ * it against the named zones the declaration already carries — the four
870
+ * quadrants of a Core Domain Chart, the phases of a Wardley map — so a rule can
871
+ * say "an outsourced subdomain has no business in the Core quadrant" without a
872
+ * single coordinate being restated anywhere.
873
+ *
874
+ * The zone rectangles come from the DECLARATION (ratios of the plot) resolved
875
+ * against the bounds of the instance the subject actually sits on, so the
876
+ * verdict survives the map being moved and resized, exactly like every other
877
+ * geometry in this engine.
878
+ */
879
+ export interface ElementInZoneDef {
880
+ /**
881
+ * The zones this rule is about, by their id in
882
+ * {@link FrameworkBackgroundDef.zones}. An id the frame does not declare is a
883
+ * typo in the data: the rule warns once and evaluates NOTHING rather than
884
+ * quietly measuring against the zones it happened to recognise — a smaller
885
+ * union is a different rule, and nobody would see the difference.
886
+ */
887
+ zoneIds: readonly string[];
888
+ /**
889
+ * `'inside'` — the subject belongs in one of those zones and is indicted
890
+ * anywhere else on the map; `'outside'` — the zones are forbidden ground.
891
+ */
892
+ expect: 'inside' | 'outside';
893
+ /**
894
+ * WHAT of the subject is measured. `'center'` (the default) reads the centre
895
+ * of its bounds — where the eye puts the artefact, and the only honest answer
896
+ * for something bigger than a cell. `'extent'` reads the whole box: `inside`
897
+ * then asks for full containment in ONE cited zone and `outside` for no shared
898
+ * area at all.
899
+ *
900
+ * Containment is tested zone by zone rather than against their union: a
901
+ * subject straddling two adjacent cited zones is precisely the ambiguous case
902
+ * a strict rule wants to hear about, and a union test would swallow it.
903
+ */
904
+ measure?: 'center' | 'extent';
905
+ }
906
+ /**
907
+ * WHERE a rule's authority comes from.
908
+ *
909
+ * - `standard` — the rule restates a normative sentence of a published
910
+ * specification. The tool is reporting a conformance defect.
911
+ * - `recommendation` — a SHOULD of the specification, or an industry linter's
912
+ * rule (bpmnlint, and its equivalents elsewhere). Widely agreed practice; not
913
+ * a conformance defect.
914
+ * - `labre-convention` — a house style of this editor, and nothing else. No
915
+ * norm speaks of it, and the rule must never let a user believe one does.
916
+ * - `organization` — a level of requirement an ORGANISATION adds on top, which
917
+ * the PRD names as future org profiles. Reserved: nothing declares it today.
918
+ */
919
+ export type ProvenanceSource = 'standard' | 'recommendation' | 'labre-convention' | 'organization';
920
+ /**
921
+ * Where a rule's authority comes from, as DATA rather than as prose buried in
922
+ * its message.
923
+ *
924
+ * A Labre convention presented as a norm violation is the one thing an
925
+ * architecture review will not forgive, and until now the distinction lived
926
+ * only in each rule's wording and in the comment above it — invisible to the
927
+ * UI, unqueryable by a host, unassertable by a test. Promoting it to a field is
928
+ * the same move the platform already made for severity and for moment: a rule
929
+ * says once, in its own declaration, what kind of thing it is.
930
+ *
931
+ * ## Purely descriptive
932
+ *
933
+ * **No evaluator reads it.** Not one of the fourteen family functions branches
934
+ * on it, `evaluateRules` and `evaluateCheckup` never look at it, and a rule
935
+ * declaring it evaluates identically to the same rule with the field removed
936
+ * ({@link ValidationRule.provenance} is pinned inert by a test). It exists for
937
+ * the violation bubble, for a conformance report, and for a host that wants to
938
+ * separate "your diagram breaks the standard" from "we suggest".
939
+ *
940
+ * ## One rule, one provenance
941
+ *
942
+ * The field describes THE RULE, so a rule whose clauses would answer
943
+ * differently is a rule that should be two — BPMN's sequence-flow endpoints
944
+ * (p.95, standard) and its no-self-loop house style split for exactly that
945
+ * reason, rather than declaring one provenance that is wrong half the time.
946
+ */
947
+ export interface RuleProvenance {
948
+ /** Where this rule's authority comes from. */
949
+ source: ProvenanceSource;
950
+ /**
951
+ * Human-readable citation — e.g. `'OMG BPMN 2.0.2 (ISO/IEC 19510) p.244'` or
952
+ * `'bpmnlint no-duplicate-sequence-flows'`.
953
+ *
954
+ * Prose, deliberately, and displayed VERBATIM: a page number, a clause, a
955
+ * linter rule name and a book chapter have nothing in common but being
956
+ * readable, and a schema that tried to model all four would model none of
957
+ * them. It is never translated — a citation is the same in every language.
958
+ */
959
+ reference?: string;
960
+ }
961
+ /**
962
+ * A rule is declarative, versioned data owned by its framework (PRD principle
963
+ * 5) — never a subclass, never a closure. It is comparable, serializable and
964
+ * can be shipped by a host.
965
+ */
966
+ export interface ValidationRule extends RuleMessage {
967
+ /** Stable id, namespaced by framework: `wardley.change-arrow-against-evolution`. */
968
+ id: string;
969
+ /** Owning framework, `wardley`. Rules never leave their framework. */
970
+ framework: string;
971
+ family: RuleFamily;
972
+ severity: ViolationSeverity;
973
+ /**
974
+ * When this rule runs. Absent = `'realtime'`, which is what every rule
975
+ * written before PF5.14 means and what the vast majority of rules want.
976
+ *
977
+ * `'on-demand'` takes the rule OUT of {@link evaluateRules} entirely — not
978
+ * out of the canvas affordance, out of the evaluation — and into
979
+ * {@link evaluateCheckup}, which only a user gesture calls.
980
+ */
981
+ moment?: ValidationMoment;
982
+ /**
983
+ * The role this rule is written on. An element matches when its own role IS
984
+ * that role or SPECIALISES it ({@link roleIsA}), so a rule on
985
+ * `wardley:component` covers `wardley:market` for free. An element with no
986
+ * role (a generalist square, a free text) never matches — proportionality,
987
+ * PRD principle 8.
988
+ *
989
+ * Absent for `no-overlap`, whose subjects are declared per PAIR, and for
990
+ * `view-admissibility`, whose subjects are declared per LEVEL: in both cases
991
+ * the rule has no single subject role, and naming one would be data that
992
+ * lies.
993
+ */
994
+ appliesTo?: RoleId;
995
+ /** The framework's role vocabulary, for the inheritance walk. */
996
+ roles: RoleDefs;
997
+ /** Bumped when the rule's meaning changes, so a host can pin behaviour. */
998
+ version: number;
999
+ /**
1000
+ * Where this rule's authority comes from — see {@link RuleProvenance}.
1001
+ *
1002
+ * Optional, framework-agnostic and purely DESCRIPTIVE: the engine's
1003
+ * evaluators never read it, so declaring it changes no verdict, no severity
1004
+ * and no message. A rule that omits it simply says nothing about its
1005
+ * authority, exactly as every rule did before the field existed.
1006
+ */
1007
+ provenance?: RuleProvenance;
1008
+ /**
1009
+ * The ROLE of the framework's background (`wardley:map`), i.e. the frame the
1010
+ * subject roles are measured against.
1011
+ *
1012
+ * A role, not an element type: the engine never looks at a shape type, on
1013
+ * either side of a rule (see `role.ts`). A background authored before its
1014
+ * role existed carries none, frames nothing and raises nothing.
1015
+ *
1016
+ * Required by `element-in-background` and by any family reading the frame's
1017
+ * declared facts; optional for `no-overlap`, where it only decides whether a
1018
+ * finding can be waived map-wide.
1019
+ */
1020
+ backgroundRole?: RoleId;
1021
+ /**
1022
+ * The framework's background DECLARATION, carried as data exactly like
1023
+ * {@link roles} is.
1024
+ *
1025
+ * This is what lets a rule read the frame's SEMANTICS — which axes it has and
1026
+ * which way they run, where its zones meet — without the engine owning a
1027
+ * registry of backgrounds or importing a renderer. The facts come out of
1028
+ * `../framework-background/facts.js`, and are a pure function of this
1029
+ * declaration plus the bounds of the instance a finding is measured against.
1030
+ */
1031
+ background?: FrameworkBackgroundDef;
1032
+ /** `orientation-against-axis` only. */
1033
+ against?: AgainstAxisDef;
1034
+ /** `attachment` only. */
1035
+ attachment?: AttachmentDef;
1036
+ /** `no-overlap` only: the combinations that must not collide. */
1037
+ overlap?: readonly OverlapPair[];
1038
+ /** `relative-order-along-axis` only. */
1039
+ relativeOrder?: RelativeOrderDef;
1040
+ /** `relation-endpoints` only. */
1041
+ endpoints?: RelationEndpointsDef;
1042
+ /** `element-in-zone` only. */
1043
+ inZone?: ElementInZoneDef;
1044
+ /**
1045
+ * `no-overlap` only: how DEEP a collision has to be, in model units, before
1046
+ * it is worth reporting. Absent or `0` means any shared area at all.
1047
+ *
1048
+ * Penetration depth, not shared area: how far the two geometries reach INTO
1049
+ * each other — `min(overlapX, overlapY)` for two boxes, and for a path the
1050
+ * greatest distance any point of it gets under the edge of the box it
1051
+ * crosses. A link clipping the corner of a name and a link drawn through the
1052
+ * middle of it share the same "they overlap"; only the second one is
1053
+ * something the eye trips over.
1054
+ *
1055
+ * Two paths crossing have no depth to measure — a line has no width — so a
1056
+ * declared crossing is reported whatever this says.
1057
+ */
1058
+ minPenetration?: number;
1059
+ /** `tone-convention` only. */
1060
+ tone?: ToneConventionDef;
1061
+ /** `majority-fact` only. */
1062
+ majority?: MajorityDef;
1063
+ /** `edge-degree` only: the subject nodes are named by {@link appliesTo}. */
1064
+ degree?: EdgeDegreeDef;
1065
+ /** `role-count` only: the frames are named by {@link backgroundRole}. */
1066
+ roleCount?: RoleCountDef;
1067
+ /** `edge-locality` only: the frames are named by {@link backgroundRole}. */
1068
+ locality?: EdgeLocalityDef;
1069
+ /** `reachability` only. */
1070
+ reachability?: ReachabilityDef;
1071
+ /** `label-presence` only: the subjects are named by {@link appliesTo}. */
1072
+ label?: LabelPresenceDef;
1073
+ /**
1074
+ * `view-admissibility` only: the views are named by {@link backgroundRole},
1075
+ * and the subjects by the level the view declares.
1076
+ */
1077
+ admissibility?: ViewAdmissibilityDef;
1078
+ }
1079
+ /**
1080
+ * A level of requirement, as DATA (PF9) — the same declarative, versioned,
1081
+ * host-shippable shape as a rule, a role or a background.
1082
+ *
1083
+ * A framework exposes several: Wardley ships a permissive learning profile and
1084
+ * a strict one; BPMN would ship descriptive / analytic / executable. A profile
1085
+ * says, for each rule of its framework, how hard that rule bites — or that it
1086
+ * does not apply at all.
1087
+ *
1088
+ * ## What "absent from {@link rules}" means
1089
+ *
1090
+ * The rule keeps its OWN declared severity. A profile is an override table, not
1091
+ * an allow-list: a rule the framework ships later must not silently vanish from
1092
+ * a strict profile that was written before it existed. A profile that wants a
1093
+ * rule gone says so — `'off'` — and a profile that wants it louder says that
1094
+ * too. Nothing is ever raised implicitly (PF9.4): every severity a user gets is
1095
+ * either the one the rule declares or one this table spells out.
1096
+ *
1097
+ * ## Scope
1098
+ *
1099
+ * A profile is CHOSEN per root instance, on the framework's background element
1100
+ * (`GfxPrimitiveElementModel.validationProfile`) — see PF9.1. Two maps on one
1101
+ * canvas therefore hold two independent levels of requirement.
1102
+ *
1103
+ * A background that names none INHERITS the choice made on the frame it is
1104
+ * drawn inside ({@link inheritChosenProfiles}), and falls back to its
1105
+ * framework's {@link isDefault} profile only when it sits inside nothing that
1106
+ * chose. That is what lets a framework offer the picker on its outer frame
1107
+ * alone and still govern the rules it frames against an inner one.
1108
+ */
1109
+ export interface ValidationProfile {
1110
+ /** Stable id, namespaced by framework: `wardley.sketch`. */
1111
+ id: string;
1112
+ /** Owning framework, `wardley`. A profile never applies across frameworks. */
1113
+ framework: string;
1114
+ /** i18n key of the human name; resolved by the host. No prose here either. */
1115
+ labelKey: string;
1116
+ /**
1117
+ * The framework's own wording when the host ships no catalogue for the key —
1118
+ * the same `labelKey` + `fallback` pair the background declaration uses for
1119
+ * its axis and phase labels. The framework owns the word; the library still
1120
+ * never invents one.
1121
+ */
1122
+ fallback?: string;
1123
+ /**
1124
+ * The one profile that applies when a background names none — and the one
1125
+ * that, chosen explicitly, writes NOTHING on the element. It is the most
1126
+ * permissive reasonable level, because the sketch wins (PRD principle 3).
1127
+ */
1128
+ isDefault?: boolean;
1129
+ /** Severity override per rule id. A rule absent here keeps its own. */
1130
+ rules: Readonly<Record<string, ProfileSeverity>>;
1131
+ }
1132
+ /**
1133
+ * Severity `profile` gives `rule` — the rule's own when the profile is silent
1134
+ * about it, or when there is no profile at all.
1135
+ */
1136
+ export declare function profileSeverity(rule: ValidationRule, profile: ValidationProfile | undefined): ProfileSeverity;
1137
+ /**
1138
+ * The profile a background of `framework` is checked against when it names
1139
+ * none: the one flagged {@link ValidationProfile.isDefault}, or — failing that
1140
+ * — the first one registered, so a framework that forgot the flag still has a
1141
+ * resolvable answer instead of silently losing its profiles.
1142
+ */
1143
+ export declare function defaultProfileOf(profiles: readonly ValidationProfile[], framework: string): ValidationProfile | undefined;
1144
+ /**
1145
+ * The result of a rule that did not hold (PRD principle 6): an OBJECT, not a
1146
+ * string and not a rendering. It names the rule, the elements at fault and an
1147
+ * i18n key — never a sentence.
1148
+ */
1149
+ export interface Violation {
1150
+ ruleId: string;
1151
+ /**
1152
+ * The elements the rule indicts — one for an element-local family, TWO for
1153
+ * `no-overlap` (which is about a pair and not about either half of it), and
1154
+ * THREE for `relative-order-along-axis`: the two elements the relation links
1155
+ * plus the edge that states it.
1156
+ *
1157
+ * The edge is in there deliberately. The finding has two honest resolutions —
1158
+ * move a node, or reverse the relation — and the second one is only reachable
1159
+ * from the edge, which carries the inversion command (`docs/adr/0010` M3). A
1160
+ * finding that named the nodes alone would show the user two brackets and no
1161
+ * way to the gesture that fixes half the cases.
1162
+ *
1163
+ * Always sorted by id, so the same situation reports the same way whichever
1164
+ * order the surface happened to be walked in.
1165
+ */
1166
+ elementIds: string[];
1167
+ severity: ViolationSeverity;
1168
+ messageKey: string;
1169
+ /** The framework's own wording for {@link messageKey}. */
1170
+ messageFallback?: string;
1171
+ /** i18n key of a remediation hint, when the rule carries one. */
1172
+ suggestion?: string;
1173
+ /** The framework's own wording for {@link suggestion}. */
1174
+ suggestionFallback?: string;
1175
+ /**
1176
+ * The background this finding is attributed to — for `element-in-background`,
1177
+ * the NEAREST one, none of them having contained the element (that is what
1178
+ * being in violation means here).
1179
+ *
1180
+ * Recorded by the family at the moment it picks it, because nothing
1181
+ * downstream can reconstruct it: a board carries several maps, and "which one
1182
+ * did the user mean" is a question only the evaluation is in a position to
1183
+ * answer. It is what makes the `map` exemption scope mean ONE map instead of
1184
+ * every map on the document — see {@link ExemptionScope}.
1185
+ *
1186
+ * A heuristic, and an honest one: nearest by edge-to-edge gap
1187
+ * ({@link gapSquared}), ties broken by the smaller id so that it never
1188
+ * depends on the order the surface happened to be walked in.
1189
+ *
1190
+ * Absent for a family that measures against no background.
1191
+ */
1192
+ backgroundId?: string;
1193
+ /**
1194
+ * The named FRONTIER of that background the finding is about, when the family
1195
+ * measured against one: `custom-built|product` for a transition band
1196
+ * ({@link BackgroundTransitionBand}).
1197
+ *
1198
+ * "This bar is outside the equilibrium zone" is only half an answer — the
1199
+ * other half is which zone it should have been in, and the band already knows
1200
+ * its own name. Recorded at the moment the family picks the frontier, for the
1201
+ * same reason {@link backgroundId} is: nothing downstream can reconstruct
1202
+ * which of several transitions the user was aiming at.
1203
+ *
1204
+ * Absent for a family that measures against no such region.
1205
+ */
1206
+ boundaryId?: string;
1207
+ /**
1208
+ * Set when a user exception covers this finding (PF8), and names the SCOPE
1209
+ * that covers it. Absent = live.
1210
+ *
1211
+ * The engine keeps reporting the violation either way — an exception changes
1212
+ * its STATE, it never makes it vanish, so a board can never hide an
1213
+ * arbitration it made (PF8.3). Suppressing the canvas affordance is a
1214
+ * downstream filter ({@link liveViolations}); the panel and the bubble keep
1215
+ * the whole list.
1216
+ */
1217
+ exemption?: ExemptionScope;
1218
+ }
1219
+ /**
1220
+ * How far an exception reaches.
1221
+ *
1222
+ * - `element` — written on the element itself: the rule is disarmed for it and
1223
+ * for nothing else on the board (PF8.2).
1224
+ * - `map` — written on ONE background element, the one named by the finding's
1225
+ * {@link Violation.backgroundId}: the rule is disarmed for the elements
1226
+ * measured against THAT map, and for no other map on the board (PF8.4).
1227
+ *
1228
+ * There is no third scope, and in particular no document-wide one: an exception
1229
+ * is always carried by an element that can be selected, copied and deleted, so
1230
+ * it has an owner, a lifetime and no hidden global state to garbage-collect.
1231
+ * A board with three maps therefore holds three independent arbitrations, and
1232
+ * deleting one map takes exactly its own with it.
1233
+ */
1234
+ export type ExemptionScope = 'element' | 'map';
1235
+ /**
1236
+ * Every element on the surface acting as a framework background for a REAL-TIME
1237
+ * rule.
1238
+ *
1239
+ * Recorded by the manager after each evaluation, and read on the next one — the
1240
+ * one fact about a deleted background that nothing else can reconstruct. See
1241
+ * {@link ValidationManager._backgrounds}.
1242
+ *
1243
+ * ## Why the moment is filtered here too
1244
+ *
1245
+ * This runs on the gesture path, once per evaluation, and it is a FULL surface
1246
+ * walk per rule. `evaluateRules` already refuses to walk an on-demand rule, so
1247
+ * leaving it in here would have handed the drawing budget back exactly what the
1248
+ * second moment took away from it — measured at +58 % on the manager's tick with
1249
+ * the two Wardley check-up rules registered, and invisible to a bench that times
1250
+ * `evaluateRules` alone.
1251
+ *
1252
+ * It is also the right answer and not merely the cheap one: `_backgrounds`
1253
+ * exists to decide whether an incremental REAL-TIME pass must fall back to a
1254
+ * full sweep. An on-demand rule never takes part in that pass, so the frames it
1255
+ * measures against have nothing to invalidate — and a framework whose only rules
1256
+ * are on-demand has no incremental pass to protect in the first place.
1257
+ */
1258
+ export declare function backgroundElementIds(rules: readonly ValidationRule[], elements: readonly GfxPrimitiveElementModel[]): ReadonlySet<string>;
1259
+ /**
1260
+ * The tone families a colour can fall into — the granularity a colour CONVENTION
1261
+ * is actually written at ("the landscape is grey, red is what changes"), and
1262
+ * deliberately not finer. A framework's palette entry and a user's colour are
1263
+ * both reduced to one of these before they are compared.
1264
+ */
1265
+ export type ColourTone = 'grey' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'purple' | 'magenta';
1266
+ /**
1267
+ * Which tone family a colour belongs to, or `undefined` when the engine cannot
1268
+ * honestly say.
1269
+ *
1270
+ * Two readings, in order: the NUMBER when the colour is a hex the process can
1271
+ * actually see, and the NAME when it is a theme token it cannot. Anything else —
1272
+ * `transparent`, a gradient, an `rgb()` triple, a variable with no tone in its
1273
+ * name — is unclassifiable, and unclassifiable means silence: a convention rule
1274
+ * that guessed would indict a user over a colour nobody here can see.
1275
+ */
1276
+ export declare function toneOf(value: string | undefined): ColourTone | undefined;
1277
+ /**
1278
+ * What a caller knows about a change, when it knows anything.
1279
+ *
1280
+ * `dirty` is every element id added, removed or updated since the findings in
1281
+ * `previous` were computed. Handed in only by the manager's debounced path,
1282
+ * where exactly that is known; every other caller — the first evaluation, a
1283
+ * gesture that must land immediately, the bench, a test — evaluates in full.
1284
+ *
1285
+ * Only {@link evaluateNoOverlap} honours it. The element-local families are
1286
+ * already constant per element and would gain nothing but a way to be subtly
1287
+ * wrong.
1288
+ */
1289
+ export interface IncrementalContext {
1290
+ dirty: ReadonlySet<string>;
1291
+ previous: readonly Violation[];
1292
+ }
1293
+ /** The exceptions an element carries, always an array, never a copy to keep. */
1294
+ export declare function elementExceptions(element: GfxPrimitiveElementModel): readonly ValidationException[];
1295
+ /** Whether `element` is excused from `ruleId`. */
1296
+ export declare function hasException(element: GfxPrimitiveElementModel, ruleId: string): boolean;
1297
+ /**
1298
+ * Run every rule over every element. Pure and synchronous — the unit of the
1299
+ * 16 ms budget (PF5.12), and the only thing the bench measures.
1300
+ *
1301
+ * `profiles` is the level of requirement in force (PF9). Omitted, every rule is
1302
+ * judged by its own declared severity, which is exactly what a framework
1303
+ * shipping no profile gets.
1304
+ *
1305
+ * `incremental` is what the caller knows about what CHANGED. Omitted — the
1306
+ * default, and what every test and the bench's full-evaluation case pass — the
1307
+ * whole surface is re-judged from scratch. Handed in, the pair-wise family
1308
+ * re-tests only the couples a change can have affected; the answer is the same,
1309
+ * it is just reached without walking the grid against itself.
1310
+ */
1311
+ export declare function evaluateRules(rules: readonly ValidationRule[], elements: readonly GfxPrimitiveElementModel[], profiles?: readonly ValidationProfile[], incremental?: IncrementalContext): Violation[];
1312
+ /** The registered rules a check-up runs — and nothing else ever evaluates. */
1313
+ export declare function onDemandRules(rules: readonly ValidationRule[]): readonly ValidationRule[];
1314
+ /**
1315
+ * Run the ON-DEMAND rules over the surface (PF5.14). The exact mirror of
1316
+ * {@link evaluateRules}, for the moment the drawing path never touches.
1317
+ *
1318
+ * Synchronous and total: this is what a test, a host and a report call. The
1319
+ * manager drives the same pipeline one rule at a time so a long check-up can
1320
+ * yield the thread — see {@link ValidationManager.runCheckup} — and both reach
1321
+ * the same answer, because both are {@link runRules}.
1322
+ *
1323
+ * The findings are ordinary {@link Violation} objects and go through the same
1324
+ * profile and exception passes as any other. What makes them REMARKS rather
1325
+ * than verdicts is where they land: they never reach `violations$`, so they
1326
+ * never reach the timeline, the bracket or the badge. A framework declares them
1327
+ * `audit` on top of that, which is the severity for "collected, invisible to the
1328
+ * drawing user" — belt and braces, and the braces are structural.
1329
+ */
1330
+ export declare function evaluateCheckup(rules: readonly ValidationRule[], elements: readonly GfxPrimitiveElementModel[], profiles?: readonly ValidationProfile[]): Violation[];
1331
+ /**
1332
+ * One check-up, as the panel reads it: what it found, when it was asked for,
1333
+ * and how far it has got.
1334
+ *
1335
+ * ONE timestamp for the whole run, taken when the user asked — a single click is
1336
+ * a single question, whatever number of rules it happens to walk. The same rule
1337
+ * `setException` follows for an arbitration.
1338
+ *
1339
+ * Session state, never persisted: a document says what it contains, not when
1340
+ * somebody last looked at it.
1341
+ */
1342
+ export interface CheckupRun {
1343
+ /**
1344
+ * The INSTANCE this run is about — the map the user asked about, and the only
1345
+ * one its remarks are allowed to be measured on.
1346
+ *
1347
+ * A check-up walks the whole surface, because that is where the elements are;
1348
+ * a board carries several maps, and without this the panel on one map would
1349
+ * confidently list the components of the one next to it, and a map nobody has
1350
+ * ever checked would show somebody else's timestamp. That is precisely the
1351
+ * "tally over the whole surface" {@link evaluateMajorityFact} refuses to
1352
+ * compute, reintroduced one layer up.
1353
+ *
1354
+ * The filter is applied in {@link ValidationManager.runCheckup}, on
1355
+ * {@link Violation.backgroundId} — recorded by every family that measures
1356
+ * against a frame — so `results` is already about this instance and nothing
1357
+ * downstream has to remember to narrow it.
1358
+ */
1359
+ backgroundId: string;
1360
+ /** Epoch ms, taken at the moment of the gesture. */
1361
+ at: number;
1362
+ /** The remarks so far — complete once {@link done} reaches {@link total}. */
1363
+ results: readonly Violation[];
1364
+ /** Rules evaluated so far. */
1365
+ done: number;
1366
+ /** Rules this run has to walk. `done < total` means it is still going. */
1367
+ total: number;
1368
+ /**
1369
+ * Set when a rule threw and the run stopped early.
1370
+ *
1371
+ * The run is still reported FINISHED (`done === total`), because the one thing
1372
+ * a failure must not do is leave the panel believing a check-up is in flight:
1373
+ * that reads as "Checking…" for ever and disables the only button that could
1374
+ * try again. A visible failure the user can retry beats a silent lock.
1375
+ */
1376
+ error?: true;
1377
+ }
1378
+ /**
1379
+ * How long a check-up may hold the thread before yielding it back.
1380
+ *
1381
+ * One frame, so a check-up that turns out to be expensive costs a dropped frame
1382
+ * at worst instead of a locked tab. A rule is the unit of interruption — the
1383
+ * smallest slice that has a meaning — so a single rule slower than this still
1384
+ * runs to completion and the next one waits for the following task.
1385
+ *
1386
+ * The rules shipped today cost well under a millisecond between them, so the
1387
+ * yield never fires in the delivered configuration — which would leave the
1388
+ * generation counter and the supersession path as code nothing reaches. It is
1389
+ * therefore a DEFAULT rather than a constant: {@link ValidationManager.checkupSliceMs}
1390
+ * is settable, and lowering it makes every rule a slice, which is how a test
1391
+ * exercises the yield and the race with the real rules instead of a stub.
1392
+ */
1393
+ export declare const CHECKUP_SLICE_MS = 16;
1394
+ /**
1395
+ * Grant `ruleId` an exception on `element`, unless it already has one.
1396
+ *
1397
+ * The write goes through the declared `@field()` accessor, so it lands in the
1398
+ * Y.Map, syncs to every peer, joins the undo stack and survives a copy — see the
1399
+ * note on `GfxPrimitiveElementModel.validationExceptions`.
1400
+ */
1401
+ export declare function grantException(element: GfxPrimitiveElementModel, ruleId: string, author?: string, now?: number): void;
1402
+ /** Remove `ruleId`'s exception from `element`, if it has one. */
1403
+ export declare function revokeException(element: GfxPrimitiveElementModel, ruleId: string): void;
1404
+ /** One stored exception, and the element it is actually written on. */
1405
+ export interface AnchoredException {
1406
+ /** The element carrying the exception — a group member, or the element. */
1407
+ element: GfxPrimitiveElementModel;
1408
+ ruleId: string;
1409
+ }
1410
+ /**
1411
+ * The exceptions `element` ANSWERS FOR, i.e. the ones a menu on it should be
1412
+ * able to revoke.
1413
+ *
1414
+ * Same rule the canvas mark follows ({@link anchorOf}): an exception is
1415
+ * answered for by the outermost canvas group containing the element that
1416
+ * carries it, or by that element when it is not grouped. So the entry lives on
1417
+ * the whole Wardley component rather than on the bare node inside it, moves
1418
+ * down to the element the moment the group is dissolved, and appears on a
1419
+ * framework background for the map-wide arbitration it carries.
1420
+ *
1421
+ * Reads STORED exceptions, not current violations: an exception outlives the
1422
+ * violation that prompted it (move the component back onto the map and the
1423
+ * finding goes, the arbitration stays), and it is the arbitration the user is
1424
+ * asking to take back.
1425
+ */
1426
+ export declare function exceptionsAnchoredOn(element: GfxPrimitiveElementModel, surface: SurfaceBlockModel): AnchoredException[];
1427
+ /** One rule's arbitration taken back, as reported to telemetry. */
1428
+ export interface RevokedException {
1429
+ ruleId: string;
1430
+ framework: string;
1431
+ scope: ExemptionScope;
1432
+ /** How many elements the single gesture wrote to. */
1433
+ elementCount: number;
1434
+ }
1435
+ /** A framework registers its rules here; nothing else registers rules. */
1436
+ export declare const ValidationRuleIdentifier: import("../../global/di/types.js").ServiceIdentifier<ValidationRule> & (<U extends ValidationRule = ValidationRule>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
1437
+ /**
1438
+ * Register a framework's rules. Call it from the FLAG-GATED view extension —
1439
+ * validation is tooling, so a disabled framework must contribute nothing.
1440
+ *
1441
+ * ```ts
1442
+ * context.register(ValidationRuleExtension(WARDLEY_RULES));
1443
+ * ```
1444
+ */
1445
+ export declare function ValidationRuleExtension(rules: readonly ValidationRule[]): ExtensionType;
1446
+ /** A framework registers its profiles here; nothing else registers profiles. */
1447
+ export declare const ValidationProfileIdentifier: import("../../global/di/types.js").ServiceIdentifier<ValidationProfile> & (<U extends ValidationProfile = ValidationProfile>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
1448
+ /**
1449
+ * Register a framework's profiles. Call it from the FLAG-GATED view extension,
1450
+ * beside {@link ValidationRuleExtension}: a level of requirement is tooling, so
1451
+ * a disabled framework offers none — and the id already written on a background
1452
+ * simply goes unread until the flag comes back.
1453
+ *
1454
+ * ```ts
1455
+ * context.register(ValidationProfileExtension(WARDLEY_PROFILES));
1456
+ * ```
1457
+ */
1458
+ export declare function ValidationProfileExtension(profiles: readonly ValidationProfile[]): ExtensionType;
1459
+ /**
1460
+ * A framework declaring that a ROLE is one of its root instances — with no rule
1461
+ * to derive it from.
1462
+ *
1463
+ * ## Why this exists
1464
+ *
1465
+ * Until now, "is this element a framework's frame" was read off the registered
1466
+ * rules: a rule names the role of the background it measures against, so the
1467
+ * answer came for free and no framework had to say the same thing twice. It is
1468
+ * still the answer for every framework that ships a rule, and this declaration
1469
+ * changes none of it.
1470
+ *
1471
+ * What it fixes is the framework that ships NONE. Estuarine has nudges and a
1472
+ * quality panel and nothing the tool can compute — a map's constraints are
1473
+ * negotiated, not measured — so under the derived-only gate its background was a
1474
+ * root instance of nothing, its checklist was offered on no element, and the
1475
+ * only way to give it one would have been to invent a rule that never fires.
1476
+ * Data claiming an effect it does not have is the one thing this engine has
1477
+ * refused everywhere else (see the Wardley `blocking-overridable` note); so the
1478
+ * gate gets a second, explicit source instead.
1479
+ *
1480
+ * Registered from the FLAG-GATED view extension, beside the rules and the
1481
+ * nudges: being a root instance is what the tooling is offered ON, so it goes
1482
+ * off with the tooling and the ids already written on the element go unread
1483
+ * until the flag comes back.
1484
+ */
1485
+ export interface ValidationFrameworkDef {
1486
+ /** Owning framework, `estuarine`. */
1487
+ framework: string;
1488
+ /** The role its background carries — the same thing a rule's `backgroundRole` names. */
1489
+ backgroundRole: RoleId;
1490
+ /** The framework's role vocabulary, for the inheritance walk. */
1491
+ roles: RoleDefs;
1492
+ }
1493
+ /** A framework declares its root instances here, when no rule already does. */
1494
+ export declare const ValidationFrameworkIdentifier: import("../../global/di/types.js").ServiceIdentifier<ValidationFrameworkDef> & (<U extends ValidationFrameworkDef = ValidationFrameworkDef>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
1495
+ /**
1496
+ * Register a framework's root-instance declaration.
1497
+ *
1498
+ * ```ts
1499
+ * context.register(
1500
+ * ValidationFrameworkExtension([
1501
+ * { framework: 'estuarine', backgroundRole: 'estuarine:map', roles: ESTUARINE_ROLES },
1502
+ * ])
1503
+ * );
1504
+ * ```
1505
+ *
1506
+ * Keyed by framework AND role, so a framework with two kinds of board declares
1507
+ * both and neither silently replaces the other.
1508
+ */
1509
+ export declare function ValidationFrameworkExtension(defs: readonly ValidationFrameworkDef[]): ExtensionType;
1510
+ /**
1511
+ * The frameworks `role` is a ROOT INSTANCE of — the one test that decides
1512
+ * whether an element is somebody's frame, and the only one.
1513
+ *
1514
+ * TWO sources, and they answer the same question:
1515
+ *
1516
+ * - a registered RULE naming this role as the background it measures against.
1517
+ * A rule that frames against a role is a framework saying "this is my map",
1518
+ * with no second registry to keep in step;
1519
+ * - a registered {@link ValidationFrameworkDef}, for the framework whose whole
1520
+ * contribution is nudges and which therefore has no rule to be derived from.
1521
+ *
1522
+ * Pure, and exported, because every per-instance surface downstream — the
1523
+ * profile picker, the nudge checklist, the check-up — is built on this answer,
1524
+ * and a function taking its inputs is testable without a DI container, a
1525
+ * surface or an editor.
1526
+ *
1527
+ * Empty for a neutral element, and for a background authored before its role
1528
+ * existed: no role, no framework, no tooling.
1529
+ */
1530
+ export declare function frameworksOfRole(role: RoleId | undefined, rules: readonly ValidationRule[], frameworkDefs?: readonly ValidationFrameworkDef[]): ReadonlySet<string>;
1531
+ /**
1532
+ * Element props that can change a verdict, WHATEVER the registered rules are.
1533
+ * Everything else — `opacity` and the other `@local()` fields, colours,
1534
+ * labels — is ignored, so brushing a canvas (`SpotlightManager` writes
1535
+ * `opacity` on every element it dims) neither re-evaluates the surface nor
1536
+ * pushes the pending evaluation further away.
1537
+ *
1538
+ * A framework can add to this list without the engine learning its name: see
1539
+ * {@link verdictPropsOf}.
1540
+ */
1541
+ export declare const VERDICT_PROPS: string[];
1542
+ /**
1543
+ * {@link VERDICT_PROPS} plus what the REGISTERED rules make verdict-bearing.
1544
+ *
1545
+ * A framework background can carry visibility toggles, and one of them may be
1546
+ * the toggle that shows the frontiers a rule measures against — hide the
1547
+ * dashed columns of a Wardley map and the findings about them stop being
1548
+ * findings ({@link backgroundTransitionBands}). Without this the toggle would be
1549
+ * as inert as a colour: the marks would stay on screen until some unrelated
1550
+ * drag happened to wake the engine, which is a board that lies about a document
1551
+ * that has already changed.
1552
+ *
1553
+ * Derived from the DECLARATIONS the engine was handed, never from a name it
1554
+ * knows: `backgroundTransitionVisibleProps` reads the prop each framework
1555
+ * writes beside the line it gates. A framework whose background declares no
1556
+ * toggle contributes nothing and the set is the constant.
1557
+ *
1558
+ * ## `text`, and why it is not in the constant
1559
+ *
1560
+ * `label-presence` is the one family whose verdict turns on an element's words,
1561
+ * and words are what a user changes by TYPING. Watched unconditionally, every
1562
+ * keystroke in every shape on the board would wake the debounced evaluation —
1563
+ * a cost paid by every document, for a question most of them never ask.
1564
+ *
1565
+ * So it is added exactly when a REAL-TIME rule of that family is registered.
1566
+ * The moment filter is deliberate and mirrors {@link backgroundElementIds}: an
1567
+ * on-demand rule is never evaluated on the gesture path, so waking that path for
1568
+ * it would hand back precisely what declaring the second moment bought — and a
1569
+ * framework that wants its naming checked while the user types says so by
1570
+ * declaring the rule real-time, which is the one place that decision belongs.
1571
+ */
1572
+ export declare function verdictPropsOf(rules: readonly ValidationRule[]): ReadonlySet<string>;
1573
+ /**
1574
+ * Whether an `elementUpdated` payload can have changed a verdict.
1575
+ *
1576
+ * It has to read `oldValues` as well as `props`, because a Y.Map **delete**
1577
+ * fills only the former (`syncElementFromY` puts a key in `props` for `add` and
1578
+ * `update` only). `validationExceptions` is the first {@link VERDICT_PROPS}
1579
+ * entry whose normal life includes being removed — `xywh` and `rotate` are
1580
+ * never deleted, `role` is only ever added — so this branch had never been
1581
+ * exercised. Reading `props` alone means an UNDO of an exception, which deletes
1582
+ * the key, wakes nothing: the board keeps showing a finding as excused when the
1583
+ * document no longer says so, and its Revoke button becomes a no-op.
1584
+ *
1585
+ * A payload carrying neither is unreadable, so it counts as "might have": the
1586
+ * cost of a spurious re-evaluation is a debounce tick, the cost of a missed one
1587
+ * is a board that lies.
1588
+ */
1589
+ export declare function touchesVerdict(payload: {
1590
+ props?: Record<string, unknown>;
1591
+ oldValues?: Record<string, unknown>;
1592
+ }, watched?: ReadonlySet<string> | readonly string[]): boolean;
1593
+ /**
1594
+ * Owns the evaluation and the reactive violation list. No-op until a framework
1595
+ * registers a rule.
1596
+ */
1597
+ export declare class ValidationManager extends InteractivityExtension {
1598
+ static key: string;
1599
+ /**
1600
+ * Current violations. The reactive seam a host panel (wave 2) subscribes to;
1601
+ * wave 1 ships only the canvas affordance.
1602
+ */
1603
+ readonly violations$: import("@preact/signals-core").Signal<readonly Violation[]>;
1604
+ /**
1605
+ * Level 3 — what an AI audit reported, and ONLY that (PF14.1).
1606
+ *
1607
+ * A second signal rather than a marked subset of {@link violations$}, and the
1608
+ * reason is the invariant the whole audit seam exists to protect: **the
1609
+ * deterministic engine never depends on the AI**. Nothing in `evaluate()`
1610
+ * reads this signal, writes it or is slowed by it; nothing here is ever
1611
+ * recomputed, carried over by an incremental pass, or judged by a profile.
1612
+ * The 16 ms budget is measured on a function that cannot see this field.
1613
+ *
1614
+ * Merging the two lists and discriminating by severity would have been
1615
+ * cheaper to type and much more expensive to reason about: every consumer of
1616
+ * `violations$` — the overlay, the timeline, the bubble, the exception
1617
+ * toolbar, `userFacingViolations`, the incremental carry-over — would have
1618
+ * had to learn to skip entries it must never touch, and forgetting one of
1619
+ * them in some future slice would put a model's opinion behind a canvas
1620
+ * bracket. Two signals make that a type error instead of a review.
1621
+ *
1622
+ * The findings ARE violation objects (`AuditFinding` is assignable to
1623
+ * {@link Violation}, pinned by a test), so a host panel renders them with the
1624
+ * code it already has. They are session state, never persisted: an audit is
1625
+ * an opinion at a moment, and the document says what it contains, not what a
1626
+ * model thought of it on Tuesday.
1627
+ */
1628
+ readonly auditFindings$: import("@preact/signals-core").Signal<readonly AuditFinding[]>;
1629
+ /**
1630
+ * Publish an audit's results. The ONLY writer of {@link auditFindings$}, and
1631
+ * deliberately dumb: it stores, it does not evaluate, re-judge or merge.
1632
+ *
1633
+ * Replaces rather than appends — a run's findings are a whole answer about
1634
+ * the board as it was, so accumulating two runs would show a user a
1635
+ * contradiction and call it a list.
1636
+ */
1637
+ setAuditFindings(findings: readonly AuditFinding[]): void;
1638
+ /**
1639
+ * Which violations are still FRESH, i.e. still owed the loud bracket.
1640
+ *
1641
+ * It lives here rather than inside the overlay because the affordance has two
1642
+ * halves on two different technologies — a canvas bracket that fades, and a
1643
+ * DOM badge that takes over — and they are mutually exclusive: the badge
1644
+ * appears only once the bracket is fully gone. Two copies of "when did I
1645
+ * first see this" would drift, and the handover would show both at once or
1646
+ * neither.
1647
+ *
1648
+ * Session state, never persisted: a document says which rules it breaks, not
1649
+ * when you happened to look at them.
1650
+ */
1651
+ readonly timeline: ViolationTimeline;
1652
+ /**
1653
+ * The last check-up (PF5.14), or `null` while none has been asked for.
1654
+ *
1655
+ * A SEPARATE signal from {@link violations$}, and that separation is the whole
1656
+ * design: a remark never reaches the timeline, the bracket or the badge,
1657
+ * because it never reaches the list those three read. "Outside the canvas
1658
+ * affordance" is therefore a property of the wiring, not a filter somebody has
1659
+ * to remember to apply.
1660
+ *
1661
+ * Reset to `null` on unmount and never persisted: a document says what it
1662
+ * contains, not when somebody last checked it.
1663
+ */
1664
+ readonly checkup$: import("@preact/signals-core").Signal<CheckupRun | null>;
1665
+ /**
1666
+ * The element whose Map quality panel is OPEN, or `null` — the seam between
1667
+ * the toolbar entry that asks for it (`validation-toolbar.ts`, PF7.11) and the
1668
+ * widget that draws it.
1669
+ *
1670
+ * A signal rather than a DOM call because the two live in different trees: the
1671
+ * entry is a lit template inside `editor-menu-button`'s shadow root, and the
1672
+ * panel is a widget on the root block. Session state, like every other "what
1673
+ * is open" in this file.
1674
+ */
1675
+ readonly mapQualityFor$: import("@preact/signals-core").Signal<string | null>;
1676
+ private _pending;
1677
+ /**
1678
+ * Bumped by every {@link runCheckup}, so a run that yielded the thread can
1679
+ * tell it has been superseded and drop its partial results on the floor
1680
+ * instead of overwriting a newer answer.
1681
+ */
1682
+ private _checkupGeneration;
1683
+ /**
1684
+ * How long {@link runCheckup} may hold the thread between two rules.
1685
+ *
1686
+ * Settable rather than fixed so the interruption and the supersession are
1687
+ * TESTABLE with the rules a framework actually ships: at the shipped default
1688
+ * the Wardley check-up costs half a millisecond and never yields, which would
1689
+ * leave the whole race path unreached by anything. Dropped to zero, every rule
1690
+ * becomes a slice.
1691
+ */
1692
+ checkupSliceMs: number;
1693
+ /**
1694
+ * Element ids added, removed or updated since the last verdict — the dirty
1695
+ * set of PF5.13. Filled by the subscriptions, drained by every evaluation.
1696
+ */
1697
+ private _dirty;
1698
+ /** Whether {@link violations$} holds a verdict a dirty set can build on. */
1699
+ private _evaluated;
1700
+ /**
1701
+ * The ids that were framework BACKGROUNDS at the last evaluation.
1702
+ *
1703
+ * `no-overlap` already sends the surface back through a full sweep when a
1704
+ * frame is touched, and it finds a DELETED one by looking for its id in the
1705
+ * previous findings — the only trace a departed element leaves. That trace
1706
+ * does not exist when the frame's profile put the rule on `'off'`: the
1707
+ * findings measured against it were dropped by `applyProfiles`, so `previous`
1708
+ * is empty, the deletion looks like an ordinary one, and the overlap that
1709
+ * comes back to life under the default profile is never reported. No family
1710
+ * can close that hole — an element that is gone from the surface AND absent
1711
+ * from the findings is invisible to everything except a memory of it.
1712
+ *
1713
+ * So the manager keeps that memory. A dirty id that used to be a background
1714
+ * forces the full pass, whatever the previous findings say or fail to say —
1715
+ * which makes `incremental === full` true by construction rather than by the
1716
+ * luck of no shipped profile using `'off'` yet.
1717
+ */
1718
+ private _backgrounds;
1719
+ private _rules;
1720
+ /** Registered rules, resolved once. Empty when every framework is flagged off. */
1721
+ private get _activeRules();
1722
+ private _verdictProps;
1723
+ /**
1724
+ * The props worth re-evaluating for, given what is registered. Resolved once,
1725
+ * beside the rules it is derived from — see {@link verdictPropsOf}.
1726
+ */
1727
+ private get _watchedProps();
1728
+ private _nudges;
1729
+ /**
1730
+ * Registered nudges, resolved once. Empty when no framework ships one, or
1731
+ * when every framework is flagged off.
1732
+ */
1733
+ private get _activeNudges();
1734
+ private _frameworks;
1735
+ /**
1736
+ * Registered root-instance declarations, resolved once. Empty when every
1737
+ * framework derives its frames from its rules, which is all of them but the
1738
+ * ones that ship no rule at all — see {@link ValidationFrameworkDef}.
1739
+ */
1740
+ private get _activeFrameworks();
1741
+ private _profiles;
1742
+ /**
1743
+ * Registered profiles, resolved once. Empty when no framework ships one, in
1744
+ * which case every rule is judged by its own declared severity.
1745
+ */
1746
+ private get _activeProfiles();
1747
+ private _subscriptions;
1748
+ private _disposeSurfaceEffect;
1749
+ private get _overlay();
1750
+ mounted(): void;
1751
+ unmounted(): void;
1752
+ private _unsubscribe;
1753
+ private _resubscribe;
1754
+ private _schedule;
1755
+ /**
1756
+ * Evaluate now. Exposed so a host (and the bench) can drive it directly.
1757
+ *
1758
+ * `incremental` is the DEBOUNCED path's privilege and nobody else's: it is
1759
+ * the only caller that knows exactly which elements moved since the last
1760
+ * verdict. Everything else — a gesture that must land on the spot, a surface
1761
+ * arriving, a host asking — pays for a full pass, because a full pass is
1762
+ * always right and a wrong dirty set is a board that lies.
1763
+ */
1764
+ evaluate(incremental?: boolean): void;
1765
+ /** The registered rule with this id, if its framework is enabled. */
1766
+ ruleOf(ruleId: string): ValidationRule | undefined;
1767
+ /**
1768
+ * The profiles selectable on `element`, i.e. those of every framework it is a
1769
+ * ROOT INSTANCE of ({@link frameworksOf}).
1770
+ *
1771
+ * Gated for free: flag off, nothing registered, no framework, no profile
1772
+ * offered. A framework that ships profiles and is a root instance of nothing —
1773
+ * neither a rule framing against the role nor a declaration naming it —
1774
+ * offers nothing to choose between, correctly.
1775
+ *
1776
+ * Empty for a neutral element, and for a background authored before its role
1777
+ * existed: no role, no framework, no profile.
1778
+ */
1779
+ profilesFor(element: GfxPrimitiveElementModel): readonly ValidationProfile[];
1780
+ /**
1781
+ * The frameworks `element` is a ROOT INSTANCE of — those with a registered
1782
+ * rule measuring against a background carrying this element's role, and those
1783
+ * that declared the role outright ({@link ValidationFrameworkDef}).
1784
+ *
1785
+ * The one test that decides whether an element is a framework's frame, and the
1786
+ * only one: every per-instance surface (the profile picker, the nudge
1787
+ * checklist, the check-up) agrees about what a root instance is without any of
1788
+ * them saying so twice. Both sources are registered from the flag-gated view
1789
+ * extension, so it stays gated for free — flag off, nothing registered, no
1790
+ * framework.
1791
+ *
1792
+ * Empty for a neutral element, and for a background authored before its role
1793
+ * existed.
1794
+ */
1795
+ frameworksOf(element: GfxPrimitiveElementModel): ReadonlySet<string>;
1796
+ /**
1797
+ * The nudges offered on `element` (PF7.10), in declared order.
1798
+ *
1799
+ * Same derivation as {@link profilesFor} and gated the same way: a framework
1800
+ * that registers no nudge — or whose flag is off — offers none, and the ids
1801
+ * already ticked on the element stay written, unread, until it comes back.
1802
+ */
1803
+ nudgesFor(element: GfxPrimitiveElementModel): readonly QualityNudge[];
1804
+ /** The on-demand rules a check-up on `element` would walk (PF5.14). */
1805
+ checkupRulesFor(element: GfxPrimitiveElementModel): readonly ValidationRule[];
1806
+ /**
1807
+ * Whether `element` has a Map quality panel to open at all: a framework of
1808
+ * its own declaring a NUDGE.
1809
+ *
1810
+ * The panel is the checklist and nothing else since the PO recette of
1811
+ * 02/08/2026, so this asks for the checklist and nothing else — a framework
1812
+ * that declared only on-demand rules would otherwise be offered a panel with
1813
+ * nothing in it. {@link checkupRulesFor} and {@link runCheckup} are unchanged
1814
+ * and unrelated: a host can still ask for a check-up, it simply is not what
1815
+ * this panel is.
1816
+ *
1817
+ * Generic by construction (PF7.11) — nothing here names a framework. A second
1818
+ * framework shipping nudges gets the entry and the panel with no code written
1819
+ * anywhere.
1820
+ */
1821
+ hasMapQuality(element: GfxPrimitiveElementModel): boolean;
1822
+ /**
1823
+ * Open the Map quality panel on `element`; the widget draws it.
1824
+ *
1825
+ * Opening on a DIFFERENT instance forgets the last check-up. The panel already
1826
+ * refuses to render a run belonging to another map ({@link CheckupRun.backgroundId}),
1827
+ * so this is not what makes the display correct — it is what stops a result
1828
+ * measured on a map the user has moved on from (or deleted) sitting in memory
1829
+ * waiting to be shown again. Reopening on the SAME map keeps its stamp, which
1830
+ * is the one case where "last check-up: 01:51" is worth reading.
1831
+ */
1832
+ openMapQuality(element: GfxPrimitiveElementModel): void;
1833
+ closeMapQuality(): void;
1834
+ /**
1835
+ * Drop the current check-up when it is about `backgroundId` — or, with
1836
+ * `unless`, when it is about anything else.
1837
+ *
1838
+ * The two callers are the two ways a run stops being about something the user
1839
+ * can look at: the instance it measured was deleted, and the panel moved to a
1840
+ * different instance.
1841
+ */
1842
+ private _forgetCheckupOf;
1843
+ /**
1844
+ * Run the check-up on `element` (PF5.14).
1845
+ *
1846
+ * ## It is about ONE instance
1847
+ *
1848
+ * The walk covers the whole surface — that is where the elements are — but the
1849
+ * ANSWER is narrowed to the map that was asked about, on
1850
+ * {@link Violation.backgroundId}, which every family measuring against a frame
1851
+ * already records. A board carrying two Wardley maps holds two independent
1852
+ * answers, and handing the panel a tally over both would be exactly the
1853
+ * whole-surface count {@link evaluateMajorityFact} goes out of its way not to
1854
+ * compute. Narrowed HERE and not at the rendering: a run that reaches a host,
1855
+ * a report or the agent has to already be about one map.
1856
+ *
1857
+ * ## Why this is async, for two rules that take a microsecond
1858
+ *
1859
+ * Because the moment exists precisely so that a framework may ship a control
1860
+ * that does NOT fit a frame. A check-up walks the surface with no dirty set
1861
+ * and no budget over its head, and the honest way to offer that is to be
1862
+ * interruptible: the driver evaluates ONE RULE at a time — the smallest slice
1863
+ * that has a meaning — and yields the thread whenever the slice has held it
1864
+ * for {@link checkupSliceMs}. The panel sees `done` climb towards `total`, so
1865
+ * progress is the same value the results arrive in and there is no second
1866
+ * signal to keep in step.
1867
+ *
1868
+ * A run started while another is still yielding SUPERSEDES it: the older one
1869
+ * notices its generation is stale on its next slice and drops what it had.
1870
+ * Clicking twice therefore gives the second answer, never a race between two.
1871
+ *
1872
+ * ## A rule that throws
1873
+ *
1874
+ * ...ends the run, visibly. The failure must not leave the panel believing a
1875
+ * check-up is in flight — that reads as "Checking…" for ever and disables the
1876
+ * one button that could try again, on every map, until the editor is
1877
+ * remounted. So the run is finished with {@link CheckupRun.error} and whatever
1878
+ * it had managed to collect.
1879
+ *
1880
+ * @returns the finished run, or `null` if it was superseded or there was
1881
+ * nothing to run.
1882
+ */
1883
+ runCheckup(element: GfxPrimitiveElementModel): Promise<CheckupRun | null>;
1884
+ /**
1885
+ * The profile `element` is actually checked against — the one it names, or
1886
+ * its framework's default. `undefined` when it is not a root instance of any
1887
+ * enabled framework, or when its framework ships no profile.
1888
+ */
1889
+ profileOf(element: GfxPrimitiveElementModel): ValidationProfile | undefined;
1890
+ /**
1891
+ * Put `element` on `profileId`, and re-judge the board on the spot.
1892
+ *
1893
+ * Choosing the DEFAULT clears the key rather than writing it, so a background
1894
+ * that never left the default stays byte-identical to one created before
1895
+ * profiles existed — and a user who tries strict and comes back leaves no
1896
+ * trace. Everything else is one flat string in the same `@field()` the role
1897
+ * and the exceptions live in: it syncs, it undoes, it survives a copy and an
1898
+ * export, with no block schema change.
1899
+ *
1900
+ * Exceptions are deliberately left alone. A level of requirement is not an
1901
+ * amnesty: raising it must not resurrect decisions the user made, and
1902
+ * lowering it must not quietly delete them (PF9.3).
1903
+ *
1904
+ * @returns whether the document actually changed.
1905
+ */
1906
+ setProfile(element: GfxPrimitiveElementModel, profileId: string): boolean;
1907
+ /**
1908
+ * Which elements an exception of the given scope is written on.
1909
+ *
1910
+ * `element` — the elements the rule actually indicts, which is what makes the
1911
+ * exception local (PF8.2): excusing one component says nothing about the next.
1912
+ *
1913
+ * `map` — the background element these findings were MEASURED AGAINST, and
1914
+ * only that one. It comes from {@link Violation.backgroundId}, recorded by the
1915
+ * rule family when it picked the frame, so a board carrying three maps holds
1916
+ * three independent arbitrations and a gesture made on one writes on one.
1917
+ * That choice is what lets a map-wide arbitration exist with NO block schema
1918
+ * change and no hidden per-document store: it is one more value in the same
1919
+ * `@field()`, on an element that is selected, copied, exported and deleted
1920
+ * like any other. A family that measures against no background records no
1921
+ * `backgroundId`, has no map to hang an exception on, and offers no map scope.
1922
+ */
1923
+ private _targetsOf;
1924
+ /**
1925
+ * Grant or revoke `ruleId`'s exception at `scope`, over the elements the given
1926
+ * violations indict.
1927
+ *
1928
+ * Takes the whole set rather than one violation on purpose: a Wardley
1929
+ * component is a GROUP, so one bubble line can stand for several indicted
1930
+ * members, and one click has to settle all of them.
1931
+ *
1932
+ * Re-evaluates on the spot instead of waiting for the 120 ms debounce the
1933
+ * field write would trigger anyway — the gesture must apply immediately
1934
+ * (PF8.1).
1935
+ *
1936
+ * @returns the elements actually written to, so the caller can tell a real
1937
+ * arbitration from a no-op and only report the former.
1938
+ */
1939
+ setException(violations: readonly Violation[], scope: ExemptionScope, granted: boolean, author?: string): GfxPrimitiveElementModel[];
1940
+ /**
1941
+ * The exceptions on `element` that can still be taken back — those it answers
1942
+ * for ({@link exceptionsAnchoredOn}) whose rule is actually REGISTERED.
1943
+ *
1944
+ * The rule filter is what makes the menu entry disappear with the framework:
1945
+ * flag off, no rule reaches the container, so there is nothing to arbitrate
1946
+ * on and nothing to offer. The exceptions themselves are untouched — they are
1947
+ * document data and outlive the tooling (PF8.6).
1948
+ */
1949
+ revocableExceptionsOn(element: GfxPrimitiveElementModel): AnchoredException[];
1950
+ /**
1951
+ * Take back every exception `element` answers for, in one gesture.
1952
+ *
1953
+ * @returns one entry per (rule, scope) actually written, so the caller can
1954
+ * report the arbitration and tell a real one from a no-op.
1955
+ */
1956
+ revokeExceptionsOn(element: GfxPrimitiveElementModel): RevokedException[];
1957
+ }
1958
+ /**
1959
+ * What SHAPE the anchor is, and therefore where its persistent badge belongs.
1960
+ *
1961
+ * The same split {@link RoleKind} makes for MEASURING, made here for MARKING,
1962
+ * and for the same reason: the bounding box of a diagonal link covers half the
1963
+ * map, so its top-right corner is a point on the white paper with nothing under
1964
+ * it. The PO's capture of 02/08 is exactly that — an amber dot floating a
1965
+ * hundred units away from the trait it accuses.
1966
+ *
1967
+ * - `node` — marked on the top-right corner of its bounds, as before.
1968
+ * - `edge` — marked on the MIDDLE of the link: the midpoint of the drawn path
1969
+ * when the element exposes one, and otherwise the intersection of the
1970
+ * bounding rectangle's diagonals, which is its centre.
1971
+ */
1972
+ export type ViolationAnchorKind = 'node' | 'edge';
1973
+ /**
1974
+ * One anchor and everything reported against it: where to draw, and what the
1975
+ * detail bubble has to list when the badge on it is clicked.
1976
+ */
1977
+ export interface ViolationAnchor {
1978
+ /** The element the mark is drawn on — the outermost group, or the element. */
1979
+ id: string;
1980
+ bound: Bound;
1981
+ /** What the mark is pinned to. See {@link ViolationAnchorKind}. */
1982
+ kind: ViolationAnchorKind;
1983
+ /**
1984
+ * Where the persistent badge is pinned, in MODEL space — the one point both
1985
+ * the badge and the bubble it opens are laid out from.
1986
+ *
1987
+ * Computed here rather than by the widget so it is one pure function of the
1988
+ * document, testable with asserted coordinates and identical for every
1989
+ * surface that ever draws a mark.
1990
+ */
1991
+ markAt: [number, number];
1992
+ violations: Violation[];
1993
+ }
1994
+ /**
1995
+ * Group violations by the anchor their mark is drawn on — one entry per
1996
+ * anchor, so several violating members of the same group share a single
1997
+ * bracket, a single badge and a single bubble.
1998
+ *
1999
+ * Pure and stateless, and called at paint time by both halves of the
2000
+ * affordance, so the mark follows a group that moves and falls back onto the
2001
+ * element the moment the group is dissolved, with nothing to invalidate.
2002
+ *
2003
+ * @param vocabularies the registered role vocabularies, for the SEMANTIC half
2004
+ * of "is this an edge" ({@link anchorKindOf}). Optional: a caller that only
2005
+ * reads `bound` — the canvas overlay draws the same bracket either way — needs
2006
+ * none, and still gets the geometric answer.
2007
+ */
2008
+ export declare function resolveViolationAnchors(violations: readonly Violation[], surface: SurfaceBlockModel, vocabularies?: readonly RoleDefs[]): ViolationAnchor[];
2009
+ /**
2010
+ * Violations the drawing user is meant to SEE. `audit` is collected for
2011
+ * reporting and stays invisible on the canvas — that is what the severity
2012
+ * means (see {@link ViolationSeverity}), and the UI is the only place that can
2013
+ * honour it: the engine reports everything, unfiltered, to the host panel.
2014
+ */
2015
+ export declare function userFacingViolations(violations: readonly Violation[]): Violation[];
2016
+ /**
2017
+ * Violations still asking for something, i.e. not covered by an exception.
2018
+ *
2019
+ * This is the whole of PF8's canvas behaviour: an exempted finding is dropped
2020
+ * from the timeline, so it never flashes, and from the overlay, so it carries no
2021
+ * bracket. It keeps its badge and its line in the bubble, where it reads as
2022
+ * "exception" and can be revoked — the state changed, the finding did not
2023
+ * disappear.
2024
+ */
2025
+ export declare function liveViolations(violations: readonly Violation[]): Violation[];
2026
+ /**
2027
+ * One violation per RULE, first occurrence wins.
2028
+ *
2029
+ * What a detail bubble renders is rule-level — a label, a severity, a hint —
2030
+ * so two components of the same group both drawn off the map, which are two
2031
+ * violations, would produce the same sentence twice. The engine is right to
2032
+ * report both (it names the elements); a list that repeats itself is just
2033
+ * noise. Which member moved is on the canvas, not in a list.
2034
+ */
2035
+ export declare function distinctByRule(violations: readonly Violation[]): Violation[];
2036
+ /**
2037
+ * How loudly an ANCHOR is drawn: the loudest of the violations sharing it, so
2038
+ * a fresh finding is not muted by an older one on the same group.
2039
+ *
2040
+ * The single arbiter between the two markers. `> 0` means the bracket still has
2041
+ * the anchor; exactly `0` means it is done and the badge takes over. Both
2042
+ * halves call this, on the same timeline, so they can never both claim it.
2043
+ */
2044
+ export declare function anchorEmphasis(anchor: ViolationAnchor, timeline: ViolationTimeline, now: number): number;
2045
+ /**
2046
+ * Gap between the anchor's bounds and the mark, in MODEL units. Exported
2047
+ * because the badge sits ON the bracket's top-right corner and has to use the
2048
+ * same gap to land there.
2049
+ */
2050
+ export declare const VIOLATION_MARK_PADDING = 6;
2051
+ /** Diameter of the persistent badge, in MODEL units. */
2052
+ export declare const VIOLATION_BADGE_SIZE = 16;
2053
+ /** The one amber the affordance is drawn in, canvas and DOM alike. */
2054
+ export declare const VIOLATION_MARK_COLOR = "#f5a623";
2055
+ /**
2056
+ * The EPHEMERAL half of the PF7 affordance: amber corner brackets that flash on
2057
+ * the anchor of a violation the moment it appears, hold for a few seconds, then
2058
+ * fade out (see {@link ViolationTimeline}). What stays behind afterwards is the
2059
+ * badge — `affine-violation-detail-widget`, a DOM sibling of this overlay.
2060
+ *
2061
+ * The handover is strict: an anchor whose emphasis has reached zero is skipped
2062
+ * here and picked up by the badge, so the two markers are never on screen at
2063
+ * the same time. {@link anchorEmphasis} is the single arbiter, read from the
2064
+ * one timeline the manager owns.
2065
+ *
2066
+ * An overlay rather than a renderer change: it touches no element model, writes
2067
+ * nothing to the document, creates no undo entry, and disappears with the rule
2068
+ * that produced it. The fade is session state too — nothing about "when did I
2069
+ * first see this" ever reaches the document.
2070
+ *
2071
+ * The mark is anchored on the outermost enclosing canvas group rather than on
2072
+ * the bare element — see {@link resolveMarkAnchors}. Evaluation is untouched by
2073
+ * this: it stays on the element carrying the role, because its position is what
2074
+ * the rule is about.
2075
+ */
2076
+ export declare class ValidationOverlay extends Overlay {
2077
+ static overlayName: string;
2078
+ /**
2079
+ * The violations themselves — NOT their bounds, and not their groups either.
2080
+ * Both are resolved at paint time so the mark tracks what it accuses:
2081
+ * evaluation is debounced, the renderer is not, so a frozen snapshot would
2082
+ * leave the bracket behind at the drag's starting point until 120 ms after
2083
+ * the user let go — and a dissolved group would keep framing nothing.
2084
+ */
2085
+ private _violations;
2086
+ /**
2087
+ * Handed in with the violations by {@link ValidationManager}, which owns it —
2088
+ * the DOM badge reads the same instance, and the two markers must never
2089
+ * disagree about whether the bracket is done.
2090
+ */
2091
+ private _timeline;
2092
+ /** Armed only while something is still fading. */
2093
+ private _frame;
2094
+ /**
2095
+ * Whether the renderer this overlay paints into is gone.
2096
+ *
2097
+ * It matters because the two ends of the affordance are on different
2098
+ * lifecycles: the overlay dies with the surface COMPONENT (the renderer
2099
+ * disposes it), while {@link ValidationManager} lives on the gfx scope and
2100
+ * keeps its subscriptions on the surface MODEL, which outlives the component.
2101
+ * So an evaluation can perfectly well land here after teardown — switch to
2102
+ * page mode, edit the doc — and without this flag it would arm an animation
2103
+ * loop repainting a dead renderer sixty times a second for three seconds.
2104
+ *
2105
+ * Not permanent: the overlay is a DI singleton and is handed a new renderer
2106
+ * if the surface comes back.
2107
+ */
2108
+ private _detached;
2109
+ private readonly _onFrame;
2110
+ /**
2111
+ * Repaint, and keep repainting for as long as a mark is inside its window.
2112
+ *
2113
+ * This is the only clock the affordance runs, and it stops on its own: a
2114
+ * board with no violation, or whose violations have all settled, requests no
2115
+ * animation frame at all.
2116
+ */
2117
+ private _schedule;
2118
+ private _cancelFrame;
2119
+ private _forget;
2120
+ /**
2121
+ * @param violations already filtered to what the user is meant to see.
2122
+ * @param timeline the manager's, already synced against these violations.
2123
+ */
2124
+ setViolations(violations: readonly Violation[], timeline: ViolationTimeline): void;
2125
+ setRenderer(renderer: CanvasRenderer | null): void;
2126
+ clear(): void;
2127
+ dispose(): void;
2128
+ render(ctx: CanvasRenderingContext2D, _rc: RoughCanvas): void;
2129
+ }