@beyondwork/docx-react-component 1.0.67 → 1.0.70

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 (384) hide show
  1. package/README.md +75 -932
  2. package/package.json +26 -27
  3. package/src/api/anchor-conversion.ts +43 -0
  4. package/src/api/editor-state-types.ts +2 -1
  5. package/src/api/public-types.ts +504 -101
  6. package/src/api/session-state.ts +4 -0
  7. package/src/api/v3/README.md +91 -0
  8. package/src/api/v3/_create.ts +146 -0
  9. package/src/api/v3/_layer-metadata.ts +362 -0
  10. package/src/api/v3/_mocks.ts +84 -0
  11. package/src/api/v3/_runtime-handle.ts +162 -0
  12. package/src/api/v3/_ux-response.ts +73 -0
  13. package/src/api/v3/ai/_metadata-audit.ts +225 -0
  14. package/src/api/v3/ai/attach.ts +235 -0
  15. package/src/api/v3/ai/bundle.ts +132 -0
  16. package/src/api/v3/ai/explain.ts +144 -0
  17. package/src/api/v3/ai/export.ts +54 -0
  18. package/src/api/v3/ai/inspect.ts +118 -0
  19. package/src/api/v3/ai/policy.ts +77 -0
  20. package/src/api/v3/ai/replacement.ts +341 -0
  21. package/src/api/v3/ai/resolve.ts +133 -0
  22. package/src/api/v3/index.ts +79 -0
  23. package/src/api/v3/runtime/chart.ts +310 -0
  24. package/src/api/v3/runtime/clipboard.ts +81 -0
  25. package/src/api/v3/runtime/collab.ts +331 -0
  26. package/src/api/v3/runtime/content.ts +236 -0
  27. package/src/api/v3/runtime/document.ts +282 -0
  28. package/src/api/v3/runtime/formatting.ts +186 -0
  29. package/src/api/v3/runtime/geometry.ts +349 -0
  30. package/src/api/v3/runtime/layout.ts +108 -0
  31. package/src/api/v3/runtime/review.ts +129 -0
  32. package/src/api/v3/runtime/search.ts +74 -0
  33. package/src/api/v3/runtime/table.ts +63 -0
  34. package/src/api/v3/runtime/workflow.ts +434 -0
  35. package/src/api/v3/ui/_context.ts +86 -0
  36. package/src/api/v3/ui/_create.ts +65 -0
  37. package/src/api/v3/ui/_types.ts +520 -0
  38. package/src/api/v3/ui/chrome-composition.ts +342 -0
  39. package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
  40. package/src/api/v3/ui/chrome.ts +476 -0
  41. package/src/api/v3/ui/debug.ts +124 -0
  42. package/src/api/v3/ui/index.ts +64 -0
  43. package/src/api/v3/ui/overlays-visibility.ts +170 -0
  44. package/src/api/v3/ui/overlays.ts +427 -0
  45. package/src/api/v3/ui/scope.ts +71 -0
  46. package/src/api/v3/ui/session.ts +100 -0
  47. package/src/api/v3/ui/surface.ts +170 -0
  48. package/src/api/v3/ui/viewport.ts +303 -0
  49. package/src/core/commands/index.ts +28 -6
  50. package/src/core/commands/list-commands.ts +3 -2
  51. package/src/core/commands/section-layout-commands.ts +9 -8
  52. package/src/core/schema/text-schema.ts +16 -0
  53. package/src/core/selection/mapping.ts +33 -72
  54. package/src/core/state/editor-state.ts +96 -189
  55. package/src/index.ts +23 -4
  56. package/src/io/chart-preview-resolver.ts +1 -1
  57. package/src/io/docx-session.ts +36 -4797
  58. package/src/io/export/build-app-properties-xml.ts +1 -1
  59. package/src/io/export/serialize-comments.ts +1 -1
  60. package/src/io/export/serialize-headers-footers.ts +6 -1
  61. package/src/io/export/serialize-main-document.ts +45 -0
  62. package/src/io/export/serialize-run-formatting.ts +17 -2
  63. package/src/io/export/twip.ts +1 -1
  64. package/src/io/normalize/normalize-text.ts +27 -20
  65. package/src/io/ooxml/chart/parse-series.ts +1 -1
  66. package/src/io/ooxml/chart/resolve-color.ts +2 -2
  67. package/src/io/ooxml/chart/types.ts +1 -1
  68. package/src/io/ooxml/classify-embedding.ts +83 -33
  69. package/src/io/ooxml/parse-fill.ts +1 -1
  70. package/src/io/ooxml/parse-main-document.ts +71 -1
  71. package/src/io/ooxml/parse-object.ts +14 -10
  72. package/src/io/ooxml/parse-run-formatting.ts +47 -1
  73. package/src/io/ooxml/property-grab-bag.ts +2 -2
  74. package/src/io/ooxml/units.ts +11 -0
  75. package/src/io/ooxml/workflow-payload.ts +282 -7
  76. package/src/model/anchor.ts +85 -0
  77. package/src/model/canonical-document.ts +351 -15
  78. package/src/model/chart-types.ts +1 -1
  79. package/src/model/layout/index.ts +83 -0
  80. package/src/model/layout/page-graph-types.ts +181 -0
  81. package/src/model/layout/page-layout-snapshot.ts +105 -0
  82. package/src/model/layout/resolved-layout-types.ts +47 -0
  83. package/src/model/layout/runtime-page-graph-types.ts +102 -0
  84. package/src/model/paragraph-scope-ids.ts +72 -0
  85. package/src/model/review/comment-types.ts +112 -0
  86. package/src/model/review/index.ts +2 -0
  87. package/src/model/review/revision-types.ts +215 -0
  88. package/src/model/snapshot.ts +32 -0
  89. package/src/review/store/comment-store.ts +21 -47
  90. package/src/review/store/revision-types.ts +40 -198
  91. package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
  92. package/src/runtime/collab/runtime-collab-sync.ts +13 -3
  93. package/src/runtime/collab-session.ts +1 -1
  94. package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
  95. package/src/runtime/debug/event-ring-buffer.ts +64 -0
  96. package/src/runtime/debug/probability-sampler.ts +18 -0
  97. package/src/runtime/debug/runtime-debug-facet.ts +67 -0
  98. package/src/runtime/debug/stage-tokens.ts +31 -0
  99. package/src/runtime/debug/telemetry-bus.ts +271 -0
  100. package/src/runtime/debug/types.ts +275 -0
  101. package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
  102. package/src/runtime/document-layout.ts +8 -6
  103. package/src/runtime/document-runtime.ts +843 -1141
  104. package/src/runtime/document-search.ts +1 -1
  105. package/src/runtime/edit-ops/index.ts +1 -1
  106. package/src/runtime/external-send-runtime.ts +1 -1
  107. package/src/runtime/formatting/document-lookup.ts +235 -0
  108. package/src/runtime/formatting/field/registry.ts +41 -0
  109. package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
  110. package/src/runtime/formatting/font-resolution.ts +83 -0
  111. package/src/runtime/formatting/formatting-context.ts +903 -0
  112. package/src/runtime/formatting/formatting-types.ts +157 -0
  113. package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
  114. package/src/runtime/formatting/index.ts +125 -0
  115. package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
  116. package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
  117. package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
  118. package/src/runtime/formatting/projector.ts +75 -0
  119. package/src/runtime/formatting/resolve-effective.ts +407 -0
  120. package/src/runtime/formatting/revision-display.ts +105 -0
  121. package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
  122. package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
  123. package/src/runtime/formatting/telemetry-bridge.ts +106 -0
  124. package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
  125. package/src/runtime/geometry/caret-geometry.ts +164 -0
  126. package/src/runtime/geometry/geometry-facet.ts +364 -0
  127. package/src/runtime/geometry/geometry-types.ts +256 -0
  128. package/src/runtime/geometry/hit-test.ts +125 -0
  129. package/src/runtime/geometry/index.ts +71 -0
  130. package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
  131. package/src/runtime/geometry/invalidation.ts +35 -0
  132. package/src/runtime/geometry/object-handles.ts +77 -0
  133. package/src/runtime/geometry/overlay-rects.ts +85 -0
  134. package/src/runtime/geometry/project-anchors.ts +100 -0
  135. package/src/runtime/geometry/project-fragments.ts +216 -0
  136. package/src/runtime/geometry/projector.ts +129 -0
  137. package/src/runtime/geometry/replacement-envelope.ts +130 -0
  138. package/src/runtime/geometry/viewport.ts +218 -0
  139. package/src/runtime/layout/compat-input-ledger.ts +211 -0
  140. package/src/runtime/layout/index.ts +6 -1
  141. package/src/runtime/layout/inert-layout-facet.ts +12 -7
  142. package/src/runtime/layout/layout-engine-instance.ts +189 -11
  143. package/src/runtime/layout/layout-engine-version.ts +450 -1
  144. package/src/runtime/layout/layout-facet-types.ts +60 -0
  145. package/src/runtime/layout/layout-measurement-provider.ts +13 -0
  146. package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
  147. package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
  148. package/src/runtime/layout/page-graph.ts +62 -209
  149. package/src/runtime/layout/page-story-resolver.ts +7 -12
  150. package/src/runtime/layout/paginated-layout-engine.ts +186 -11
  151. package/src/runtime/layout/project-block-fragments.ts +11 -0
  152. package/src/runtime/layout/projector.ts +90 -0
  153. package/src/runtime/layout/public-facet.ts +187 -442
  154. package/src/runtime/layout/resolved-formatting-state.ts +158 -26
  155. package/src/runtime/layout/table-render-plan.ts +1 -1
  156. package/src/runtime/prerender/cache-envelope.ts +6 -1
  157. package/src/runtime/prerender/prerender-document.ts +18 -23
  158. package/src/runtime/render/decoration-resolver.ts +1 -1
  159. package/src/runtime/render/render-frame-types.ts +20 -0
  160. package/src/runtime/render/render-kernel.ts +94 -25
  161. package/src/runtime/scopes/_formatting-seam.ts +262 -0
  162. package/src/runtime/scopes/_scope-dependencies.ts +49 -0
  163. package/src/runtime/scopes/action-validation.ts +356 -0
  164. package/src/runtime/scopes/attach-explanation.ts +102 -0
  165. package/src/runtime/scopes/audit-bundle.ts +71 -0
  166. package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
  167. package/src/runtime/scopes/compile-scope.ts +262 -0
  168. package/src/runtime/scopes/compiler-service.ts +431 -0
  169. package/src/runtime/scopes/create-issue.ts +107 -0
  170. package/src/runtime/scopes/enumerate-scopes.ts +543 -0
  171. package/src/runtime/scopes/evidence.ts +233 -0
  172. package/src/runtime/scopes/index.ts +150 -0
  173. package/src/runtime/scopes/position-map.ts +214 -0
  174. package/src/runtime/scopes/preservation-boundary.ts +91 -0
  175. package/src/runtime/scopes/projector.ts +49 -0
  176. package/src/runtime/scopes/replaceability.ts +87 -0
  177. package/src/runtime/scopes/replacement/apply.ts +228 -0
  178. package/src/runtime/scopes/replacement/compile.ts +59 -0
  179. package/src/runtime/scopes/replacement/propose.ts +42 -0
  180. package/src/runtime/scopes/resolve-reference.ts +347 -0
  181. package/src/runtime/scopes/review-bundle.ts +141 -0
  182. package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
  183. package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
  184. package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
  185. package/src/runtime/scopes/scope-kinds/field.ts +65 -0
  186. package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
  187. package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
  188. package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
  189. package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
  190. package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
  191. package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
  192. package/src/runtime/scopes/scope-kinds/table.ts +55 -0
  193. package/src/runtime/scopes/scope-range.ts +208 -0
  194. package/src/runtime/scopes/semantic-scope-types.ts +454 -0
  195. package/src/runtime/scopes/workflow-overlap.ts +92 -0
  196. package/src/runtime/selection/index.ts +1 -1
  197. package/src/runtime/structure-ops/fragment-insert.ts +1 -1
  198. package/src/runtime/structure-ops/index.ts +1 -1
  199. package/src/runtime/surface-projection.ts +232 -262
  200. package/src/runtime/units.ts +4 -2
  201. package/src/runtime/workflow/coordinator.ts +1348 -0
  202. package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
  203. package/src/runtime/workflow/index.ts +25 -0
  204. package/src/runtime/workflow/markup-mode-policy.ts +98 -0
  205. package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
  206. package/src/runtime/workflow/metadata-persistence.ts +306 -0
  207. package/src/runtime/workflow/metadata-writer.ts +123 -0
  208. package/src/runtime/workflow/overlay-store.ts +690 -0
  209. package/src/runtime/workflow/projector.ts +127 -0
  210. package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
  211. package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
  212. package/src/runtime/workflow/rail/types.ts +198 -0
  213. package/src/runtime/workflow/scope-rail-composer.ts +39 -0
  214. package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
  215. package/src/runtime/workflow/scope-writer.ts +188 -0
  216. package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
  217. package/src/runtime/workflow/visibility-policy.ts +129 -0
  218. package/src/session/_sync-legacy.ts +66 -0
  219. package/src/session/export/embedded-reconstitute.ts +104 -0
  220. package/src/session/export/export-diagnostics.ts +85 -0
  221. package/src/session/export/export-validation.ts +110 -0
  222. package/src/session/export/index.ts +34 -0
  223. package/src/session/export/preservation-reattach.ts +30 -0
  224. package/src/session/export/serialize-dispatch.ts +165 -0
  225. package/src/session/export/stateful-export-pipeline.ts +432 -0
  226. package/src/session/export/stateful-export.ts +684 -0
  227. package/src/session/import/canonical-assembly.ts +227 -0
  228. package/src/session/import/diagnostics-session.ts +54 -0
  229. package/src/session/import/embedded-discovery.ts +225 -0
  230. package/src/session/import/embedded-offload.ts +337 -0
  231. package/src/session/import/import-diagnostics.ts +69 -0
  232. package/src/session/import/loader-types.ts +313 -0
  233. package/src/session/import/loader.ts +1834 -0
  234. package/src/session/import/normalize.ts +195 -0
  235. package/src/session/import/package-parts.ts +217 -0
  236. package/src/session/import/package-read.ts +195 -0
  237. package/src/session/import/parse-orchestration.ts +105 -0
  238. package/src/session/import/part-constants.ts +70 -0
  239. package/src/session/import/part-discovery.ts +94 -0
  240. package/src/session/import/preservation-index.ts +46 -0
  241. package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
  242. package/src/session/import/review-import.ts +508 -0
  243. package/src/session/import/styles-consolidation.ts +281 -0
  244. package/src/session/import/workflow-scope-import.ts +256 -0
  245. package/src/session/index.ts +37 -0
  246. package/src/session/session-state.ts +69 -0
  247. package/src/session/session.ts +532 -0
  248. package/src/session/shared/protection.ts +228 -0
  249. package/src/session/shared/session-utils.ts +82 -0
  250. package/src/session/types.ts +499 -0
  251. package/src/shell/chart-snapshots.ts +96 -0
  252. package/src/shell/media-previews.ts +85 -0
  253. package/src/shell/overlay-anchor-bridge.ts +53 -0
  254. package/src/shell/paste-adapter.ts +23 -0
  255. package/src/shell/ref-commands.ts +1697 -0
  256. package/src/shell/ref-utilities.ts +48 -0
  257. package/src/shell/search.ts +51 -0
  258. package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
  259. package/src/shell/ui-subscriber-channels.ts +81 -0
  260. package/src/shell/use-collab-sync.ts +116 -0
  261. package/src/ui/WordReviewEditor.tsx +496 -2051
  262. package/src/ui/editor-shell-view.tsx +30 -1
  263. package/src/ui/editor-surface-controller.tsx +49 -1
  264. package/src/ui/headless/revision-decoration-model.ts +83 -0
  265. package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
  266. package/src/ui/headless/scoped-chrome-policy.ts +2 -2
  267. package/src/ui/headless/selection-tool-context.ts +1 -1
  268. package/src/ui/headless/selection-tool-resolver.ts +1 -1
  269. package/src/ui/runtime-shortcut-dispatch.ts +46 -1
  270. package/src/ui/ui-controller-factory.ts +221 -0
  271. package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
  272. package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
  273. package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
  274. package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
  275. package/src/ui-tailwind/chart/render/area.tsx +3 -3
  276. package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
  277. package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
  278. package/src/ui-tailwind/chart/render/combo.tsx +2 -2
  279. package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
  280. package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
  281. package/src/ui-tailwind/chart/render/line.tsx +3 -3
  282. package/src/ui-tailwind/chart/render/pie.tsx +6 -6
  283. package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
  284. package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
  285. package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
  286. package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
  287. package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
  288. package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
  289. package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
  290. package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
  291. package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
  292. package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
  293. package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
  294. package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
  295. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
  296. package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
  297. package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
  298. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
  299. package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
  300. package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
  301. package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
  302. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
  303. package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
  304. package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
  305. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
  306. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
  307. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
  308. package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
  309. package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
  310. package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
  311. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
  312. package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
  313. package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
  314. package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
  315. package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
  316. package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
  317. package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
  318. package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
  319. package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
  320. package/src/ui-tailwind/debug/README.md +57 -0
  321. package/src/ui-tailwind/debug/index.ts +3 -0
  322. package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
  323. package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
  324. package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
  325. package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
  326. package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
  327. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
  328. package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
  329. package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
  330. package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
  331. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
  332. package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
  333. package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
  334. package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
  335. package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
  336. package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
  337. package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
  338. package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
  339. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
  340. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
  341. package/src/ui-tailwind/index.ts +0 -5
  342. package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
  343. package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
  344. package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
  345. package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
  346. package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
  347. package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
  348. package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
  349. package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
  350. package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
  351. package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
  352. package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
  353. package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
  354. package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
  355. package/src/ui-tailwind/review-workspace/types.ts +408 -0
  356. package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
  357. package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
  358. package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
  359. package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
  360. package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
  361. package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
  362. package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
  363. package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
  364. package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
  365. package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
  366. package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
  367. package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
  368. package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
  369. package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
  370. package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
  371. package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
  372. package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
  373. package/src/ui-tailwind/theme/editor-theme.css +25 -0
  374. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
  375. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
  376. package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
  377. package/src/ui-tailwind/ui-api-context.tsx +43 -0
  378. package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
  379. package/src/validation/compatibility-engine.ts +6 -6
  380. package/src/runtime/styles-cascade.ts +0 -33
  381. package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
  382. /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
  383. /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
  384. /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
