@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
@@ -0,0 +1,331 @@
1
+ /**
2
+ * @endStateApi v3 — `runtime.collab` family.
3
+ *
4
+ * getSessionInfo (live-with-adapter) / getPresence (live-with-adapter) /
5
+ * getPosture (live-with-adapter).
6
+ *
7
+ * Shape note: "Runtime API + Collab" is the layer-07 name per the refactor
8
+ * master plan. `RuntimeApiHandle` now exposes `collabSession` as an
9
+ * optional accessor — hosts that wire Yjs/Awareness supply it, and the
10
+ * getPresence + getPosture functions delegate to
11
+ * `CollabSession.getPresenceSnapshot` / `.getCollabPosture` directly.
12
+ * Headless callers that don't wire collab get a deterministic mock
13
+ * fallback, so the family remains safe to call on any handle.
14
+ */
15
+
16
+ import type { Awareness } from "y-protocols/awareness";
17
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
18
+ import type { ApiV3FnMetadata, MockPayload } from "../_layer-metadata.ts";
19
+ import { mockPayload } from "../_mocks.ts";
20
+ import type { MetadataIntegrity } from "../../public-types.ts";
21
+ import {
22
+ getRemoteCursorStates as getRemoteCursorStatesImpl,
23
+ type RemoteCursorState,
24
+ } from "../../../runtime/collab/remote-cursor-awareness.ts";
25
+
26
+ // Re-export so L11 consumers (remote-cursor-plugin) don't peek into
27
+ // `src/runtime/collab/**` for the state type.
28
+ export type { RemoteCursorState };
29
+
30
+ /**
31
+ * L11-facing named re-export of the remote-cursor-awareness helper
32
+ * (coord-11 §4.4 · §4.8 collab-family migration). `remote-cursor-plugin.ts`
33
+ * — a pure PM plugin with no runtime handle in scope — uses this form
34
+ * so it doesn't reach into `src/runtime/collab/**` directly. Identity
35
+ * re-export of the same impl the factory binds; mirrors the pattern
36
+ * `chart.ts` established for the pure chart helpers.
37
+ */
38
+ export { getRemoteCursorStatesImpl as getRemoteCursorStates };
39
+
40
+ /* ================================================================== */
41
+ /* getSessionInfo — live-with-adapter */
42
+ /* ================================================================== */
43
+
44
+ export interface CollabSessionInfo {
45
+ readonly documentId: string;
46
+ readonly docId: string;
47
+ readonly sessionVersion: string;
48
+ readonly schemaVersion: string;
49
+ readonly hasWorkflowOverlay: boolean;
50
+ readonly hasSharedWorkflowState: boolean;
51
+ }
52
+
53
+ export const getSessionInfoMetadata: ApiV3FnMetadata = {
54
+ name: "runtime.collab.getSessionInfo",
55
+ status: "live-with-adapter",
56
+ sourceLayer: "package-session",
57
+ liveEvidence: {
58
+ runnerTest: "test/api/v3/behavioral-coverage.test.ts",
59
+ commit: "layer-07-closure-pass",
60
+ },
61
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
62
+ agentMetadata: {
63
+ readOrMutate: "read",
64
+ boundedScope: "session",
65
+ auditCategory: "collab-session-info",
66
+ },
67
+ stateClass: "B-session",
68
+ persistsTo: "none",
69
+ broadcastsVia: "awareness",
70
+ rwdReference:
71
+ "§Runtime API § runtime.collab.getSessionInfo. Adapter reads handle.getSessionState() + handle.getWorkflowOverlay() and projects a session-scoped CollabSessionInfo. Promotes to `live` when RuntimeApiHandle exposes a direct `collabSession` accessor.",
72
+ };
73
+
74
+ /* ================================================================== */
75
+ /* getPresence — mock (collab facet not yet on handle) */
76
+ /* ================================================================== */
77
+
78
+ export interface CollabPresenceSnapshot {
79
+ readonly peers: readonly unknown[];
80
+ readonly transportStatus: "online" | "syncing" | "offline";
81
+ readonly queuedLocalEvents: number;
82
+ readonly __mock?: true;
83
+ }
84
+
85
+ export const getPresenceMetadata: ApiV3FnMetadata = {
86
+ name: "runtime.collab.getPresence",
87
+ status: "live-with-adapter",
88
+ sourceLayer: "workflow-review",
89
+ liveEvidence: {
90
+ runnerTest: "test/api/v3/behavioral-coverage.test.ts",
91
+ commit: "layer-07-closure-pass-graduation",
92
+ },
93
+ mockShape: {
94
+ deterministic: true,
95
+ seededFrom: "fixed",
96
+ shapeDescription:
97
+ "Empty presence snapshot — peers:[], transportStatus:'offline', queuedLocalEvents:0. Emitted only when the handle carries no `collabSession` (headless drivers, pre-wire tests). Hosts that supply `collabSession` get the live PresenceSnapshot projected into the v3 shape.",
98
+ carriesMockFlag: true,
99
+ },
100
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
101
+ agentMetadata: {
102
+ readOrMutate: "read",
103
+ boundedScope: "session",
104
+ auditCategory: "collab-presence",
105
+ },
106
+ stateClass: "B-session",
107
+ persistsTo: "none",
108
+ broadcastsVia: "awareness",
109
+ rwdReference:
110
+ "§Runtime API § runtime.collab.getPresence. Adapter delegates to handle.collabSession.getPresenceSnapshot() when the handle carries one; falls back to deterministic mock when absent. Promotes to `live` when collabSession is no longer optional (hosts default-attach).",
111
+ };
112
+
113
+ /* ================================================================== */
114
+ /* getPosture — mock (collab facet not yet on handle) */
115
+ /* ================================================================== */
116
+
117
+ export interface CollabPostureSnapshot {
118
+ readonly role: "author" | "reviewer" | "observer" | "unattached";
119
+ readonly peerCount: number;
120
+ readonly transportStatus: "online" | "syncing" | "offline";
121
+ readonly __mock?: true;
122
+ }
123
+
124
+ export const getPostureMetadata: ApiV3FnMetadata = {
125
+ name: "runtime.collab.getPosture",
126
+ status: "live-with-adapter",
127
+ sourceLayer: "workflow-review",
128
+ liveEvidence: {
129
+ runnerTest: "test/api/v3/behavioral-coverage.test.ts",
130
+ commit: "layer-07-closure-pass-graduation",
131
+ },
132
+ mockShape: {
133
+ deterministic: true,
134
+ seededFrom: "fixed",
135
+ shapeDescription:
136
+ "Default posture — role:'unattached', peerCount:0, transportStatus:'offline'. Emitted only when the handle carries no `collabSession`. Hosts that supply `collabSession` get the live CollabPosture projected into the v3 shape.",
137
+ carriesMockFlag: true,
138
+ },
139
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
140
+ agentMetadata: {
141
+ readOrMutate: "read",
142
+ boundedScope: "session",
143
+ auditCategory: "collab-posture",
144
+ },
145
+ stateClass: "B-session",
146
+ persistsTo: "none",
147
+ broadcastsVia: "awareness",
148
+ rwdReference:
149
+ "§Runtime API § runtime.collab.getPosture. Adapter delegates to handle.collabSession.getCollabPosture() when the handle carries one; falls back to deterministic mock when absent. Promotes to `live` when collabSession is no longer optional (hosts default-attach).",
150
+ };
151
+
152
+ /* ================================================================== */
153
+ /* getMetadataIntegrity — live-with-adapter (collab expansion) */
154
+ /* ================================================================== */
155
+
156
+ /**
157
+ * Snapshot shape — wraps the `MetadataIntegrity` union
158
+ * (`"unsigned" | "verified" | "tampered"`) in an object so the mock
159
+ * fallback can carry `__mock: true`. Agents reading the tamper gate
160
+ * branch on `snapshot.integrity`.
161
+ */
162
+ export interface CollabMetadataIntegritySnapshot {
163
+ readonly integrity: MetadataIntegrity;
164
+ readonly __mock?: true;
165
+ }
166
+
167
+ export const getMetadataIntegrityMetadata: ApiV3FnMetadata = {
168
+ name: "runtime.collab.getMetadataIntegrity",
169
+ status: "live-with-adapter",
170
+ sourceLayer: "workflow-review",
171
+ liveEvidence: {
172
+ runnerTest: "test/api/v3/behavioral-coverage.test.ts",
173
+ commit: "refactor-07-collab-expansion-tamper-read-2026-04-23",
174
+ },
175
+ mockShape: {
176
+ deterministic: true,
177
+ seededFrom: "fixed",
178
+ shapeDescription:
179
+ "Default integrity 'unsigned' — emitted only when the handle carries no `collabSession` (headless drivers, pre-wire tests). Hosts that supply `collabSession` get the live MetadataIntegrity from the tamper-gate.",
180
+ carriesMockFlag: true,
181
+ },
182
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
183
+ agentMetadata: {
184
+ readOrMutate: "read",
185
+ boundedScope: "session",
186
+ auditCategory: "collab-tamper-read",
187
+ },
188
+ stateClass: "B-session",
189
+ persistsTo: "none",
190
+ broadcastsVia: "awareness",
191
+ rwdReference:
192
+ "§Runtime API § runtime.collab.getMetadataIntegrity. Adapter delegates to handle.collabSession.getMetadataIntegrity() when the handle carries one; falls back to a deterministic 'unsigned' snapshot otherwise. Backs coord-07 §2.1 collab expansion: agent-facing tamper-state read without reaching into `src/runtime/workflow/tamper-gate.ts`. Promotes to `live` when collabSession is no longer optional.",
193
+ };
194
+
195
+ /* ================================================================== */
196
+ /* getRemoteCursorStates — live (collab expansion remainder) */
197
+ /* ================================================================== */
198
+
199
+ export interface GetRemoteCursorStatesInput {
200
+ readonly awareness: Awareness;
201
+ readonly localClientId: number;
202
+ }
203
+
204
+ export const getRemoteCursorStatesMetadata: ApiV3FnMetadata = {
205
+ name: "runtime.collab.getRemoteCursorStates",
206
+ status: "live",
207
+ sourceLayer: "workflow-review",
208
+ liveEvidence: {
209
+ runnerTest: "test/api/v3/behavioral-coverage.test.ts",
210
+ commit: "refactor-07-collab-remote-cursor-2026-04-23",
211
+ },
212
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
213
+ agentMetadata: {
214
+ readOrMutate: "read",
215
+ boundedScope: "session",
216
+ auditCategory: "collab-remote-cursor-read",
217
+ },
218
+ stateClass: "B-session",
219
+ persistsTo: "none",
220
+ broadcastsVia: "awareness",
221
+ rwdReference:
222
+ "§Runtime API § runtime.collab.getRemoteCursorStates. Direct delegation to getRemoteCursorStates (src/runtime/collab/remote-cursor-awareness.ts). Extracts remote peers' cursor states from a Yjs Awareness instance, filtered by localClientId and sanitized (color allowlisted to safe-hex or hashed fallback). Backs coord-07 §2.1 collab expansion remainder — PM remote-cursor plugin flips from src/runtime/collab/** to this seam.",
223
+ };
224
+
225
+ /* ================================================================== */
226
+ /* family factory */
227
+ /* ================================================================== */
228
+
229
+ export function createCollabFamily(runtime: RuntimeApiHandle) {
230
+ return {
231
+ getSessionInfo(): CollabSessionInfo {
232
+ // @endStateApi — live-with-adapter. Composes handle.getSessionState()
233
+ // + handle.getWorkflowOverlay() into a session-scoped projection.
234
+ // No __mock flag — every field is sourced from real runtime state.
235
+ const state = runtime.getSessionState();
236
+ const overlay = runtime.getWorkflowOverlay();
237
+ return {
238
+ documentId: state.documentId,
239
+ docId: state.docId ?? state.documentId,
240
+ sessionVersion: state.sessionVersion ?? "editor-session-state/1",
241
+ schemaVersion: String(state.schemaVersion ?? "cds/1.0.0"),
242
+ hasWorkflowOverlay: overlay !== null && overlay !== undefined,
243
+ hasSharedWorkflowState: Boolean(
244
+ overlay && typeof overlay === "object" && "sharedWorkflowState" in overlay,
245
+ ),
246
+ };
247
+ },
248
+
249
+ getPresence(): CollabPresenceSnapshot & Partial<MockPayload> {
250
+ // @endStateApi — live-with-adapter. When the host wires
251
+ // handle.collabSession, delegates to getPresenceSnapshot() and
252
+ // projects into the v3 shape. Otherwise returns the mock fallback
253
+ // so headless drivers stay safe.
254
+ const session = runtime.collabSession;
255
+ if (session) {
256
+ const live = session.getPresenceSnapshot();
257
+ return {
258
+ peers: live.peers as readonly unknown[],
259
+ transportStatus: live.transportStatus as "online" | "syncing" | "offline",
260
+ queuedLocalEvents: live.queuedLocalEvents,
261
+ };
262
+ }
263
+ return mockPayload(
264
+ "handle.collabSession not wired; hosts attach it via createCollabSession({ydoc,awareness,...}) and pass through to createApiV3",
265
+ "CollabPresenceSnapshot",
266
+ {
267
+ peers: [] as readonly unknown[],
268
+ transportStatus: "offline" as const,
269
+ queuedLocalEvents: 0,
270
+ },
271
+ );
272
+ },
273
+
274
+ getPosture(): CollabPostureSnapshot & Partial<MockPayload> {
275
+ // @endStateApi — live-with-adapter. Same delegation pattern as
276
+ // getPresence — live via handle.collabSession.getCollabPosture()
277
+ // or mock fallback.
278
+ const session = runtime.collabSession;
279
+ if (session) {
280
+ const live = session.getCollabPosture();
281
+ // CollabPosture.transport is "none" | "attached"; v3 surface
282
+ // reshapes to the consumer-friendly "online/syncing/offline"
283
+ // triad. `attached` → `online` at this layer; hosts wanting
284
+ // syncing granularity pass a transportStatus override.
285
+ const transportStatus: "online" | "syncing" | "offline" =
286
+ live.transport === "attached" ? "online" : "offline";
287
+ return {
288
+ role: live.role as "author" | "reviewer" | "observer" | "unattached",
289
+ peerCount: live.peers,
290
+ transportStatus,
291
+ };
292
+ }
293
+ return mockPayload(
294
+ "handle.collabSession not wired; hosts attach it via createCollabSession({ydoc,awareness,...}) and pass through to createApiV3",
295
+ "CollabPostureSnapshot",
296
+ {
297
+ role: "unattached" as const,
298
+ peerCount: 0,
299
+ transportStatus: "offline" as const,
300
+ },
301
+ );
302
+ },
303
+
304
+ getRemoteCursorStates(input: GetRemoteCursorStatesInput): RemoteCursorState[] {
305
+ // @endStateApi — live. Pure delegation; `awareness` is the host-
306
+ // owned Yjs Awareness instance. Returns [] when no remote peer has
307
+ // published a cursor state. Color is sanitized to a safe-hex
308
+ // allowlist or hashed fallback by the underlying helper — callers
309
+ // can interpolate the value into inline style without re-validating.
310
+ return getRemoteCursorStatesImpl(input.awareness, input.localClientId);
311
+ },
312
+
313
+ getMetadataIntegrity(): CollabMetadataIntegritySnapshot & Partial<MockPayload> {
314
+ // @endStateApi — live-with-adapter. Coord-07 §2.1 collab expansion
315
+ // — exposes the tamper-gate state for agents without reaching into
316
+ // `src/runtime/workflow/tamper-gate.ts`. Live via
317
+ // handle.collabSession.getMetadataIntegrity() or "unsigned"
318
+ // mock fallback (the same default the fresh tamper-gate reports
319
+ // before any signed payload attaches).
320
+ const session = runtime.collabSession;
321
+ if (session) {
322
+ return { integrity: session.getMetadataIntegrity() };
323
+ }
324
+ return mockPayload(
325
+ "handle.collabSession not wired; hosts attach it via createCollabSession({ydoc,awareness,...}) and pass through to createApiV3",
326
+ "CollabMetadataIntegritySnapshot",
327
+ { integrity: "unsigned" as MetadataIntegrity },
328
+ );
329
+ },
330
+ };
331
+ }
@@ -0,0 +1,236 @@
1
+ /**
2
+ * @endStateApi v3 — `runtime.content` family.
3
+ *
4
+ * search (live-with-adapter) / getLocation (live-with-adapter) /
5
+ * replaceText (live-with-adapter) / insertFragment (live-with-adapter).
6
+ *
7
+ * 2026-04-23 — insertFragment graduated off the last v3 mock. Routes
8
+ * through the L08 compiler-service facade (same path as replaceText +
9
+ * ai.applyReplacementScope) carrying `proposedContent.kind === "structured"`.
10
+ * v3 is now 100% non-mock.
11
+ */
12
+
13
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
14
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
15
+ import type { CanonicalDocumentFragment } from "../../public-types.ts";
16
+ import { emitUxResponse } from "../_ux-response.ts";
17
+ import { createScopeCompilerService } from "../../../runtime/scopes/index.ts";
18
+
19
+ /* ================================================================== */
20
+ /* search */
21
+ /* ================================================================== */
22
+
23
+ export interface SearchInput {
24
+ readonly query: string;
25
+ readonly caseSensitive?: boolean;
26
+ readonly limit?: number;
27
+ }
28
+
29
+ export const searchMetadata: ApiV3FnMetadata = {
30
+ name: "runtime.content.search",
31
+ status: "live-with-adapter",
32
+ sourceLayer: "canonical",
33
+ liveEvidence: {
34
+ runnerTest: "test/api/v3/live-parity.test.ts",
35
+ commit: "phase-p-prime",
36
+ },
37
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
38
+ agentMetadata: { readOrMutate: "read", boundedScope: "document", auditCategory: "search" },
39
+ stateClass: "A-canonical",
40
+ persistsTo: "canonical",
41
+ rwdReference: "§Runtime API § runtime.content.search",
42
+ };
43
+
44
+ /* ================================================================== */
45
+ /* getLocation */
46
+ /* ================================================================== */
47
+
48
+ export interface GetLocationInput {
49
+ readonly scopeId?: string;
50
+ readonly blockId?: string;
51
+ }
52
+
53
+ export const getLocationMetadata: ApiV3FnMetadata = {
54
+ name: "runtime.content.getLocation",
55
+ status: "live-with-adapter",
56
+ sourceLayer: "canonical",
57
+ liveEvidence: {
58
+ runnerTest: "test/api/v3/live-parity.test.ts",
59
+ commit: "layer-07-closure-pass",
60
+ },
61
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
62
+ agentMetadata: { readOrMutate: "read", boundedScope: "scope", auditCategory: "location" },
63
+ stateClass: "A-canonical",
64
+ persistsTo: "canonical",
65
+ rwdReference:
66
+ "§Runtime API § runtime.content.getLocation. Adapter: scopeId path composes handle.getScope(scopeId) + handle.getLocationForAnchor(scope.anchor) — typed L07 seam, no debug-facet dependency. blockId path is NOT supported today — no shipped blockId → anchor resolver exists.",
67
+ };
68
+
69
+ /* ================================================================== */
70
+ /* replaceText */
71
+ /* ================================================================== */
72
+
73
+ export interface ReplaceTextInput {
74
+ readonly scopeId: string;
75
+ readonly replacement: string;
76
+ }
77
+
78
+ export interface ReplaceTextResult {
79
+ readonly applied: boolean;
80
+ readonly reason?: string;
81
+ }
82
+
83
+ export const replaceTextMetadata: ApiV3FnMetadata = {
84
+ name: "runtime.content.replaceText",
85
+ status: "live-with-adapter",
86
+ sourceLayer: "semantic-scope-compiler",
87
+ liveEvidence: {
88
+ runnerTest: "test/runtime/scopes/replacement-text-only.test.ts",
89
+ commit: "refactor-08-slice-5",
90
+ },
91
+ uxIntent: { uiVisible: true, expectsUxResponse: "inline-change", expectedDelta: "text inside target scope changes" },
92
+ agentMetadata: { readOrMutate: "mutate", boundedScope: "scope", auditCategory: "text-replacement" },
93
+ stateClass: "A-canonical",
94
+ persistsTo: "canonical",
95
+ broadcastsVia: "crdt",
96
+ rwdReference:
97
+ "§Runtime API § runtime.content.replaceText. Adapter: resolves scopeId, re-validates, compiles per-kind plan, dispatches via DocumentRuntime.applyScopeReplacement, emits one ScopeActionAudit. No AI action policy here — this is the host/UI path (actorId defaults to 'user').",
98
+ };
99
+
100
+ /* ================================================================== */
101
+ /* insertFragment */
102
+ /* ================================================================== */
103
+
104
+ /**
105
+ * Scope-scoped structured-fragment insert. `scopeId` names the
106
+ * compiled scope whose range will be replaced with `fragment`; this
107
+ * matches the `replaceText` contract but takes a structured
108
+ * `CanonicalDocumentFragment` payload instead of flat text. Under the
109
+ * L08 compiler pipeline the "insert" resolves to a `fragment-replace`
110
+ * step dispatched through the runtime's existing `insertFragment`
111
+ * command — see coord-08 §8 (paragraph-kind shipped 2026-04-22).
112
+ */
113
+ export interface InsertFragmentInput {
114
+ readonly scopeId: string;
115
+ readonly fragment: CanonicalDocumentFragment;
116
+ }
117
+
118
+ export interface InsertFragmentResult {
119
+ readonly applied: boolean;
120
+ readonly reason?: string;
121
+ }
122
+
123
+ export const insertFragmentMetadata: ApiV3FnMetadata = {
124
+ name: "runtime.content.insertFragment",
125
+ status: "live-with-adapter",
126
+ sourceLayer: "semantic-scope-compiler",
127
+ liveEvidence: {
128
+ runnerTest: "test/api/v3/live-parity.test.ts",
129
+ commit: "refactor-07-insert-fragment-graduation-2026-04-23",
130
+ },
131
+ uxIntent: {
132
+ uiVisible: true,
133
+ expectsUxResponse: "surface-refresh",
134
+ expectedDelta: "selected scope is replaced with the supplied structured fragment",
135
+ },
136
+ agentMetadata: { readOrMutate: "mutate", boundedScope: "scope", auditCategory: "fragment-insert" },
137
+ stateClass: "A-canonical",
138
+ persistsTo: "canonical",
139
+ broadcastsVia: "crdt",
140
+ rwdReference:
141
+ "§Runtime API § runtime.content.insertFragment. Graduation (2026-04-23): routes through createScopeCompilerService(runtime).applyReplacement({targetScopeId, operation:'replace', proposedContent:{kind:'structured', structured: fragment}}) — same L08 pipeline replaceText uses. Emits one ScopeActionAudit via the compiler's lifecycle. Promotes to `live` when an insert-after-anchor primitive exists that matches a distinct agent semantic (this call is replace-with-fragment-shaped today).",
142
+ };
143
+
144
+ /* ================================================================== */
145
+ /* family factory */
146
+ /* ================================================================== */
147
+
148
+ export function createContentFamily(runtime: RuntimeApiHandle) {
149
+ const compiler = createScopeCompilerService(runtime);
150
+ return {
151
+ search(input: SearchInput) {
152
+ // @endStateApi — live-with-adapter. Reshape of EditorAnchorProjection[]
153
+ // + optional limit slicing. v3 spells its boolean `caseSensitive`;
154
+ // runtime SearchOptions spells the same field `matchCase` — the prior
155
+ // cast was passing `{caseSensitive}` which the runtime silently ignored.
156
+ const hits = runtime.findAllText(input.query, { matchCase: input.caseSensitive });
157
+ const limited = typeof input.limit === "number" ? hits.slice(0, input.limit) : hits;
158
+ return limited;
159
+ },
160
+
161
+ getLocation(input: GetLocationInput) {
162
+ // @endStateApi — live-with-adapter. scopeId path composes
163
+ // handle.getScope(scopeId) + handle.getLocationForAnchor(scope.anchor).
164
+ // This replaced the earlier `runtime.debug.getSnapshot({scopeFilter})`
165
+ // composition (debug channel was an escape hatch around a missing L07
166
+ // seam; the typed scope+anchor path is the real L07 read). blockId
167
+ // input is NOT supported — no shipped blockId → anchor resolver —
168
+ // returns null.
169
+ if (input.scopeId) {
170
+ const scope = runtime.getScope(input.scopeId);
171
+ if (!scope) return null;
172
+ return runtime.getLocationForAnchor(scope.anchor) ?? null;
173
+ }
174
+ return null;
175
+ },
176
+
177
+ replaceText(input: ReplaceTextInput): ReplaceTextResult {
178
+ // @endStateApi — live-with-adapter (Slice 5). Routes through the
179
+ // Layer-08 compiler-service facade. Same pipeline as
180
+ // ai.applyReplacementScope; the host/UI path omits actionId (not
181
+ // an agent action) and tags origin:"ui" + actorId:"user".
182
+ const result = compiler.applyReplacement({
183
+ targetScopeId: input.scopeId,
184
+ operation: "replace",
185
+ proposedText: input.replacement,
186
+ actorId: "user",
187
+ origin: "ui",
188
+ emittedAtUtc: new Date(0).toISOString(),
189
+ });
190
+
191
+ emitUxResponse(runtime, {
192
+ apiFn: replaceTextMetadata.name,
193
+ intent: replaceTextMetadata.uxIntent.expectedDelta ?? "",
194
+ mockOrLive: "live",
195
+ uiVisible: true,
196
+ expectedDelta: replaceTextMetadata.uxIntent.expectedDelta,
197
+ });
198
+
199
+ return {
200
+ applied: result.applied,
201
+ ...(result.reason ? { reason: result.reason } : {}),
202
+ };
203
+ },
204
+
205
+ insertFragment(input: InsertFragmentInput): InsertFragmentResult {
206
+ // @endStateApi — live-with-adapter. Coord-07 §1.1 closed 2026-04-23
207
+ // after L08 §8 shipped the structured-fragment compile path
208
+ // (paragraph-kind). Delegates to the same compiler-service facade
209
+ // replaceText uses, flagging `proposedContent.kind = "structured"`
210
+ // so compileReplacement emits `fragment-replace` instead of
211
+ // `text-replace`. One ScopeActionAudit emits on the scope channel
212
+ // via the compiler's lifecycle.
213
+ const result = compiler.applyReplacement({
214
+ targetScopeId: input.scopeId,
215
+ operation: "replace",
216
+ proposedContent: { kind: "structured", structured: input.fragment },
217
+ actorId: "user",
218
+ origin: "ui",
219
+ emittedAtUtc: new Date(0).toISOString(),
220
+ });
221
+
222
+ emitUxResponse(runtime, {
223
+ apiFn: insertFragmentMetadata.name,
224
+ intent: insertFragmentMetadata.uxIntent.expectedDelta ?? "",
225
+ mockOrLive: "live",
226
+ uiVisible: true,
227
+ expectedDelta: insertFragmentMetadata.uxIntent.expectedDelta,
228
+ });
229
+
230
+ return {
231
+ applied: result.applied,
232
+ ...(result.reason ? { reason: result.reason } : {}),
233
+ };
234
+ },
235
+ };
236
+ }