@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,431 @@
1
+ /**
2
+ * Slice 7 adversarial-closure pass — Layer 8 compiler-service facade.
3
+ *
4
+ * A single runtime-side entry point for compiler orchestration. Before
5
+ * this module, v3 adapters each reconstructed the enumerate + compile
6
+ * + position-map dance in isolation:
7
+ *
8
+ * const doc = runtime.getCanonicalDocument();
9
+ * const overlay = runtime.getWorkflowOverlay();
10
+ * const paragraphIndexByBlockIndex = buildParagraphIndexMap(doc);
11
+ * for (const entry of enumerateScopes(doc, { overlay })) {
12
+ * const scope = compileScope(entry, {...});
13
+ * ...
14
+ * }
15
+ *
16
+ * The duplication drifted easily — different files rebuilt the setup
17
+ * with subtly different option threading, and "boundary" was a
18
+ * maintenance claim more than a shape.
19
+ *
20
+ * The compiler-service consolidates that orchestration. v3 adapters
21
+ * call `createScopeCompilerService(runtime).{compileAllScopes, compileScopeById,
22
+ * compileBundleById, applyReplacement, attachExplanation, createIssue}`.
23
+ * Each call is a fresh compile — no caching across calls (S3
24
+ * determinism). Within a single call, the paragraph-index-map is
25
+ * built once and threaded to every `compileScope` invocation.
26
+ *
27
+ * The runtime interface is declared narrowly (`CompilerServiceRuntime`)
28
+ * rather than depending on the full `RuntimeApiHandle`, so the facade
29
+ * is unit-testable with a plain object and the compiler layer stays
30
+ * free of upward imports it does not need.
31
+ */
32
+
33
+ import type {
34
+ CompatibilityReport,
35
+ InteractionGuardSnapshot,
36
+ ScopeSessionState,
37
+ WorkflowMetadataEntry,
38
+ WorkflowMetadataSnapshot,
39
+ WorkflowOverlay,
40
+ } from "./_scope-dependencies.ts";
41
+ import type { CanonicalDocumentEnvelope } from "../../core/state/editor-state.ts";
42
+ import type { TelemetryBus } from "../debug/telemetry-bus.ts";
43
+ import type { AIAction } from "../workflow/ai-action-policy.ts";
44
+
45
+ import {
46
+ buildParagraphIndexMap,
47
+ buildSectionIndexByBlockIndex,
48
+ compileScope,
49
+ } from "./compile-scope.ts";
50
+ import { compileScopeBundleById } from "./compile-scope-bundle.ts";
51
+ import { enumerateScopes, type EnumeratedScope } from "./enumerate-scopes.ts";
52
+ import {
53
+ attachExplanation,
54
+ type AttachExplanationResult,
55
+ } from "./attach-explanation.ts";
56
+ import {
57
+ createIssue,
58
+ type CreateIssueResult,
59
+ type IssueSeverity,
60
+ type IssueStatus,
61
+ } from "./create-issue.ts";
62
+ import {
63
+ applyScopeReplacement,
64
+ type ApplyScopeReplacementResult,
65
+ } from "./replacement/apply.ts";
66
+ import { proposeReplacement } from "./replacement/propose.ts";
67
+ import type {
68
+ ReplacementOperationKind,
69
+ ReplacementPreservePolicy,
70
+ ReplacementScope,
71
+ RuntimeOperationPlan,
72
+ ScopeBundle,
73
+ ScopeHandle,
74
+ SemanticScope,
75
+ } from "./semantic-scope-types.ts";
76
+
77
+ /**
78
+ * Narrow runtime-side interface the compiler-service reads + dispatches
79
+ * through. Declared inline rather than importing the v3 `RuntimeApiHandle`
80
+ * because:
81
+ *
82
+ * 1. `src/runtime/scopes/` must not import from `src/api/v3/**` (purity
83
+ * guard); declaring the shape here keeps the dependency downward.
84
+ * 2. Unit tests can satisfy this with a plain object — no full runtime
85
+ * needed.
86
+ * 3. Any real `DocumentRuntime` structurally satisfies it because its
87
+ * methods carry the same public-types shapes.
88
+ */
89
+ export interface CompilerServiceRuntime {
90
+ getCanonicalDocument(): CanonicalDocumentEnvelope;
91
+ getWorkflowOverlay(): WorkflowOverlay | null;
92
+ getInteractionGuardSnapshot(): InteractionGuardSnapshot;
93
+ getCompatibilityReport(): CompatibilityReport;
94
+ getWorkflowMetadataSnapshot(): WorkflowMetadataSnapshot;
95
+ setWorkflowMetadataEntries(entries: readonly WorkflowMetadataEntry[]): void;
96
+ getSessionState(): ScopeSessionState;
97
+ applyScopeReplacement(plan: RuntimeOperationPlan): void;
98
+ debug?: { bus: TelemetryBus };
99
+ }
100
+
101
+ export interface CompileScopeByIdResult {
102
+ readonly scope: SemanticScope;
103
+ readonly document: CanonicalDocumentEnvelope;
104
+ readonly enumerated: EnumeratedScope;
105
+ }
106
+
107
+ export interface ApplyReplacementRequest {
108
+ readonly targetScopeId: string;
109
+ readonly operation: ReplacementOperationKind;
110
+ /**
111
+ * Flat text payload. Shorthand for
112
+ * `proposedContent: {kind: "text", text}`. Ignored when
113
+ * `proposedContent` is supplied.
114
+ */
115
+ readonly proposedText?: string;
116
+ /**
117
+ * Full proposed-content shape. Use this for structured-fragment
118
+ * replacement (`kind: "structured"` with a
119
+ * `CanonicalDocumentFragment`-shaped payload). Unblocks /09
120
+ * `cross-layer-coord-09.md §1.5`: v3 consumers that need to pass a
121
+ * structured fragment through `ai.applyReplacementScope` supply it
122
+ * here. Widened 2026-04-22 after L08's structured-fragment runtime
123
+ * dispatch shipped (see `cross-layer-coord-08.md §8`).
124
+ */
125
+ readonly proposedContent?: ReplacementScope["proposedContent"];
126
+ readonly preserve?: ReplacementPreservePolicy;
127
+ readonly reason?: string;
128
+ readonly actionId?: AIAction;
129
+ readonly actorId: string;
130
+ readonly origin: "ui" | "agent" | "host";
131
+ readonly emittedAtUtc: string;
132
+ }
133
+
134
+ export interface AttachExplanationRequest {
135
+ readonly scopeId: string;
136
+ readonly explanation: string;
137
+ readonly explanationId?: string;
138
+ readonly createdAtUtc?: string;
139
+ }
140
+
141
+ export interface CreateIssueRequest {
142
+ readonly scopeId: string;
143
+ readonly summary: string;
144
+ readonly severity?: IssueSeverity;
145
+ readonly issueId?: string;
146
+ readonly createdAtUtc?: string;
147
+ readonly status?: IssueStatus;
148
+ }
149
+
150
+ export interface ScopeCompilerService {
151
+ /**
152
+ * Enumerate + compile every live scope in the document. Per-call the
153
+ * paragraph-index-map is built once and shared across every compile.
154
+ * Callers filter / limit on the returned array.
155
+ */
156
+ compileAllScopes(): SemanticScope[];
157
+
158
+ /**
159
+ * Resolve a scopeId against the live enumeration + compile it. Returns
160
+ * null when the id does not enumerate. Also surfaces the raw
161
+ * `EnumeratedScope` + `document` so callers that need to compose a
162
+ * downstream operation (e.g. per-kind replacement compile) do not have
163
+ * to re-enumerate.
164
+ */
165
+ compileScopeById(scopeId: string): CompileScopeByIdResult | null;
166
+
167
+ /**
168
+ * Compile a `ScopeBundle` keyed by id. Delegates to
169
+ * `compileScopeBundleById`; `nowUtc` is caller-supplied per S3
170
+ * (determinism) — no `new Date()` fallback.
171
+ */
172
+ compileBundleById(scopeId: string, nowUtc: string): ScopeBundle | null;
173
+
174
+ /**
175
+ * Build a `ReplacementScope` from a plain request + the resolved
176
+ * handle. The `proposedAtUtc` stamp is caller-supplied; pass a fixed
177
+ * reference instant in tests.
178
+ */
179
+ buildReplacementScope(
180
+ targetHandle: ScopeHandle,
181
+ input: {
182
+ readonly operation: ReplacementOperationKind;
183
+ readonly proposedText?: string;
184
+ readonly preserve?: ReplacementPreservePolicy;
185
+ readonly reason?: string;
186
+ readonly proposedAtUtc: string;
187
+ },
188
+ ): ReplacementScope;
189
+
190
+ /**
191
+ * Run the full propose → re-validate → compile → apply pipeline and
192
+ * emit exactly one `ScopeActionAudit` on the `scope` telemetry
193
+ * channel. Refuses with a typed `ApplyScopeReplacementResult` when
194
+ * validation is unsafe or compile refuses the kind; no dispatch
195
+ * happens in those cases.
196
+ */
197
+ applyReplacement(request: ApplyReplacementRequest): ApplyScopeReplacementResult;
198
+
199
+ /**
200
+ * Attach an agent-authored explanation via the Layer-06
201
+ * `attachScopeMetadata` writer. Resolves against the workflow
202
+ * overlay first, then falls back to a paragraph/heading/list-item
203
+ * derived-scope resolver (coord-06 §13c). Returns
204
+ * `{attached: false, reason: "scope-not-resolvable:…"}` for
205
+ * scopeIds neither path can resolve (e.g. `table:*`, `field:*`,
206
+ * arbitrary host strings).
207
+ */
208
+ attachExplanation(request: AttachExplanationRequest): AttachExplanationResult;
209
+
210
+ /**
211
+ * Create an agent-authored issue on an overlay scope. Same
212
+ * overlay-only constraint as `attachExplanation`.
213
+ */
214
+ createIssue(request: CreateIssueRequest): CreateIssueResult;
215
+ }
216
+
217
+ /**
218
+ * Factory for the Layer-08 compiler-service facade.
219
+ *
220
+ * Stateless — every call enumerates + compiles fresh. Callers pay the
221
+ * cost per call; callers that compile the same document repeatedly
222
+ * within a tight loop should hoist the `compileAllScopes()` result
223
+ * themselves (the compiler does not internally cache).
224
+ */
225
+ export function createScopeCompilerService(
226
+ runtime: CompilerServiceRuntime,
227
+ ): ScopeCompilerService {
228
+ function allEnumerated(): {
229
+ readonly document: CanonicalDocumentEnvelope;
230
+ readonly overlay: WorkflowOverlay | null;
231
+ readonly paragraphIndexByBlockIndex: ReturnType<typeof buildParagraphIndexMap>;
232
+ readonly sectionIndexByBlockIndex: ReturnType<typeof buildSectionIndexByBlockIndex>;
233
+ readonly entries: readonly EnumeratedScope[];
234
+ } {
235
+ const document = runtime.getCanonicalDocument();
236
+ const overlay = runtime.getWorkflowOverlay();
237
+ const paragraphIndexByBlockIndex = buildParagraphIndexMap(document);
238
+ const sectionIndexByBlockIndex = buildSectionIndexByBlockIndex(document);
239
+ const enumerateInputs = overlay ? { overlay } : {};
240
+ const entries = [...enumerateScopes(document, enumerateInputs)];
241
+ return {
242
+ document,
243
+ overlay,
244
+ paragraphIndexByBlockIndex,
245
+ sectionIndexByBlockIndex,
246
+ entries,
247
+ };
248
+ }
249
+
250
+ return {
251
+ compileAllScopes(): SemanticScope[] {
252
+ const {
253
+ document,
254
+ overlay,
255
+ paragraphIndexByBlockIndex,
256
+ sectionIndexByBlockIndex,
257
+ entries,
258
+ } = allEnumerated();
259
+ const out: SemanticScope[] = [];
260
+ for (const entry of entries) {
261
+ const compiled = compileScope(entry, {
262
+ document,
263
+ ...(overlay ? { overlay } : {}),
264
+ paragraphIndexByBlockIndex,
265
+ sectionIndexByBlockIndex,
266
+ });
267
+ if (compiled) out.push(compiled);
268
+ }
269
+ return out;
270
+ },
271
+
272
+ compileScopeById(scopeId: string): CompileScopeByIdResult | null {
273
+ const {
274
+ document,
275
+ overlay,
276
+ paragraphIndexByBlockIndex,
277
+ sectionIndexByBlockIndex,
278
+ entries,
279
+ } = allEnumerated();
280
+ for (const entry of entries) {
281
+ if (entry.handle.scopeId !== scopeId) continue;
282
+ const scope = compileScope(entry, {
283
+ document,
284
+ ...(overlay ? { overlay } : {}),
285
+ paragraphIndexByBlockIndex,
286
+ sectionIndexByBlockIndex,
287
+ });
288
+ if (scope) return { scope, document, enumerated: entry };
289
+ }
290
+ return null;
291
+ },
292
+
293
+ compileBundleById(scopeId: string, nowUtc: string): ScopeBundle | null {
294
+ const document = runtime.getCanonicalDocument();
295
+ const overlay = runtime.getWorkflowOverlay();
296
+ // Read-side join — thread metadata entries through so the bundle's
297
+ // evidence surfaces ai.explanation / ai.issue entries. Write
298
+ // operations go through `attachScopeMetadata` via this same
299
+ // runtime surface, so the snapshot is always fresh here.
300
+ const workflowMetadataEntries = runtime.getWorkflowMetadataSnapshot().entries;
301
+ return compileScopeBundleById(scopeId, {
302
+ document,
303
+ ...(overlay ? { overlay } : {}),
304
+ nowUtc,
305
+ catalog: document.styles,
306
+ workflowMetadataEntries,
307
+ });
308
+ },
309
+
310
+ buildReplacementScope(targetHandle, input) {
311
+ return proposeReplacement({
312
+ targetHandle,
313
+ operation: input.operation,
314
+ proposedContent:
315
+ typeof input.proposedText === "string"
316
+ ? { kind: "text", text: input.proposedText }
317
+ : { kind: "text", text: "" },
318
+ ...(input.preserve ? { preserve: input.preserve } : {}),
319
+ ...(input.reason ? { reason: input.reason } : {}),
320
+ proposedAtUtc: input.proposedAtUtc,
321
+ });
322
+ },
323
+
324
+ applyReplacement(
325
+ request: ApplyReplacementRequest,
326
+ ): ApplyScopeReplacementResult {
327
+ // Resolve + build the ReplacementScope fresh. `applyScopeReplacement`
328
+ // re-enumerates + re-compiles + re-validates on live state (§7 trap
329
+ // 2 — never trust a propose-time verdict).
330
+ const compiled = this.compileScopeById(request.targetScopeId);
331
+ if (!compiled) {
332
+ return {
333
+ applied: false,
334
+ reason: "scope-not-resolvable",
335
+ validation: {
336
+ safe: false,
337
+ blockedReasons: Object.freeze([
338
+ `scope-not-resolvable:${request.targetScopeId}`,
339
+ ]),
340
+ warnings: Object.freeze([]),
341
+ },
342
+ };
343
+ }
344
+ // Caller-supplied proposedContent takes precedence (structured-
345
+ // fragment path); otherwise we fall back to the flat-text
346
+ // shorthand via proposedText.
347
+ const proposed = request.proposedContent
348
+ ? proposeReplacement({
349
+ targetHandle: compiled.scope.handle,
350
+ operation: request.operation,
351
+ proposedContent: request.proposedContent,
352
+ ...(request.preserve ? { preserve: request.preserve } : {}),
353
+ ...(request.reason ? { reason: request.reason } : {}),
354
+ proposedAtUtc: request.emittedAtUtc,
355
+ })
356
+ : this.buildReplacementScope(compiled.scope.handle, {
357
+ operation: request.operation,
358
+ ...(request.proposedText !== undefined
359
+ ? { proposedText: request.proposedText }
360
+ : {}),
361
+ ...(request.preserve ? { preserve: request.preserve } : {}),
362
+ ...(request.reason ? { reason: request.reason } : {}),
363
+ proposedAtUtc: request.emittedAtUtc,
364
+ });
365
+ return applyScopeReplacement({
366
+ sink: {
367
+ getCanonicalDocument: () => runtime.getCanonicalDocument(),
368
+ getWorkflowOverlay: () => runtime.getWorkflowOverlay(),
369
+ getInteractionGuardSnapshot: () =>
370
+ runtime.getInteractionGuardSnapshot(),
371
+ getCompatibilityReport: () => runtime.getCompatibilityReport(),
372
+ applyScopeReplacement: (plan) => runtime.applyScopeReplacement(plan),
373
+ },
374
+ proposed,
375
+ ...(request.actionId ? { actionId: request.actionId } : {}),
376
+ actorId: request.actorId,
377
+ origin: request.origin,
378
+ emittedAtUtc: request.emittedAtUtc,
379
+ ...(runtime.debug?.bus ? { bus: runtime.debug.bus } : {}),
380
+ });
381
+ },
382
+
383
+ attachExplanation(
384
+ request: AttachExplanationRequest,
385
+ ): AttachExplanationResult {
386
+ return attachExplanation(
387
+ {
388
+ getWorkflowOverlay: () => runtime.getWorkflowOverlay(),
389
+ getWorkflowMetadataSnapshot: () =>
390
+ runtime.getWorkflowMetadataSnapshot(),
391
+ setWorkflowMetadataEntries: (entries) =>
392
+ runtime.setWorkflowMetadataEntries([...entries]),
393
+ getCanonicalDocument: () => runtime.getCanonicalDocument(),
394
+ },
395
+ {
396
+ scopeId: request.scopeId,
397
+ explanation: request.explanation,
398
+ ...(request.explanationId
399
+ ? { explanationId: request.explanationId }
400
+ : {}),
401
+ ...(request.createdAtUtc
402
+ ? { createdAtUtc: request.createdAtUtc }
403
+ : {}),
404
+ },
405
+ );
406
+ },
407
+
408
+ createIssue(request: CreateIssueRequest): CreateIssueResult {
409
+ return createIssue(
410
+ {
411
+ getWorkflowOverlay: () => runtime.getWorkflowOverlay(),
412
+ getWorkflowMetadataSnapshot: () =>
413
+ runtime.getWorkflowMetadataSnapshot(),
414
+ setWorkflowMetadataEntries: (entries) =>
415
+ runtime.setWorkflowMetadataEntries([...entries]),
416
+ getCanonicalDocument: () => runtime.getCanonicalDocument(),
417
+ },
418
+ {
419
+ scopeId: request.scopeId,
420
+ summary: request.summary,
421
+ ...(request.severity ? { severity: request.severity } : {}),
422
+ ...(request.issueId ? { issueId: request.issueId } : {}),
423
+ ...(request.createdAtUtc
424
+ ? { createdAtUtc: request.createdAtUtc }
425
+ : {}),
426
+ ...(request.status ? { status: request.status } : {}),
427
+ },
428
+ );
429
+ },
430
+ };
431
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Slice 6 — `ai.createIssue` live-with-adapter primitive.
3
+ *
4
+ * Creates an agent-authored issue record scoped to a handle by routing
5
+ * through Layer-06's `attachScopeMetadata` writer. The issue persists
6
+ * as a `WorkflowMetadataEntry` with `metadataId: "ai.issue"` and
7
+ * `value: {issueId, summary, severity, status, createdAtUtc}`.
8
+ *
9
+ * Issues are metadata records rather than a dedicated overlay section
10
+ * in this slice — matches the Slice-6 plan's "issue store is a new
11
+ * section on the workflow overlay" intent without requiring an
12
+ * overlay-schema minor bump. When CLM workblocks need richer lifecycle
13
+ * (resolve/reopen transitions, assigned owners), a follow-up sub-slice
14
+ * promotes issues to a first-class overlay kind and the storage
15
+ * migrates — the metadataId stays stable so callers don't break.
16
+ *
17
+ * Scope coverage (coord-06 §13c shipped 2026-04-23): both overlay
18
+ * (workflow) scopes AND derived paragraph / heading / list-item
19
+ * scopes are valid targets. Derived scopeIds resolve against the
20
+ * canonical document and produce an `ai.issue` entry whose anchor is
21
+ * the resolver's range output; the result carries
22
+ * `resolvedFrom: "derived"`. Non-paragraph-like scopeIds still
23
+ * return `created: false`.
24
+ */
25
+
26
+ import type {
27
+ AttachScopeMetadataResult,
28
+ MetadataWriterRuntime,
29
+ } from "../workflow/metadata-writer.ts";
30
+ import { attachScopeMetadata } from "../workflow/metadata-writer.ts";
31
+
32
+ /** Stable metadataId for AI-authored issues. */
33
+ export const AI_ISSUE_METADATA_ID = "ai.issue" as const;
34
+
35
+ export type IssueSeverity = "info" | "warning" | "error";
36
+ export type IssueStatus = "open" | "resolved";
37
+
38
+ export interface CreateIssueInput {
39
+ readonly scopeId: string;
40
+ readonly summary: string;
41
+ readonly severity?: IssueSeverity;
42
+ readonly issueId?: string;
43
+ readonly createdAtUtc?: string;
44
+ readonly status?: IssueStatus;
45
+ }
46
+
47
+ export type CreateIssueResult =
48
+ | {
49
+ readonly created: true;
50
+ readonly issueId: string;
51
+ readonly entryId: string;
52
+ /**
53
+ * Coord-06 §13c — `"overlay"` when the scope was on the workflow
54
+ * overlay, `"derived"` when it was a paragraph / heading /
55
+ * list-item scopeId resolved from the canonical document.
56
+ */
57
+ readonly resolvedFrom: "overlay" | "derived";
58
+ }
59
+ | {
60
+ readonly created: false;
61
+ readonly issueId: string;
62
+ /**
63
+ * `scope-not-resolvable:<scopeId>` — the scopeId is neither on
64
+ * the workflow overlay nor a paragraph-like derived id the
65
+ * canonical walk can resolve. Pre-§13c this was always
66
+ * `scope-not-in-overlay`.
67
+ */
68
+ readonly reason: string;
69
+ };
70
+
71
+ export function createIssue(
72
+ runtime: MetadataWriterRuntime,
73
+ input: CreateIssueInput,
74
+ ): CreateIssueResult {
75
+ const issueId = input.issueId ?? `issue-${input.scopeId}`;
76
+ const createdAtUtc = input.createdAtUtc ?? new Date(0).toISOString();
77
+ const severity: IssueSeverity = input.severity ?? "info";
78
+ const status: IssueStatus = input.status ?? "open";
79
+ const writerResult: AttachScopeMetadataResult = attachScopeMetadata(runtime, {
80
+ scopeId: input.scopeId,
81
+ metadataId: AI_ISSUE_METADATA_ID,
82
+ // Entry id is issueId-scoped so multiple issues can co-exist on
83
+ // one scope (the default attachScopeMetadata entryId would
84
+ // collide on `${scopeId}::ai.issue`).
85
+ entryId: `${input.scopeId}::${AI_ISSUE_METADATA_ID}::${issueId}`,
86
+ value: {
87
+ issueId,
88
+ summary: input.summary,
89
+ severity,
90
+ status,
91
+ createdAtUtc,
92
+ },
93
+ });
94
+ if (writerResult.status === "attached") {
95
+ return {
96
+ created: true,
97
+ issueId,
98
+ entryId: writerResult.entryId,
99
+ resolvedFrom: writerResult.resolvedFrom,
100
+ };
101
+ }
102
+ return {
103
+ created: false,
104
+ issueId,
105
+ reason: `scope-not-resolvable:${writerResult.scopeId}`,
106
+ };
107
+ }