@@ -39,6 +39,8 @@ export function editorSessionStateFromPersistedSnapshot(
39
39
  sourcePackage: snapshot.sourcePackage,
40
40
  workflowOverlay: snapshot.workflowOverlay,
41
41
  workflowMetadata: snapshot.workflowMetadata,
42
+ visibilityPolicies: snapshot.visibilityPolicies,
43
+ markupModePolicy: snapshot.markupModePolicy,
42
44
  });
43
45
  }
44
46
 
@@ -64,6 +66,8 @@ export function persistedSnapshotFromEditorSessionState(
64
66
  sourcePackage: sessionState.sourcePackage,
65
67
  workflowOverlay: sessionState.workflowOverlay,
66
68
  workflowMetadata: sessionState.workflowMetadata,
69
+ visibilityPolicies: sessionState.visibilityPolicies,
70
+ markupModePolicy: sessionState.markupModePolicy,
67
71
  });
68
72
  }
69
73
 
@@ -0,0 +1,91 @@
1
+ # `src/api/v3/` — End-state public API surface
2
+
3
+ > **@endStateApi v3** — the canonical Beyond Work build-team contract.
4
+ > Do NOT treat this as a rename of `WordReviewEditorRef`. It is a
5
+ > separate, additive API that mirrors the target architecture in
6
+ > [`docs/architecture/00-overview.md`](../../../docs/architecture/00-overview.md)
7
+ > (Runtime API + AI API split per §9 + §10).
8
+
9
+ ## What this directory is
10
+
11
+ - The shape every new Beyond Work consumer builds against, today.
12
+ - Each function carries `ApiV3FnMetadata` declaring
13
+ `status: "mock" | "partial" | "live-with-adapter" | "live"`, its
14
+ target layer, UX intent, and agent metadata.
15
+ - Every UX-visible function emits one `UxResponse` event on the
16
+ `api` telemetry channel per invocation so the future debug UX
17
+ (Phase Q) and agent-facing audit can observe it identically in
18
+ mock and live modes.
19
+
20
+ ### Four-status taxonomy (Phase P')
21
+
22
+ | Status | Meaning |
23
+ |---|---|
24
+ | `mock` | No live path attempted; returns a `mockPayload(...)` / `mockArray(...)` carrying `__mock: true`. |
25
+ | `partial` | Live path attempted; falls back to a mock-shaped payload when the runtime cannot satisfy it. `mockShape` is required. |
26
+ | `live-with-adapter` | Delegates to a real runtime/facet method through a nontrivial adapter or composition layer. `mockShape` optional. |
27
+ | `live` | Direct delegation to a single runtime/facet method. `mockShape` is forbidden. |
28
+
29
+ The current distribution (as reported by the authoritative
30
+ `test/runtime/debug/api-contract.test.ts` runner) is `9 live / 18
31
+ live-with-adapter / 1 partial / 7 mock / 35 total`. See the Changelog
32
+ in [`docs/reference/public-api.md`](../../../docs/reference/public-api.md)
33
+ for the latest entry.
34
+
35
+ ## What this directory is NOT
36
+
37
+ - NOT a re-export of the existing `WordReviewEditorRef`. The two CI
38
+ guards `scripts/ci-check-api-v3-no-ref-reexport.mjs` and
39
+ `scripts/ci-check-api-v3-metadata.mjs` enforce this. Adding a
40
+ convenience re-export of a ref method trips the guard.
41
+ - NOT the place for internal runtime refactoring (`src/session/`,
42
+ `src/runtime/formatting/`, etc.). That work lands behind this
43
+ surface — v3 stays stable while internals move.
44
+ - NOT a sandbox. `status: "live"` functions MUST parity-match the
45
+ underlying runtime behavior (asserted in per-family tests).
46
+
47
+ ## Consumers
48
+
49
+ - **Beyond Work build team** (canonical). Import via
50
+ `import { createApiV3 } from "@beyondwork/docx-react-component/api/v3"`.
51
+ - **Debug UX (Phase Q)**. Uses `UxResponse` events to render mock-or-live
52
+ visualizations.
53
+ - **Phase D runners** (Layer-level validators). Use `createApiV3` as the
54
+ single entry point so runners don't depend on internal runtime shape.
55
+
56
+ ## Graduating a function's status
57
+
58
+ The intended progression is `mock → partial → live-with-adapter → live`.
59
+ Skipping a stage is allowed when justified, but each flip requires
60
+ evidence:
61
+
62
+ 1. Implement the live path (delegate to the appropriate runtime
63
+ facet or layer extractor). For `live-with-adapter`, write the
64
+ adapter/composition in the family file; for `live`, the body
65
+ must be a single delegation call.
66
+ 2. Add a validator log entry under `services/debug/docs/` with the
67
+ new evidence.
68
+ 3. Update the function's `<fnName>Metadata.liveEvidence` field to
69
+ point at the log + the commit SHA; update `mockShape` per the
70
+ taxonomy rules above (required for `mock` and `partial`, optional
71
+ for `live-with-adapter`, forbidden for `live`).
72
+ 4. Update the per-family test's parity assertion and the matching
73
+ inline `// @endStateApi — <status>.` comment on the function
74
+ body so the status-drift canary stays green.
75
+
76
+ Silent flips — changing `status` without updating `liveEvidence` or
77
+ the inline annotation — are a review-time reject.
78
+
79
+ ## Canonical reference doc
80
+
81
+ [`docs/reference/public-api.md`](../../../docs/reference/public-api.md).
82
+ That's the URL the BW team bookmarks. This README is the in-repo
83
+ maintainer-facing companion.
84
+
85
+ ## Phase Q (debug UX refactor) dependency
86
+
87
+ Phase Q ships a runtime-embedded debug UX (`src/ui-tailwind/debug/**`)
88
+ that subscribes to the `UxResponse` event stream emitted from this
89
+ directory. Phase Q does NOT re-import the existing harness debug
90
+ panel — it renders against `UxResponse` + `runtime.debug.getSnapshot`
91
+ directly. See the Phase P plan for the full Phase Q spec.
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @endStateApi v3 — `createApiV3(runtime)` entry point.
3
+ *
4
+ * Single binding point. Every v3 family is a record of functions bound to
5
+ * the runtime supplied here. Consumers get one value with typed sub-namespaces:
6
+ *
7
+ * const api = createApiV3(runtime);
8
+ * await api.runtime.review.getComments();
9
+ * await api.ai.inspectDocument();
10
+ *
11
+ * No other import path is supported. The family modules under `runtime/**`
12
+ * and `ai/**` export `createXxxFamily(runtime)` factories; this file wires
13
+ * them. The resulting object is frozen to prevent monkey-patching.
14
+ */
15
+
16
+ import type { RuntimeApiHandle } from "./_runtime-handle.ts";
17
+
18
+ import { createDocumentFamily } from "./runtime/document.ts";
19
+ import { createContentFamily } from "./runtime/content.ts";
20
+ import { createReviewFamily } from "./runtime/review.ts";
21
+ import { createWorkflowFamily } from "./runtime/workflow.ts";
22
+ import { createLayoutFamily } from "./runtime/layout.ts";
23
+ import { createGeometryFamily } from "./runtime/geometry.ts";
24
+ import { createCollabFamily } from "./runtime/collab.ts";
25
+ import { createFormattingFamily } from "./runtime/formatting.ts";
26
+ import { createClipboardFamily } from "./runtime/clipboard.ts";
27
+ import { createChartFamily } from "./runtime/chart.ts";
28
+ import { createSearchFamily } from "./runtime/search.ts";
29
+ import { createTableFamily } from "./runtime/table.ts";
30
+
31
+ import { createInspectFamily } from "./ai/inspect.ts";
32
+ import { createResolveFamily } from "./ai/resolve.ts";
33
+ import { createBundleFamily } from "./ai/bundle.ts";
34
+ import { createReplacementFamily } from "./ai/replacement.ts";
35
+ import { createAttachFamily } from "./ai/attach.ts";
36
+ import { createExportFamily } from "./ai/export.ts";
37
+ import { createExplainFamily } from "./ai/explain.ts";
38
+ import { createPolicyFamily } from "./ai/policy.ts";
39
+
40
+ import { createUiApi } from "./ui/_create.ts";
41
+ import type { ApiV3Ui, UiControllerFactory } from "./ui/_types.ts";
42
+
43
+ /**
44
+ * @endStateApi
45
+ * End-state v3 API surface. See `docs/reference/public-api.md`.
46
+ *
47
+ * Shape mirrors `docs/architecture/00-overview.md §Runtime API vs AI API`:
48
+ * runtime.* is sub-grouped (document/content/review/workflow/layout/geometry);
49
+ * ai.* is intentionally flat (inspectDocument / resolveReference / etc.) so
50
+ * agents call them as single-level tools without sub-namespace stitching.
51
+ */
52
+ export type ApiV3Runtime = {
53
+ readonly document: ReturnType<typeof createDocumentFamily>;
54
+ readonly content: ReturnType<typeof createContentFamily>;
55
+ readonly review: ReturnType<typeof createReviewFamily>;
56
+ readonly workflow: ReturnType<typeof createWorkflowFamily>;
57
+ readonly layout: ReturnType<typeof createLayoutFamily>;
58
+ readonly geometry: ReturnType<typeof createGeometryFamily>;
59
+ readonly collab: ReturnType<typeof createCollabFamily>;
60
+ readonly formatting: ReturnType<typeof createFormattingFamily>;
61
+ readonly clipboard: ReturnType<typeof createClipboardFamily>;
62
+ readonly chart: ReturnType<typeof createChartFamily>;
63
+ readonly search: ReturnType<typeof createSearchFamily>;
64
+ readonly table: ReturnType<typeof createTableFamily>;
65
+ };
66
+
67
+ export type ApiV3Ai = ReturnType<typeof createInspectFamily>
68
+ & ReturnType<typeof createResolveFamily>
69
+ & ReturnType<typeof createBundleFamily>
70
+ & ReturnType<typeof createReplacementFamily>
71
+ & ReturnType<typeof createAttachFamily>
72
+ & ReturnType<typeof createExportFamily>
73
+ & ReturnType<typeof createExplainFamily>
74
+ & ReturnType<typeof createPolicyFamily>;
75
+
76
+ export interface ApiV3 {
77
+ readonly runtime: ApiV3Runtime;
78
+ readonly ai: ApiV3Ai;
79
+ /**
80
+ * UI API namespace. Present iff the caller passed
81
+ * `createApiV3(handle, { ui: factory })`. Hosts that do not mount a
82
+ * React surface (services/debug, headless tests, stateless agents)
83
+ * omit the factory and get `{ runtime, ai }` only.
84
+ */
85
+ readonly ui?: ApiV3Ui;
86
+ }
87
+
88
+ /**
89
+ * @endStateApi
90
+ * Optional construction options. Currently only `ui` — a
91
+ * `UiControllerFactory` that the UI API consumes to wire mounted-surface
92
+ * dispatch + subscription hooks. Additive; hosts that only need runtime
93
+ * + AI drop the options argument entirely.
94
+ *
95
+ * Per the staircase in `docs/plans/refactor-master-plan.md §2`:
96
+ * /07 Slice 1 (RuntimeApiHandle) → /10 Slice 1 (src/api/v3/ui/**) →
97
+ * /07 Slice 2 (this extension).
98
+ */
99
+ export interface CreateApiV3Opts {
100
+ readonly ui?: UiControllerFactory;
101
+ }
102
+
103
+ /**
104
+ * @endStateApi
105
+ * Single entry point. Returns a frozen `ApiV3` bound to the handle. Back-
106
+ * compat: `createApiV3(handle)` still returns `{ runtime, ai }` without a
107
+ * `ui` property so existing callers (services/debug, headless drivers)
108
+ * stay green.
109
+ */
110
+ export function createApiV3(handle: RuntimeApiHandle, opts?: CreateApiV3Opts): ApiV3 {
111
+ const ai: ApiV3Ai = {
112
+ ...createInspectFamily(handle),
113
+ ...createResolveFamily(handle),
114
+ ...createBundleFamily(handle),
115
+ ...createReplacementFamily(handle),
116
+ ...createAttachFamily(handle),
117
+ ...createExportFamily(handle),
118
+ ...createExplainFamily(handle),
119
+ ...createPolicyFamily(handle),
120
+ };
121
+ const runtime: ApiV3Runtime = {
122
+ document: createDocumentFamily(handle),
123
+ content: createContentFamily(handle),
124
+ review: createReviewFamily(handle),
125
+ workflow: createWorkflowFamily(handle),
126
+ layout: createLayoutFamily(handle),
127
+ geometry: createGeometryFamily(handle),
128
+ collab: createCollabFamily(handle),
129
+ formatting: createFormattingFamily(handle),
130
+ clipboard: createClipboardFamily(handle),
131
+ chart: createChartFamily(handle),
132
+ search: createSearchFamily(handle),
133
+ table: createTableFamily(handle),
134
+ };
135
+ // Construct the UI namespace only when a factory is supplied.
136
+ // `ui` remains `undefined` otherwise — the shape in ApiV3 is optional
137
+ // so consumer snapshot tests that already assert `{ runtime, ai }`
138
+ // continue to match.
139
+ const ui: ApiV3Ui | undefined = opts?.ui ? createUiApi(handle, opts.ui) : undefined;
140
+
141
+ const api: ApiV3 = ui ? { runtime, ai, ui } : { runtime, ai };
142
+ Object.freeze(api.runtime);
143
+ Object.freeze(api.ai);
144
+ // api.ui is already frozen by createUiApi.
145
+ return Object.freeze(api);
146
+ }
@@ -0,0 +1,362 @@
1
+ /**
2
+ * @endStateApi v3 — metadata primitives. See docs/reference/public-api.md.
3
+ *
4
+ * Every exported v3 function has a sibling `<fnName>Metadata: ApiV3FnMetadata`
5
+ * export. The two CI guards under `scripts/ci-check-api-v3-*.mjs` enforce this.
6
+ * Replacing a mock with a live implementation requires updating `liveEvidence`
7
+ * with a validator log + commit SHA.
8
+ */
9
+
10
+ /**
11
+ * @endStateApi
12
+ * 4-status discriminator (Phase P' taxonomy).
13
+ *
14
+ * - `mock` — no valid runtime-backed path yet; deterministic mock only.
15
+ * - `partial` — some behavior is real and some is still mocked (e.g. read
16
+ * path live, write path mocked; or only a subset of the contract
17
+ * satisfied).
18
+ * - `live-with-adapter` — a valid shipped runtime/facet/debug candidate
19
+ * exists and the contract is semantically supportable now, but only
20
+ * through a nontrivial adapter / rebinding / composition layer rather
21
+ * than direct 1:1 delegation. Stays visible in metadata until the
22
+ * adapter is promoted to a first-class surface or replaced by a
23
+ * cleaner underlying contract.
24
+ * - `live` — direct delegation to a shipped runtime contract (no
25
+ * meaningful adapter debt).
26
+ */
27
+ export type ApiStatus = "mock" | "partial" | "live-with-adapter" | "live";
28
+
29
+ /**
30
+ * @endStateApi
31
+ * 11-layer taxonomy from `docs/architecture/00-overview.md § Target End-State
32
+ * Stack`. Each v3 function declares which layer it belongs to so future
33
+ * layer-extraction refactors can move the implementation behind the surface
34
+ * without breaking consumers.
35
+ */
36
+ export type SourceLayer =
37
+ | "beyond-work-substrate"
38
+ | "package-session"
39
+ | "canonical"
40
+ | "formatting-semantics"
41
+ | "layout-semantics"
42
+ | "geometry-projection"
43
+ | "workflow-review"
44
+ | "runtime-core"
45
+ | "semantic-scope-compiler"
46
+ | "ai"
47
+ | "presentation";
48
+
49
+ /**
50
+ * @endStateApi
51
+ * Pointers to the evidence that backs a `live` or `partial` claim. At least
52
+ * one of these fields is required for a non-mock function; mock functions
53
+ * leave this undefined.
54
+ */
55
+ export interface LiveEvidence {
56
+ readonly validatorLog?: string;
57
+ readonly runnerTest?: string;
58
+ readonly probeScript?: string;
59
+ readonly commit?: string;
60
+ }
61
+
62
+ /**
63
+ * @endStateApi
64
+ * Shape declaration for mock-returning functions. Every mock payload carries
65
+ * `__mock: true` so consumer tests can snapshot against it without
66
+ * accidentally depending on mock-specific fields in production code.
67
+ */
68
+ export interface MockShape {
69
+ readonly deterministic: boolean;
70
+ readonly seededFrom?: "documentId" | "hash" | "fixed" | "counter";
71
+ readonly shapeDescription: string;
72
+ readonly carriesMockFlag: true;
73
+ }
74
+
75
+ /**
76
+ * @endStateApi
77
+ * UX expectation. Functions with `uiVisible: true` MUST emit exactly one
78
+ * UxResponse event on the `api` channel per invocation. Asserted in tests.
79
+ */
80
+ export interface UxIntent {
81
+ readonly uiVisible: boolean;
82
+ readonly expectsUxResponse?:
83
+ | "toast"
84
+ | "overlay"
85
+ | "inline-change"
86
+ | "surface-refresh"
87
+ | "selection-change"
88
+ | "warning-added"
89
+ | "scope-created"
90
+ | "none";
91
+ readonly expectedDelta?: string;
92
+ }
93
+
94
+ /**
95
+ * @endStateApi
96
+ * Agent-facing metadata. Drives prompt-context inclusion, audit categorization,
97
+ * and policy hinting in the future Beyond Work agent surface.
98
+ */
99
+ export interface AgentMetadata {
100
+ readonly readOrMutate: "read" | "mutate" | "compound";
101
+ readonly boundedScope?: "document" | "scope" | "selection" | "session";
102
+ readonly auditCategory?: string;
103
+ readonly policyHints?: readonly string[];
104
+ readonly contextPromptShape?: string;
105
+ }
106
+
107
+ /**
108
+ * @endStateApi
109
+ * Shape contract for UI-API subscription-style channels. When a
110
+ * `bidirectional: true` function produces an ongoing stream rather
111
+ * than a single request/response (e.g. `ui.viewport.subscribe`), its
112
+ * metadata carries this record so consumers can reason about the
113
+ * payload and coalescing discipline without reading the implementation.
114
+ *
115
+ * - `eventType` — the `ux.response.<fn>.subscribed` event emitted once
116
+ * per subscribe call (the seam acknowledgement) AND the ongoing
117
+ * event type the bind-side pushes per coalesced tick.
118
+ * - `payloadType` — a human-readable name for the payload shape
119
+ * (matches an exported TS type name like `"ViewportState"`).
120
+ * - `coalescing` — how the bind-side batches upstream events before
121
+ * firing the listener. `"raf"` is the default for viewport /
122
+ * overlay channels; `"microtask"` for state-store-backed posture;
123
+ * `"immediate"` only when the upstream already throttles.
124
+ */
125
+ export interface SubscriptionShape {
126
+ readonly eventType: string;
127
+ readonly payloadType: string;
128
+ readonly coalescing: "raf" | "microtask" | "immediate";
129
+ }
130
+
131
+ /**
132
+ * @endStateApi
133
+ * Complete metadata record. `liveEvidence` is required when `status !==
134
+ * "mock"`; `mockShape` is required when `status !== "live"`. A function can
135
+ * be both (partial: both live and mock in different paths).
136
+ *
137
+ * `bidirectional` + `subscriptionShape` are UI-API specific fields added
138
+ * by refactor/07 Slice 2. A function is `bidirectional: true` when it
139
+ * carries data across the runtime ↔ UI seam in both directions — either
140
+ * as a dispatch/echo pair (`ui.surface.setSelection` requests, runtime
141
+ * emits `selection.changed`) or as a subscribe/stream pair (the
142
+ * subscribe call establishes the channel, the runtime pushes events).
143
+ * The invariant asserted by `validateApiV3Metadata` is:
144
+ * bidirectional: true ⇒ uxIntent.uiVisible: true
145
+ * ∧ (dispatch form: expectsUxResponse != "none")
146
+ * ∨ (stream form: subscriptionShape present)
147
+ * Dispatch-form functions (no `subscriptionShape`) must emit exactly one
148
+ * `ux.response.<fn>` event per invocation; stream-form functions
149
+ * (`subscriptionShape` present) emit exactly one
150
+ * `ux.response.<fn>.subscribed` event on the establishing call, then
151
+ * deliver events through the subscription.
152
+ */
153
+ /**
154
+ * @endStateApi
155
+ * Three-way state model classifier (per `docs/architecture/00-overview.md §9.1`
156
+ * + `07-runtime-api.md §R9`).
157
+ *
158
+ * - `A-canonical` — document-authored state. Lives in the canonical
159
+ * document or its overlay; persists across sessions; broadcasts via
160
+ * CRDT (Yjs). Examples: scope metadata, comments, tracked changes.
161
+ * - `B-session` — session-shared transient state. Present for the
162
+ * duration of a session, shared across tabs/peers in the same session
163
+ * via Awareness; does not persist beyond the session. Examples:
164
+ * presence, posture, cursor position.
165
+ * - `C-local` — local view preference. Never leaves the user's tab.
166
+ * Does not persist in the document or the session. Examples: UI
167
+ * overlay visibility, chrome posture, viewport scroll.
168
+ */
169
+ export type StateClass = "A-canonical" | "B-session" | "C-local";
170
+
171
+ /**
172
+ * @endStateApi
173
+ * Persistence target for a function's effect.
174
+ *
175
+ * - `canonical` — write lands in the canonical document structure
176
+ * (class-A mutation that rides a scope-scoped command).
177
+ * - `customXml` — write lands in the `bw:*` customXml overlay parts
178
+ * (class-A workflow mutation — scopes, metadata, visibility policy).
179
+ * - `none` — function does not persist (reads, local-view toggles,
180
+ * transient session-shared broadcasts).
181
+ */
182
+ export type PersistsTo = "canonical" | "customXml" | "none";
183
+
184
+ /**
185
+ * @endStateApi
186
+ * Transport for class-A or class-B broadcasts.
187
+ *
188
+ * - `crdt` — Yjs document broadcast. Eventually-consistent with
189
+ * deterministic merge. Used by class-A mutations.
190
+ * - `awareness` — Y.Awareness ephemeral broadcast. Last-writer-wins,
191
+ * bounded per-peer. Used by class-B session-shared state.
192
+ *
193
+ * Omit for class-C (local-only) functions.
194
+ */
195
+ export type BroadcastsVia = "crdt" | "awareness";
196
+
197
+ export interface ApiV3FnMetadata {
198
+ readonly name: string;
199
+ readonly status: ApiStatus;
200
+ readonly sourceLayer: SourceLayer;
201
+ readonly liveEvidence?: LiveEvidence;
202
+ readonly mockShape?: MockShape;
203
+ readonly uxIntent: UxIntent;
204
+ readonly agentMetadata: AgentMetadata;
205
+ readonly rwdReference?: string;
206
+ readonly bidirectional?: boolean;
207
+ readonly subscriptionShape?: SubscriptionShape;
208
+ /**
209
+ * @endStateApi
210
+ * Three-way state class (§R9 / §9.1). Required on every metadata
211
+ * record. CI-guard-enforced with namespace-class coherence rules:
212
+ *
213
+ * - `ui.*` → `C-local`
214
+ * - `runtime.collab.*` → `B-session`
215
+ * - `runtime.workflow.*` → `A-canonical`
216
+ * - Other `runtime.*` → `A-canonical` (per namespace rules below)
217
+ * - `ai.*` → follows the runtime function it delegates to
218
+ */
219
+ readonly stateClass: StateClass;
220
+ /**
221
+ * @endStateApi
222
+ * Where a mutation's effect lands. Required on every metadata
223
+ * record. Rules:
224
+ *
225
+ * - `C-local` ⇒ `"none"`
226
+ * - `B-session` ⇒ `"none"`
227
+ * - `A-canonical` + read ⇒ `"none"`
228
+ * - `A-canonical` + runtime.workflow mutate ⇒ `"customXml"`
229
+ * - `A-canonical` + other runtime mutate ⇒ `"canonical"`
230
+ */
231
+ readonly persistsTo: PersistsTo;
232
+ /**
233
+ * @endStateApi
234
+ * Broadcast transport. Required for class-B and for class-A
235
+ * mutations; forbidden for class-C.
236
+ *
237
+ * - `B-session` ⇒ `"awareness"`
238
+ * - `A-canonical` + runtime.workflow mutate ⇒ `"crdt"`
239
+ * - `A-canonical` + other ⇒ optional (`"crdt"` when the write
240
+ * broadcasts to peers; omit when it's purely local/read)
241
+ * - `C-local` ⇒ omit
242
+ */
243
+ readonly broadcastsVia?: BroadcastsVia;
244
+ }
245
+
246
+ /**
247
+ * @endStateApi
248
+ * Marker type every mock payload uses. Consumer code can narrow on
249
+ * `__mock: true` to explicitly branch test doubles vs. real responses.
250
+ */
251
+ export interface MockPayload {
252
+ readonly __mock: true;
253
+ readonly reason: string;
254
+ readonly shape: string;
255
+ }
256
+
257
+ /**
258
+ * @endStateApi
259
+ * Validate a metadata record. Used by CI guards + runtime tests. Returns
260
+ * null if valid; returns a human-readable error string otherwise.
261
+ *
262
+ * Contract (intentional asymmetry — do not "tighten"):
263
+ * - `liveEvidence` is required whenever status ≠ `mock` (live,
264
+ * live-with-adapter, partial all need evidence).
265
+ * - `mockShape` is required only for `mock` or `partial` — adapter-
266
+ * backed functions with a fallback branch SHOULD declare `mockShape`
267
+ * for the fallback, but bare `live-with-adapter` functions that
268
+ * return null instead of a mock-flagged payload are valid without it.
269
+ * `live` functions never carry `mockShape`.
270
+ */
271
+ export function validateApiV3Metadata(m: ApiV3FnMetadata): string | null {
272
+ if (!m.name || typeof m.name !== "string") return "missing name";
273
+ if (!m.status) return "missing status";
274
+ if (!m.sourceLayer) return "missing sourceLayer";
275
+ if (!m.uxIntent) return "missing uxIntent";
276
+ if (typeof m.uxIntent.uiVisible !== "boolean") return "uxIntent.uiVisible must be boolean";
277
+ if (!m.agentMetadata) return "missing agentMetadata";
278
+ if (!m.agentMetadata.readOrMutate) return "missing agentMetadata.readOrMutate";
279
+ if (m.status !== "mock" && !m.liveEvidence) {
280
+ return `status "${m.status}" requires liveEvidence`;
281
+ }
282
+ const mockShapeRequired = m.status === "mock" || m.status === "partial";
283
+ if (mockShapeRequired && !m.mockShape) {
284
+ return `status "${m.status}" requires mockShape`;
285
+ }
286
+ if (m.mockShape && m.mockShape.carriesMockFlag !== true) {
287
+ return "mockShape.carriesMockFlag must be true";
288
+ }
289
+ if (m.bidirectional === true) {
290
+ if (m.uxIntent.uiVisible !== true) {
291
+ return "bidirectional: true requires uxIntent.uiVisible: true";
292
+ }
293
+ const hasStream = !!m.subscriptionShape;
294
+ const hasDispatch =
295
+ typeof m.uxIntent.expectsUxResponse === "string" &&
296
+ m.uxIntent.expectsUxResponse !== "none";
297
+ if (!hasStream && !hasDispatch) {
298
+ return (
299
+ "bidirectional: true requires either subscriptionShape (stream form) " +
300
+ "or uxIntent.expectsUxResponse != 'none' (dispatch form)"
301
+ );
302
+ }
303
+ }
304
+ if (m.subscriptionShape) {
305
+ const s = m.subscriptionShape;
306
+ if (!s.eventType || typeof s.eventType !== "string") {
307
+ return "subscriptionShape.eventType must be a non-empty string";
308
+ }
309
+ if (!s.payloadType || typeof s.payloadType !== "string") {
310
+ return "subscriptionShape.payloadType must be a non-empty string";
311
+ }
312
+ if (s.coalescing !== "raf" && s.coalescing !== "microtask" && s.coalescing !== "immediate") {
313
+ return "subscriptionShape.coalescing must be 'raf' | 'microtask' | 'immediate'";
314
+ }
315
+ }
316
+ // Three-way state model checks (§R9). `stateClass` describes where the
317
+ // function's state LIVES; `persistsTo` and `broadcastsVia` describe the
318
+ // persistence home + broadcast transport of that state class (not the
319
+ // per-call effect). Reads and mutations of the same class share the same
320
+ // values. CI guard `scripts/ci-check-api-v3-metadata.mjs` runs the
321
+ // namespace-coherence rules (which names must declare which classes)
322
+ // over the file AST; this validator enforces the shape invariants that
323
+ // are independent of the function's name.
324
+ if (m.stateClass !== "A-canonical" && m.stateClass !== "B-session" && m.stateClass !== "C-local") {
325
+ return `stateClass must be "A-canonical" | "B-session" | "C-local"; got ${JSON.stringify(m.stateClass)}`;
326
+ }
327
+ if (m.persistsTo !== "canonical" && m.persistsTo !== "customXml" && m.persistsTo !== "none") {
328
+ return `persistsTo must be "canonical" | "customXml" | "none"; got ${JSON.stringify(m.persistsTo)}`;
329
+ }
330
+ if (m.broadcastsVia !== undefined && m.broadcastsVia !== "crdt" && m.broadcastsVia !== "awareness") {
331
+ return `broadcastsVia must be "crdt" | "awareness" (or omitted); got ${JSON.stringify(m.broadcastsVia)}`;
332
+ }
333
+ // Class-C: local-only. Never persists, never broadcasts.
334
+ if (m.stateClass === "C-local") {
335
+ if (m.persistsTo !== "none") {
336
+ return `stateClass "C-local" requires persistsTo "none"; got ${m.persistsTo}`;
337
+ }
338
+ if (m.broadcastsVia !== undefined) {
339
+ return `stateClass "C-local" must omit broadcastsVia; got ${m.broadcastsVia}`;
340
+ }
341
+ }
342
+ // Class-B: session-shared via awareness. Does not persist.
343
+ if (m.stateClass === "B-session") {
344
+ if (m.persistsTo !== "none") {
345
+ return `stateClass "B-session" requires persistsTo "none"; got ${m.persistsTo}`;
346
+ }
347
+ if (m.broadcastsVia !== "awareness") {
348
+ return `stateClass "B-session" requires broadcastsVia "awareness"; got ${m.broadcastsVia}`;
349
+ }
350
+ }
351
+ // Class-A: document-authored. Persists canonical or customXml; may
352
+ // broadcast crdt (required for workflow overlay writes).
353
+ if (m.stateClass === "A-canonical") {
354
+ if (m.persistsTo === "none") {
355
+ return `stateClass "A-canonical" ${m.name} must persist (canonical or customXml); got "none"`;
356
+ }
357
+ if (m.broadcastsVia === "awareness") {
358
+ return `stateClass "A-canonical" cannot broadcast via "awareness" (class-B transport); ${m.name}`;
359
+ }
360
+ }
361
+ return null;
362
+ }