@beyondwork/docx-react-component 1.0.71 → 1.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +964 -75
  2. package/package.json +1 -1
  3. package/src/api/public-types.ts +280 -1
  4. package/src/api/v3/_create.ts +16 -1
  5. package/src/api/v3/_runtime-handle.ts +2 -0
  6. package/src/api/v3/ai/evaluate.ts +113 -0
  7. package/src/api/v3/ai/outline.ts +140 -0
  8. package/src/api/v3/ai/policy.ts +31 -0
  9. package/src/api/v3/ai/replacement.ts +8 -0
  10. package/src/api/v3/ai/review.ts +342 -0
  11. package/src/api/v3/ai/stats.ts +62 -0
  12. package/src/api/v3/runtime/viewport.ts +181 -0
  13. package/src/api/v3/runtime/workflow.ts +114 -1
  14. package/src/api/v3/ui/_types.ts +35 -0
  15. package/src/api/v3/ui/chrome-preset-model.ts +6 -0
  16. package/src/api/v3/ui/index.ts +1 -0
  17. package/src/api/v3/ui/viewport.ts +112 -0
  18. package/src/compare/diff-engine.ts +2 -0
  19. package/src/core/commands/formatting-commands.ts +1 -0
  20. package/src/core/commands/table-structure-commands.ts +1 -0
  21. package/src/core/state/editor-state.ts +49 -6
  22. package/src/io/export/serialize-footnotes.ts +6 -0
  23. package/src/io/export/serialize-headers-footers.ts +7 -0
  24. package/src/io/export/serialize-main-document.ts +20 -0
  25. package/src/io/export/serialize-paragraph-formatting.ts +34 -0
  26. package/src/io/export/split-review-boundaries.ts +1 -0
  27. package/src/io/normalize/normalize-text.ts +49 -2
  28. package/src/io/ooxml/parse-headers-footers.ts +31 -0
  29. package/src/io/ooxml/parse-main-document.ts +148 -7
  30. package/src/io/ooxml/parse-paragraph-formatting.ts +105 -0
  31. package/src/model/canonical-document.ts +401 -1
  32. package/src/runtime/formatting/formatting-context.ts +2 -1
  33. package/src/runtime/geometry/overlay-rects.ts +7 -10
  34. package/src/runtime/layout/layout-engine-version.ts +278 -1
  35. package/src/runtime/layout/paginated-layout-engine.ts +181 -8
  36. package/src/runtime/layout/resolved-formatting-state.ts +108 -13
  37. package/src/runtime/markdown-sanitizer.ts +21 -4
  38. package/src/runtime/render/render-kernel.ts +21 -1
  39. package/src/runtime/scopes/action-validation.ts +30 -4
  40. package/src/runtime/scopes/audit-bundle.ts +8 -0
  41. package/src/runtime/scopes/compiler-service.ts +1 -0
  42. package/src/runtime/scopes/enumerate-scopes.ts +61 -3
  43. package/src/runtime/scopes/replacement/apply.ts +50 -3
  44. package/src/runtime/scopes/scope-kinds/paragraph.ts +170 -7
  45. package/src/runtime/scopes/semantic-scope-types.ts +27 -0
  46. package/src/runtime/surface-projection.ts +77 -0
  47. package/src/runtime/workflow/coordinator.ts +3 -0
  48. package/src/runtime/workflow/scope-writer.ts +34 -0
  49. package/src/session/export/embedded-reconstitute.ts +37 -3
  50. package/src/session/import/embedded-offload.ts +26 -1
  51. package/src/session/import/loader-types.ts +18 -0
  52. package/src/session/import/loader.ts +2 -0
  53. package/src/shell/media-previews.ts +8 -6
  54. package/src/ui/WordReviewEditor.tsx +1 -0
  55. package/src/ui/editor-surface-controller.tsx +11 -0
  56. package/src/ui/headless/selection-helpers.ts +2 -2
  57. package/src/ui/runtime-shortcut-dispatch.ts +4 -4
  58. package/src/ui-tailwind/chrome/tw-runtime-repl-dialog.tsx +22 -4
  59. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +11 -11
  60. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +1 -1
  61. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +5 -0
  62. package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +18 -1
  63. package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +22 -6
  64. package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +18 -1
  65. package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +98 -3
  66. package/src/ui-tailwind/editor-surface/pm-schema.ts +50 -4
  67. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +6 -0
  68. package/src/ui-tailwind/editor-surface/scroll-anchor.ts +8 -1
  69. package/src/ui-tailwind/editor-surface/search-plugin.ts +2 -4
  70. package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +114 -0
  71. package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +12 -4
  72. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +29 -4
  73. package/src/ui-tailwind/index.ts +4 -2
  74. package/src/ui-tailwind/page-chrome-model.ts +5 -7
  75. package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +54 -34
  76. package/src/ui-tailwind/page-stack/tw-endnote-area.tsx +4 -1
  77. package/src/ui-tailwind/page-stack/tw-footnote-area.tsx +4 -1
  78. package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +10 -1
  79. package/src/ui-tailwind/page-stack/tw-page-footer-band.tsx +8 -1
  80. package/src/ui-tailwind/page-stack/tw-page-header-band.tsx +11 -1
  81. package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +7 -1
  82. package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +139 -10
  83. package/src/ui-tailwind/review/comment-markdown-renderer.tsx +1 -1
  84. package/src/ui-tailwind/review-workspace/page-chrome.ts +4 -4
  85. package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +1 -1
  86. package/src/ui-tailwind/theme/editor-theme.css +15 -16
  87. package/src/ui-tailwind/tw-review-workspace.tsx +22 -14
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beyondwork/docx-react-component",
3
3
  "publisher": "beyondwork",
