@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.
- package/README.md +75 -932
- package/package.json +26 -27
- package/src/api/anchor-conversion.ts +43 -0
- package/src/api/editor-state-types.ts +2 -1
- package/src/api/public-types.ts +504 -101
- package/src/api/session-state.ts +4 -0
- package/src/api/v3/README.md +91 -0
- package/src/api/v3/_create.ts +146 -0
- package/src/api/v3/_layer-metadata.ts +362 -0
- package/src/api/v3/_mocks.ts +84 -0
- package/src/api/v3/_runtime-handle.ts +162 -0
- package/src/api/v3/_ux-response.ts +73 -0
- package/src/api/v3/ai/_metadata-audit.ts +225 -0
- package/src/api/v3/ai/attach.ts +235 -0
- package/src/api/v3/ai/bundle.ts +132 -0
- package/src/api/v3/ai/explain.ts +144 -0
- package/src/api/v3/ai/export.ts +54 -0
- package/src/api/v3/ai/inspect.ts +118 -0
- package/src/api/v3/ai/policy.ts +77 -0
- package/src/api/v3/ai/replacement.ts +341 -0
- package/src/api/v3/ai/resolve.ts +133 -0
- package/src/api/v3/index.ts +79 -0
- package/src/api/v3/runtime/chart.ts +310 -0
- package/src/api/v3/runtime/clipboard.ts +81 -0
- package/src/api/v3/runtime/collab.ts +331 -0
- package/src/api/v3/runtime/content.ts +236 -0
- package/src/api/v3/runtime/document.ts +282 -0
- package/src/api/v3/runtime/formatting.ts +186 -0
- package/src/api/v3/runtime/geometry.ts +349 -0
- package/src/api/v3/runtime/layout.ts +108 -0
- package/src/api/v3/runtime/review.ts +129 -0
- package/src/api/v3/runtime/search.ts +74 -0
- package/src/api/v3/runtime/table.ts +63 -0
- package/src/api/v3/runtime/workflow.ts +434 -0
- package/src/api/v3/ui/_context.ts +86 -0
- package/src/api/v3/ui/_create.ts +65 -0
- package/src/api/v3/ui/_types.ts +520 -0
- package/src/api/v3/ui/chrome-composition.ts +342 -0
- package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
- package/src/api/v3/ui/chrome.ts +476 -0
- package/src/api/v3/ui/debug.ts +124 -0
- package/src/api/v3/ui/index.ts +64 -0
- package/src/api/v3/ui/overlays-visibility.ts +170 -0
- package/src/api/v3/ui/overlays.ts +427 -0
- package/src/api/v3/ui/scope.ts +71 -0
- package/src/api/v3/ui/session.ts +100 -0
- package/src/api/v3/ui/surface.ts +170 -0
- package/src/api/v3/ui/viewport.ts +303 -0
- package/src/core/commands/index.ts +28 -6
- package/src/core/commands/list-commands.ts +3 -2
- package/src/core/commands/section-layout-commands.ts +9 -8
- package/src/core/schema/text-schema.ts +16 -0
- package/src/core/selection/mapping.ts +33 -72
- package/src/core/state/editor-state.ts +96 -189
- package/src/index.ts +23 -4
- package/src/io/chart-preview-resolver.ts +1 -1
- package/src/io/docx-session.ts +36 -4797
- package/src/io/export/build-app-properties-xml.ts +1 -1
- package/src/io/export/serialize-comments.ts +1 -1
- package/src/io/export/serialize-headers-footers.ts +6 -1
- package/src/io/export/serialize-main-document.ts +45 -0
- package/src/io/export/serialize-run-formatting.ts +17 -2
- package/src/io/export/twip.ts +1 -1
- package/src/io/normalize/normalize-text.ts +27 -20
- package/src/io/ooxml/chart/parse-series.ts +1 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +1 -1
- package/src/io/ooxml/classify-embedding.ts +83 -33
- package/src/io/ooxml/parse-fill.ts +1 -1
- package/src/io/ooxml/parse-main-document.ts +71 -1
- package/src/io/ooxml/parse-object.ts +14 -10
- package/src/io/ooxml/parse-run-formatting.ts +47 -1
- package/src/io/ooxml/property-grab-bag.ts +2 -2
- package/src/io/ooxml/units.ts +11 -0
- package/src/io/ooxml/workflow-payload.ts +282 -7
- package/src/model/anchor.ts +85 -0
- package/src/model/canonical-document.ts +351 -15
- package/src/model/chart-types.ts +1 -1
- package/src/model/layout/index.ts +83 -0
- package/src/model/layout/page-graph-types.ts +181 -0
- package/src/model/layout/page-layout-snapshot.ts +105 -0
- package/src/model/layout/resolved-layout-types.ts +47 -0
- package/src/model/layout/runtime-page-graph-types.ts +102 -0
- package/src/model/paragraph-scope-ids.ts +72 -0
- package/src/model/review/comment-types.ts +112 -0
- package/src/model/review/index.ts +2 -0
- package/src/model/review/revision-types.ts +215 -0
- package/src/model/snapshot.ts +32 -0
- package/src/review/store/comment-store.ts +21 -47
- package/src/review/store/revision-types.ts +40 -198
- package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
- package/src/runtime/collab/runtime-collab-sync.ts +13 -3
- package/src/runtime/collab-session.ts +1 -1
- package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
- package/src/runtime/debug/event-ring-buffer.ts +64 -0
- package/src/runtime/debug/probability-sampler.ts +18 -0
- package/src/runtime/debug/runtime-debug-facet.ts +67 -0
- package/src/runtime/debug/stage-tokens.ts +31 -0
- package/src/runtime/debug/telemetry-bus.ts +271 -0
- package/src/runtime/debug/types.ts +275 -0
- package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
- package/src/runtime/document-layout.ts +8 -6
- package/src/runtime/document-runtime.ts +843 -1141
- package/src/runtime/document-search.ts +1 -1
- package/src/runtime/edit-ops/index.ts +1 -1
- package/src/runtime/external-send-runtime.ts +1 -1
- package/src/runtime/formatting/document-lookup.ts +235 -0
- package/src/runtime/formatting/field/registry.ts +41 -0
- package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
- package/src/runtime/formatting/font-resolution.ts +83 -0
- package/src/runtime/formatting/formatting-context.ts +903 -0
- package/src/runtime/formatting/formatting-types.ts +157 -0
- package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
- package/src/runtime/formatting/index.ts +125 -0
- package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
- package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
- package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
- package/src/runtime/formatting/projector.ts +75 -0
- package/src/runtime/formatting/resolve-effective.ts +407 -0
- package/src/runtime/formatting/revision-display.ts +105 -0
- package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
- package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
- package/src/runtime/formatting/telemetry-bridge.ts +106 -0
- package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
- package/src/runtime/geometry/caret-geometry.ts +164 -0
- package/src/runtime/geometry/geometry-facet.ts +364 -0
- package/src/runtime/geometry/geometry-types.ts +256 -0
- package/src/runtime/geometry/hit-test.ts +125 -0
- package/src/runtime/geometry/index.ts +71 -0
- package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
- package/src/runtime/geometry/invalidation.ts +35 -0
- package/src/runtime/geometry/object-handles.ts +77 -0
- package/src/runtime/geometry/overlay-rects.ts +85 -0
- package/src/runtime/geometry/project-anchors.ts +100 -0
- package/src/runtime/geometry/project-fragments.ts +216 -0
- package/src/runtime/geometry/projector.ts +129 -0
- package/src/runtime/geometry/replacement-envelope.ts +130 -0
- package/src/runtime/geometry/viewport.ts +218 -0
- package/src/runtime/layout/compat-input-ledger.ts +211 -0
- package/src/runtime/layout/index.ts +6 -1
- package/src/runtime/layout/inert-layout-facet.ts +12 -7
- package/src/runtime/layout/layout-engine-instance.ts +189 -11
- package/src/runtime/layout/layout-engine-version.ts +450 -1
- package/src/runtime/layout/layout-facet-types.ts +60 -0
- package/src/runtime/layout/layout-measurement-provider.ts +13 -0
- package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
- package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
- package/src/runtime/layout/page-graph.ts +62 -209
- package/src/runtime/layout/page-story-resolver.ts +7 -12
- package/src/runtime/layout/paginated-layout-engine.ts +186 -11
- package/src/runtime/layout/project-block-fragments.ts +11 -0
- package/src/runtime/layout/projector.ts +90 -0
- package/src/runtime/layout/public-facet.ts +187 -442
- package/src/runtime/layout/resolved-formatting-state.ts +158 -26
- package/src/runtime/layout/table-render-plan.ts +1 -1
- package/src/runtime/prerender/cache-envelope.ts +6 -1
- package/src/runtime/prerender/prerender-document.ts +18 -23
- package/src/runtime/render/decoration-resolver.ts +1 -1
- package/src/runtime/render/render-frame-types.ts +20 -0
- package/src/runtime/render/render-kernel.ts +94 -25
- package/src/runtime/scopes/_formatting-seam.ts +262 -0
- package/src/runtime/scopes/_scope-dependencies.ts +49 -0
- package/src/runtime/scopes/action-validation.ts +356 -0
- package/src/runtime/scopes/attach-explanation.ts +102 -0
- package/src/runtime/scopes/audit-bundle.ts +71 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
- package/src/runtime/scopes/compile-scope.ts +262 -0
- package/src/runtime/scopes/compiler-service.ts +431 -0
- package/src/runtime/scopes/create-issue.ts +107 -0
- package/src/runtime/scopes/enumerate-scopes.ts +543 -0
- package/src/runtime/scopes/evidence.ts +233 -0
- package/src/runtime/scopes/index.ts +150 -0
- package/src/runtime/scopes/position-map.ts +214 -0
- package/src/runtime/scopes/preservation-boundary.ts +91 -0
- package/src/runtime/scopes/projector.ts +49 -0
- package/src/runtime/scopes/replaceability.ts +87 -0
- package/src/runtime/scopes/replacement/apply.ts +228 -0
- package/src/runtime/scopes/replacement/compile.ts +59 -0
- package/src/runtime/scopes/replacement/propose.ts +42 -0
- package/src/runtime/scopes/resolve-reference.ts +347 -0
- package/src/runtime/scopes/review-bundle.ts +141 -0
- package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
- package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
- package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
- package/src/runtime/scopes/scope-kinds/field.ts +65 -0
- package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
- package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
- package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
- package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
- package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
- package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
- package/src/runtime/scopes/scope-kinds/table.ts +55 -0
- package/src/runtime/scopes/scope-range.ts +208 -0
- package/src/runtime/scopes/semantic-scope-types.ts +454 -0
- package/src/runtime/scopes/workflow-overlap.ts +92 -0
- package/src/runtime/selection/index.ts +1 -1
- package/src/runtime/structure-ops/fragment-insert.ts +1 -1
- package/src/runtime/structure-ops/index.ts +1 -1
- package/src/runtime/surface-projection.ts +232 -262
- package/src/runtime/units.ts +4 -2
- package/src/runtime/workflow/coordinator.ts +1348 -0
- package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
- package/src/runtime/workflow/index.ts +25 -0
- package/src/runtime/workflow/markup-mode-policy.ts +98 -0
- package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
- package/src/runtime/workflow/metadata-persistence.ts +306 -0
- package/src/runtime/workflow/metadata-writer.ts +123 -0
- package/src/runtime/workflow/overlay-store.ts +690 -0
- package/src/runtime/workflow/projector.ts +127 -0
- package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
- package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
- package/src/runtime/workflow/rail/types.ts +198 -0
- package/src/runtime/workflow/scope-rail-composer.ts +39 -0
- package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
- package/src/runtime/workflow/scope-writer.ts +188 -0
- package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
- package/src/runtime/workflow/visibility-policy.ts +129 -0
- package/src/session/_sync-legacy.ts +66 -0
- package/src/session/export/embedded-reconstitute.ts +104 -0
- package/src/session/export/export-diagnostics.ts +85 -0
- package/src/session/export/export-validation.ts +110 -0
- package/src/session/export/index.ts +34 -0
- package/src/session/export/preservation-reattach.ts +30 -0
- package/src/session/export/serialize-dispatch.ts +165 -0
- package/src/session/export/stateful-export-pipeline.ts +432 -0
- package/src/session/export/stateful-export.ts +684 -0
- package/src/session/import/canonical-assembly.ts +227 -0
- package/src/session/import/diagnostics-session.ts +54 -0
- package/src/session/import/embedded-discovery.ts +225 -0
- package/src/session/import/embedded-offload.ts +337 -0
- package/src/session/import/import-diagnostics.ts +69 -0
- package/src/session/import/loader-types.ts +313 -0
- package/src/session/import/loader.ts +1834 -0
- package/src/session/import/normalize.ts +195 -0
- package/src/session/import/package-parts.ts +217 -0
- package/src/session/import/package-read.ts +195 -0
- package/src/session/import/parse-orchestration.ts +105 -0
- package/src/session/import/part-constants.ts +70 -0
- package/src/session/import/part-discovery.ts +94 -0
- package/src/session/import/preservation-index.ts +46 -0
- package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
- package/src/session/import/review-import.ts +508 -0
- package/src/session/import/styles-consolidation.ts +281 -0
- package/src/session/import/workflow-scope-import.ts +256 -0
- package/src/session/index.ts +37 -0
- package/src/session/session-state.ts +69 -0
- package/src/session/session.ts +532 -0
- package/src/session/shared/protection.ts +228 -0
- package/src/session/shared/session-utils.ts +82 -0
- package/src/session/types.ts +499 -0
- package/src/shell/chart-snapshots.ts +96 -0
- package/src/shell/media-previews.ts +85 -0
- package/src/shell/overlay-anchor-bridge.ts +53 -0
- package/src/shell/paste-adapter.ts +23 -0
- package/src/shell/ref-commands.ts +1697 -0
- package/src/shell/ref-utilities.ts +48 -0
- package/src/shell/search.ts +51 -0
- package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
- package/src/shell/ui-subscriber-channels.ts +81 -0
- package/src/shell/use-collab-sync.ts +116 -0
- package/src/ui/WordReviewEditor.tsx +496 -2051
- package/src/ui/editor-shell-view.tsx +30 -1
- package/src/ui/editor-surface-controller.tsx +49 -1
- package/src/ui/headless/revision-decoration-model.ts +83 -0
- package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
- package/src/ui/headless/scoped-chrome-policy.ts +2 -2
- package/src/ui/headless/selection-tool-context.ts +1 -1
- package/src/ui/headless/selection-tool-resolver.ts +1 -1
- package/src/ui/runtime-shortcut-dispatch.ts +46 -1
- package/src/ui/ui-controller-factory.ts +221 -0
- package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
- package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
- package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
- package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
- package/src/ui-tailwind/chart/render/area.tsx +3 -3
- package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
- package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
- package/src/ui-tailwind/chart/render/combo.tsx +2 -2
- package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
- package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
- package/src/ui-tailwind/chart/render/line.tsx +3 -3
- package/src/ui-tailwind/chart/render/pie.tsx +6 -6
- package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
- package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
- package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
- package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
- package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
- package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
- package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
- package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
- package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
- package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
- package/src/ui-tailwind/debug/README.md +57 -0
- package/src/ui-tailwind/debug/index.ts +3 -0
- package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
- package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
- package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
- package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
- package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
- package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
- package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
- package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
- package/src/ui-tailwind/index.ts +0 -5
- package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
- package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
- package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
- package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
- package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
- package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
- package/src/ui-tailwind/review-workspace/types.ts +408 -0
- package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
- package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
- package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
- package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
- package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
- package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
- package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
- package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
- package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
- package/src/ui-tailwind/theme/editor-theme.css +25 -0
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
- package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
- package/src/ui-tailwind/ui-api-context.tsx +43 -0
- package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
- package/src/validation/compatibility-engine.ts +6 -6
- package/src/runtime/styles-cascade.ts +0 -33
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
- /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
- /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
- /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @endStateApi v3 — `runtime.collab` family.
|
|
3
|
+
*
|
|
4
|
+
* getSessionInfo (live-with-adapter) / getPresence (live-with-adapter) /
|
|
5
|
+
* getPosture (live-with-adapter).
|
|
6
|
+
*
|
|
7
|
+
* Shape note: "Runtime API + Collab" is the layer-07 name per the refactor
|
|
8
|
+
* master plan. `RuntimeApiHandle` now exposes `collabSession` as an
|
|
9
|
+
* optional accessor — hosts that wire Yjs/Awareness supply it, and the
|
|
10
|
+
* getPresence + getPosture functions delegate to
|
|
11
|
+
* `CollabSession.getPresenceSnapshot` / `.getCollabPosture` directly.
|
|
12
|
+
* Headless callers that don't wire collab get a deterministic mock
|
|
13
|
+
* fallback, so the family remains safe to call on any handle.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Awareness } from "y-protocols/awareness";
|
|
17
|
+
import type { RuntimeApiHandle } from "../_runtime-handle.ts";
|
|
18
|
+
import type { ApiV3FnMetadata, MockPayload } from "../_layer-metadata.ts";
|
|
19
|
+
import { mockPayload } from "../_mocks.ts";
|
|
20
|
+
import type { MetadataIntegrity } from "../../public-types.ts";
|
|
21
|
+
import {
|
|
22
|
+
getRemoteCursorStates as getRemoteCursorStatesImpl,
|
|
23
|
+
type RemoteCursorState,
|
|
24
|
+
} from "../../../runtime/collab/remote-cursor-awareness.ts";
|
|
25
|
+
|
|
26
|
+
// Re-export so L11 consumers (remote-cursor-plugin) don't peek into
|
|
27
|
+
// `src/runtime/collab/**` for the state type.
|
|
28
|
+
export type { RemoteCursorState };
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* L11-facing named re-export of the remote-cursor-awareness helper
|
|
32
|
+
* (coord-11 §4.4 · §4.8 collab-family migration). `remote-cursor-plugin.ts`
|
|
33
|
+
* — a pure PM plugin with no runtime handle in scope — uses this form
|
|
34
|
+
* so it doesn't reach into `src/runtime/collab/**` directly. Identity
|
|
35
|
+
* re-export of the same impl the factory binds; mirrors the pattern
|
|
36
|
+
* `chart.ts` established for the pure chart helpers.
|
|
37
|
+
*/
|
|
38
|
+
export { getRemoteCursorStatesImpl as getRemoteCursorStates };
|
|
39
|
+
|
|
40
|
+
/* ================================================================== */
|
|
41
|
+
/* getSessionInfo — live-with-adapter */
|
|
42
|
+
/* ================================================================== */
|
|
43
|
+
|
|
44
|
+
export interface CollabSessionInfo {
|
|
45
|
+
readonly documentId: string;
|
|
46
|
+
readonly docId: string;
|
|
47
|
+
readonly sessionVersion: string;
|
|
48
|
+
readonly schemaVersion: string;
|
|
49
|
+
readonly hasWorkflowOverlay: boolean;
|
|
50
|
+
readonly hasSharedWorkflowState: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const getSessionInfoMetadata: ApiV3FnMetadata = {
|
|
54
|
+
name: "runtime.collab.getSessionInfo",
|
|
55
|
+
status: "live-with-adapter",
|
|
56
|
+
sourceLayer: "package-session",
|
|
57
|
+
liveEvidence: {
|
|
58
|
+
runnerTest: "test/api/v3/behavioral-coverage.test.ts",
|
|
59
|
+
commit: "layer-07-closure-pass",
|
|
60
|
+
},
|
|
61
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
62
|
+
agentMetadata: {
|
|
63
|
+
readOrMutate: "read",
|
|
64
|
+
boundedScope: "session",
|
|
65
|
+
auditCategory: "collab-session-info",
|
|
66
|
+
},
|
|
67
|
+
stateClass: "B-session",
|
|
68
|
+
persistsTo: "none",
|
|
69
|
+
broadcastsVia: "awareness",
|
|
70
|
+
rwdReference:
|
|
71
|
+
"§Runtime API § runtime.collab.getSessionInfo. Adapter reads handle.getSessionState() + handle.getWorkflowOverlay() and projects a session-scoped CollabSessionInfo. Promotes to `live` when RuntimeApiHandle exposes a direct `collabSession` accessor.",
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/* ================================================================== */
|
|
75
|
+
/* getPresence — mock (collab facet not yet on handle) */
|
|
76
|
+
/* ================================================================== */
|
|
77
|
+
|
|
78
|
+
export interface CollabPresenceSnapshot {
|
|
79
|
+
readonly peers: readonly unknown[];
|
|
80
|
+
readonly transportStatus: "online" | "syncing" | "offline";
|
|
81
|
+
readonly queuedLocalEvents: number;
|
|
82
|
+
readonly __mock?: true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const getPresenceMetadata: ApiV3FnMetadata = {
|
|
86
|
+
name: "runtime.collab.getPresence",
|
|
87
|
+
status: "live-with-adapter",
|
|
88
|
+
sourceLayer: "workflow-review",
|
|
89
|
+
liveEvidence: {
|
|
90
|
+
runnerTest: "test/api/v3/behavioral-coverage.test.ts",
|
|
91
|
+
commit: "layer-07-closure-pass-graduation",
|
|
92
|
+
},
|
|
93
|
+
mockShape: {
|
|
94
|
+
deterministic: true,
|
|
95
|
+
seededFrom: "fixed",
|
|
96
|
+
shapeDescription:
|
|
97
|
+
"Empty presence snapshot — peers:[], transportStatus:'offline', queuedLocalEvents:0. Emitted only when the handle carries no `collabSession` (headless drivers, pre-wire tests). Hosts that supply `collabSession` get the live PresenceSnapshot projected into the v3 shape.",
|
|
98
|
+
carriesMockFlag: true,
|
|
99
|
+
},
|
|
100
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
101
|
+
agentMetadata: {
|
|
102
|
+
readOrMutate: "read",
|
|
103
|
+
boundedScope: "session",
|
|
104
|
+
auditCategory: "collab-presence",
|
|
105
|
+
},
|
|
106
|
+
stateClass: "B-session",
|
|
107
|
+
persistsTo: "none",
|
|
108
|
+
broadcastsVia: "awareness",
|
|
109
|
+
rwdReference:
|
|
110
|
+
"§Runtime API § runtime.collab.getPresence. Adapter delegates to handle.collabSession.getPresenceSnapshot() when the handle carries one; falls back to deterministic mock when absent. Promotes to `live` when collabSession is no longer optional (hosts default-attach).",
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/* ================================================================== */
|
|
114
|
+
/* getPosture — mock (collab facet not yet on handle) */
|
|
115
|
+
/* ================================================================== */
|
|
116
|
+
|
|
117
|
+
export interface CollabPostureSnapshot {
|
|
118
|
+
readonly role: "author" | "reviewer" | "observer" | "unattached";
|
|
119
|
+
readonly peerCount: number;
|
|
120
|
+
readonly transportStatus: "online" | "syncing" | "offline";
|
|
121
|
+
readonly __mock?: true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const getPostureMetadata: ApiV3FnMetadata = {
|
|
125
|
+
name: "runtime.collab.getPosture",
|
|
126
|
+
status: "live-with-adapter",
|
|
127
|
+
sourceLayer: "workflow-review",
|
|
128
|
+
liveEvidence: {
|
|
129
|
+
runnerTest: "test/api/v3/behavioral-coverage.test.ts",
|
|
130
|
+
commit: "layer-07-closure-pass-graduation",
|
|
131
|
+
},
|
|
132
|
+
mockShape: {
|
|
133
|
+
deterministic: true,
|
|
134
|
+
seededFrom: "fixed",
|
|
135
|
+
shapeDescription:
|
|
136
|
+
"Default posture — role:'unattached', peerCount:0, transportStatus:'offline'. Emitted only when the handle carries no `collabSession`. Hosts that supply `collabSession` get the live CollabPosture projected into the v3 shape.",
|
|
137
|
+
carriesMockFlag: true,
|
|
138
|
+
},
|
|
139
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
140
|
+
agentMetadata: {
|
|
141
|
+
readOrMutate: "read",
|
|
142
|
+
boundedScope: "session",
|
|
143
|
+
auditCategory: "collab-posture",
|
|
144
|
+
},
|
|
145
|
+
stateClass: "B-session",
|
|
146
|
+
persistsTo: "none",
|
|
147
|
+
broadcastsVia: "awareness",
|
|
148
|
+
rwdReference:
|
|
149
|
+
"§Runtime API § runtime.collab.getPosture. Adapter delegates to handle.collabSession.getCollabPosture() when the handle carries one; falls back to deterministic mock when absent. Promotes to `live` when collabSession is no longer optional (hosts default-attach).",
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/* ================================================================== */
|
|
153
|
+
/* getMetadataIntegrity — live-with-adapter (collab expansion) */
|
|
154
|
+
/* ================================================================== */
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Snapshot shape — wraps the `MetadataIntegrity` union
|
|
158
|
+
* (`"unsigned" | "verified" | "tampered"`) in an object so the mock
|
|
159
|
+
* fallback can carry `__mock: true`. Agents reading the tamper gate
|
|
160
|
+
* branch on `snapshot.integrity`.
|
|
161
|
+
*/
|
|
162
|
+
export interface CollabMetadataIntegritySnapshot {
|
|
163
|
+
readonly integrity: MetadataIntegrity;
|
|
164
|
+
readonly __mock?: true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export const getMetadataIntegrityMetadata: ApiV3FnMetadata = {
|
|
168
|
+
name: "runtime.collab.getMetadataIntegrity",
|
|
169
|
+
status: "live-with-adapter",
|
|
170
|
+
sourceLayer: "workflow-review",
|
|
171
|
+
liveEvidence: {
|
|
172
|
+
runnerTest: "test/api/v3/behavioral-coverage.test.ts",
|
|
173
|
+
commit: "refactor-07-collab-expansion-tamper-read-2026-04-23",
|
|
174
|
+
},
|
|
175
|
+
mockShape: {
|
|
176
|
+
deterministic: true,
|
|
177
|
+
seededFrom: "fixed",
|
|
178
|
+
shapeDescription:
|
|
179
|
+
"Default integrity 'unsigned' — emitted only when the handle carries no `collabSession` (headless drivers, pre-wire tests). Hosts that supply `collabSession` get the live MetadataIntegrity from the tamper-gate.",
|
|
180
|
+
carriesMockFlag: true,
|
|
181
|
+
},
|
|
182
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
183
|
+
agentMetadata: {
|
|
184
|
+
readOrMutate: "read",
|
|
185
|
+
boundedScope: "session",
|
|
186
|
+
auditCategory: "collab-tamper-read",
|
|
187
|
+
},
|
|
188
|
+
stateClass: "B-session",
|
|
189
|
+
persistsTo: "none",
|
|
190
|
+
broadcastsVia: "awareness",
|
|
191
|
+
rwdReference:
|
|
192
|
+
"§Runtime API § runtime.collab.getMetadataIntegrity. Adapter delegates to handle.collabSession.getMetadataIntegrity() when the handle carries one; falls back to a deterministic 'unsigned' snapshot otherwise. Backs coord-07 §2.1 collab expansion: agent-facing tamper-state read without reaching into `src/runtime/workflow/tamper-gate.ts`. Promotes to `live` when collabSession is no longer optional.",
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/* ================================================================== */
|
|
196
|
+
/* getRemoteCursorStates — live (collab expansion remainder) */
|
|
197
|
+
/* ================================================================== */
|
|
198
|
+
|
|
199
|
+
export interface GetRemoteCursorStatesInput {
|
|
200
|
+
readonly awareness: Awareness;
|
|
201
|
+
readonly localClientId: number;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export const getRemoteCursorStatesMetadata: ApiV3FnMetadata = {
|
|
205
|
+
name: "runtime.collab.getRemoteCursorStates",
|
|
206
|
+
status: "live",
|
|
207
|
+
sourceLayer: "workflow-review",
|
|
208
|
+
liveEvidence: {
|
|
209
|
+
runnerTest: "test/api/v3/behavioral-coverage.test.ts",
|
|
210
|
+
commit: "refactor-07-collab-remote-cursor-2026-04-23",
|
|
211
|
+
},
|
|
212
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
213
|
+
agentMetadata: {
|
|
214
|
+
readOrMutate: "read",
|
|
215
|
+
boundedScope: "session",
|
|
216
|
+
auditCategory: "collab-remote-cursor-read",
|
|
217
|
+
},
|
|
218
|
+
stateClass: "B-session",
|
|
219
|
+
persistsTo: "none",
|
|
220
|
+
broadcastsVia: "awareness",
|
|
221
|
+
rwdReference:
|
|
222
|
+
"§Runtime API § runtime.collab.getRemoteCursorStates. Direct delegation to getRemoteCursorStates (src/runtime/collab/remote-cursor-awareness.ts). Extracts remote peers' cursor states from a Yjs Awareness instance, filtered by localClientId and sanitized (color allowlisted to safe-hex or hashed fallback). Backs coord-07 §2.1 collab expansion remainder — PM remote-cursor plugin flips from src/runtime/collab/** to this seam.",
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/* ================================================================== */
|
|
226
|
+
/* family factory */
|
|
227
|
+
/* ================================================================== */
|
|
228
|
+
|
|
229
|
+
export function createCollabFamily(runtime: RuntimeApiHandle) {
|
|
230
|
+
return {
|
|
231
|
+
getSessionInfo(): CollabSessionInfo {
|
|
232
|
+
// @endStateApi — live-with-adapter. Composes handle.getSessionState()
|
|
233
|
+
// + handle.getWorkflowOverlay() into a session-scoped projection.
|
|
234
|
+
// No __mock flag — every field is sourced from real runtime state.
|
|
235
|
+
const state = runtime.getSessionState();
|
|
236
|
+
const overlay = runtime.getWorkflowOverlay();
|
|
237
|
+
return {
|
|
238
|
+
documentId: state.documentId,
|
|
239
|
+
docId: state.docId ?? state.documentId,
|
|
240
|
+
sessionVersion: state.sessionVersion ?? "editor-session-state/1",
|
|
241
|
+
schemaVersion: String(state.schemaVersion ?? "cds/1.0.0"),
|
|
242
|
+
hasWorkflowOverlay: overlay !== null && overlay !== undefined,
|
|
243
|
+
hasSharedWorkflowState: Boolean(
|
|
244
|
+
overlay && typeof overlay === "object" && "sharedWorkflowState" in overlay,
|
|
245
|
+
),
|
|
246
|
+
};
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
getPresence(): CollabPresenceSnapshot & Partial<MockPayload> {
|
|
250
|
+
// @endStateApi — live-with-adapter. When the host wires
|
|
251
|
+
// handle.collabSession, delegates to getPresenceSnapshot() and
|
|
252
|
+
// projects into the v3 shape. Otherwise returns the mock fallback
|
|
253
|
+
// so headless drivers stay safe.
|
|
254
|
+
const session = runtime.collabSession;
|
|
255
|
+
if (session) {
|
|
256
|
+
const live = session.getPresenceSnapshot();
|
|
257
|
+
return {
|
|
258
|
+
peers: live.peers as readonly unknown[],
|
|
259
|
+
transportStatus: live.transportStatus as "online" | "syncing" | "offline",
|
|
260
|
+
queuedLocalEvents: live.queuedLocalEvents,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return mockPayload(
|
|
264
|
+
"handle.collabSession not wired; hosts attach it via createCollabSession({ydoc,awareness,...}) and pass through to createApiV3",
|
|
265
|
+
"CollabPresenceSnapshot",
|
|
266
|
+
{
|
|
267
|
+
peers: [] as readonly unknown[],
|
|
268
|
+
transportStatus: "offline" as const,
|
|
269
|
+
queuedLocalEvents: 0,
|
|
270
|
+
},
|
|
271
|
+
);
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
getPosture(): CollabPostureSnapshot & Partial<MockPayload> {
|
|
275
|
+
// @endStateApi — live-with-adapter. Same delegation pattern as
|
|
276
|
+
// getPresence — live via handle.collabSession.getCollabPosture()
|
|
277
|
+
// or mock fallback.
|
|
278
|
+
const session = runtime.collabSession;
|
|
279
|
+
if (session) {
|
|
280
|
+
const live = session.getCollabPosture();
|
|
281
|
+
// CollabPosture.transport is "none" | "attached"; v3 surface
|
|
282
|
+
// reshapes to the consumer-friendly "online/syncing/offline"
|
|
283
|
+
// triad. `attached` → `online` at this layer; hosts wanting
|
|
284
|
+
// syncing granularity pass a transportStatus override.
|
|
285
|
+
const transportStatus: "online" | "syncing" | "offline" =
|
|
286
|
+
live.transport === "attached" ? "online" : "offline";
|
|
287
|
+
return {
|
|
288
|
+
role: live.role as "author" | "reviewer" | "observer" | "unattached",
|
|
289
|
+
peerCount: live.peers,
|
|
290
|
+
transportStatus,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return mockPayload(
|
|
294
|
+
"handle.collabSession not wired; hosts attach it via createCollabSession({ydoc,awareness,...}) and pass through to createApiV3",
|
|
295
|
+
"CollabPostureSnapshot",
|
|
296
|
+
{
|
|
297
|
+
role: "unattached" as const,
|
|
298
|
+
peerCount: 0,
|
|
299
|
+
transportStatus: "offline" as const,
|
|
300
|
+
},
|
|
301
|
+
);
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
getRemoteCursorStates(input: GetRemoteCursorStatesInput): RemoteCursorState[] {
|
|
305
|
+
// @endStateApi — live. Pure delegation; `awareness` is the host-
|
|
306
|
+
// owned Yjs Awareness instance. Returns [] when no remote peer has
|
|
307
|
+
// published a cursor state. Color is sanitized to a safe-hex
|
|
308
|
+
// allowlist or hashed fallback by the underlying helper — callers
|
|
309
|
+
// can interpolate the value into inline style without re-validating.
|
|
310
|
+
return getRemoteCursorStatesImpl(input.awareness, input.localClientId);
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
getMetadataIntegrity(): CollabMetadataIntegritySnapshot & Partial<MockPayload> {
|
|
314
|
+
// @endStateApi — live-with-adapter. Coord-07 §2.1 collab expansion
|
|
315
|
+
// — exposes the tamper-gate state for agents without reaching into
|
|
316
|
+
// `src/runtime/workflow/tamper-gate.ts`. Live via
|
|
317
|
+
// handle.collabSession.getMetadataIntegrity() or "unsigned"
|
|
318
|
+
// mock fallback (the same default the fresh tamper-gate reports
|
|
319
|
+
// before any signed payload attaches).
|
|
320
|
+
const session = runtime.collabSession;
|
|
321
|
+
if (session) {
|
|
322
|
+
return { integrity: session.getMetadataIntegrity() };
|
|
323
|
+
}
|
|
324
|
+
return mockPayload(
|
|
325
|
+
"handle.collabSession not wired; hosts attach it via createCollabSession({ydoc,awareness,...}) and pass through to createApiV3",
|
|
326
|
+
"CollabMetadataIntegritySnapshot",
|
|
327
|
+
{ integrity: "unsigned" as MetadataIntegrity },
|
|
328
|
+
);
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @endStateApi v3 — `runtime.content` family.
|
|
3
|
+
*
|
|
4
|
+
* search (live-with-adapter) / getLocation (live-with-adapter) /
|
|
5
|
+
* replaceText (live-with-adapter) / insertFragment (live-with-adapter).
|
|
6
|
+
*
|
|
7
|
+
* 2026-04-23 — insertFragment graduated off the last v3 mock. Routes
|
|
8
|
+
* through the L08 compiler-service facade (same path as replaceText +
|
|
9
|
+
* ai.applyReplacementScope) carrying `proposedContent.kind === "structured"`.
|
|
10
|
+
* v3 is now 100% non-mock.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { RuntimeApiHandle } from "../_runtime-handle.ts";
|
|
14
|
+
import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
|
|
15
|
+
import type { CanonicalDocumentFragment } from "../../public-types.ts";
|
|
16
|
+
import { emitUxResponse } from "../_ux-response.ts";
|
|
17
|
+
import { createScopeCompilerService } from "../../../runtime/scopes/index.ts";
|
|
18
|
+
|
|
19
|
+
/* ================================================================== */
|
|
20
|
+
/* search */
|
|
21
|
+
/* ================================================================== */
|
|
22
|
+
|
|
23
|
+
export interface SearchInput {
|
|
24
|
+
readonly query: string;
|
|
25
|
+
readonly caseSensitive?: boolean;
|
|
26
|
+
readonly limit?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const searchMetadata: ApiV3FnMetadata = {
|
|
30
|
+
name: "runtime.content.search",
|
|
31
|
+
status: "live-with-adapter",
|
|
32
|
+
sourceLayer: "canonical",
|
|
33
|
+
liveEvidence: {
|
|
34
|
+
runnerTest: "test/api/v3/live-parity.test.ts",
|
|
35
|
+
commit: "phase-p-prime",
|
|
36
|
+
},
|
|
37
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
38
|
+
agentMetadata: { readOrMutate: "read", boundedScope: "document", auditCategory: "search" },
|
|
39
|
+
stateClass: "A-canonical",
|
|
40
|
+
persistsTo: "canonical",
|
|
41
|
+
rwdReference: "§Runtime API § runtime.content.search",
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/* ================================================================== */
|
|
45
|
+
/* getLocation */
|
|
46
|
+
/* ================================================================== */
|
|
47
|
+
|
|
48
|
+
export interface GetLocationInput {
|
|
49
|
+
readonly scopeId?: string;
|
|
50
|
+
readonly blockId?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const getLocationMetadata: ApiV3FnMetadata = {
|
|
54
|
+
name: "runtime.content.getLocation",
|
|
55
|
+
status: "live-with-adapter",
|
|
56
|
+
sourceLayer: "canonical",
|
|
57
|
+
liveEvidence: {
|
|
58
|
+
runnerTest: "test/api/v3/live-parity.test.ts",
|
|
59
|
+
commit: "layer-07-closure-pass",
|
|
60
|
+
},
|
|
61
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
62
|
+
agentMetadata: { readOrMutate: "read", boundedScope: "scope", auditCategory: "location" },
|
|
63
|
+
stateClass: "A-canonical",
|
|
64
|
+
persistsTo: "canonical",
|
|
65
|
+
rwdReference:
|
|
66
|
+
"§Runtime API § runtime.content.getLocation. Adapter: scopeId path composes handle.getScope(scopeId) + handle.getLocationForAnchor(scope.anchor) — typed L07 seam, no debug-facet dependency. blockId path is NOT supported today — no shipped blockId → anchor resolver exists.",
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/* ================================================================== */
|
|
70
|
+
/* replaceText */
|
|
71
|
+
/* ================================================================== */
|
|
72
|
+
|
|
73
|
+
export interface ReplaceTextInput {
|
|
74
|
+
readonly scopeId: string;
|
|
75
|
+
readonly replacement: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ReplaceTextResult {
|
|
79
|
+
readonly applied: boolean;
|
|
80
|
+
readonly reason?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const replaceTextMetadata: ApiV3FnMetadata = {
|
|
84
|
+
name: "runtime.content.replaceText",
|
|
85
|
+
status: "live-with-adapter",
|
|
86
|
+
sourceLayer: "semantic-scope-compiler",
|
|
87
|
+
liveEvidence: {
|
|
88
|
+
runnerTest: "test/runtime/scopes/replacement-text-only.test.ts",
|
|
89
|
+
commit: "refactor-08-slice-5",
|
|
90
|
+
},
|
|
91
|
+
uxIntent: { uiVisible: true, expectsUxResponse: "inline-change", expectedDelta: "text inside target scope changes" },
|
|
92
|
+
agentMetadata: { readOrMutate: "mutate", boundedScope: "scope", auditCategory: "text-replacement" },
|
|
93
|
+
stateClass: "A-canonical",
|
|
94
|
+
persistsTo: "canonical",
|
|
95
|
+
broadcastsVia: "crdt",
|
|
96
|
+
rwdReference:
|
|
97
|
+
"§Runtime API § runtime.content.replaceText. Adapter: resolves scopeId, re-validates, compiles per-kind plan, dispatches via DocumentRuntime.applyScopeReplacement, emits one ScopeActionAudit. No AI action policy here — this is the host/UI path (actorId defaults to 'user').",
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/* ================================================================== */
|
|
101
|
+
/* insertFragment */
|
|
102
|
+
/* ================================================================== */
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Scope-scoped structured-fragment insert. `scopeId` names the
|
|
106
|
+
* compiled scope whose range will be replaced with `fragment`; this
|
|
107
|
+
* matches the `replaceText` contract but takes a structured
|
|
108
|
+
* `CanonicalDocumentFragment` payload instead of flat text. Under the
|
|
109
|
+
* L08 compiler pipeline the "insert" resolves to a `fragment-replace`
|
|
110
|
+
* step dispatched through the runtime's existing `insertFragment`
|
|
111
|
+
* command — see coord-08 §8 (paragraph-kind shipped 2026-04-22).
|
|
112
|
+
*/
|
|
113
|
+
export interface InsertFragmentInput {
|
|
114
|
+
readonly scopeId: string;
|
|
115
|
+
readonly fragment: CanonicalDocumentFragment;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface InsertFragmentResult {
|
|
119
|
+
readonly applied: boolean;
|
|
120
|
+
readonly reason?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const insertFragmentMetadata: ApiV3FnMetadata = {
|
|
124
|
+
name: "runtime.content.insertFragment",
|
|
125
|
+
status: "live-with-adapter",
|
|
126
|
+
sourceLayer: "semantic-scope-compiler",
|
|
127
|
+
liveEvidence: {
|
|
128
|
+
runnerTest: "test/api/v3/live-parity.test.ts",
|
|
129
|
+
commit: "refactor-07-insert-fragment-graduation-2026-04-23",
|
|
130
|
+
},
|
|
131
|
+
uxIntent: {
|
|
132
|
+
uiVisible: true,
|
|
133
|
+
expectsUxResponse: "surface-refresh",
|
|
134
|
+
expectedDelta: "selected scope is replaced with the supplied structured fragment",
|
|
135
|
+
},
|
|
136
|
+
agentMetadata: { readOrMutate: "mutate", boundedScope: "scope", auditCategory: "fragment-insert" },
|
|
137
|
+
stateClass: "A-canonical",
|
|
138
|
+
persistsTo: "canonical",
|
|
139
|
+
broadcastsVia: "crdt",
|
|
140
|
+
rwdReference:
|
|
141
|
+
"§Runtime API § runtime.content.insertFragment. Graduation (2026-04-23): routes through createScopeCompilerService(runtime).applyReplacement({targetScopeId, operation:'replace', proposedContent:{kind:'structured', structured: fragment}}) — same L08 pipeline replaceText uses. Emits one ScopeActionAudit via the compiler's lifecycle. Promotes to `live` when an insert-after-anchor primitive exists that matches a distinct agent semantic (this call is replace-with-fragment-shaped today).",
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/* ================================================================== */
|
|
145
|
+
/* family factory */
|
|
146
|
+
/* ================================================================== */
|
|
147
|
+
|
|
148
|
+
export function createContentFamily(runtime: RuntimeApiHandle) {
|
|
149
|
+
const compiler = createScopeCompilerService(runtime);
|
|
150
|
+
return {
|
|
151
|
+
search(input: SearchInput) {
|
|
152
|
+
// @endStateApi — live-with-adapter. Reshape of EditorAnchorProjection[]
|
|
153
|
+
// + optional limit slicing. v3 spells its boolean `caseSensitive`;
|
|
154
|
+
// runtime SearchOptions spells the same field `matchCase` — the prior
|
|
155
|
+
// cast was passing `{caseSensitive}` which the runtime silently ignored.
|
|
156
|
+
const hits = runtime.findAllText(input.query, { matchCase: input.caseSensitive });
|
|
157
|
+
const limited = typeof input.limit === "number" ? hits.slice(0, input.limit) : hits;
|
|
158
|
+
return limited;
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
getLocation(input: GetLocationInput) {
|
|
162
|
+
// @endStateApi — live-with-adapter. scopeId path composes
|
|
163
|
+
// handle.getScope(scopeId) + handle.getLocationForAnchor(scope.anchor).
|
|
164
|
+
// This replaced the earlier `runtime.debug.getSnapshot({scopeFilter})`
|
|
165
|
+
// composition (debug channel was an escape hatch around a missing L07
|
|
166
|
+
// seam; the typed scope+anchor path is the real L07 read). blockId
|
|
167
|
+
// input is NOT supported — no shipped blockId → anchor resolver —
|
|
168
|
+
// returns null.
|
|
169
|
+
if (input.scopeId) {
|
|
170
|
+
const scope = runtime.getScope(input.scopeId);
|
|
171
|
+
if (!scope) return null;
|
|
172
|
+
return runtime.getLocationForAnchor(scope.anchor) ?? null;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
replaceText(input: ReplaceTextInput): ReplaceTextResult {
|
|
178
|
+
// @endStateApi — live-with-adapter (Slice 5). Routes through the
|
|
179
|
+
// Layer-08 compiler-service facade. Same pipeline as
|
|
180
|
+
// ai.applyReplacementScope; the host/UI path omits actionId (not
|
|
181
|
+
// an agent action) and tags origin:"ui" + actorId:"user".
|
|
182
|
+
const result = compiler.applyReplacement({
|
|
183
|
+
targetScopeId: input.scopeId,
|
|
184
|
+
operation: "replace",
|
|
185
|
+
proposedText: input.replacement,
|
|
186
|
+
actorId: "user",
|
|
187
|
+
origin: "ui",
|
|
188
|
+
emittedAtUtc: new Date(0).toISOString(),
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
emitUxResponse(runtime, {
|
|
192
|
+
apiFn: replaceTextMetadata.name,
|
|
193
|
+
intent: replaceTextMetadata.uxIntent.expectedDelta ?? "",
|
|
194
|
+
mockOrLive: "live",
|
|
195
|
+
uiVisible: true,
|
|
196
|
+
expectedDelta: replaceTextMetadata.uxIntent.expectedDelta,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
applied: result.applied,
|
|
201
|
+
...(result.reason ? { reason: result.reason } : {}),
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
insertFragment(input: InsertFragmentInput): InsertFragmentResult {
|
|
206
|
+
// @endStateApi — live-with-adapter. Coord-07 §1.1 closed 2026-04-23
|
|
207
|
+
// after L08 §8 shipped the structured-fragment compile path
|
|
208
|
+
// (paragraph-kind). Delegates to the same compiler-service facade
|
|
209
|
+
// replaceText uses, flagging `proposedContent.kind = "structured"`
|
|
210
|
+
// so compileReplacement emits `fragment-replace` instead of
|
|
211
|
+
// `text-replace`. One ScopeActionAudit emits on the scope channel
|
|
212
|
+
// via the compiler's lifecycle.
|
|
213
|
+
const result = compiler.applyReplacement({
|
|
214
|
+
targetScopeId: input.scopeId,
|
|
215
|
+
operation: "replace",
|
|
216
|
+
proposedContent: { kind: "structured", structured: input.fragment },
|
|
217
|
+
actorId: "user",
|
|
218
|
+
origin: "ui",
|
|
219
|
+
emittedAtUtc: new Date(0).toISOString(),
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
emitUxResponse(runtime, {
|
|
223
|
+
apiFn: insertFragmentMetadata.name,
|
|
224
|
+
intent: insertFragmentMetadata.uxIntent.expectedDelta ?? "",
|
|
225
|
+
mockOrLive: "live",
|
|
226
|
+
uiVisible: true,
|
|
227
|
+
expectedDelta: insertFragmentMetadata.uxIntent.expectedDelta,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
applied: result.applied,
|
|
232
|
+
...(result.reason ? { reason: result.reason } : {}),
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|