@beyondwork/docx-react-component 1.0.66 → 1.0.69

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 -931
  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 -4795
  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,235 @@
1
+ /**
2
+ * @endStateApi v3 — `ai.attach` family.
3
+ *
4
+ * attachExplanation (live-with-adapter) / createIssue (live-with-adapter).
5
+ *
6
+ * Both route through the Layer-08 compiler-service facade
7
+ * (`createScopeCompilerService`), which wraps Layer-06's
8
+ * `attachScopeMetadata` writer. Metadata persists as
9
+ * `WorkflowMetadataEntry` records with stable `metadataId` prefixes
10
+ * (`ai.explanation`, `ai.issue`).
11
+ *
12
+ * Coverage: /06's derived-scope resolver (2026-04-23, `1a3d127e`) lets
13
+ * both paths succeed on paragraph-like derived scopeIds (`para:*`,
14
+ * `heading:*`, `li:*`) in addition to overlay scopes — no overlay
15
+ * promotion step required. Non-paragraph-like derived scopeIds (`table:*`,
16
+ * `field:*`, comment-thread, revision) return `{attached: false,
17
+ * reason: "scope-not-resolvable:<id>"}` / `{created: false, reason}`
18
+ * — the broader prefix reflects §13c's two-stage resolution (overlay
19
+ * miss then derived-resolver miss); pre-§13c was `scope-not-in-overlay:`.
20
+ *
21
+ * Architecture A4 — every mutating function emits exactly one
22
+ * `ScopeActionAudit` on the `scope` telemetry channel. The facade does
23
+ * not own audit emission for metadata writes; this module does, via
24
+ * `_metadata-audit.ts`. `applyReplacementScope`'s audit emission stays
25
+ * inside /08's replacement pipeline. Together the three mutating
26
+ * functions (`applyReplacementScope`, `attachExplanation`, `createIssue`)
27
+ * carry exactly-one-audit-per-mutation coverage.
28
+ */
29
+
30
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
31
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
32
+ import { mockId } from "../_mocks.ts";
33
+ import { emitUxResponse } from "../_ux-response.ts";
34
+ import { createScopeCompilerService } from "../../../runtime/scopes/index.ts";
35
+ import {
36
+ captureScopeSnapshot,
37
+ emitScopeMetadataAudit,
38
+ snapshotDocumentHash,
39
+ } from "./_metadata-audit.ts";
40
+
41
+ export interface AttachExplanationInput {
42
+ readonly scopeId: string;
43
+ readonly explanation: string;
44
+ }
45
+
46
+ export interface AttachExplanationResult {
47
+ readonly explanationId: string;
48
+ readonly attached: boolean;
49
+ /**
50
+ * Present when `attached: false`. Mirrors the primitive's refusal
51
+ * reason (`scope-not-resolvable:<scopeId>` post-coord-06 §13c;
52
+ * pre-§13c: `scope-not-in-overlay:<scopeId>`). Restored in
53
+ * `cross-layer-coord-09.md §1.17` — symmetry with
54
+ * `CreateIssueResult.reason`.
55
+ */
56
+ readonly reason?: string;
57
+ }
58
+
59
+ export const attachExplanationMetadata: ApiV3FnMetadata = {
60
+ name: "ai.attachExplanation",
61
+ status: "live-with-adapter",
62
+ sourceLayer: "semantic-scope-compiler",
63
+ liveEvidence: {
64
+ runnerTest: "test/runtime/scopes/attach-explanation.test.ts",
65
+ commit: "refactor-08-slice-6",
66
+ },
67
+ uxIntent: {
68
+ uiVisible: true,
69
+ expectsUxResponse: "inline-change",
70
+ expectedDelta: "scope card gains explanation chip",
71
+ },
72
+ agentMetadata: {
73
+ readOrMutate: "mutate",
74
+ boundedScope: "scope",
75
+ auditCategory: "explanation-attach",
76
+ },
77
+ stateClass: "A-canonical",
78
+ persistsTo: "customXml",
79
+ broadcastsVia: "crdt",
80
+ rwdReference:
81
+ "§AI API § ai.attachExplanation. Adapter: routes through the Layer-08 compiler-service facade with metadataId=ai.explanation. /06's derived-scope resolver (§13c) now handles paragraph/heading/list-item derived scopeIds in addition to overlay scopes. Returns `attached:false` with a typed `reason` on non-paragraph-like derived scopeIds (table/field/comment-thread/revision) and on unresolvable ids. Emits one ScopeActionAudit per successful attachment on the `scope` telemetry channel (A4).",
82
+ };
83
+
84
+ export interface CreateIssueInput {
85
+ readonly scopeId: string;
86
+ readonly summary: string;
87
+ readonly severity?: "info" | "warning" | "error";
88
+ }
89
+
90
+ export interface CreateIssueResult {
91
+ readonly issueId: string;
92
+ readonly created: boolean;
93
+ readonly reason?: string;
94
+ }
95
+
96
+ export const createIssueMetadata: ApiV3FnMetadata = {
97
+ name: "ai.createIssue",
98
+ status: "live-with-adapter",
99
+ sourceLayer: "semantic-scope-compiler",
100
+ liveEvidence: {
101
+ runnerTest: "test/runtime/scopes/create-issue.test.ts",
102
+ commit: "refactor-08-slice-6",
103
+ },
104
+ uxIntent: {
105
+ uiVisible: true,
106
+ expectsUxResponse: "warning-added",
107
+ expectedDelta: "issue rail shows new issue card",
108
+ },
109
+ agentMetadata: {
110
+ readOrMutate: "mutate",
111
+ boundedScope: "scope",
112
+ auditCategory: "issue-create",
113
+ },
114
+ stateClass: "A-canonical",
115
+ persistsTo: "customXml",
116
+ broadcastsVia: "crdt",
117
+ rwdReference:
118
+ "§AI API § ai.createIssue. Adapter: routes through the Layer-08 compiler-service facade with metadataId=ai.issue; issues are metadata entries keyed by issueId carrying {summary, severity, status, createdAtUtc}. /06's derived-scope resolver (§13c) now handles paragraph/heading/list-item derived scopeIds in addition to overlay scopes. Returns `created:false` with a typed `reason` on non-paragraph-like derived scopeIds and on unresolvable ids. Emits one ScopeActionAudit per successful issue creation on the `scope` telemetry channel (A4).",
119
+ };
120
+
121
+ export function createAttachFamily(runtime: RuntimeApiHandle) {
122
+ const compiler = createScopeCompilerService(runtime);
123
+ return {
124
+ attachExplanation(input: AttachExplanationInput): AttachExplanationResult {
125
+ // @endStateApi — live-with-adapter (Slice 6). Routes through the
126
+ // Layer-08 compiler-service facade.
127
+ //
128
+ // A4 wiring: capture scope snapshot + document hash BEFORE the
129
+ // primitive runs (the scope can shift post-mutation if a same-
130
+ // session replacement just ran); on `attached: true` emit one
131
+ // `ScopeActionAudit` with `operation: "annotate"`. `attached:
132
+ // false` (scope-not-on-overlay) → no mutation → no audit.
133
+ const explanationId = mockId(
134
+ runtime.getSessionState().documentId,
135
+ `explanation-${input.scopeId}`,
136
+ );
137
+ const preScope = captureScopeSnapshot(runtime, input.scopeId);
138
+ const documentHashBefore = snapshotDocumentHash(runtime);
139
+ const primitiveResult = compiler.attachExplanation({
140
+ scopeId: input.scopeId,
141
+ explanation: input.explanation,
142
+ explanationId,
143
+ });
144
+ if (primitiveResult.attached && preScope) {
145
+ emitScopeMetadataAudit({
146
+ runtime,
147
+ actionId: attachExplanationMetadata.name,
148
+ scopeId: input.scopeId,
149
+ targetScopeSnapshot: preScope,
150
+ proposedContent: {
151
+ kind: "explanation",
152
+ payload: {
153
+ explanationId: primitiveResult.explanationId,
154
+ explanation: input.explanation,
155
+ },
156
+ },
157
+ compiledOperationKind: "metadata-attach-explanation",
158
+ compiledOperationSummary: `attach explanation ${primitiveResult.explanationId} to scope ${input.scopeId}`,
159
+ emittedAtUtc: new Date(0).toISOString(),
160
+ documentHashBefore,
161
+ });
162
+ }
163
+ emitUxResponse(runtime, {
164
+ apiFn: attachExplanationMetadata.name,
165
+ intent: attachExplanationMetadata.uxIntent.expectedDelta ?? "",
166
+ mockOrLive: "live",
167
+ uiVisible: true,
168
+ expectedDelta: attachExplanationMetadata.uxIntent.expectedDelta,
169
+ });
170
+ return {
171
+ explanationId: primitiveResult.explanationId,
172
+ attached: primitiveResult.attached,
173
+ // §1.17 — surface primitive's reason on refusal for symmetry
174
+ // with CreateIssueResult. The primitive returns `reason` only
175
+ // when `attached: false`; passthrough preserves that contract.
176
+ ...(primitiveResult.attached
177
+ ? {}
178
+ : { reason: (primitiveResult as { reason?: string }).reason }),
179
+ };
180
+ },
181
+
182
+ createIssue(input: CreateIssueInput): CreateIssueResult {
183
+ // @endStateApi — live-with-adapter (Slice 6). Routes through the
184
+ // Layer-08 compiler-service facade.
185
+ //
186
+ // A4 wiring: same pattern as attachExplanation — pre-snapshot +
187
+ // primitive + audit on the happy path only.
188
+ const issueId = mockId(
189
+ runtime.getSessionState().documentId,
190
+ `issue-${input.scopeId}`,
191
+ );
192
+ const preScope = captureScopeSnapshot(runtime, input.scopeId);
193
+ const documentHashBefore = snapshotDocumentHash(runtime);
194
+ const primitiveResult = compiler.createIssue({
195
+ scopeId: input.scopeId,
196
+ summary: input.summary,
197
+ ...(input.severity ? { severity: input.severity } : {}),
198
+ issueId,
199
+ });
200
+ if (primitiveResult.created && preScope) {
201
+ emitScopeMetadataAudit({
202
+ runtime,
203
+ actionId: createIssueMetadata.name,
204
+ scopeId: input.scopeId,
205
+ targetScopeSnapshot: preScope,
206
+ proposedContent: {
207
+ kind: "issue",
208
+ payload: {
209
+ issueId: primitiveResult.issueId,
210
+ summary: input.summary,
211
+ ...(input.severity ? { severity: input.severity } : {}),
212
+ },
213
+ },
214
+ compiledOperationKind: "metadata-attach-issue",
215
+ compiledOperationSummary: `create issue ${primitiveResult.issueId} on scope ${input.scopeId}`,
216
+ emittedAtUtc: new Date(0).toISOString(),
217
+ documentHashBefore,
218
+ });
219
+ }
220
+ emitUxResponse(runtime, {
221
+ apiFn: createIssueMetadata.name,
222
+ intent: createIssueMetadata.uxIntent.expectedDelta ?? "",
223
+ mockOrLive: "live",
224
+ uiVisible: true,
225
+ expectedDelta: createIssueMetadata.uxIntent.expectedDelta,
226
+ });
227
+ const out: CreateIssueResult = {
228
+ issueId: primitiveResult.issueId,
229
+ created: primitiveResult.created,
230
+ ...(primitiveResult.created ? {} : { reason: primitiveResult.reason }),
231
+ };
232
+ return out;
233
+ },
234
+ };
235
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @endStateApi v3 — `ai.bundle` family.
3
+ *
4
+ * Slice 3 of refactor/08 graduated `getScopeBundle` from `mock` to
5
+ * `live-with-adapter`. Delegates to `compileScopeBundleById` from
6
+ * `src/runtime/scopes/`.
7
+ *
8
+ * Slice 1 of refactor/09 adds `getScope({handle}): SemanticScope | null` —
9
+ * the handle-shaped reader that surfaces the full compiled scope without
10
+ * its neighborhood + evidence. Architecture contract A3
11
+ * (scope-handle-first) + A9 (plain immutable values).
12
+ *
13
+ * The caller MUST pin `nowUtc` — we do not fall back to `new Date()` here,
14
+ * because a wall-clock `generatedAtUtc` makes `ScopeBundle` non-deterministic
15
+ * and violates S3 (identical runtime inputs → identical compiler output).
16
+ * Host wrappers supply a clock; tests supply a fixed string.
17
+ */
18
+
19
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
20
+ import {
21
+ createScopeCompilerService,
22
+ type ScopeHandle,
23
+ type ScopeBundle as RuntimeScopeBundle,
24
+ type SemanticScope,
25
+ } from "../../../runtime/scopes/index.ts";
26
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
27
+
28
+ /**
29
+ * Handle-shaped input (architecture A3 — scope-handle-first targeting).
30
+ *
31
+ * Slice 1 of refactor/09 accepted a transitional `{scopeId} | {handle}`
32
+ * union; Slice 2 tightens to `{handle}` only. `resolveReference` is the
33
+ * canonical way to obtain a handle when a caller only has a bookmark
34
+ * name, offset, or scope id.
35
+ */
36
+ export interface GetScopeBundleInput {
37
+ readonly handle: ScopeHandle;
38
+ /**
39
+ * ISO-8601 UTC timestamp to stamp into `ScopeBundle.generatedAtUtc`.
40
+ * Required — see the module docstring for the determinism rationale.
41
+ */
42
+ readonly nowUtc: string;
43
+ }
44
+
45
+ /** Re-export the runtime-side `ScopeBundle` so v3 consumers get the rich shape. */
46
+ export type { RuntimeScopeBundle as ScopeBundle };
47
+
48
+ export interface ScopeBundleNotFound {
49
+ readonly notFound: true;
50
+ readonly scopeId: string;
51
+ readonly reason: string;
52
+ }
53
+
54
+ export interface GetScopeInput {
55
+ readonly handle: ScopeHandle;
56
+ }
57
+
58
+ export const getScopeMetadata: ApiV3FnMetadata = {
59
+ name: "ai.getScope",
60
+ status: "live-with-adapter",
61
+ sourceLayer: "semantic-scope-compiler",
62
+ liveEvidence: {
63
+ runnerTest: "test/api/v3/ai/ai-get-scope.test.ts",
64
+ commit: "refactor-09-slice-1",
65
+ },
66
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
67
+ agentMetadata: {
68
+ readOrMutate: "read",
69
+ boundedScope: "scope",
70
+ auditCategory: "scope-read",
71
+ contextPromptShape:
72
+ "Full SemanticScope for a handle — handle + kind + content + formatting + layout + geometry + workflow + replaceability + audit.",
73
+ },
74
+ stateClass: "A-canonical",
75
+ persistsTo: "canonical",
76
+ rwdReference: "§AI API § ai.getScope",
77
+ };
78
+
79
+ export const getScopeBundleMetadata: ApiV3FnMetadata = {
80
+ name: "ai.getScopeBundle",
81
+ status: "live-with-adapter",
82
+ sourceLayer: "semantic-scope-compiler",
83
+ liveEvidence: {
84
+ runnerTest:
85
+ "test/runtime/scopes/bundle-paragraph.test.ts,test/runtime/scopes/bundle-clause-with-review.test.ts",
86
+ commit: "refactor-08-slice-3",
87
+ },
88
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
89
+ agentMetadata: {
90
+ readOrMutate: "read",
91
+ boundedScope: "scope",
92
+ auditCategory: "scope-bundle",
93
+ contextPromptShape:
94
+ "Bundle content + formatting + layout + geometry + workflow + replaceability for prompt context.",
95
+ },
96
+ stateClass: "A-canonical",
97
+ persistsTo: "canonical",
98
+ rwdReference: "§AI API § ai.getScopeBundle",
99
+ };
100
+
101
+ export function createBundleFamily(runtime: RuntimeApiHandle) {
102
+ const compiler = createScopeCompilerService(runtime);
103
+ return {
104
+ getScope(input: GetScopeInput): SemanticScope | null {
105
+ // @endStateApi — live-with-adapter. Routes through the compiler-
106
+ // service facade. Returns null when the scopeId does not enumerate
107
+ // (handle drift, caller error, marker-backed scope on a different
108
+ // story target, etc.).
109
+ const compiled = compiler.compileScopeById(input.handle.scopeId);
110
+ return compiled?.scope ?? null;
111
+ },
112
+
113
+ getScopeBundle(input: GetScopeBundleInput): RuntimeScopeBundle | ScopeBundleNotFound {
114
+ // @endStateApi — live-with-adapter. Routes through the compiler-
115
+ // service facade.
116
+ //
117
+ // Slice 2 tightened input to `{handle}` only — A3 scope-handle-first.
118
+ // Callers with only a scope id / bookmark / offset resolve through
119
+ // `ai.resolveReference` first.
120
+ const { scopeId } = input.handle;
121
+ const bundle = compiler.compileBundleById(scopeId, input.nowUtc);
122
+ if (!bundle) {
123
+ return {
124
+ notFound: true,
125
+ scopeId,
126
+ reason: "no scope with this id in canonical document or review store",
127
+ };
128
+ }
129
+ return bundle;
130
+ },
131
+ };
132
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @endStateApi v3 — `ai.explain` family.
3
+ *
4
+ * explainFormatting — agent-facing formatting-provenance view for a run.
5
+ *
6
+ * Returns `{ effective, provenance, explanation }` where `effective` is the
7
+ * fully-cascaded formatting, `provenance` is the per-property source map
8
+ * (`direct` / `characterStyle` / `style` / `docDefaults` + `sourceId` for
9
+ * the style tiers), and `explanation` is a plain-text human-readable
10
+ * summary an agent can surface directly.
11
+ *
12
+ * Thin adapter over Layer-03's `FormattingContext.resolveRunWithProvenance`
13
+ * (shipped substrate, live on `runtime.formatting.resolveRunWithProvenance`).
14
+ * No new derivation — this function re-shapes the existing provenance
15
+ * record into an agent-prompt-friendly carrier.
16
+ *
17
+ * Cross-layer-coord history: filed by /03 §3 "L09 consume
18
+ * resolveRunWithProvenance" (2026-04-22). Closes that ask.
19
+ */
20
+
21
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
22
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
23
+ import {
24
+ createFormattingContext,
25
+ type EffectiveRunFormatting,
26
+ type RunProvenance,
27
+ type RunResolvedProperty,
28
+ } from "../../../runtime/formatting/index.ts";
29
+ import {
30
+ findParagraphByBlockId,
31
+ resolveDirectRunFormattingAtSegment,
32
+ } from "../../../runtime/formatting/document-lookup.ts";
33
+
34
+ export interface ExplainFormattingInput {
35
+ readonly blockId: string;
36
+ readonly runId: string;
37
+ }
38
+
39
+ export interface ExplainFormattingResult {
40
+ /** Fully-cascaded effective formatting for the run (direct → charStyle → paraStyle → docDefaults). */
41
+ readonly effective: EffectiveRunFormatting;
42
+ /** Per-property provenance map — which cascade tier contributed each value, and its sourceId where relevant. */
43
+ readonly provenance: {
44
+ readonly [K in keyof RunProvenance["properties"]]?: RunResolvedProperty;
45
+ };
46
+ /** Plain-text human-readable summary agents surface directly to users. */
47
+ readonly explanation: string;
48
+ }
49
+
50
+ /**
51
+ * Not-found record — distinct from a run with no populated formatting
52
+ * (which returns a valid result with empty `effective`).
53
+ */
54
+ export interface ExplainFormattingNotFound {
55
+ readonly notFound: true;
56
+ readonly blockId: string;
57
+ readonly runId: string;
58
+ readonly reason: string;
59
+ }
60
+
61
+ export const explainFormattingMetadata: ApiV3FnMetadata = {
62
+ name: "ai.explainFormatting",
63
+ status: "live-with-adapter",
64
+ sourceLayer: "formatting-semantics",
65
+ liveEvidence: {
66
+ runnerTest:
67
+ "test/api/v3/ai/ai-explain-formatting.test.ts,test/runtime/formatting/provenance.test.ts",
68
+ commit: "refactor-09-slice-5",
69
+ },
70
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
71
+ agentMetadata: {
72
+ readOrMutate: "read",
73
+ boundedScope: "scope",
74
+ auditCategory: "formatting-explain",
75
+ contextPromptShape:
76
+ "Explain why a run looks the way it does — effective formatting + per-property cascade source (direct / characterStyle / paragraphStyle / docDefaults) + plain-text summary.",
77
+ },
78
+ stateClass: "A-canonical",
79
+ persistsTo: "canonical",
80
+ rwdReference:
81
+ "§AI API § ai.explainFormatting. Adapter: re-shapes FormattingContext.resolveRunWithProvenance into an agent-friendly carrier. Closes cross-layer-coord-03.md §3 (L09 consume resolveRunWithProvenance).",
82
+ };
83
+
84
+ /**
85
+ * Build a plain-text summary from a provenance map. Keeps the output
86
+ * short (one line) and deterministic — property order fixed.
87
+ */
88
+ function formatExplanation(provenance: RunProvenance["properties"]): string {
89
+ const lines: string[] = [];
90
+ const entries = [
91
+ ["bold", (provenance as { bold?: RunResolvedProperty }).bold],
92
+ ["italic", (provenance as { italic?: RunResolvedProperty }).italic],
93
+ ["fontFamily", (provenance as { fontFamily?: RunResolvedProperty }).fontFamily],
94
+ ["fontSize", (provenance as { fontSize?: RunResolvedProperty }).fontSize],
95
+ ["color", (provenance as { color?: RunResolvedProperty }).color],
96
+ ] as const;
97
+ for (const [name, record] of entries) {
98
+ if (!record) continue;
99
+ const value = String(record.value);
100
+ const sourceId = record.sourceId ? ` (${record.sourceId})` : "";
101
+ lines.push(`${name}=${value} from ${record.source}${sourceId}`);
102
+ }
103
+ return lines.length === 0
104
+ ? "no formatting properties resolved"
105
+ : lines.join("; ");
106
+ }
107
+
108
+ export function createExplainFamily(runtime: RuntimeApiHandle) {
109
+ return {
110
+ explainFormatting(
111
+ input: ExplainFormattingInput,
112
+ ): ExplainFormattingResult | ExplainFormattingNotFound {
113
+ // @endStateApi — live-with-adapter. Delegates to Layer-03's
114
+ // FormattingContext.resolveRunWithProvenance (same substrate as
115
+ // runtime.formatting.resolveRunWithProvenance); re-shapes the
116
+ // provenance record with an agent-facing `explanation` string.
117
+ const doc = runtime.getCanonicalDocument();
118
+ const foundPara = findParagraphByBlockId(doc, input.blockId);
119
+ if (!foundPara) {
120
+ return {
121
+ notFound: true,
122
+ blockId: input.blockId,
123
+ runId: input.runId,
124
+ reason: "no paragraph with this blockId in canonical document",
125
+ };
126
+ }
127
+ const direct = resolveDirectRunFormattingAtSegment(
128
+ foundPara.paragraph,
129
+ input.runId,
130
+ );
131
+ const ctx = createFormattingContext(doc);
132
+ const provenance = ctx.resolveRunWithProvenance({
133
+ paragraphStyleId: foundPara.paragraph.styleId,
134
+ characterStyleId: direct?.characterStyleId,
135
+ direct,
136
+ });
137
+ return {
138
+ effective: provenance.run,
139
+ provenance: provenance.properties,
140
+ explanation: formatExplanation(provenance.properties),
141
+ };
142
+ },
143
+ };
144
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @endStateApi v3 — `ai.export` family.
3
+ *
4
+ * exportReviewedDocument — live (delegates to runtime.document.export).
5
+ */
6
+
7
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
8
+ import type { ExportDocxOptions, ExportResult } from "../../public-types.ts";
9
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
10
+ import { emitUxResponse } from "../_ux-response.ts";
11
+
12
+ export const exportReviewedDocumentMetadata: ApiV3FnMetadata = {
13
+ name: "ai.exportReviewedDocument",
14
+ status: "live",
15
+ sourceLayer: "ai",
16
+ liveEvidence: {
17
+ runnerTest: "services/debug/lib/session-manager.test.ts",
18
+ probeScript: "services/debug/scripts/probe-channel-emissions.ts",
19
+ commit: "6aca0666",
20
+ },
21
+ uxIntent: {
22
+ uiVisible: true,
23
+ expectsUxResponse: "toast",
24
+ expectedDelta: "toast shows export bytes size + completion; filename reflects review posture",
25
+ },
26
+ agentMetadata: {
27
+ readOrMutate: "read",
28
+ boundedScope: "document",
29
+ auditCategory: "document-export-reviewed",
30
+ contextPromptShape: "Export the document with review artefacts applied; same bytes as runtime.document.export today.",
31
+ },
32
+ stateClass: "A-canonical",
33
+ persistsTo: "canonical",
34
+ rwdReference: "§AI API § ai.exportReviewedDocument",
35
+ };
36
+
37
+ export function createExportFamily(runtime: RuntimeApiHandle) {
38
+ return {
39
+ async exportReviewedDocument(options?: ExportDocxOptions): Promise<ExportResult> {
40
+ // @endStateApi — live. Delegates to the live export path. Future review-
41
+ // posture filtering happens in Phase 5 (Apply replacement-scope lifecycle).
42
+ const result = await runtime.exportDocx(options);
43
+ emitUxResponse(runtime, {
44
+ apiFn: exportReviewedDocumentMetadata.name,
45
+ intent: exportReviewedDocumentMetadata.uxIntent.expectedDelta ?? "",
46
+ mockOrLive: "live",
47
+ uiVisible: true,
48
+ expectedDelta: exportReviewedDocumentMetadata.uxIntent.expectedDelta,
49
+ actualDelta: { kind: "toast", payload: { bytes: result.bytes?.byteLength ?? 0 } },
50
+ });
51
+ return result;
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @endStateApi v3 — `ai.inspect` family.
3
+ *
4
+ * Slice 2 of refactor/08 graduated both functions from `partial` →
5
+ * `live-with-adapter`. Live path delegates to `src/runtime/scopes/` via
6
+ * an adapter that reads canonical + overlay from the runtime.
7
+ *
8
+ * The v3 surface stays a thin shim — semantic-scope compilation lives
9
+ * under `src/runtime/scopes/**` (layer 08), not here.
10
+ */
11
+
12
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
13
+ import {
14
+ createScopeCompilerService,
15
+ type SemanticScope,
16
+ type SemanticScopeKind,
17
+ } from "../../../runtime/scopes/index.ts";
18
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
19
+
20
+ export interface InspectDocumentResult {
21
+ readonly documentId: string;
22
+ readonly scopeCount: number;
23
+ readonly pageCount?: number;
24
+ readonly semanticSummary: string;
25
+ readonly kindDistribution: Readonly<Partial<Record<SemanticScopeKind, number>>>;
26
+ }
27
+
28
+ export const inspectDocumentMetadata: ApiV3FnMetadata = {
29
+ name: "ai.inspectDocument",
30
+ status: "live-with-adapter",
31
+ sourceLayer: "semantic-scope-compiler",
32
+ liveEvidence: {
33
+ runnerTest:
34
+ "test/runtime/scopes/compile-paragraph.test.ts,test/runtime/scopes/compile-table.test.ts,test/runtime/scopes/compile-clause.test.ts",
35
+ commit: "refactor-08-slice-2",
36
+ },
37
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
38
+ agentMetadata: {
39
+ readOrMutate: "read",
40
+ boundedScope: "document",
41
+ auditCategory: "document-inspect",
42
+ contextPromptShape:
43
+ "Summarize document by scope count + page count + semantic kind distribution.",
44
+ },
45
+ stateClass: "A-canonical",
46
+ persistsTo: "canonical",
47
+ rwdReference: "§AI API § ai.inspectDocument",
48
+ };
49
+
50
+ export const listScopesMetadata: ApiV3FnMetadata = {
51
+ name: "ai.listScopes",
52
+ status: "live-with-adapter",
53
+ sourceLayer: "semantic-scope-compiler",
54
+ liveEvidence: {
55
+ runnerTest:
56
+ "test/runtime/scopes/compile-paragraph.test.ts,test/runtime/scopes/compile-table.test.ts,test/runtime/scopes/compile-clause.test.ts",
57
+ commit: "refactor-08-slice-2",
58
+ },
59
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
60
+ agentMetadata: {
61
+ readOrMutate: "read",
62
+ boundedScope: "document",
63
+ auditCategory: "scope-list",
64
+ contextPromptShape:
65
+ "List scopes with scopeId + kind + semanticPath for agent selection.",
66
+ },
67
+ stateClass: "A-canonical",
68
+ persistsTo: "canonical",
69
+ rwdReference: "§AI API § ai.listScopes",
70
+ };
71
+
72
+ function buildKindDistribution(
73
+ scopes: readonly SemanticScope[],
74
+ ): Partial<Record<SemanticScopeKind, number>> {
75
+ const out: Partial<Record<SemanticScopeKind, number>> = {};
76
+ for (const scope of scopes) {
77
+ out[scope.kind] = (out[scope.kind] ?? 0) + 1;
78
+ }
79
+ return out;
80
+ }
81
+
82
+ export function createInspectFamily(runtime: RuntimeApiHandle) {
83
+ const compiler = createScopeCompilerService(runtime);
84
+ return {
85
+ inspectDocument(): InspectDocumentResult {
86
+ // @endStateApi — live-with-adapter. Routes through the Layer-08
87
+ // compiler-service facade (src/runtime/scopes/compiler-service.ts).
88
+ const state = runtime.getSessionState();
89
+ const scopes = compiler.compileAllScopes();
90
+ const kindDistribution = buildKindDistribution(scopes);
91
+ const summary =
92
+ scopes.length === 0
93
+ ? "empty document or no enumerable scopes"
94
+ : `${scopes.length} semantic scope(s) compiled across ${Object.keys(kindDistribution).length} kind(s)`;
95
+ return {
96
+ documentId: state.documentId,
97
+ scopeCount: scopes.length,
98
+ semanticSummary: summary,
99
+ kindDistribution,
100
+ };
101
+ },
102
+
103
+ listScopes(filter?: { readonly limit?: number; readonly kind?: SemanticScopeKind }) {
104
+ // @endStateApi — live-with-adapter. Routes through the compiler-
105
+ // service facade and applies filter/limit over the compiled scope
106
+ // list. Always return a fresh array so agent code that sorts /
107
+ // splices the result never leaks into the internal scope list.
108
+ const scopes = compiler.compileAllScopes();
109
+ const byKind = filter?.kind
110
+ ? scopes.filter((scope) => scope.kind === filter.kind)
111
+ : scopes.slice();
112
+ if (typeof filter?.limit === "number") {
113
+ return byKind.slice(0, filter.limit);
114
+ }
115
+ return byKind;
116
+ },
117
+ };
118
+ }