4
- "version": "1.0.71",
4
+ "version": "1.0.73",
5
5
  "description": "Embeddable React Word (docx) editor with review, comments, tracked changes, and round-trip OOXML fidelity.",
6
6
  "type": "module",
7
7
  "sideEffects": [
@@ -103,6 +103,27 @@ export type {
103
103
  export type { CollabSession } from "../runtime/collab-session.ts";
104
104
  export type { MetadataIntegrity } from "../runtime/workflow/tamper-gate.ts";
105
105
  export type { ScopeTagRegistry } from "../runtime/workflow/scope-tag-registry.ts";
106
+ /**
107
+ * Zero-arg factory for the default-seeded `ScopeTagRegistry`. Two
108
+ * equivalent call sites ship today; pick whichever matches your scope:
109
+ *
110
+ * - `createScopeTagRegistry()` (this re-export) — handle-free path for
111
+ * L11 consumers that already import from `public-types`. §4.17
112
+ * "simple pass-through of a runtime helper" precedent. Safe when
113
+ * there's no `api` in scope (tests, pre-mount, PM-surface
114
+ * component-internal memo).
115
+ *
116
+ * - `api.runtime.workflow.createScopeTagRegistry()` — L06 proper API
117
+ * home shipped 2026-04-23 per coord-10 §L11-4 (L11 delegation).
118
+ * Preferred when a handle is already threaded: the registry is then
119
+ * reachable through the same family as `queryScopes`, `getMarkup`,
120
+ * etc., and the call appears in agent-audit telemetry.
121
+ *
122
+ * Both paths delegate to the same implementation in
123
+ * `src/runtime/workflow/scope-tag-registry.ts` and return an identical
124
+ * `ScopeTagRegistry` shape. No behavior difference.
125
+ */
126
+ export { createScopeTagRegistry } from "../runtime/workflow/scope-tag-registry.ts";
106
127
  // Semantic-scope shapes — re-exported so L10 (ui.scope.*) + L09
107
128
  // (ai.getScopeBundle) + L11 (scope-card consumers) can import the
108
129
  // canonical types from the public-types choke point instead of
@@ -119,6 +140,23 @@ export type {
119
140
  } from "../runtime/scopes/semantic-scope-types.ts";
120
141
  export type { GeometryFacet } from "../runtime/geometry/index.ts";
121
142
  export type { RuntimePageGraph } from "../runtime/layout/page-graph.ts";
143
+ export type { RuntimePageNode } from "../runtime/layout/page-graph.ts";
144
+
145
+ /**
146
+ * `resolvePageFieldDisplayText` pure helper — resolves `PAGE` /
147
+ * `NUMPAGES` field text for a specific page + graph. Used by the PM
148
+ * page-break decoration renderer to substitute the cached preserve-
149
+ * only text with a live per-page number. Pure function over the
150
+ * already-public `RuntimePageGraph` / `RuntimePageNode` +
151
+ * `SupportedFieldFamily` types; no runtime handle in scope at the
152
+ * presentation-layer call site. Matches the §4.8 / §4.17 re-export
153
+ * precedent. Canonical impl lives on
154
+ * `src/runtime/layout/resolve-page-fields.ts`.
155
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17 L04 layout
156
+ * long-tail row after `RuntimePageGraph` graduated to public-types.
157
+ */
158
+ export type { PageFieldContext } from "../runtime/layout/resolve-page-fields.ts";
159
+ export { resolvePageFieldDisplayText } from "../runtime/layout/resolve-page-fields.ts";
122
160
 
123
161
  export type {
124
162
  WordReviewEditorLayoutFacet,
@@ -182,6 +220,63 @@ export type { ScopeRailPosture } from "../runtime/workflow/rail/compose.ts";
182
220
  // reaching into `src/runtime/**` directly (P3).
183
221
  export type { SessionCapabilities } from "../runtime/session-capabilities.ts";
184
222
 
223
+ /**
224
+ * `deriveCapabilities` value re-export — pure function over the
225
+ * already-public `RuntimeRenderSnapshot` + `WorkflowScopeSnapshot`
226
+ * inputs. Matches the `storyTargetsEqual` / unit-constant precedent
227
+ * for pure-helper re-exports where no runtime handle is in scope at
228
+ * the consumer. Called by `src/ui-tailwind/index.ts`'s public
229
+ * facade so hosts can derive capabilities without reaching into
230
+ * `src/runtime/**` directly. Re-exported 2026-04-24 per refactor/11
231
+ * handoff §4.17 self-closable row (L01 session-capabilities value).
232
+ */
233
+ export { deriveCapabilities } from "../runtime/session-capabilities.ts";
234
+
235
+ /**
236
+ * Editor capability table — frozen map + accompanying pure types.
237
+ * Re-exported 2026-04-24 per coord-10 §L11-1 (delegated from
238
+ * refactor/11 handoff register). Retires the direct reach-through
239
+ * from `src/ui/runtime-shortcut-dispatch.ts` into
240
+ * `src/runtime/editor-surface/capabilities.ts`. Matches the §4.8
241
+ * precedent class: frozen value + pure types, no runtime handle at
242
+ * the consumer. L07 may later formalize this as
243
+ * `api.runtime.capabilities.getById(id)` / `.list()`; the re-export
244
+ * here is the minimum-viable unblock.
245
+ */
246
+ export type {
247
+ CapabilityKind,
248
+ CapabilityCategory,
249
+ CapabilityShortcut,
250
+ CapabilityBlockReason,
251
+ EditorCapability,
252
+ } from "../runtime/editor-surface/capabilities.ts";
253
+ export { CAPABILITY_BY_ID } from "../runtime/editor-surface/capabilities.ts";
254
+
255
+ /**
256
+ * Per-page header/footer short-text preview maps — used by the in-flow
257
+ * page-chrome bands to show live content ("Page 3 of 5") instead of
258
+ * generic "Header" / "Footer" labels. Re-exported 2026-04-24 per coord-10
259
+ * §L11-2 (delegated from refactor/11 handoff register). `buildPagePreviewMaps`
260
+ * reads only `pages[].pageId / stories / isBlankFiller` on its graph input,
261
+ * and consumers already pass a structural adapter (see
262
+ * `tw-prosemirror-surface.tsx`); the minimum-viable unblock re-exports the
263
+ * function + result type without hoisting `RuntimePageGraph` itself. L04
264
+ * may later formalize as `api.runtime.layout.getPagePreviews(nav, subParts)`.
265
+ */
266
+ export type { PagePreviewMaps } from "../runtime/layout/resolve-page-previews.ts";
267
+ export { buildPagePreviewMaps } from "../runtime/layout/resolve-page-previews.ts";
268
+
269
+ /**
270
+ * Canvas measurement backend factory — browser-only `LayoutMeasurementProvider`
271
+ * that uses Canvas2D `measureText()` for font-metric-aware width computation.
272
+ * Re-exported 2026-04-24 per coord-10 §L11-5 (delegated from refactor/11
273
+ * handoff register). Consumers pass the result to
274
+ * `WordReviewEditorLayoutFacet.swapMeasurementProvider(...)`; the provider
275
+ * type is already threaded through the facet's public surface. L04 may
276
+ * later formalize as `api.runtime.layout.createCanvasBackend()`.
277
+ */
278
+ export { createCanvasBackend } from "../runtime/layout/measurement-backend-canvas.ts";
279
+
185
280
  export type FieldFamily = import("../model/canonical-document.ts").FieldFamily;
186
281
  export type FieldRefreshStatus = import("../model/canonical-document.ts").FieldRefreshStatus;
187
282
  export type SupportedFieldFamily = import("../model/canonical-document.ts").SupportedFieldFamily;
@@ -260,6 +355,89 @@ export type { EditorStoryTarget } from "../model/layout/page-layout-snapshot.ts"
260
355
  */
261
356
  export { storyTargetsEqual, MAIN_STORY_TARGET } from "../core/selection/mapping.ts";
262
357
 
358
+ /**
359
+ * `storyTargetKey` pure function — stable string key derivation for
360
+ * `EditorStoryTarget` (`main` / `header` / `footer` / `footnote` /
361
+ * `endnote`). Used by presentation-layer caches keyed by story
362
+ * target (e.g. floating-image overlay model). Matches the
363
+ * `storyTargetsEqual` precedent — pure function over a public type,
364
+ * no runtime handle in scope at the consumer. Canonical impl lives
365
+ * on `src/runtime/story-targeting.ts`.
366
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17 self-closable row.
367
+ */
368
+ export { storyTargetKey } from "../runtime/story-targeting.ts";
369
+
370
+ /**
371
+ * Public-shape anchor constructors — pure helpers producing the
372
+ * `EditorAnchorProjection` discriminated union used in
373
+ * `SelectionSnapshot.activeRange`. `createPublicRangeAnchor`
374
+ * normalizes `from <= to` internally; `createPublicNodeAnchor`
375
+ * tags a node anchor at `at` with boundary associativity. Canonical
376
+ * impl lives on `src/core/selection/anchor-conversion.ts` — the
377
+ * single authority enforced by
378
+ * `test/api/anchor-boundary-invariants.test.ts`.
379
+ *
380
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17 — the L03/L06
381
+ * selection-primitives row names `anchor-conversion` as a candidate
382
+ * for the public-types re-export pattern (chart family precedent)
383
+ * when the consumer is a leaf helper with no runtime handle in scope,
384
+ * which `src/ui/headless/selection-helpers.ts` is.
385
+ */
386
+ export {
387
+ createPublicRangeAnchor,
388
+ createPublicNodeAnchor,
389
+ } from "../core/selection/anchor-conversion.ts";
390
+
391
+ /**
392
+ * L04 pagination pure helpers — leaf functions over already-public
393
+ * `DocumentPageSnapshot` / `PageLayoutSnapshot` / `SurfaceBlockSnapshot`
394
+ * shapes, used by presentation-layer page-chrome surfaces
395
+ * (`src/ui-tailwind/page-chrome-model.ts`). No runtime handle in scope
396
+ * at call sites — exactly the §4.8 precedent class.
397
+ *
398
+ * - `findPageForOffset(pages, offset)` — index resolver.
399
+ * - `estimateBlockHeight`, `estimateParagraphLineHeight`,
400
+ * `estimateParagraphLineCount`, `getUsableColumnWidth` — pure
401
+ * layout estimators used before real layout is available (cold
402
+ * open + placeholder chrome).
403
+ *
404
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17 L04 layout
405
+ * family long-tail. Canonical impls live on
406
+ * `src/runtime/document-navigation.ts` +
407
+ * `src/runtime/page-layout-estimation.ts`.
408
+ */
409
+ export { findPageForOffset } from "../runtime/document-navigation.ts";
410
+ export {
411
+ estimateBlockHeight,
412
+ estimateParagraphLineHeight,
413
+ estimateParagraphLineCount,
414
+ getUsableColumnWidth,
415
+ } from "../runtime/page-layout-estimation.ts";
416
+
417
+ /**
418
+ * L03/L06 search-text pure helpers + type aliases — pure functions
419
+ * over `SurfaceBlockSnapshot` + `SearchOptions` (public types) used
420
+ * by the PM search plugin at `src/ui-tailwind/editor-surface/search-plugin.ts`.
421
+ * No runtime handle in scope. Matches the handoff §4.17 "L03/L06
422
+ * selection/search primitives — promote to public-types.ts as pure
423
+ * re-exports (chart family precedent)" alternative.
424
+ *
425
+ * Canonical impl lives on `src/core/search/search-text.ts`.
426
+ *
427
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17. The larger
428
+ * `runtime.content.search` family seam on L07 is still the preferred
429
+ * long-term home; until it ships, this pragmatic re-export unblocks
430
+ * the L11 boundary register.
431
+ */
432
+ export {
433
+ buildSearchPattern,
434
+ createSearchExcerpt,
435
+ findSearchMatches,
436
+ searchSecondaryStories,
437
+ type SecondaryStorySearchResult,
438
+ type SearchTextOptions,
439
+ } from "../core/search/search-text.ts";
440
+
263
441
  /**
264
442
  * OOXML unit-conversion constants shared with presentation-layer
265
443
  * renderers. EMU (English Metric Units) is the OOXML measurement
@@ -280,6 +458,39 @@ export {
280
458
  SRCRECT_UNITS_PER_PERCENT,
281
459
  } from "../runtime/units.ts";
282
460
 
461
+ /**
462
+ * Geometry-kernel + page-estimation unit constants used by presentation-
463
+ * layer chrome (table grip, page chrome). Both fold into public-types
464
+ * alongside the OOXML unit constants above so chrome overlays can
465
+ * convert between twips and CSS px without reaching into
466
+ * `src/runtime/**`.
467
+ *
468
+ * - `DEFAULT_PX_PER_TWIP = 96 / 1440` — kernel render-frame conversion
469
+ * used by `tw-table-grip-layer` for grip positioning.
470
+ * - `DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP = 1 / 15` — page-chrome
471
+ * estimation scale used for placeholder chrome before real layout.
472
+ *
473
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17 self-closable
474
+ * rows. Canonical values live on `src/runtime/render/render-frame-types.ts`
475
+ * and `src/runtime/page-layout-estimation.ts`.
476
+ */
477
+ export { DEFAULT_PX_PER_TWIP } from "../runtime/render/render-frame-types.ts";
478
+ export { DEFAULT_PAGE_ESTIMATE_PX_PER_TWIP } from "../runtime/page-layout-estimation.ts";
479
+
480
+ /**
481
+ * Markdown sanitizer re-exported at the public-types boundary so the
482
+ * Layer-11 comment-markdown renderer can consume it without reaching
483
+ * into `src/runtime/**`. Pure function over a string; no runtime handle
484
+ * in scope at the leaf renderer. Canonical implementation lives on
485
+ * `src/runtime/markdown-sanitizer.ts` and is shared with
486
+ * `runtime/comment-presentation.ts`.
487
+ * Re-exported 2026-04-24 per refactor/11 handoff §4.17 self-closable row.
488
+ */
489
+ export {
490
+ sanitizeMarkdown,
491
+ type SanitizeResult,
492
+ } from "../runtime/markdown-sanitizer.ts";
493
+
283
494
  export interface SelectionSnapshot {
284
495
  anchor: number;
285
496
  head: number;
@@ -904,7 +1115,16 @@ export type SurfaceTextMark =
904
1115
  | "imprint"
905
1116
  | "shadow"
906
1117
  | "smallCaps"
907
- | "allCaps";
1118
+ | "allCaps"
1119
+ /**
1120
+ * Present iff the run carried `w:highlight`. The concrete highlight color
1121
+ * is on `markAttrs.backgroundColor`. Consumers that only care about the
1122
+ * presence signal (e.g. "is this run highlighted?") read `marks`; those
1123
+ * that need the color read `markAttrs.backgroundColor`. Note that
1124
+ * `backgroundColor` can also originate from `w:shd` (run shading) — only
1125
+ * the `"highlight"` mark disambiguates the source.
1126
+ */
1127
+ | "highlight";
908
1128
 
909
1129
  /**
910
1130
  * V2c.4 / V2c.5 — DrawingFrame anchor geometry projected onto image + shape
@@ -1225,6 +1445,34 @@ export type SurfaceBlockSnapshot =
1225
1445
  outlineLevel?: number;
1226
1446
  bidi?: boolean;
1227
1447
  suppressLineNumbers?: boolean;
1448
+ /**
1449
+ * `<w:framePr>` text-frame properties (ECMA-376 §17.3.1.11). Populated
1450
+ * by L03 surface projection from `CanonicalParagraphFormatting.frameProperties`
1451
+ * when present. L04 consumers use the positioning fields to decide
1452
+ * paginated-layout placement (out-of-flow framed paragraph vs. in-flow
1453
+ * block); L11 consumers use them to render `<div>` with absolute or
1454
+ * margin-anchored positioning + wrap behavior. Absent field = normal
1455
+ * in-flow paragraph.
1456
+ *
1457
+ * All sub-fields optional; absence carries the OOXML default.
1458
+ */
1459
+ frameProperties?: {
1460
+ widthTwips?: number;
1461
+ heightTwips?: number;
1462
+ hRule?: "auto" | "atLeast" | "exact";
1463
+ xTwips?: number;
1464
+ yTwips?: number;
1465
+ xAlign?: "left" | "center" | "right" | "inside" | "outside";
1466
+ yAlign?: "top" | "center" | "bottom" | "inside" | "outside" | "inline";
1467
+ hAnchor?: "text" | "margin" | "page";
1468
+ vAnchor?: "text" | "margin" | "page";
1469
+ wrap?: "around" | "auto" | "none" | "notBeside" | "tight" | "through";
1470
+ hSpaceTwips?: number;
1471
+ vSpaceTwips?: number;
1472
+ dropCap?: "none" | "drop" | "margin";
1473
+ lines?: number;
1474
+ anchorLock?: boolean;
1475
+ };
1228
1476
  segments: SurfaceInlineSegment[];
1229
1477
  }
1230
1478
  | {
@@ -1657,6 +1905,15 @@ export interface TableStructureContextSnapshot {
1657
1905
  columnCount: number;
1658
1906
  selectedCellCount: number;
1659
1907
  isSimpleTable: boolean;
1908
+ /**
1909
+ * Table-level alignment declared on the canonical `TableNode.alignment`.
1910
+ * `null` when the table has no explicit alignment (renders against the
1911
+ * parent's default — typically left). Mirrors `PublicTableSummary.alignment`
1912
+ * (refactor/11 §4.13) so the active-state of the whole-table alignment
1913
+ * toolbar button can read from the context snapshot directly without
1914
+ * a separate `getTable(tableBlockIndex).alignment` hop.
1915
+ */
1916
+ alignment: "left" | "center" | "right" | null;
1660
1917
  currentCell: {
1661
1918
  rowIndex: number;
1662
1919
  columnIndex: number;
@@ -2205,6 +2462,19 @@ export interface AddScopeParams {
2205
2462
  * held runtime-only, split across doc + workblock, or fully embedded.
2206
2463
  */
2207
2464
  metadata?: Partial<WorkflowMetadataEntry>;
2465
+ /**
2466
+ * Optional fields stamped onto the overlay scope's `metadata` array
2467
+ * at creation time. Distinct from `metadata?: Partial<WorkflowMetadataEntry>`
2468
+ * above (which writes a typed metadata *entry* keyed by `metadataId`);
2469
+ * `scopeMetadataFields` lands as plain `WorkflowScopeMetadataField[]`
2470
+ * on the `WorkflowScope.metadata` slot and survives serialization /
2471
+ * collab replication with the overlay.
2472
+ *
2473
+ * Used by coord-08 §9 — L06's `createScopeFromBlockId({stableRefHint})`
2474
+ * encodes the hint as `{key: "stableRefHint", value: <kind>}` here so
2475
+ * the L08 compiler can read it back during enumeration.
2476
+ */
2477
+ scopeMetadataFields?: readonly WorkflowScopeMetadataField[];
2208
2478
  /** Non-main-body stories (footnote / header / endnote). */
2209
2479
  storyTarget?: EditorStoryTarget;
2210
2480
  /** Optional display label for the scope card / rail. */
@@ -5337,6 +5607,15 @@ export interface WordReviewEditorChromeVisibility {
5337
5607
  pageChrome: boolean;
5338
5608
  statusBar: boolean;
5339
5609
  reviewRail: boolean;
5610
+ /**
5611
+ * TwShellHeader (Edit / Review / Workflow / More mode tabs) at the top
5612
+ * of the workspace. Defaults to `true` on every preset EXCEPT
5613
+ * `selection`, which is intended for minimal embeds and should not paint
5614
+ * a workspace chrome header. coord-11 §21 — regressing this default has
5615
+ * history, particularly for visual-fidelity captures that expect a
5616
+ * truly chrome-less `chrome=none` embed.
5617
+ */
5618
+ shellHeader: boolean;
5340
5619
  }
5341
5620
 
5342
5621
  // ---------------------------------------------------------------------------
@@ -27,6 +27,7 @@ import { createClipboardFamily } from "./runtime/clipboard.ts";
27
27
  import { createChartFamily } from "./runtime/chart.ts";
28
28
  import { createSearchFamily } from "./runtime/search.ts";
29
29
  import { createTableFamily } from "./runtime/table.ts";
30
+ import { createViewportFamily } from "./runtime/viewport.ts";
30
31
 
31
32
  import { createInspectFamily } from "./ai/inspect.ts";
32
33
  import { createResolveFamily } from "./ai/resolve.ts";
@@ -36,6 +37,10 @@ import { createAttachFamily } from "./ai/attach.ts";
36
37
  import { createExportFamily } from "./ai/export.ts";
37
38
  import { createExplainFamily } from "./ai/explain.ts";
38
39
  import { createPolicyFamily } from "./ai/policy.ts";
40
+ import { createReviewFamily as createAiReviewFamily } from "./ai/review.ts";
41
+ import { createEvaluateFamily } from "./ai/evaluate.ts";
42
+ import { createStatsFamily } from "./ai/stats.ts";
43
+ import { createOutlineFamily } from "./ai/outline.ts";
39
44
 
40
45
  import { createUiApi } from "./ui/_create.ts";
41
46
  import type { ApiV3Ui, UiControllerFactory } from "./ui/_types.ts";
@@ -62,6 +67,7 @@ export type ApiV3Runtime = {
62
67
  readonly chart: ReturnType<typeof createChartFamily>;
63
68
  readonly search: ReturnType<typeof createSearchFamily>;
64
69
  readonly table: ReturnType<typeof createTableFamily>;
70
+ readonly viewport: ReturnType<typeof createViewportFamily>;
65
71
  };
66
72
 
67
73
  export type ApiV3Ai = ReturnType<typeof createInspectFamily>
@@ -71,7 +77,11 @@ export type ApiV3Ai = ReturnType<typeof createInspectFamily>
71
77
  & ReturnType<typeof createAttachFamily>
72
78
  & ReturnType<typeof createExportFamily>
73
79
  & ReturnType<typeof createExplainFamily>
74
- & ReturnType<typeof createPolicyFamily>;
80
+ & ReturnType<typeof createPolicyFamily>
81
+ & ReturnType<typeof createAiReviewFamily>
82
+ & ReturnType<typeof createEvaluateFamily>
83
+ & ReturnType<typeof createStatsFamily>
84
+ & ReturnType<typeof createOutlineFamily>;
75
85
 
76
86
  export interface ApiV3 {
77
87
  readonly runtime: ApiV3Runtime;
@@ -117,6 +127,10 @@ export function createApiV3(handle: RuntimeApiHandle, opts?: CreateApiV3Opts): A
117
127
  ...createExportFamily(handle),
118
128
  ...createExplainFamily(handle),
119
129
  ...createPolicyFamily(handle),
130
+ ...createAiReviewFamily(handle),
131
+ ...createEvaluateFamily(handle),
132
+ ...createStatsFamily(handle),
133
+ ...createOutlineFamily(handle),
120
134
  };
121
135
  const runtime: ApiV3Runtime = {
122
136
  document: createDocumentFamily(handle),
@@ -131,6 +145,7 @@ export function createApiV3(handle: RuntimeApiHandle, opts?: CreateApiV3Opts): A
131
145
  chart: createChartFamily(handle),
132
146
  search: createSearchFamily(handle),
133
147
  table: createTableFamily(handle),
148
+ viewport: createViewportFamily(handle),
134
149
  };
135
150
  // Construct the UI namespace only when a factory is supplied.
136
151
  // `ui` remains `undefined` otherwise — the shape in ApiV3 is optional
@@ -55,6 +55,7 @@ export type RuntimeApiHandle = Pick<
55
55
  // Review (runtime.review family)
56
56
  | "getReviewWorkSnapshot"
57
57
  | "acceptChange"
58
+ | "rejectChange"
58
59
  | "resolveComment"
59
60
  // Workflow (runtime.workflow + ai.inspect families)
60
61
  | "queryScopes"
@@ -131,6 +132,7 @@ export const RUNTIME_API_HANDLE_SHAPE_CHECK: Record<keyof RuntimeApiHandle, true
131
132
  findAllText: true,
132
133
  getReviewWorkSnapshot: true,
133
134
  acceptChange: true,
135
+ rejectChange: true,
134
136
  resolveComment: true,
135
137
  queryScopes: true,
136
138
  getWorkflowMarkupSnapshot: true,
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @endStateApi v3 — `ai.evaluate` family.
3
+ *
4
+ * evaluateAction — pre-flight verdict combining /06's static policy
5
+ * matrix with live runtime state. Returns whether an action can
6
+ * currently proceed, what blockers (if any) apply, and whether human
7
+ * approval is required per the policy tier.
8
+ *
9
+ * Composition rules:
10
+ *
11
+ * 1. If `policy.support` is `'blocked'` or `'unsupported'`, emit a
12
+ * `policy-refused:<support>` blocker. `allowed: false` regardless
13
+ * of live state — the policy override wins.
14
+ *
15
+ * 2. When `input.scopeId` is supplied, resolve it via the scope
16
+ * compiler. If it does not resolve, emit
17
+ * `scope-not-resolvable:<scopeId>` and flip `allowed: false`. This
18
+ * mirrors the refusal taxonomy that `ai.validateReplacementScope`
19
+ * surfaces.
20
+ *
21
+ * 3. `approvalRequired` is the policy tier's confirmation flag —
22
+ * `support === 'confirmation-required' ||
23
+ * requirements.userConfirmation`. Agents should surface this to a
24
+ * human before calling the mutating path, even when `allowed:
25
+ * true`.
26
+ *
27
+ * Read-family function — A4 audit emission does not apply.
28
+ * `validateReplacementScope` remains the authoritative pre-flight for
29
+ * replacement-class mutations (it runs the full `composeScopeValidation`
30
+ * pipeline); `evaluateAction` is a lighter, scope-optional probe an
31
+ * agent can call against any `AIAction`, including non-replacement
32
+ * operations (resolve_comment_thread, auto_accept_changes, etc.) that
33
+ * have no scope target.
34
+ */
35
+
36
+ import type { RuntimeApiHandle } from "../_runtime-handle.ts";
37
+ import type { ApiV3FnMetadata } from "../_layer-metadata.ts";
38
+ import {
39
+ getAIActionPolicy,
40
+ type AIAction,
41
+ type AIActionPolicy,
42
+ } from "../../../runtime/workflow/ai-action-policy.ts";
43
+ import { createScopeCompilerService } from "../../../runtime/scopes/index.ts";
44
+
45
+ export interface EvaluateActionInput {
46
+ readonly action: AIAction;
47
+ readonly scopeId?: string;
48
+ }
49
+
50
+ export interface EvaluateActionResult {
51
+ readonly action: AIAction;
52
+ readonly allowed: boolean;
53
+ readonly policy: AIActionPolicy;
54
+ readonly blockers: readonly string[];
55
+ readonly approvalRequired: boolean;
56
+ }
57
+
58
+ export const evaluateActionMetadata: ApiV3FnMetadata = {
59
+ name: "ai.evaluateAction",
60
+ status: "live-with-adapter",
61
+ sourceLayer: "workflow-review",
62
+ liveEvidence: {
63
+ runnerTest: "test/api/v3/ai/ai-evaluate-action.test.ts",
64
+ commit: "refactor-09-post-closure-evaluate-action",
65
+ },
66
+ uxIntent: { uiVisible: false, expectsUxResponse: "none" },
67
+ agentMetadata: {
68
+ readOrMutate: "read",
69
+ boundedScope: "scope",
70
+ auditCategory: "policy-evaluate",
71
+ contextPromptShape:
72
+ "Pre-flight verdict: can this action proceed against (optionally) this scope? Returns {allowed, policy, blockers, approvalRequired}. Composes getPolicy() with live scope resolvability.",
73
+ },
74
+ stateClass: "A-canonical",
75
+ persistsTo: "canonical",
76
+ rwdReference:
77
+ "§AI API § ai.evaluateAction. Composes /06's static policy matrix with live scope resolvability. Returns a single-verdict carrier agents branch on before calling the mutating path. Read-only; no audit emission.",
78
+ };
79
+
80
+ export function createEvaluateFamily(runtime: RuntimeApiHandle) {
81
+ const compiler = createScopeCompilerService(runtime);
82
+ return {
83
+ evaluateAction(input: EvaluateActionInput): EvaluateActionResult {
84
+ // @endStateApi — live-with-adapter. Composes /06's static policy
85
+ // matrix with live scope resolvability from the /08 compiler.
86
+ const policy = getAIActionPolicy(input.action);
87
+ const blockers: string[] = [];
88
+
89
+ if (policy.support === "blocked" || policy.support === "unsupported") {
90
+ blockers.push(`policy-refused:${policy.support}`);
91
+ }
92
+
93
+ if (input.scopeId !== undefined) {
94
+ const compiled = compiler.compileScopeById(input.scopeId);
95
+ if (!compiled) {
96
+ blockers.push(`scope-not-resolvable:${input.scopeId}`);
97
+ }
98
+ }
99
+
100
+ const approvalRequired =
101
+ policy.support === "confirmation-required" ||
102
+ policy.requirements.userConfirmation === true;
103
+
104
+ return {
105
+ action: input.action,
106
+ allowed: blockers.length === 0,
107
+ policy,
108
+ blockers: Object.freeze([...blockers]),
109
+ approvalRequired,
110
+ };
111
+ },
112
+ };
113
+ }