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