@beyondwork/docx-react-component 1.0.127 → 1.0.129

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 (98) hide show
  1. package/dist/api/public-types.cjs +215 -61
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +2 -2
  5. package/dist/api/v3.cjs +1324 -71
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +8 -8
  9. package/dist/{canonical-document-CXCFCbAz.d.cts → canonical-document-BMtONpgf.d.cts} +6 -0
  10. package/dist/{canonical-document-CXCFCbAz.d.ts → canonical-document-BMtONpgf.d.ts} +6 -0
  11. package/dist/{chunk-KV435YXO.js → chunk-5DSHUYSY.js} +1 -1
  12. package/dist/{chunk-TQDQU2E3.js → chunk-63FYIGCT.js} +2 -2
  13. package/dist/{chunk-ZDOAUP3V.js → chunk-DDN2AIGE.js} +1 -1
  14. package/dist/{chunk-6F5QW44A.js → chunk-DJU2W4E4.js} +2 -2
  15. package/dist/{chunk-4EENH4FG.js → chunk-EZKJXIPH.js} +1 -1
  16. package/dist/{chunk-CXSYRB37.js → chunk-HUIHBBAQ.js} +166 -49
  17. package/dist/{chunk-ESJ2MES5.js → chunk-JJGVE5J7.js} +1 -1
  18. package/dist/{chunk-LZVBNDGU.js → chunk-LJH64PV3.js} +3 -3
  19. package/dist/{chunk-MWSBGJQO.js → chunk-OTQIW2TC.js} +2 -2
  20. package/dist/{chunk-2QL5DAKF.js → chunk-PGKUJZXV.js} +3 -3
  21. package/dist/{chunk-PUMZWE2D.js → chunk-PRAZBHNF.js} +460 -136
  22. package/dist/{chunk-4YJVRIUB.js → chunk-Q3QYGKFE.js} +51 -8
  23. package/dist/{chunk-YHZHPXDB.js → chunk-RMRTQGW3.js} +50 -13
  24. package/dist/{chunk-XRACP43Q.js → chunk-SKPTKQHF.js} +351 -13
  25. package/dist/{chunk-D5HYZQTG.js → chunk-VNLDQJ47.js} +1 -1
  26. package/dist/{chunk-BYSRJ4FE.js → chunk-W34X3KBR.js} +1 -1
  27. package/dist/{chunk-V6XVZFFH.js → chunk-XMHSGPLN.js} +2 -2
  28. package/dist/{chunk-46KNRA4C.js → chunk-XQCAMKIQ.js} +849 -6
  29. package/dist/{chunk-YD2JE54B.js → chunk-YZDZ4FGR.js} +1 -1
  30. package/dist/compare.d.cts +1 -1
  31. package/dist/compare.d.ts +1 -1
  32. package/dist/core/commands/formatting-commands.d.cts +2 -2
  33. package/dist/core/commands/formatting-commands.d.ts +2 -2
  34. package/dist/core/commands/image-commands.cjs +166 -49
  35. package/dist/core/commands/image-commands.d.cts +2 -2
  36. package/dist/core/commands/image-commands.d.ts +2 -2
  37. package/dist/core/commands/image-commands.js +4 -4
  38. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  39. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  40. package/dist/core/commands/style-commands.d.cts +2 -2
  41. package/dist/core/commands/style-commands.d.ts +2 -2
  42. package/dist/core/commands/table-structure-commands.cjs +166 -49
  43. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  44. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  45. package/dist/core/commands/table-structure-commands.js +3 -3
  46. package/dist/core/commands/text-commands.cjs +166 -49
  47. package/dist/core/commands/text-commands.d.cts +2 -2
  48. package/dist/core/commands/text-commands.d.ts +2 -2
  49. package/dist/core/commands/text-commands.js +4 -4
  50. package/dist/core/selection/mapping.d.cts +2 -2
  51. package/dist/core/selection/mapping.d.ts +2 -2
  52. package/dist/core/state/editor-state.d.cts +2 -2
  53. package/dist/core/state/editor-state.d.ts +2 -2
  54. package/dist/index.cjs +1943 -219
  55. package/dist/index.d.cts +5 -5
  56. package/dist/index.d.ts +5 -5
  57. package/dist/index.js +56 -22
  58. package/dist/io/docx-session.cjs +51 -8
  59. package/dist/io/docx-session.d.cts +4 -4
  60. package/dist/io/docx-session.d.ts +4 -4
  61. package/dist/io/docx-session.js +3 -3
  62. package/dist/legal.d.cts +1 -1
  63. package/dist/legal.d.ts +1 -1
  64. package/dist/legal.js +2 -2
  65. package/dist/{loader-CFICtb9m.d.ts → loader-4qsw4eIU.d.ts} +3 -3
  66. package/dist/{loader-DveZOVuC.d.cts → loader-B8TKhmQi.d.cts} +3 -3
  67. package/dist/{public-types-beSYFJRR.d.cts → public-types-B5CRoR6f.d.cts} +220 -1
  68. package/dist/{public-types-Cgl3efbO.d.ts → public-types-p9b8rfy8.d.ts} +220 -1
  69. package/dist/public-types.cjs +215 -61
  70. package/dist/public-types.d.cts +2 -2
  71. package/dist/public-types.d.ts +2 -2
  72. package/dist/public-types.js +2 -2
  73. package/dist/runtime/collab.d.cts +3 -3
  74. package/dist/runtime/collab.d.ts +3 -3
  75. package/dist/runtime/document-runtime.cjs +999 -193
  76. package/dist/runtime/document-runtime.d.cts +2 -2
  77. package/dist/runtime/document-runtime.d.ts +2 -2
  78. package/dist/runtime/document-runtime.js +13 -13
  79. package/dist/{session-B7u82EJF.d.cts → session-BnGIjaex.d.cts} +3 -3
  80. package/dist/{session-BWMJ9jm4.d.ts → session-vEYKf-w3.d.ts} +3 -3
  81. package/dist/session.cjs +51 -8
  82. package/dist/session.d.cts +5 -5
  83. package/dist/session.d.ts +5 -5
  84. package/dist/session.js +4 -4
  85. package/dist/tailwind.cjs +215 -61
  86. package/dist/tailwind.d.cts +2 -2
  87. package/dist/tailwind.d.ts +2 -2
  88. package/dist/tailwind.js +5 -5
  89. package/dist/{types-BQjdVZsh.d.cts → types-BLuvZ6cQ.d.cts} +2 -2
  90. package/dist/{types-DvvmS5A7.d.ts → types-Dutlyj0T.d.ts} +2 -2
  91. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  92. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  93. package/dist/ui-tailwind/editor-surface/search-plugin.js +3 -3
  94. package/dist/ui-tailwind.cjs +215 -61
  95. package/dist/ui-tailwind.d.cts +3 -3
  96. package/dist/ui-tailwind.d.ts +3 -3
  97. package/dist/ui-tailwind.js +5 -5
  98. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -10120,12 +10120,13 @@ function getLevelStartAt(level, levelDefinitions) {
10120
10120
  return levelDefinitions.get(level)?.startAt ?? DEFAULT_NUMBERING_START_AT;
10121
10121
  }
10122
10122
  function getNumberingFormatPosture(format, value) {
10123
- if (!isSupportedNumberingFormat(format)) {
10123
+ const registryEntry = getNumberingFormatRegistryEntry(format);
10124
+ if (!registryEntry || registryEntry.renderSupport === "approximated") {
10124
10125
  return {
10125
10126
  status: "approximated",
10126
10127
  requestedFormat: format,
10127
10128
  renderedFormat: "decimal",
10128
- reason: "unsupported-numbering-format-decimal-fallback"
10129
+ reason: registryEntry?.fallbackReason ?? "unsupported-numbering-format-decimal-fallback"
10129
10130
  };
10130
10131
  }
10131
10132
  if (value !== void 0 && ((format === "upperRoman" || format === "lowerRoman") && (value <= 0 || value >= 4e3) || (format === "cardinalText" || format === "ordinalText") && (!Number.isInteger(value) || value < 1 || value > 999) || (format === "upperLetter" || format === "lowerLetter" || format === "chicago") && value < 1)) {
@@ -10156,56 +10157,148 @@ function renderLevelText(text, counters, levelDefinitions) {
10156
10157
  });
10157
10158
  return rendered.trim().length > 0 ? rendered : null;
10158
10159
  }
10159
- var SUPPORTED_NUMBERING_FORMATS = /* @__PURE__ */ new Set([
10160
- "decimal",
10161
- "decimalZero",
10162
- "upperLetter",
10163
- "lowerLetter",
10164
- "upperRoman",
10165
- "lowerRoman",
10166
- "hex",
10167
- "ordinal",
10168
- "cardinalText",
10169
- "ordinalText",
10170
- "chicago",
10171
- "bullet",
10172
- "none"
10173
- ]);
10174
10160
  function isSupportedNumberingFormat(format) {
10175
- return SUPPORTED_NUMBERING_FORMATS.has(format);
10161
+ return getNumberingFormatRegistryEntry(format)?.renderSupport === "supported";
10162
+ }
10163
+ function getNumberingFormatRegistryEntry(format) {
10164
+ return NUMBERING_FORMAT_REGISTRY.get(format);
10176
10165
  }
10177
10166
  function formatCounter(value, format) {
10178
- switch (format) {
10179
- case "decimal":
10180
- return String(value);
10181
- case "decimalZero":
10182
- return String(value).padStart(2, "0");
10183
- case "upperLetter":
10184
- return toAlphabetic2(value).toUpperCase();
10185
- case "lowerLetter":
10186
- return toAlphabetic2(value).toLowerCase();
10187
- case "upperRoman":
10188
- return toRoman2(value).toUpperCase();
10189
- case "lowerRoman":
10190
- return toRoman2(value).toLowerCase();
10191
- case "hex":
10192
- return value >= 0 ? value.toString(16).toUpperCase() : String(value);
10193
- case "ordinal":
10194
- return toOrdinal2(value);
10195
- case "cardinalText":
10196
- return toCardinalText2(value);
10197
- case "ordinalText":
10198
- return toOrdinalText2(value);
10199
- case "chicago":
10200
- return toChicago2(value);
10201
- case "bullet":
10202
- return "";
10203
- case "none":
10204
- return "";
10205
- default:
10206
- return String(value);
10207
- }
10167
+ return getNumberingFormatRegistryEntry(format)?.render(value) ?? String(value);
10208
10168
  }
10169
+ var exactNumberingFormatEntries = [
10170
+ {
10171
+ format: "decimal",
10172
+ renderSupport: "supported",
10173
+ renderedFormat: "decimal",
10174
+ supportsMutation: true,
10175
+ render: (value) => String(value)
10176
+ },
10177
+ {
10178
+ format: "decimalZero",
10179
+ renderSupport: "supported",
10180
+ renderedFormat: "decimalZero",
10181
+ supportsMutation: true,
10182
+ render: (value) => String(value).padStart(2, "0")
10183
+ },
10184
+ {
10185
+ format: "upperLetter",
10186
+ renderSupport: "supported",
10187
+ renderedFormat: "upperLetter",
10188
+ supportsMutation: true,
10189
+ render: (value) => toAlphabetic2(value).toUpperCase()
10190
+ },
10191
+ {
10192
+ format: "lowerLetter",
10193
+ renderSupport: "supported",
10194
+ renderedFormat: "lowerLetter",
10195
+ supportsMutation: true,
10196
+ render: (value) => toAlphabetic2(value).toLowerCase()
10197
+ },
10198
+ {
10199
+ format: "upperRoman",
10200
+ renderSupport: "supported",
10201
+ renderedFormat: "upperRoman",
10202
+ supportsMutation: true,
10203
+ render: (value) => toRoman2(value).toUpperCase()
10204
+ },
10205
+ {
10206
+ format: "lowerRoman",
10207
+ renderSupport: "supported",
10208
+ renderedFormat: "lowerRoman",
10209
+ supportsMutation: true,
10210
+ render: (value) => toRoman2(value).toLowerCase()
10211
+ },
10212
+ {
10213
+ format: "hex",
10214
+ renderSupport: "supported",
10215
+ renderedFormat: "hex",
10216
+ supportsMutation: true,
10217
+ render: (value) => value >= 0 ? value.toString(16).toUpperCase() : String(value)
10218
+ },
10219
+ {
10220
+ format: "ordinal",
10221
+ renderSupport: "supported",
10222
+ renderedFormat: "ordinal",
10223
+ supportsMutation: true,
10224
+ render: toOrdinal2
10225
+ },
10226
+ {
10227
+ format: "cardinalText",
10228
+ renderSupport: "supported",
10229
+ renderedFormat: "cardinalText",
10230
+ supportsMutation: true,
10231
+ render: toCardinalText2
10232
+ },
10233
+ {
10234
+ format: "ordinalText",
10235
+ renderSupport: "supported",
10236
+ renderedFormat: "ordinalText",
10237
+ supportsMutation: true,
10238
+ render: toOrdinalText2
10239
+ },
10240
+ {
10241
+ format: "chicago",
10242
+ renderSupport: "supported",
10243
+ renderedFormat: "chicago",
10244
+ supportsMutation: true,
10245
+ render: toChicago2
10246
+ },
10247
+ {
10248
+ format: "bullet",
10249
+ renderSupport: "supported",
10250
+ renderedFormat: "bullet",
10251
+ supportsMutation: true,
10252
+ render: () => ""
10253
+ },
10254
+ {
10255
+ format: "none",
10256
+ renderSupport: "supported",
10257
+ renderedFormat: "none",
10258
+ supportsMutation: true,
10259
+ render: () => ""
10260
+ }
10261
+ ];
10262
+ var approximatedDecimalFormats = [
10263
+ "decimalEnclosedCircle",
10264
+ "decimalEnclosedFullstop",
10265
+ "decimalEnclosedParen",
10266
+ "decimalFullWidth",
10267
+ "decimalHalfWidth",
10268
+ "aiueo",
10269
+ "iroha",
10270
+ "ganada",
10271
+ "chosung",
10272
+ "russianLower",
10273
+ "russianUpper",
10274
+ "hebrew1",
10275
+ "hebrew2",
10276
+ "arabicAlpha",
10277
+ "arabicAbjad",
10278
+ "thaiLetters",
10279
+ "thaiNumbers",
10280
+ "hindiLetters",
10281
+ "hindiNumbers",
10282
+ "ideographDigital",
10283
+ "ideographTraditional",
10284
+ "chineseCounting",
10285
+ "japaneseCounting",
10286
+ "japaneseLegal"
10287
+ ];
10288
+ var approximatedNumberingFormatEntries = approximatedDecimalFormats.map((format) => ({
10289
+ format,
10290
+ renderSupport: "approximated",
10291
+ renderedFormat: "decimal",
10292
+ supportsMutation: false,
10293
+ fallbackReason: "unsupported-numbering-format-decimal-fallback",
10294
+ render: (value) => String(value)
10295
+ }));
10296
+ var NUMBERING_FORMAT_REGISTRY = new Map(
10297
+ [...exactNumberingFormatEntries, ...approximatedNumberingFormatEntries].map((entry) => [
10298
+ entry.format,
10299
+ entry
10300
+ ])
10301
+ );
10209
10302
  function toOrdinal2(value) {
10210
10303
  if (value <= 0) return String(value);
10211
10304
  const lastTwo = value % 100;
@@ -10859,12 +10952,36 @@ var DEFAULT_HYPERLINK_COLOR_HEX = "0563C1";
10859
10952
  function resolveHyperlinkRunFormatting(input, catalog, resolver) {
10860
10953
  const augmentedInput = input.characterStyleId === void 0 ? { ...input, characterStyleId: HYPERLINK_CHARACTER_STYLE_ID } : input;
10861
10954
  const cascade = resolveEffectiveRunFormatting(augmentedInput, catalog);
10862
- const resolvedColor = resolveHyperlinkColorHex(cascade, resolver);
10955
+ const resolvedColor = resolveHyperlinkColorHex(
10956
+ stripInheritedColorHexForImplicitHyperlink(input, catalog, cascade),
10957
+ resolver
10958
+ );
10863
10959
  if (resolvedColor && resolvedColor !== cascade.colorHex) {
10864
10960
  return { ...cascade, colorHex: resolvedColor };
10865
10961
  }
10866
10962
  return cascade;
10867
10963
  }
10964
+ function hasDirectNonAutoColor(input) {
10965
+ return Boolean(input.direct?.colorHex && input.direct.colorHex !== "auto");
10966
+ }
10967
+ function characterStyleDeclaresColorHex(styleId, catalog) {
10968
+ if (!catalog) return false;
10969
+ const chain = resolveCharacterStyleChain(styleId, catalog);
10970
+ return chain.some((chainStyleId) => {
10971
+ const colorHex = catalog.characters[chainStyleId]?.runProperties?.colorHex;
10972
+ return Boolean(colorHex && colorHex !== "auto");
10973
+ });
10974
+ }
10975
+ function stripInheritedColorHexForImplicitHyperlink(originalInput, catalog, cascade) {
10976
+ if (originalInput.characterStyleId !== void 0 || hasDirectNonAutoColor(originalInput) || !cascade.colorHex || cascade.colorHex === "auto" || characterStyleDeclaresColorHex(HYPERLINK_CHARACTER_STYLE_ID, catalog)) {
10977
+ return cascade;
10978
+ }
10979
+ const inheritedCascade = resolveEffectiveRunFormatting(originalInput, catalog);
10980
+ if (inheritedCascade.colorHex !== cascade.colorHex) {
10981
+ return cascade;
10982
+ }
10983
+ return { ...cascade, colorHex: void 0 };
10984
+ }
10868
10985
  function resolveHyperlinkColorHex(cascade, resolver) {
10869
10986
  if (cascade.colorHex && cascade.colorHex !== "auto") {
10870
10987
  return cascade.colorHex;
@@ -16572,6 +16689,14 @@ function paginateSectionBlocksWithSplits(section, blocks, layout, footnotes, mea
16572
16689
  pushPage(block.from);
16573
16690
  continue;
16574
16691
  }
16692
+ if (isStandalonePageBreakParagraph(block)) {
16693
+ if (columnHeight > 0) {
16694
+ pushPage(nextBoundary);
16695
+ } else {
16696
+ pageStart = Math.max(pageStart, Math.min(nextBoundary, section.end));
16697
+ }
16698
+ break;
16699
+ }
16575
16700
  const effectiveNoteHeight = estimateFootnoteReservation(
16576
16701
  block,
16577
16702
  footnotes,
@@ -16746,6 +16871,21 @@ function hasPageBreak(block) {
16746
16871
  }
16747
16872
  return nestedBlocks(block).some(hasPageBreak);
16748
16873
  }
16874
+ function isStandalonePageBreakParagraph(block) {
16875
+ if (block.kind !== "paragraph") return false;
16876
+ let sawPageBreak = false;
16877
+ for (const segment of block.segments) {
16878
+ if (segment.kind === "opaque_inline" && segment.label === "Page break") {
16879
+ sawPageBreak = true;
16880
+ continue;
16881
+ }
16882
+ if (segment.kind === "text" && segment.text.trim().length === 0) {
16883
+ continue;
16884
+ }
16885
+ return false;
16886
+ }
16887
+ return sawPageBreak;
16888
+ }
16749
16889
  function nestedBlocks(block) {
16750
16890
  if (block.kind === "sdt_block") {
16751
16891
  return block.children;
@@ -18230,6 +18370,9 @@ function projectSurfaceBlocksToPageFragments(surface, pages, splits, columnByBlo
18230
18370
  for (let blockIndex = 0; blockIndex < surface.blocks.length; blockIndex += 1) {
18231
18371
  const block = surface.blocks[blockIndex];
18232
18372
  const blockPath = `main/block[${blockIndex}]`;
18373
+ if (isStandalonePageBreakParagraph2(block)) {
18374
+ continue;
18375
+ }
18233
18376
  if (block.kind === "table") {
18234
18377
  const tableSliceList = splits?.tablesByBlockId.get(block.blockId);
18235
18378
  if (tableSliceList && tableSliceList.length > 1) {
@@ -18315,6 +18458,23 @@ function projectSurfaceBlocksToPageFragments(surface, pages, splits, columnByBlo
18315
18458
  }
18316
18459
  return byPage;
18317
18460
  }
18461
+ function isStandalonePageBreakParagraph2(block) {
18462
+ if (block.kind !== "paragraph") {
18463
+ return false;
18464
+ }
18465
+ let sawPageBreak = false;
18466
+ for (const segment of block.segments) {
18467
+ if (segment.kind === "opaque_inline" && segment.label === "Page break") {
18468
+ sawPageBreak = true;
18469
+ continue;
18470
+ }
18471
+ if (segment.kind === "text" && segment.text.trim().length === 0) {
18472
+ continue;
18473
+ }
18474
+ return false;
18475
+ }
18476
+ return sawPageBreak;
18477
+ }
18318
18478
  function projectLineBoxesForPageFragments(pages, fragmentsByPageIndex, fragmentMeasurementsByPageIndex, surface) {
18319
18479
  const byPage = /* @__PURE__ */ new Map();
18320
18480
  const blocksById = surface ? new Map(surface.blocks.map((block) => [block.blockId, block])) : /* @__PURE__ */ new Map();
@@ -18827,13 +18987,11 @@ function buildBookmarkRanges(targets) {
18827
18987
  }
18828
18988
  var EMPTY_NUMBERING_INPUT_INDEX = {
18829
18989
  byNumberingKey: /* @__PURE__ */ new Map(),
18830
- byBlockPath: /* @__PURE__ */ new Map(),
18831
- byParagraphIndex: /* @__PURE__ */ new Map()
18990
+ byBlockPath: /* @__PURE__ */ new Map()
18832
18991
  };
18833
18992
  function buildNumberingInputIndex(numberingInputs) {
18834
18993
  const byNumberingKey = /* @__PURE__ */ new Map();
18835
18994
  const byBlockPath = /* @__PURE__ */ new Map();
18836
- const byParagraph = /* @__PURE__ */ new Map();
18837
18995
  for (const input of numberingInputs) {
18838
18996
  if (!byNumberingKey.has(input.numberingKey)) {
18839
18997
  byNumberingKey.set(input.numberingKey, input);
@@ -18841,11 +18999,8 @@ function buildNumberingInputIndex(numberingInputs) {
18841
18999
  if (!byBlockPath.has(input.blockPath)) {
18842
19000
  byBlockPath.set(input.blockPath, input);
18843
19001
  }
18844
- if (!byParagraph.has(input.paragraphIndex)) {
18845
- byParagraph.set(input.paragraphIndex, input);
18846
- }
18847
19002
  }
18848
- return { byNumberingKey, byBlockPath, byParagraphIndex: byParagraph };
19003
+ return { byNumberingKey, byBlockPath };
18849
19004
  }
18850
19005
  function collectBookmarkRangeLayoutFacts(fragmentId, blockPath, bookmarkRanges) {
18851
19006
  if (!blockPath || !bookmarkRanges || bookmarkRanges.length === 0) return [];
@@ -18965,8 +19120,7 @@ function collectNumberingLayoutFactsForBlock(block, blockPath, numberingIndex, n
18965
19120
  const canonical = lookupNumberingInput(
18966
19121
  numberingIndex,
18967
19122
  numberingKey,
18968
- context.path,
18969
- paragraphIndex
19123
+ context.path
18970
19124
  );
18971
19125
  const target = findNumberingTarget(numberingTargets, context.path);
18972
19126
  const numberingLayoutId = numberingKey ?? [
@@ -19006,7 +19160,7 @@ function findNumberingTarget(numberingTargets, blockPath) {
19006
19160
  if (blockPath === void 0) return void 0;
19007
19161
  return numberingTargets.find((target) => target.blockPath === blockPath);
19008
19162
  }
19009
- function lookupNumberingInput(numberingIndex, numberingKey, blockPath, paragraphIndex) {
19163
+ function lookupNumberingInput(numberingIndex, numberingKey, blockPath) {
19010
19164
  if (!numberingIndex) return void 0;
19011
19165
  if (numberingKey !== void 0) {
19012
19166
  const byKey = numberingIndex.byNumberingKey.get(numberingKey);
@@ -19016,7 +19170,7 @@ function lookupNumberingInput(numberingIndex, numberingKey, blockPath, paragraph
19016
19170
  const byPath = numberingIndex.byBlockPath.get(blockPath);
19017
19171
  if (byPath !== void 0) return byPath;
19018
19172
  }
19019
- return paragraphIndex !== void 0 ? numberingIndex.byParagraphIndex.get(paragraphIndex) : void 0;
19173
+ return void 0;
19020
19174
  }
19021
19175
  function collectNumberingUnavailableReasons(numbering, canonical) {
19022
19176
  const reasons = [];
@@ -19435,7 +19589,7 @@ async function createCanvasProvider(fontLoader) {
19435
19589
  }
19436
19590
 
19437
19591
  // src/runtime/layout/layout-engine-version.ts
19438
- var LAYOUT_ENGINE_VERSION = 88;
19592
+ var LAYOUT_ENGINE_VERSION = 89;
19439
19593
  var LAYCACHE_SCHEMA_VERSION = 12;
19440
19594
 
19441
19595
  // src/runtime/layout/layout-engine-instance.ts
@@ -22000,6 +22154,133 @@ function clamp(value, min, max) {
22000
22154
  return Math.min(max, Math.max(min, value));
22001
22155
  }
22002
22156
 
22157
+ // src/io/ooxml/numbering-catalog-mutation.ts
22158
+ function cloneNumberingCatalog(catalog) {
22159
+ return structuredClone(catalog);
22160
+ }
22161
+ function getListKind(catalog, numberingInstanceId) {
22162
+ const instance = catalog.instances[numberingInstanceId];
22163
+ const definition = instance ? catalog.abstractDefinitions[instance.abstractNumberingId] : void 0;
22164
+ const levelZero = definition?.levels.find((level) => level.level === 0);
22165
+ if (!levelZero) return void 0;
22166
+ return levelZero.format === "bullet" ? "bulleted" : "numbered";
22167
+ }
22168
+ function ensureDefaultListInstance(catalog, kind) {
22169
+ const existing = Object.values(catalog.instances).find(
22170
+ (instance) => getListKind(catalog, instance.numberingInstanceId) === kind
22171
+ );
22172
+ if (existing) return existing.numberingInstanceId;
22173
+ const abstractNumberingId = allocateAbstractDefinition(catalog, {
22174
+ levels: defaultLevels(kind),
22175
+ multiLevelType: "hybridMultilevel"
22176
+ });
22177
+ return allocateNumberingInstance(catalog, abstractNumberingId);
22178
+ }
22179
+ function allocateNumberingInstance(catalog, abstractNumberingId, overrides = []) {
22180
+ const numberingInstanceId = nextCanonicalNumericId(
22181
+ "num:",
22182
+ Object.keys(catalog.instances)
22183
+ );
22184
+ catalog.instances[numberingInstanceId] = {
22185
+ numberingInstanceId,
22186
+ abstractNumberingId,
22187
+ overrides: cloneOverrides(overrides)
22188
+ };
22189
+ return numberingInstanceId;
22190
+ }
22191
+ function allocateAbstractDefinition(catalog, input) {
22192
+ const abstractNumberingId = input.abstractNumberingId && !catalog.abstractDefinitions[input.abstractNumberingId] ? input.abstractNumberingId : nextCanonicalNumericId("abstract-num:", Object.keys(catalog.abstractDefinitions));
22193
+ catalog.abstractDefinitions[abstractNumberingId] = {
22194
+ abstractNumberingId,
22195
+ levels: structuredClone(input.levels),
22196
+ ...input.nsid ? { nsid: input.nsid } : { nsid: freshLongHex(catalog, abstractNumberingId, "nsid") },
22197
+ ...input.multiLevelType ? { multiLevelType: input.multiLevelType } : {},
22198
+ ...input.tplc ? { tplc: input.tplc } : { tplc: freshLongHex(catalog, abstractNumberingId, "tmpl") },
22199
+ ...input.styleLink ? { styleLink: input.styleLink } : {},
22200
+ ...input.numStyleLink ? { numStyleLink: input.numStyleLink } : {}
22201
+ };
22202
+ return abstractNumberingId;
22203
+ }
22204
+ function setStartOverride(catalog, numberingInstanceId, level, startAt) {
22205
+ const instance = catalog.instances[numberingInstanceId];
22206
+ if (!instance) return;
22207
+ catalog.instances[numberingInstanceId] = {
22208
+ ...instance,
22209
+ overrides: mergeOverride(instance.overrides, { level, startAt })
22210
+ };
22211
+ }
22212
+ function mergeOverride(overrides, nextOverride) {
22213
+ return [
22214
+ ...overrides.filter((override) => override.level !== nextOverride.level),
22215
+ structuredClone(nextOverride)
22216
+ ].sort((left, right) => left.level - right.level);
22217
+ }
22218
+ function cloneOverrides(overrides) {
22219
+ return overrides.map((override) => structuredClone(override));
22220
+ }
22221
+ function defaultLevels(kind) {
22222
+ if (kind === "bulleted") {
22223
+ return [
22224
+ { level: 0, format: "bullet", text: "\u2022" },
22225
+ { level: 1, format: "bullet", text: "o" },
22226
+ { level: 2, format: "bullet", text: "\u25A0" },
22227
+ { level: 3, format: "bullet", text: "\u2022" },
22228
+ { level: 4, format: "bullet", text: "o" },
22229
+ { level: 5, format: "bullet", text: "\u25A0" },
22230
+ { level: 6, format: "bullet", text: "\u2022" },
22231
+ { level: 7, format: "bullet", text: "o" },
22232
+ { level: 8, format: "bullet", text: "\u25A0" }
22233
+ ];
22234
+ }
22235
+ return [
22236
+ { level: 0, format: "decimal", text: "%1." },
22237
+ { level: 1, format: "decimal", text: "%1.%2." },
22238
+ { level: 2, format: "lowerLetter", text: "(%3)" },
22239
+ { level: 3, format: "lowerRoman", text: "(%4)" },
22240
+ { level: 4, format: "decimal", text: "%5." },
22241
+ { level: 5, format: "lowerLetter", text: "(%6)" },
22242
+ { level: 6, format: "lowerRoman", text: "(%7)" },
22243
+ { level: 7, format: "decimal", text: "%8." },
22244
+ { level: 8, format: "lowerLetter", text: "(%9)" }
22245
+ ];
22246
+ }
22247
+ function nextCanonicalNumericId(prefix, ids) {
22248
+ return `${prefix}${nextNumericString(ids.map((id) => stripPrefix(id, prefix)))}`;
22249
+ }
22250
+ function nextNumericString(ids) {
22251
+ const used = new Set(ids);
22252
+ let next = 1;
22253
+ for (const id of ids) {
22254
+ const parsed = Number.parseInt(id, 10);
22255
+ if (Number.isFinite(parsed) && parsed >= next) next = parsed + 1;
22256
+ }
22257
+ while (used.has(String(next))) next += 1;
22258
+ return String(next);
22259
+ }
22260
+ function stripPrefix(value, prefix) {
22261
+ return value.startsWith(prefix) ? value.slice(prefix.length) : value;
22262
+ }
22263
+ function freshLongHex(catalog, abstractNumberingId, salt) {
22264
+ const existing = new Set(
22265
+ Object.values(catalog.abstractDefinitions).map((definition) => salt === "nsid" ? definition.nsid : definition.tplc).filter((value) => Boolean(value))
22266
+ );
22267
+ let attempt = 0;
22268
+ while (attempt < 1e3) {
22269
+ const candidate = hashLongHex(`${salt}:${abstractNumberingId}:${attempt}`);
22270
+ if (!existing.has(candidate)) return candidate;
22271
+ attempt += 1;
22272
+ }
22273
+ return hashLongHex(`${salt}:${abstractNumberingId}:${Date.now()}`);
22274
+ }
22275
+ function hashLongHex(input) {
22276
+ let hash = 2166136261;
22277
+ for (let index = 0; index < input.length; index += 1) {
22278
+ hash ^= input.charCodeAt(index);
22279
+ hash = Math.imul(hash, 16777619) >>> 0;
22280
+ }
22281
+ return hash.toString(16).toUpperCase().padStart(8, "0").slice(-8);
22282
+ }
22283
+
22003
22284
  // src/core/commands/list-commands.ts
22004
22285
  function toggleNumberedList(document2, paragraphIndexes, context, options = {}) {
22005
22286
  return toggleListKind(document2, paragraphIndexes, "numbered", context, options);
@@ -22151,7 +22432,7 @@ function restartNumbering(document2, paragraphIndex, context, startAt = 1, optio
22151
22432
  affectedParagraphIndexes: []
22152
22433
  };
22153
22434
  }
22154
- const catalog = ensureNumberingCatalog(working.numbering);
22435
+ const catalog = cloneNumberingCatalog(working.numbering);
22155
22436
  const existingInstance = catalog.instances[target.numbering.numberingInstanceId];
22156
22437
  if (!existingInstance) {
22157
22438
  return {
@@ -22159,15 +22440,12 @@ function restartNumbering(document2, paragraphIndex, context, startAt = 1, optio
22159
22440
  affectedParagraphIndexes: []
22160
22441
  };
22161
22442
  }
22162
- const numberingInstanceId = createNumberingInstanceId(catalog);
22163
- catalog.instances[numberingInstanceId] = {
22164
- numberingInstanceId,
22165
- abstractNumberingId: existingInstance.abstractNumberingId,
22166
- overrides: mergeOverride(existingInstance.overrides, {
22167
- level: target.numbering.level,
22168
- startAt
22169
- })
22170
- };
22443
+ const numberingInstanceId = allocateNumberingInstance(
22444
+ catalog,
22445
+ existingInstance.abstractNumberingId,
22446
+ existingInstance.overrides
22447
+ );
22448
+ setStartOverride(catalog, numberingInstanceId, target.numbering.level, startAt);
22171
22449
  const affectedParagraphIndexes = [];
22172
22450
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
22173
22451
  const paragraph = paragraphs[index];
@@ -22221,7 +22499,7 @@ function continueNumbering(document2, paragraphIndex, context, options = {}) {
22221
22499
  affectedParagraphIndexes: []
22222
22500
  };
22223
22501
  }
22224
- const catalog = ensureNumberingCatalog(working.numbering);
22502
+ const catalog = cloneNumberingCatalog(working.numbering);
22225
22503
  const currentInstanceId = target.numbering.numberingInstanceId;
22226
22504
  const currentKind = getListKind(catalog, currentInstanceId);
22227
22505
  if (!currentKind) {
@@ -22288,7 +22566,7 @@ function toggleListKind(document2, paragraphIndexes, kind, context, options) {
22288
22566
  affectedParagraphIndexes: []
22289
22567
  };
22290
22568
  }
22291
- const catalog = ensureNumberingCatalog(working.numbering);
22569
+ const catalog = cloneNumberingCatalog(working.numbering);
22292
22570
  const allAlreadyKind = normalizedIndexes.every((index) => {
22293
22571
  const paragraph = paragraphs[index];
22294
22572
  return paragraph.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
@@ -22303,7 +22581,7 @@ function toggleListKind(document2, paragraphIndexes, kind, context, options) {
22303
22581
  affectedParagraphIndexes: normalizedIndexes
22304
22582
  };
22305
22583
  }
22306
- const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultInstance(catalog, kind);
22584
+ const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultListInstance(catalog, kind);
22307
22585
  for (const index of normalizedIndexes) {
22308
22586
  const paragraph = paragraphs[index];
22309
22587
  paragraph.numbering = {
@@ -22468,23 +22746,6 @@ function sortJson(value) {
22468
22746
  }
22469
22747
  return value;
22470
22748
  }
22471
- function ensureDefaultInstance(catalog, kind) {
22472
- const existing = Object.values(catalog.instances).find(
22473
- (instance) => getListKind(catalog, instance.numberingInstanceId) === kind
22474
- );
22475
- if (existing) {
22476
- return existing.numberingInstanceId;
22477
- }
22478
- const abstractNumberingId = createAbstractNumberingId(catalog);
22479
- catalog.abstractDefinitions[abstractNumberingId] = kind === "bulleted" ? createDefaultBulletedDefinition(abstractNumberingId) : createDefaultNumberedDefinition(abstractNumberingId);
22480
- const numberingInstanceId = createNumberingInstanceId(catalog);
22481
- catalog.instances[numberingInstanceId] = {
22482
- numberingInstanceId,
22483
- abstractNumberingId,
22484
- overrides: []
22485
- };
22486
- return numberingInstanceId;
22487
- }
22488
22749
  function findAdjacentCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
22489
22750
  const previous = paragraphs[fromIndex - 1];
22490
22751
  if (previous?.numbering) {
@@ -22507,69 +22768,6 @@ function findPreviousCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
22507
22768
  }
22508
22769
  return void 0;
22509
22770
  }
22510
- function getListKind(catalog, numberingInstanceId) {
22511
- const instance = catalog.instances[numberingInstanceId];
22512
- const definition = instance ? catalog.abstractDefinitions[instance.abstractNumberingId] : void 0;
22513
- const levelZero = definition?.levels.find((level) => level.level === 0);
22514
- if (!levelZero) {
22515
- return void 0;
22516
- }
22517
- return levelZero.format === "bullet" ? "bulleted" : "numbered";
22518
- }
22519
- function mergeOverride(overrides, nextOverride) {
22520
- const filtered = overrides.filter((override) => override.level !== nextOverride.level);
22521
- filtered.push(nextOverride);
22522
- return filtered.sort((left, right) => left.level - right.level);
22523
- }
22524
- function createDefaultNumberedDefinition(abstractNumberingId) {
22525
- return {
22526
- abstractNumberingId,
22527
- levels: [
22528
- { level: 0, format: "decimal", text: "%1." },
22529
- { level: 1, format: "decimal", text: "%1.%2." },
22530
- { level: 2, format: "lowerLetter", text: "(%3)" },
22531
- { level: 3, format: "lowerRoman", text: "(%4)" },
22532
- { level: 4, format: "decimal", text: "%5." },
22533
- { level: 5, format: "lowerLetter", text: "(%6)" },
22534
- { level: 6, format: "lowerRoman", text: "(%7)" },
22535
- { level: 7, format: "decimal", text: "%8." },
22536
- { level: 8, format: "lowerLetter", text: "(%9)" }
22537
- ]
22538
- };
22539
- }
22540
- function createDefaultBulletedDefinition(abstractNumberingId) {
22541
- return {
22542
- abstractNumberingId,
22543
- levels: [
22544
- { level: 0, format: "bullet", text: "\u2022" },
22545
- { level: 1, format: "bullet", text: "o" },
22546
- { level: 2, format: "bullet", text: "\u25A0" },
22547
- { level: 3, format: "bullet", text: "\u2022" },
22548
- { level: 4, format: "bullet", text: "o" },
22549
- { level: 5, format: "bullet", text: "\u25A0" },
22550
- { level: 6, format: "bullet", text: "\u2022" },
22551
- { level: 7, format: "bullet", text: "o" },
22552
- { level: 8, format: "bullet", text: "\u25A0" }
22553
- ]
22554
- };
22555
- }
22556
- function createAbstractNumberingId(catalog) {
22557
- let index = 1;
22558
- while (catalog.abstractDefinitions[`abstract-num:generated-${index}`]) {
22559
- index += 1;
22560
- }
22561
- return `abstract-num:generated-${index}`;
22562
- }
22563
- function createNumberingInstanceId(catalog) {
22564
- let index = 1;
22565
- while (catalog.instances[`num:generated-${index}`]) {
22566
- index += 1;
22567
- }
22568
- return `num:generated-${index}`;
22569
- }
22570
- function ensureNumberingCatalog(value) {
22571
- return structuredClone(value);
22572
- }
22573
22771
  function cloneEnvelope(document2, timestamp) {
22574
22772
  return {
22575
22773
  ...structuredClone(document2),
@@ -33916,7 +34114,7 @@ function applyFragmentInsert(document2, selection, fragment, context) {
33916
34114
  );
33917
34115
  workingDocument = collapseResult.document;
33918
34116
  workingSelection = collapseResult.selection;
33919
- if (context.textTarget?.kind === "table-paragraph") {
34117
+ if (context.textTarget?.kind === "table-paragraph" || context.textTarget?.kind === "text-leaf") {
33920
34118
  workingContext = {
33921
34119
  ...context,
33922
34120
  textTarget: {
@@ -33938,11 +34136,11 @@ function applyFragmentInsert(document2, selection, fragment, context) {
33938
34136
  selection
33939
34137
  };
33940
34138
  }
33941
- const targetedTablePath = workingContext.textTarget?.kind === "table-paragraph" ? workingContext.textTarget.blockPath : void 0;
33942
- if (targetedTablePath) {
34139
+ const targetedBlockPath = workingContext.textTarget?.kind === "table-paragraph" || workingContext.textTarget?.kind === "text-leaf" ? workingContext.textTarget.blockPath : void 0;
34140
+ if (targetedBlockPath) {
33943
34141
  const targeted = insertFragmentBlocksAfterPath(
33944
34142
  splitResult.document,
33945
- targetedTablePath,
34143
+ targetedBlockPath,
33946
34144
  fragment.blocks
33947
34145
  );
33948
34146
  if (targeted) {
@@ -43194,7 +43392,7 @@ function emptyCompatibilityReport() {
43194
43392
  }
43195
43393
 
43196
43394
  // src/runtime/debug/runtime-debug-facet.ts
43197
- function createRuntimeDebugFacet(getRuntime, bus) {
43395
+ function createRuntimeDebugFacet(getRuntime, bus, options = {}) {
43198
43396
  return {
43199
43397
  bus,
43200
43398
  getSnapshot(query) {
@@ -43212,7 +43410,318 @@ function createRuntimeDebugFacet(getRuntime, bus) {
43212
43410
  },
43213
43411
  getChannels() {
43214
43412
  return bus.getChannels();
43413
+ },
43414
+ getHotEditTraces() {
43415
+ return options.getHotEditTraces?.() ?? [];
43416
+ }
43417
+ };
43418
+ }
43419
+
43420
+ // src/runtime/hot-edit/hot-edit-trace.ts
43421
+ var HOT_EDIT_TRACE_LIMIT = 64;
43422
+ var HotEditTraceRecorder = class {
43423
+ traces = [];
43424
+ sequence = 0;
43425
+ begin(input) {
43426
+ this.sequence += 1;
43427
+ return {
43428
+ sequence: this.sequence,
43429
+ commandType: input.commandType,
43430
+ startedAtUtc: input.nowUtc,
43431
+ startedAtMs: nowMs(),
43432
+ startCounters: input.counters.snapshot()
43433
+ };
43434
+ }
43435
+ complete(pending, input) {
43436
+ const endCounters = input.counters.snapshot();
43437
+ const refreshAllCount = counterDelta(pending.startCounters, endCounters, "refresh.all");
43438
+ const patchHitCount = counterDelta(pending.startCounters, endCounters, "surface.localText.patchHit");
43439
+ const patchBudgetFallbackCount = counterDelta(
43440
+ pending.startCounters,
43441
+ endCounters,
43442
+ "surface.localText.patchBudgetFallback"
43443
+ );
43444
+ const boundedEditableTargetBuildCount = counterDelta(
43445
+ pending.startCounters,
43446
+ endCounters,
43447
+ "runtime.editableTargets.boundedBuilds"
43448
+ );
43449
+ const tier = refineTier(input.tier, {
43450
+ refreshAllCount,
43451
+ patchHitCount,
43452
+ patchBudgetFallbackCount,
43453
+ boundedEditableTargetBuildCount
43454
+ });
43455
+ const trace = {
43456
+ sequence: pending.sequence,
43457
+ startedAtUtc: pending.startedAtUtc,
43458
+ commandType: pending.commandType,
43459
+ tier,
43460
+ patchMissReason: input.patchMissReason,
43461
+ totalDurationUs: Math.max(0, Math.round((nowMs() - pending.startedAtMs) * 1e3)),
43462
+ refreshAllCount,
43463
+ patchHitCount,
43464
+ patchBudgetFallbackCount,
43465
+ boundedEditableTargetBuildCount
43466
+ };
43467
+ this.traces.push(trace);
43468
+ if (this.traces.length > HOT_EDIT_TRACE_LIMIT) {
43469
+ this.traces.splice(0, this.traces.length - HOT_EDIT_TRACE_LIMIT);
43470
+ }
43471
+ input.counters.increment(`hotEdit.tier.${trace.tier}`);
43472
+ if (trace.patchMissReason !== "none") {
43473
+ input.counters.increment(`hotEdit.patchMiss.${trace.patchMissReason}`);
43474
+ }
43475
+ return trace;
43476
+ }
43477
+ getTraces() {
43478
+ return Object.freeze([...this.traces]);
43479
+ }
43480
+ clear() {
43481
+ this.traces.splice(0, this.traces.length);
43482
+ }
43483
+ };
43484
+ function refineTier(requested, counters) {
43485
+ if (requested === "blocked") return requested;
43486
+ if (counters.refreshAllCount > 0) return "full-refresh";
43487
+ if (counters.patchBudgetFallbackCount > 0 || counters.boundedEditableTargetBuildCount > 0) {
43488
+ return "bounded-projection";
43489
+ }
43490
+ if (counters.patchHitCount > 0) return "patch";
43491
+ return requested;
43492
+ }
43493
+ function counterDelta(start, end, key) {
43494
+ return (end[key] ?? 0) - (start[key] ?? 0);
43495
+ }
43496
+ function nowMs() {
43497
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
43498
+ }
43499
+
43500
+ // src/runtime/hot-edit/surface-local-patcher.ts
43501
+ function patchSurfaceTextSegment(surface, patch) {
43502
+ const delta = patch.insertedText.length - Math.max(0, patch.to - patch.from);
43503
+ let patched = false;
43504
+ const blocks = surface.blocks.map((block) => {
43505
+ const result = patchBlock(block, patch, delta);
43506
+ if (result.patched) patched = true;
43507
+ return result.block;
43508
+ });
43509
+ if (!patched) {
43510
+ return { status: "miss", reason: "segment-not-found" };
43511
+ }
43512
+ return {
43513
+ status: "patched",
43514
+ surface: {
43515
+ ...surface,
43516
+ storySize: surface.storySize + delta,
43517
+ plainText: surface.plainText.slice(0, patch.from) + patch.insertedText + surface.plainText.slice(patch.to),
43518
+ blocks
43519
+ }
43520
+ };
43521
+ }
43522
+ function patchBlock(block, patch, delta) {
43523
+ if (patch.to < block.from) return { block, patched: false };
43524
+ if (patch.from > block.to) {
43525
+ return { block: shiftBlock(block, delta), patched: false };
43526
+ }
43527
+ switch (block.kind) {
43528
+ case "paragraph":
43529
+ return patchParagraph(block, patch, delta);
43530
+ case "sdt_block": {
43531
+ let patched = false;
43532
+ const children = block.children.map((child) => {
43533
+ const result = patchBlock(child, patch, delta);
43534
+ patched ||= result.patched;
43535
+ return result.block;
43536
+ });
43537
+ return {
43538
+ block: patched ? { ...block, to: block.to + delta, children } : block,
43539
+ patched
43540
+ };
43541
+ }
43542
+ case "table": {
43543
+ let patched = false;
43544
+ const rows = block.rows.map((row2) => ({
43545
+ ...row2,
43546
+ cells: row2.cells.map((cell) => ({
43547
+ ...cell,
43548
+ content: cell.content.map((child) => {
43549
+ const result = patchBlock(child, patch, delta);
43550
+ patched ||= result.patched;
43551
+ return result.block;
43552
+ })
43553
+ }))
43554
+ }));
43555
+ return {
43556
+ block: patched ? { ...block, to: block.to + delta, rows } : block,
43557
+ patched
43558
+ };
43559
+ }
43560
+ case "opaque_block":
43561
+ return { block, patched: false };
43562
+ }
43563
+ }
43564
+ function patchParagraph(block, patch, delta) {
43565
+ if (patch.from < block.from || patch.to > block.to) {
43566
+ return { block, patched: false };
43567
+ }
43568
+ const segmentIndex = block.segments.findIndex(
43569
+ (segment2) => segment2.kind === "text" && patch.from >= segment2.from && patch.to <= segment2.to
43570
+ );
43571
+ if (segmentIndex < 0) return { block, patched: false };
43572
+ const segment = block.segments[segmentIndex];
43573
+ if (segment.kind !== "text") return { block, patched: false };
43574
+ const localFrom = patch.from - segment.from;
43575
+ const localTo = patch.to - segment.from;
43576
+ const segments = block.segments.map((candidate, index) => {
43577
+ if (index < segmentIndex) return candidate;
43578
+ if (index === segmentIndex) {
43579
+ return {
43580
+ ...segment,
43581
+ text: segment.text.slice(0, localFrom) + patch.insertedText + segment.text.slice(localTo),
43582
+ to: segment.to + delta
43583
+ };
43215
43584
  }
43585
+ return shiftInlineSegment(candidate, delta);
43586
+ });
43587
+ return {
43588
+ block: {
43589
+ ...block,
43590
+ to: block.to + delta,
43591
+ segments
43592
+ },
43593
+ patched: true
43594
+ };
43595
+ }
43596
+ function shiftBlock(block, delta) {
43597
+ if (delta === 0) return block;
43598
+ switch (block.kind) {
43599
+ case "paragraph":
43600
+ return {
43601
+ ...block,
43602
+ from: block.from + delta,
43603
+ to: block.to + delta,
43604
+ segments: block.segments.map((segment) => shiftInlineSegment(segment, delta))
43605
+ };
43606
+ case "sdt_block":
43607
+ return {
43608
+ ...block,
43609
+ from: block.from + delta,
43610
+ to: block.to + delta,
43611
+ children: block.children.map((child) => shiftBlock(child, delta))
43612
+ };
43613
+ case "table":
43614
+ return {
43615
+ ...block,
43616
+ from: block.from + delta,
43617
+ to: block.to + delta,
43618
+ rows: block.rows.map((row2) => ({
43619
+ ...row2,
43620
+ cells: row2.cells.map((cell) => ({
43621
+ ...cell,
43622
+ content: cell.content.map((child) => shiftBlock(child, delta))
43623
+ }))
43624
+ }))
43625
+ };
43626
+ case "opaque_block":
43627
+ return {
43628
+ ...block,
43629
+ from: block.from + delta,
43630
+ to: block.to + delta
43631
+ };
43632
+ }
43633
+ }
43634
+ function shiftInlineSegment(segment, delta) {
43635
+ if (delta === 0) return segment;
43636
+ return {
43637
+ ...segment,
43638
+ from: segment.from + delta,
43639
+ to: segment.to + delta
43640
+ };
43641
+ }
43642
+
43643
+ // src/runtime/hot-edit/hot-edit-profiler.ts
43644
+ var HEAVY_REVIEW_ITEM_THRESHOLD = 24;
43645
+ var DENSE_BLOCK_NODE_THRESHOLD = 256;
43646
+ function deriveHotEditDocumentProfile(document2) {
43647
+ const blocks = document2.content.children ?? [];
43648
+ let tableBlockCount = 0;
43649
+ let maxNestedSurfaceNodesPerBlock = 0;
43650
+ for (const block of blocks) {
43651
+ if (block.type === "table") tableBlockCount += 1;
43652
+ maxNestedSurfaceNodesPerBlock = Math.max(
43653
+ maxNestedSurfaceNodesPerBlock,
43654
+ countBlockNodes(block)
43655
+ );
43656
+ }
43657
+ const commentCount = Object.keys(document2.review.comments ?? {}).length;
43658
+ const revisionCount = Object.keys(document2.review.revisions ?? {}).length;
43659
+ const secondaryStoryBlockCount = countSecondaryStoryBlocks(document2);
43660
+ return {
43661
+ blockCount: blocks.length,
43662
+ tableBlockCount,
43663
+ maxNestedSurfaceNodesPerBlock,
43664
+ commentCount,
43665
+ revisionCount,
43666
+ secondaryStoryBlockCount,
43667
+ hasHeavyReview: commentCount + revisionCount >= HEAVY_REVIEW_ITEM_THRESHOLD,
43668
+ hasDenseTables: tableBlockCount > 0 && maxNestedSurfaceNodesPerBlock > DENSE_BLOCK_NODE_THRESHOLD
43669
+ };
43670
+ }
43671
+ function countBlockNodes(block) {
43672
+ const value = block;
43673
+ let total = 1;
43674
+ if (Array.isArray(value.children)) {
43675
+ total += value.children.length;
43676
+ for (const child of value.children) {
43677
+ if (isBlockLike(child)) total += countBlockNodes(child);
43678
+ }
43679
+ }
43680
+ if (Array.isArray(value.rows)) {
43681
+ for (const row2 of value.rows) {
43682
+ total += 1;
43683
+ for (const cell of row2.cells ?? []) {
43684
+ total += 1;
43685
+ for (const child of cell.children ?? []) {
43686
+ total += countBlockNodes(child);
43687
+ }
43688
+ }
43689
+ }
43690
+ }
43691
+ return total;
43692
+ }
43693
+ function isBlockLike(value) {
43694
+ return Boolean(value && typeof value === "object" && "type" in value);
43695
+ }
43696
+ function countSecondaryStoryBlocks(document2) {
43697
+ const subParts = document2.subParts;
43698
+ if (!subParts) return 0;
43699
+ let count = 0;
43700
+ for (const value of Object.values(subParts)) {
43701
+ count += countBlocksInUnknownStory(value);
43702
+ }
43703
+ return count;
43704
+ }
43705
+ function countBlocksInUnknownStory(value) {
43706
+ if (!value || typeof value !== "object") return 0;
43707
+ const candidate = value;
43708
+ if (Array.isArray(candidate.children)) return candidate.children.length;
43709
+ if (Array.isArray(candidate.content?.children)) return candidate.content.children.length;
43710
+ return Object.values(value).reduce((total, entry) => total + countBlocksInUnknownStory(entry), 0);
43711
+ }
43712
+
43713
+ // src/runtime/hot-edit/hot-edit-policy.ts
43714
+ var DEFAULT_MAX_SHIFTED_SURFACE_NODES = 5e3;
43715
+ var DEFAULT_MAX_SHIFTED_NODES_PER_BLOCK = 256;
43716
+ var DEFAULT_SELECTION_CORRIDOR_BLOCK_RADIUS = 8;
43717
+ var HEAVY_DOCUMENT_SELECTION_CORRIDOR_BLOCK_RADIUS = 12;
43718
+ function resolveHotEditPolicy(profile) {
43719
+ const complexGeometry = profile.hasDenseTables || profile.secondaryStoryBlockCount > 0;
43720
+ return {
43721
+ maxShiftedSurfaceNodes: DEFAULT_MAX_SHIFTED_SURFACE_NODES,
43722
+ maxShiftedNodesPerBlock: DEFAULT_MAX_SHIFTED_NODES_PER_BLOCK,
43723
+ selectionCorridorBlockRadius: complexGeometry ? HEAVY_DOCUMENT_SELECTION_CORRIDOR_BLOCK_RADIUS : DEFAULT_SELECTION_CORRIDOR_BLOCK_RADIUS,
43724
+ preferBoundedProjectionForDenseTails: profile.hasDenseTables
43216
43725
  };
43217
43726
  }
43218
43727
 
@@ -46755,6 +47264,12 @@ function resolveScopeRange(entry, handle, positionMap) {
46755
47264
  if (inlineRange) return inlineRange;
46756
47265
  return positionMap.blocks.get(entry.blockIndex) ?? null;
46757
47266
  }
47267
+ case "image": {
47268
+ const key = `${entry.blockIndex}:${entry.inlineIndex}`;
47269
+ const inlineRange = positionMap.inlines.get(key);
47270
+ if (inlineRange) return inlineRange;
47271
+ return positionMap.blocks.get(entry.blockIndex) ?? null;
47272
+ }
46758
47273
  case "comment-thread":
46759
47274
  return anchorToRange(entry.thread.anchor);
46760
47275
  case "revision":
@@ -46893,6 +47408,11 @@ function deriveReplaceability(kind, provenance) {
46893
47408
  level: "preserve-only",
46894
47409
  reason: "field-result-is-computed-preserve-only"
46895
47410
  };
47411
+ case "image":
47412
+ return {
47413
+ level: "preserve-only",
47414
+ reason: "image-object-command-required"
47415
+ };
46896
47416
  case "comment-thread":
46897
47417
  return {
46898
47418
  level: "preserve-only",
@@ -47597,6 +48117,55 @@ function compileHeadingScope(entry, options = {}) {
47597
48117
  };
47598
48118
  }
47599
48119
 
48120
+ // src/runtime/scopes/scope-kinds/image.ts
48121
+ function imageAltText(image) {
48122
+ if (image.type === "image") return image.altText ?? "";
48123
+ return image.anchor.docPr?.descr ?? image.anchor.docPr?.name ?? "";
48124
+ }
48125
+ function imageMediaId(image) {
48126
+ if (image.type === "image") return image.mediaId;
48127
+ return image.content.type === "picture" ? image.content.mediaId : void 0;
48128
+ }
48129
+ function imageDisplay(image) {
48130
+ if (image.type === "image") return image.display;
48131
+ return image.anchor.display;
48132
+ }
48133
+ function imageSourceKind(image) {
48134
+ return image.type === "image" ? "legacy-image" : "drawing-picture";
48135
+ }
48136
+ function compileImageScope(entry) {
48137
+ const { handle, image } = entry;
48138
+ const altText = imageAltText(image);
48139
+ const mediaId = imageMediaId(image);
48140
+ const display = imageDisplay(image);
48141
+ const sourceKind = imageSourceKind(image);
48142
+ return {
48143
+ handle,
48144
+ kind: "image",
48145
+ classifications: entry.classifications,
48146
+ content: {
48147
+ text: altText,
48148
+ excerpt: buildExcerpt(altText),
48149
+ authority: "structural-summary"
48150
+ },
48151
+ formatting: {},
48152
+ layout: display ? { flowKind: display } : {},
48153
+ geometry: {},
48154
+ workflow: { scopeIds: [], effectiveMode: "edit" },
48155
+ replaceability: deriveReplaceability("image", handle.provenance),
48156
+ audit: {
48157
+ source: "runtime",
48158
+ derivedFrom: [
48159
+ "canonical",
48160
+ `image-source:${sourceKind}`,
48161
+ ...mediaId ? [`media-id:${mediaId}`] : []
48162
+ ],
48163
+ confidence: "medium"
48164
+ },
48165
+ partial: true
48166
+ };
48167
+ }
48168
+
47600
48169
  // src/runtime/scopes/scope-kinds/list-item.ts
47601
48170
  function compileListItemScope(entry, options = {}) {
47602
48171
  const { handle, paragraph } = entry;
@@ -48185,6 +48754,8 @@ function compileScope(entry, optionsOrCatalog) {
48185
48754
  });
48186
48755
  case "field":
48187
48756
  return compileFieldScope(entry);
48757
+ case "image":
48758
+ return compileImageScope(entry);
48188
48759
  case "comment-thread":
48189
48760
  return compileCommentThreadScope(entry);
48190
48761
  case "revision":
@@ -48373,6 +48944,44 @@ function enumerateFieldsInParagraph(paragraph, blockIndex, documentId, parentSco
48373
48944
  }
48374
48945
  return out;
48375
48946
  }
48947
+ function isImageInline(child) {
48948
+ return child.type === "image" || child.type === "drawing_frame" && child.content.type === "picture";
48949
+ }
48950
+ function enumerateImagesInParagraph(paragraph, blockIndex, documentId, parentScopeId) {
48951
+ const out = [];
48952
+ for (let i = 0; i < paragraph.children.length; i += 1) {
48953
+ const child = paragraph.children[i];
48954
+ if (!isImageInline(child)) continue;
48955
+ const semanticPath = [
48956
+ "body",
48957
+ "paragraph",
48958
+ String(blockIndex),
48959
+ "image",
48960
+ String(i)
48961
+ ];
48962
+ const scopeId = `image:${blockIndex}:${i}`;
48963
+ const handle = {
48964
+ scopeId,
48965
+ documentId,
48966
+ storyTarget: MAIN_STORY2,
48967
+ semanticPath,
48968
+ parentScopeId,
48969
+ stableRef: { kind: "semantic-path", value: semanticPath.join("/") },
48970
+ provenance: "derived",
48971
+ rangePrecision: "canonical"
48972
+ };
48973
+ out.push({
48974
+ kind: "image",
48975
+ handle,
48976
+ image: child,
48977
+ paragraph,
48978
+ blockIndex,
48979
+ inlineIndex: i,
48980
+ classifications: Object.freeze([])
48981
+ });
48982
+ }
48983
+ return out;
48984
+ }
48376
48985
  function enumerateCommentThreads(document2, documentId) {
48377
48986
  const review = document2.review;
48378
48987
  const comments = review?.comments;
@@ -48503,6 +49112,8 @@ function enumerateScopes(document2, inputs = {}) {
48503
49112
  });
48504
49113
  const fields = enumerateFieldsInParagraph(block, index, documentId, scopeId);
48505
49114
  for (const field of fields) results.push(field);
49115
+ const images = enumerateImagesInParagraph(block, index, documentId, scopeId);
49116
+ for (const image of images) results.push(image);
48506
49117
  continue;
48507
49118
  }
48508
49119
  if (block.type === "table") {
@@ -48892,6 +49503,15 @@ var LIST_TEXT_TARGET_KINDS = /* @__PURE__ */ new Set([
48892
49503
  "sdt-paragraph-text",
48893
49504
  "secondary-story-paragraph-text"
48894
49505
  ]);
49506
+ var OBJECT_COMMAND_INTENTS = /* @__PURE__ */ new Set([
49507
+ "image-layout",
49508
+ "image-frame",
49509
+ "chart-edit",
49510
+ "custom-xml-update",
49511
+ "embedded-content-update",
49512
+ "opaque-content-preserve",
49513
+ "object-edit"
49514
+ ]);
48895
49515
  function freezeList(values) {
48896
49516
  return Object.freeze([...values]);
48897
49517
  }
@@ -49436,6 +50056,35 @@ function listStructureCapability(scope, context) {
49436
50056
  ]
49437
50057
  );
49438
50058
  }
50059
+ function objectEditCapability(context) {
50060
+ const objectTargets = (context?.editableTargets?.entries ?? []).filter(
50061
+ (entry) => entry.kind === "object-anchor" || entry.kind === "custom-xml-content" || entry.kind === "opaque-content" || entry.commandFamily === "object" || entry.commandFamily === "preserve-only-refusal" || entry.runtimeCommand.intents.some((intent) => OBJECT_COMMAND_INTENTS.has(intent))
50062
+ );
50063
+ const supportedTargets = objectTargets.filter(
50064
+ (entry) => entry.runtimeCommand.status === "supported" && entry.runtimeCommand.intents.some((intent) => OBJECT_COMMAND_INTENTS.has(intent))
50065
+ );
50066
+ if (supportedTargets.length > 0) {
50067
+ return supportedCommand(
50068
+ "compile-supported:object-edit:editable-target",
50069
+ supportedTargets
50070
+ );
50071
+ }
50072
+ if (objectTargets.length > 0) {
50073
+ const blockers = commandTargetBlockers(objectTargets);
50074
+ return blocked(
50075
+ "compile-blocked:object-edit:target-ref-blocked",
50076
+ blockers.length > 0 ? blockers : ["compile-blocked:object-edit:target-ref-blocked"]
50077
+ );
50078
+ }
50079
+ return unsupported(
50080
+ "compile-unsupported:object-edit:no-target-family",
50081
+ [
50082
+ "compile-unsupported:object-edit:no-target-family",
50083
+ "capability:object-edit:l02-object-target-required",
50084
+ "capability:object-edit:l07-command-support-required"
50085
+ ]
50086
+ );
50087
+ }
49439
50088
  function deriveScopeCapabilities(scope, context = {}) {
49440
50089
  return {
49441
50090
  canReplaceText: replaceTextCapability(scope, context),
@@ -49452,7 +50101,8 @@ function deriveScopeCapabilities(scope, context = {}) {
49452
50101
  canEditTableStructure: tableStructureCapability(scope, context),
49453
50102
  canUseTableContinuationEvidence: tableContinuationEvidenceCapability(scope, context),
49454
50103
  canEditListText: listTextCapability(scope, context),
49455
- canEditListStructure: listStructureCapability(scope, context)
50104
+ canEditListStructure: listStructureCapability(scope, context),
50105
+ canEditObject: objectEditCapability(context)
49456
50106
  };
49457
50107
  }
49458
50108
 
@@ -49724,6 +50374,11 @@ function tokensForScope(entry) {
49724
50374
  { kind: "row", index: entry.rowIndex },
49725
50375
  { kind: "cell", index: entry.cellIndex }
49726
50376
  ]);
50377
+ case "image":
50378
+ return Object.freeze([
50379
+ { kind: "block", index: entry.blockIndex },
50380
+ { kind: "inline", index: entry.inlineIndex }
50381
+ ]);
49727
50382
  default:
49728
50383
  return null;
49729
50384
  }
@@ -50471,6 +51126,64 @@ function deriveScopeEditableTargetEvidence(document2, scope, entry, options = {}
50471
51126
  };
50472
51127
  }
50473
51128
 
51129
+ // src/runtime/scopes/object-evidence.ts
51130
+ var OBJECT_INTENTS = /* @__PURE__ */ new Set([
51131
+ "image-layout",
51132
+ "image-frame",
51133
+ "chart-edit",
51134
+ "custom-xml-update",
51135
+ "embedded-content-update",
51136
+ "opaque-content-preserve",
51137
+ "object-edit",
51138
+ "preserve-only-refusal"
51139
+ ]);
51140
+ function unique2(values) {
51141
+ return Object.freeze([...new Set(values.filter((value) => value.length > 0))]);
51142
+ }
51143
+ function isObjectTarget(entry) {
51144
+ return entry.object !== void 0 || entry.kind === "object-anchor" || entry.kind === "custom-xml-content" || entry.kind === "opaque-content" || entry.commandFamily === "object" || entry.runtimeCommand.intents.some((intent) => OBJECT_INTENTS.has(intent));
51145
+ }
51146
+ function blockersFor(entry) {
51147
+ return unique2([
51148
+ ...entry.posture.blockers,
51149
+ ...entry.runtimeCommand.blockers ?? [],
51150
+ ...entry.runtimeTextCommand.blockers ?? [],
51151
+ ...(entry.workflowBlockers ?? []).flatMap((blocker2) => [
51152
+ blocker2.blocker,
51153
+ blocker2.refusalId
51154
+ ]),
51155
+ entry.runtimeCommand.status === "blocked" ? entry.runtimeCommand.reason : ""
51156
+ ]);
51157
+ }
51158
+ function projectEntry2(entry) {
51159
+ const blockers = blockersFor(entry);
51160
+ return {
51161
+ targetKey: entry.targetKey,
51162
+ kind: entry.kind,
51163
+ ...entry.object?.objectKind ? { objectKind: entry.object.objectKind } : {},
51164
+ relation: entry.relation,
51165
+ commandFamily: entry.commandFamily,
51166
+ editability: entry.editability,
51167
+ ...entry.sourceRef ? { sourceRef: entry.sourceRef } : {},
51168
+ ...entry.object ? { object: entry.object } : {},
51169
+ runtimeCommand: entry.runtimeCommand,
51170
+ blockers,
51171
+ ...entry.posture.preserveOnly ? { preserveOnly: true } : {}
51172
+ };
51173
+ }
51174
+ function deriveScopeObjectEvidence(editableTargets) {
51175
+ const entries = Object.freeze(
51176
+ [...editableTargets?.entries ?? []].filter(isObjectTarget).map(projectEntry2).sort((left, right) => left.targetKey.localeCompare(right.targetKey))
51177
+ );
51178
+ const blockers = unique2(entries.flatMap((entry) => [...entry.blockers]));
51179
+ return {
51180
+ status: entries.length > 0 ? "present" : "none",
51181
+ count: entries.length,
51182
+ blockers,
51183
+ entries
51184
+ };
51185
+ }
51186
+
50474
51187
  // src/runtime/scopes/table-evidence.ts
50475
51188
  function isTableFamilyEntry(entry) {
50476
51189
  return entry?.kind === "table" || entry?.kind === "table-row" || entry?.kind === "table-cell";
@@ -51040,7 +51753,7 @@ function deriveScopeGeometryEvidence(scopeId, provider, context) {
51040
51753
  function freezeList2(values) {
51041
51754
  return values ? Object.freeze([...values]) : void 0;
51042
51755
  }
51043
- function unique2(values) {
51756
+ function unique3(values) {
51044
51757
  return Object.freeze([...new Set(values)]);
51045
51758
  }
51046
51759
  function parseTableFamilyScopeId2(scopeId) {
@@ -51070,7 +51783,7 @@ function candidateTableBlockIds(blockIndex, mapped) {
51070
51783
  const mappedId = mapped?.get(blockIndex);
51071
51784
  if (mappedId) ids.push(mappedId);
51072
51785
  ids.push(`table-${blockIndex}`, `table:${blockIndex}`, `block-${blockIndex}`);
51073
- return unique2(ids);
51786
+ return unique3(ids);
51074
51787
  }
51075
51788
  function rowInFragment(fragment, rowIndex) {
51076
51789
  const range = fragment.tableRowRange;
@@ -51107,19 +51820,19 @@ function projectTableFramePage(fragment) {
51107
51820
  ...fragment.tableRowRange ? { rowRange: { ...fragment.tableRowRange } } : {},
51108
51821
  ...fragment.continuation?.continuesFromPreviousPage !== void 0 ? { continuesFromPreviousPage: fragment.continuation.continuesFromPreviousPage } : {},
51109
51822
  ...fragment.continuation?.continuesToNextPage !== void 0 ? { continuesToNextPage: fragment.continuation.continuesToNextPage } : {},
51110
- ...repeated ? { repeatedHeaderRowIndexes: unique2(repeated) } : {},
51823
+ ...repeated ? { repeatedHeaderRowIndexes: unique3(repeated) } : {},
51111
51824
  ...splitRowCarry ? { splitRowCarry: Object.freeze(splitRowCarry.map((item) => ({ ...item }))) } : {},
51112
51825
  ...carry ? { verticalMergeCarry: Object.freeze(carry.map((item) => ({ ...item }))) } : {}
51113
51826
  };
51114
51827
  }
51115
51828
  function projectTableFrame(blockId, parsed, fragments) {
51116
- const pageIds = unique2(fragments.map((fragment) => fragment.pageId));
51117
- const pageSliceIds = unique2(fragments.map((fragment) => fragment.fragmentId));
51118
- const layoutObjectIds = unique2(
51829
+ const pageIds = unique3(fragments.map((fragment) => fragment.pageId));
51830
+ const pageSliceIds = unique3(fragments.map((fragment) => fragment.fragmentId));
51831
+ const layoutObjectIds = unique3(
51119
51832
  fragments.map((fragment) => fragment.layoutObject?.objectId).filter((objectId) => typeof objectId === "string" && objectId.length > 0)
51120
51833
  );
51121
51834
  const rowRangesByPage = Object.freeze(fragments.map(projectTableFramePage));
51122
- const repeatedHeaderRowIndexes = unique2(
51835
+ const repeatedHeaderRowIndexes = unique3(
51123
51836
  fragments.flatMap((fragment) => fragment.continuation?.repeatedHeaderRowIndexes ?? [])
51124
51837
  );
51125
51838
  const verticalMergeCarry = Object.freeze(
@@ -51144,7 +51857,7 @@ function projectTableFrame(blockId, parsed, fragments) {
51144
51857
  };
51145
51858
  }
51146
51859
  function continuationFromTableFrame(fragments) {
51147
- const pageIds = unique2(fragments.map((fragment) => fragment.pageId));
51860
+ const pageIds = unique3(fragments.map((fragment) => fragment.pageId));
51148
51861
  return {
51149
51862
  ...pageIds.length > 0 ? { pageIds } : {},
51150
51863
  pageCount: pageIds.length,
@@ -51442,6 +52155,7 @@ function composeEvidence(inputs) {
51442
52155
  ...editableTargets ? { editableTargets } : {},
51443
52156
  layout
51444
52157
  });
52158
+ const objects = deriveScopeObjectEvidence(editableTargets);
51445
52159
  return {
51446
52160
  formattingSummary: formattingSummaryOf(scope),
51447
52161
  reviewItemIds,
@@ -51452,6 +52166,7 @@ function composeEvidence(inputs) {
51452
52166
  ...adjacentGeometry ? { adjacentGeometry } : {},
51453
52167
  visualization: deriveScopeVisualization(scope),
51454
52168
  ...editableTargets ? { editableTargets } : {},
52169
+ objects,
51455
52170
  ...table ? { table } : {},
51456
52171
  contentControls,
51457
52172
  capabilities,
@@ -58679,7 +59394,7 @@ function shouldYield(scheduler, lastYieldAt) {
58679
59394
  const deadline = scheduler.frameDeadlineMs ?? DEFAULT_FRAME_DEADLINE_MS;
58680
59395
  return now3 - lastYieldAt >= deadline;
58681
59396
  }
58682
- function nowMs() {
59397
+ function nowMs2() {
58683
59398
  return typeof performance !== "undefined" ? performance.now() : Date.now();
58684
59399
  }
58685
59400
  function createLoadScheduler(options = {}) {
@@ -59690,7 +60405,7 @@ function parseNumberingXml(xml, context) {
59690
60405
  abstractDefinitions[abstractNumberingId] = {
59691
60406
  abstractNumberingId,
59692
60407
  ...context?.partPath !== void 0 ? { sourceRef: createNumberingSourceRef(context.partPath, "abstractNum", rawId, childXmlPath) } : {},
59693
- levels: readLevels(child),
60408
+ levels: readLevels(child, context, childXmlPath, rawId),
59694
60409
  ...nsid ? { nsid } : {},
59695
60410
  ...multiLevelType ? { multiLevelType } : {},
59696
60411
  ...tplc ? { tplc } : {},
@@ -59711,7 +60426,7 @@ function parseNumberingXml(xml, context) {
59711
60426
  numberingInstanceId,
59712
60427
  ...context?.partPath !== void 0 ? { sourceRef: createNumberingSourceRef(context.partPath, "num", rawId, childXmlPath) } : {},
59713
60428
  abstractNumberingId: toCanonicalAbstractNumberingId(rawAbstractId),
59714
- overrides: readOverrides(child)
60429
+ overrides: readOverrides(child, context, childXmlPath, rawId)
59715
60430
  };
59716
60431
  break;
59717
60432
  }
@@ -59732,6 +60447,16 @@ function createNumberingSourceRef(partPath, element, rawId, xmlPath) {
59732
60447
  ...xmlPath !== void 0 ? { xmlPath } : {}
59733
60448
  };
59734
60449
  }
60450
+ function createNumberingChildSourceRef(partPath, element, sourceIdSuffix, xmlPath) {
60451
+ if (partPath === void 0) return void 0;
60452
+ return {
60453
+ sourceId: `part:${partPath}#${sourceIdSuffix}`,
60454
+ partPath,
60455
+ storyKind: "numbering",
60456
+ element,
60457
+ ...xmlPath !== void 0 ? { xmlPath } : {}
60458
+ };
60459
+ }
59735
60460
  function readNumPicBullet(node, numPicBulletId, context, xmlPath) {
59736
60461
  let widthEmu;
59737
60462
  let heightEmu;
@@ -59808,18 +60533,29 @@ function toCanonicalAbstractNumberingId(value) {
59808
60533
  function toCanonicalNumberingInstanceId(value) {
59809
60534
  return value.startsWith("num:") ? value : `num:${value}`;
59810
60535
  }
59811
- function readLevels(abstractNode) {
60536
+ function readLevels(abstractNode, context, abstractXmlPath, rawAbstractId) {
59812
60537
  const levels = [];
60538
+ let levelOrdinal = 0;
59813
60539
  for (const child of abstractNode.children) {
59814
60540
  if (child.type !== "element" || localName(child.name) !== "lvl") {
59815
60541
  continue;
59816
60542
  }
60543
+ levelOrdinal += 1;
59817
60544
  const rawLevel = readStringAttr(child, "w:ilvl");
59818
60545
  const level = rawLevel === void 0 ? void 0 : parseInteger(rawLevel);
59819
60546
  if (level === void 0) {
59820
60547
  continue;
59821
60548
  }
59822
- const definition = readLevelDefinition(child, level);
60549
+ const definition = readLevelDefinition(
60550
+ child,
60551
+ level,
60552
+ createNumberingChildSourceRef(
60553
+ context?.partPath,
60554
+ "lvl",
60555
+ `abstractNum:${rawAbstractId}:lvl:${level}`,
60556
+ `${abstractXmlPath}/lvl[${levelOrdinal}]`
60557
+ )
60558
+ );
59823
60559
  if (!definition) {
59824
60560
  continue;
59825
60561
  }
@@ -59827,12 +60563,14 @@ function readLevels(abstractNode) {
59827
60563
  }
59828
60564
  return levels.sort((left, right) => left.level - right.level);
59829
60565
  }
59830
- function readOverrides(numNode) {
60566
+ function readOverrides(numNode, context, numXmlPath, rawNumId) {
59831
60567
  const overrides = [];
60568
+ let overrideOrdinal = 0;
59832
60569
  for (const child of numNode.children) {
59833
60570
  if (child.type !== "element" || localName(child.name) !== "lvlOverride") {
59834
60571
  continue;
59835
60572
  }
60573
+ overrideOrdinal += 1;
59836
60574
  const rawLevel = readStringAttr(child, "w:ilvl");
59837
60575
  const level = rawLevel === void 0 ? void 0 : parseInteger(rawLevel);
59838
60576
  if (level === void 0) {
@@ -59842,8 +60580,26 @@ function readOverrides(numNode) {
59842
60580
  const rawStart = startOverrideNode ? readStringAttr(startOverrideNode, "w:val") : void 0;
59843
60581
  const startAt = rawStart === void 0 ? void 0 : parseInteger(rawStart);
59844
60582
  const levelDefinitionNode = findChildElementOptional(child, "lvl");
59845
- const levelDefinition = levelDefinitionNode ? readLevelOverrideDefinition(levelDefinitionNode, level) : void 0;
60583
+ const overrideXmlPath = `${numXmlPath}/lvlOverride[${overrideOrdinal}]`;
60584
+ const levelDefinition = levelDefinitionNode ? readLevelOverrideDefinition(
60585
+ levelDefinitionNode,
60586
+ level,
60587
+ createNumberingChildSourceRef(
60588
+ context?.partPath,
60589
+ "lvl",
60590
+ `num:${rawNumId}:lvlOverride:${level}:lvl`,
60591
+ `${overrideXmlPath}/lvl[1]`
60592
+ )
60593
+ ) : void 0;
59846
60594
  overrides.push({
60595
+ ...context?.partPath !== void 0 ? {
60596
+ sourceRef: createNumberingChildSourceRef(
60597
+ context.partPath,
60598
+ "lvlOverride",
60599
+ `num:${rawNumId}:lvlOverride:${level}`,
60600
+ overrideXmlPath
60601
+ )
60602
+ } : {},
59847
60603
  level,
59848
60604
  ...startAt !== void 0 ? { startAt } : {},
59849
60605
  ...levelDefinition ? { levelDefinition } : {}
@@ -59851,7 +60607,7 @@ function readOverrides(numNode) {
59851
60607
  }
59852
60608
  return overrides.sort((left, right) => left.level - right.level);
59853
60609
  }
59854
- function readLevelDefinition(levelNode, fallbackLevel) {
60610
+ function readLevelDefinition(levelNode, fallbackLevel, sourceRef) {
59855
60611
  const rawLevel = readStringAttr(levelNode, "w:ilvl");
59856
60612
  const level = rawLevel === void 0 ? fallbackLevel : parseInteger(rawLevel);
59857
60613
  if (level === void 0) {
@@ -59881,6 +60637,7 @@ function readLevelDefinition(levelNode, fallbackLevel) {
59881
60637
  const lvlPicBulletNode = findChildElementOptional(levelNode, "lvlPicBulletId");
59882
60638
  const picBulletId = lvlPicBulletNode ? readStringAttr(lvlPicBulletNode, "w:val") : void 0;
59883
60639
  return {
60640
+ ...sourceRef ? { sourceRef } : {},
59884
60641
  level,
59885
60642
  format,
59886
60643
  text,
@@ -59894,7 +60651,7 @@ function readLevelDefinition(levelNode, fallbackLevel) {
59894
60651
  ...picBulletId !== void 0 ? { picBulletId } : {}
59895
60652
  };
59896
60653
  }
59897
- function readLevelOverrideDefinition(levelNode, fallbackLevel) {
60654
+ function readLevelOverrideDefinition(levelNode, fallbackLevel, sourceRef) {
59898
60655
  const rawLevel = readStringAttr(levelNode, "w:ilvl");
59899
60656
  const level = rawLevel === void 0 ? fallbackLevel : parseInteger(rawLevel);
59900
60657
  if (level === void 0) {
@@ -59928,6 +60685,7 @@ function readLevelOverrideDefinition(levelNode, fallbackLevel) {
59928
60685
  return void 0;
59929
60686
  }
59930
60687
  return {
60688
+ ...sourceRef ? { sourceRef } : {},
59931
60689
  level,
59932
60690
  ...startAt !== void 0 ? { startAt } : {},
59933
60691
  ...format !== void 0 ? { format } : {},
@@ -66121,7 +66879,7 @@ async function normalizeParsedTextDocumentAsync(document2, packagePartName = "/w
66121
66879
  };
66122
66880
  const children = [];
66123
66881
  let previousParagraph = false;
66124
- let lastYieldAt = nowMs();
66882
+ let lastYieldAt = nowMs2();
66125
66883
  for (let i = 0; i < document2.blocks.length; i += 1) {
66126
66884
  const block = document2.blocks[i];
66127
66885
  const normalizedBlocks = normalizeBlocks(block, state, packagePartName);
@@ -66134,7 +66892,7 @@ async function normalizeParsedTextDocumentAsync(document2, packagePartName = "/w
66134
66892
  }
66135
66893
  if (i > 0 && i % NORMALIZE_YIELD_STRIDE === 0 && shouldYield(scheduler, lastYieldAt)) {
66136
66894
  await scheduler.yield();
66137
- lastYieldAt = nowMs();
66895
+ lastYieldAt = nowMs2();
66138
66896
  }
66139
66897
  }
66140
66898
  const content = { type: "doc", children };
@@ -67505,8 +68263,6 @@ function sortJson2(value) {
67505
68263
 
67506
68264
  // src/runtime/document-runtime.ts
67507
68265
  var CANONICAL_BLOCK_REFS_SYMBOL2 = /* @__PURE__ */ Symbol.for("wre.canonical-block-refs");
67508
- var LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES = 5e3;
67509
- var LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK = 256;
67510
68266
  function getLocalTextPatchMetadata(mapping) {
67511
68267
  const metadata = mapping.metadata?.localTextPatch;
67512
68268
  if (!metadata || typeof metadata !== "object") {
@@ -67613,6 +68369,17 @@ function createDocumentRuntime(options) {
67613
68369
  const loadScheduler = options.loadScheduler ?? createLoadScheduler({ backendOverride: "sync" });
67614
68370
  let effectiveMarkupModeProvider;
67615
68371
  const perfCounters = new PerfCounters();
68372
+ const hotEditTraces = new HotEditTraceRecorder();
68373
+ let cachedHotEditPolicy = null;
68374
+ function getHotEditPolicy() {
68375
+ if (cachedHotEditPolicy?.document === state.document) {
68376
+ return cachedHotEditPolicy.policy;
68377
+ }
68378
+ const profile = deriveHotEditDocumentProfile(state.document);
68379
+ const policy = resolveHotEditPolicy(profile);
68380
+ cachedHotEditPolicy = { document: state.document, profile, policy };
68381
+ return policy;
68382
+ }
67616
68383
  let analyticsEmitScheduled = false;
67617
68384
  let analyticsEmitScheduleMode = "none";
67618
68385
  let deferNextContextAnalyticsEmit = false;
@@ -67684,7 +68451,6 @@ function createDocumentRuntime(options) {
67684
68451
  let viewportBlockRanges = null;
67685
68452
  let viewportRangesKey = serializeViewportRanges(viewportBlockRanges);
67686
68453
  let viewportBlocksPerPageEstimate = null;
67687
- const EDITING_CORRIDOR_BLOCK_RADIUS = 8;
67688
68454
  const getRuntimeForLayoutFacet = () => {
67689
68455
  if (!runtimeRef) {
67690
68456
  throw new Error("Document runtime viewport methods are not initialized");
@@ -68018,8 +68784,8 @@ function createDocumentRuntime(options) {
68018
68784
  return viewportBlockRanges;
68019
68785
  }
68020
68786
  const corridor = {
68021
- start: Math.max(0, caretBlockIndex - EDITING_CORRIDOR_BLOCK_RADIUS),
68022
- end: Math.min(previousSurface.blocks.length, caretBlockIndex + EDITING_CORRIDOR_BLOCK_RADIUS + 1)
68787
+ start: Math.max(0, caretBlockIndex - getHotEditPolicy().selectionCorridorBlockRadius),
68788
+ end: Math.min(previousSurface.blocks.length, caretBlockIndex + getHotEditPolicy().selectionCorridorBlockRadius + 1)
68023
68789
  };
68024
68790
  return normalizeViewportRanges([...viewportBlockRanges ?? [], corridor]);
68025
68791
  }
@@ -68100,8 +68866,12 @@ function createDocumentRuntime(options) {
68100
68866
  (block2) => block2.kind === "paragraph" && editFrom >= block2.from && editTo <= block2.to
68101
68867
  );
68102
68868
  if (blockIndex < 0) {
68103
- perfCounters.increment("surface.localText.patchMiss");
68104
- return null;
68869
+ return tryPatchNestedLocalTextSurface(
68870
+ previousSurface,
68871
+ editFrom,
68872
+ editTo,
68873
+ patch.insertedText
68874
+ );
68105
68875
  }
68106
68876
  const block = previousSurface.blocks[blockIndex];
68107
68877
  if (block.kind !== "paragraph") {
@@ -68176,6 +68946,34 @@ function createDocumentRuntime(options) {
68176
68946
  perfCounters.increment("surface.localText.total.us", Math.round((performance.now() - tTotal0) * 1e3));
68177
68947
  }
68178
68948
  }
68949
+ function tryPatchNestedLocalTextSurface(previousSurface, editFrom, editTo, insertedText) {
68950
+ const shiftBudget = estimateLocalTextPatchShiftBudget(previousSurface.blocks, 0);
68951
+ perfCounters.increment("surface.localText.shiftedBlocks", shiftBudget.shiftedBlocks);
68952
+ perfCounters.increment("surface.localText.shiftedNodes", shiftBudget.shiftedNodes);
68953
+ if (!shiftBudget.withinBudget) {
68954
+ perfCounters.increment("surface.localText.patchBudgetFallback");
68955
+ return null;
68956
+ }
68957
+ const patched = patchSurfaceTextSegment(previousSurface, {
68958
+ from: editFrom,
68959
+ to: editTo,
68960
+ insertedText
68961
+ });
68962
+ if (patched.status !== "patched") {
68963
+ perfCounters.increment("surface.localText.patchMiss");
68964
+ return null;
68965
+ }
68966
+ const refs = getSurfaceCanonicalBlockRefs(previousSurface);
68967
+ if (refs) {
68968
+ const nextRefs = state.document.content.children.map(
68969
+ (block, index) => block ?? refs[index] ?? null
68970
+ );
68971
+ attachSurfaceCanonicalBlockRefs(patched.surface, nextRefs);
68972
+ }
68973
+ perfCounters.increment("surface.localText.patchHit");
68974
+ perfCounters.increment("surface.localText.patchDelta", insertedText.length - (editTo - editFrom));
68975
+ return patched.surface;
68976
+ }
68179
68977
  function shiftSurfaceInlineSegment(segment, delta) {
68180
68978
  if (delta === 0) return segment;
68181
68979
  return {
@@ -68223,25 +69021,26 @@ function createDocumentRuntime(options) {
68223
69021
  }
68224
69022
  }
68225
69023
  function estimateLocalTextPatchShiftBudget(blocks, startIndex) {
69024
+ const policy = getHotEditPolicy();
68226
69025
  const shiftedBlocks = Math.max(0, blocks.length - startIndex);
68227
69026
  let shiftedNodes = 0;
68228
69027
  for (let index = startIndex; index < blocks.length; index += 1) {
68229
69028
  const shiftedBlockNodes = countSurfaceShiftNodesUpTo(
68230
69029
  blocks[index],
68231
69030
  Math.min(
68232
- LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK,
68233
- LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES - shiftedNodes
69031
+ policy.maxShiftedNodesPerBlock,
69032
+ policy.maxShiftedSurfaceNodes - shiftedNodes
68234
69033
  ) + 1
68235
69034
  );
68236
69035
  shiftedNodes += shiftedBlockNodes;
68237
- if (shiftedBlockNodes > LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK) {
69036
+ if (shiftedBlockNodes > policy.maxShiftedNodesPerBlock) {
68238
69037
  return {
68239
69038
  shiftedBlocks,
68240
69039
  shiftedNodes,
68241
69040
  withinBudget: false
68242
69041
  };
68243
69042
  }
68244
- if (shiftedNodes > LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES) {
69043
+ if (shiftedNodes > policy.maxShiftedSurfaceNodes) {
68245
69044
  return {
68246
69045
  shiftedBlocks,
68247
69046
  shiftedNodes,
@@ -69205,7 +70004,9 @@ function createDocumentRuntime(options) {
69205
70004
  });
69206
70005
  const r5ScratchReplayState = { ...state };
69207
70006
  const r5ScratchReplaySnapshot = { ...cachedRenderSnapshot };
69208
- const debugFacet = createRuntimeDebugFacet(() => runtime, telemetryBus);
70007
+ const debugFacet = createRuntimeDebugFacet(() => runtime, telemetryBus, {
70008
+ getHotEditTraces: () => hotEditTraces.getTraces()
70009
+ });
69209
70010
  function prepareTableStructureCommandForExecution(command, document2, storyTarget) {
69210
70011
  const resolution = resolveEditableTableStructureTarget({
69211
70012
  document: document2,
@@ -69298,15 +70099,16 @@ function createDocumentRuntime(options) {
69298
70099
  ...resolution.textTarget ? { textTarget: resolution.textTarget } : {}
69299
70100
  };
69300
70101
  }
69301
- function prepareFragmentInsertCommandForExecution(command, document2, surface, storyTarget) {
70102
+ function prepareFragmentInsertCommandForExecution(command, document2, surface, storyTarget, selection) {
69302
70103
  if (!command.editableTarget) {
69303
- return { kind: "accepted", selection: state.selection };
70104
+ return { kind: "accepted", selection };
69304
70105
  }
69305
70106
  const resolution = resolveEditableTextTarget({
69306
70107
  document: document2,
69307
70108
  surface,
69308
70109
  target: command.editableTarget,
69309
70110
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
70111
+ selection,
69310
70112
  editableTargetCache: editableTargetBlockCache
69311
70113
  });
69312
70114
  if (resolution.kind === "rejected") {
@@ -69324,7 +70126,7 @@ function createDocumentRuntime(options) {
69324
70126
  }
69325
70127
  return {
69326
70128
  kind: "accepted",
69327
- selection: createSelectionSnapshot(resolution.range.from, resolution.range.to),
70129
+ selection,
69328
70130
  ...resolution.textTarget ? { textTarget: resolution.textTarget } : {}
69329
70131
  };
69330
70132
  }
@@ -69496,7 +70298,8 @@ function createDocumentRuntime(options) {
69496
70298
  command,
69497
70299
  state.document,
69498
70300
  cachedRenderSnapshot.surface?.blocks ?? [],
69499
- activeStory
70301
+ activeStory,
70302
+ commandSelection
69500
70303
  );
69501
70304
  if (prepared.kind === "rejected") {
69502
70305
  return;
@@ -69659,7 +70462,8 @@ function createDocumentRuntime(options) {
69659
70462
  command,
69660
70463
  replayState.document,
69661
70464
  replaySnapshot.surface?.blocks ?? [],
69662
- replayStory
70465
+ replayStory,
70466
+ replayState.selection
69663
70467
  );
69664
70468
  if (prepared.kind === "rejected") {
69665
70469
  return;
@@ -69802,7 +70606,8 @@ function createDocumentRuntime(options) {
69802
70606
  command,
69803
70607
  stateForCommand.document,
69804
70608
  snapshotForCommand.surface?.blocks ?? [],
69805
- replayStory
70609
+ replayStory,
70610
+ stateForCommand.selection
69806
70611
  );
69807
70612
  if (prepared.kind === "rejected") {
69808
70613
  continue;
@@ -70366,7 +71171,7 @@ function createDocumentRuntime(options) {
70366
71171
  try {
70367
71172
  const timestamp = clock();
70368
71173
  const selection = target ? createSelectionFromPublicAnchor(target) : state.selection;
70369
- const editableTarget = editContext?.editableTarget && isTableParagraphEditableTarget(editContext.editableTarget) ? editContext.editableTarget : inferEditableTargetForFragmentInsert(
71174
+ const editableTarget = editContext?.editableTarget && isFragmentInsertEditableTarget(editContext.editableTarget) ? editContext.editableTarget : inferEditableTargetForFragmentInsert(
70370
71175
  cachedRenderSnapshot.surface?.blocks ?? [],
70371
71176
  selection
70372
71177
  );
@@ -70497,12 +71302,23 @@ function createDocumentRuntime(options) {
70497
71302
  return actionDepth > 0;
70498
71303
  },
70499
71304
  applyActiveStoryTextCommand(command) {
71305
+ const pendingHotEditTrace = hotEditTraces.begin({
71306
+ commandType: command.type,
71307
+ nowUtc: clock(),
71308
+ counters: perfCounters
71309
+ });
70500
71310
  try {
70501
- return applyTextCommandInActiveStory(command);
71311
+ const ack = applyTextCommandInActiveStory(command);
71312
+ hotEditTraces.complete(pendingHotEditTrace, {
71313
+ tier: classifyHotEditTier(ack),
71314
+ patchMissReason: classifyHotEditPatchMissReason(ack),
71315
+ counters: perfCounters
71316
+ });
71317
+ return ack;
70502
71318
  } catch (error) {
70503
71319
  const runtimeError = toRuntimeError(error);
70504
71320
  emitError(runtimeError);
70505
- return {
71321
+ const ack = {
70506
71322
  kind: "rejected",
70507
71323
  refreshClass: "blocked",
70508
71324
  opId: command.origin?.opId,
@@ -70514,6 +71330,12 @@ function createDocumentRuntime(options) {
70514
71330
  }
70515
71331
  ]
70516
71332
  };
71333
+ hotEditTraces.complete(pendingHotEditTrace, {
71334
+ tier: "blocked",
71335
+ patchMissReason: "participant-blocked",
71336
+ counters: perfCounters
71337
+ });
71338
+ return ack;
70517
71339
  }
70518
71340
  },
70519
71341
  addComment(params) {
@@ -72184,7 +73006,7 @@ function createDocumentRuntime(options) {
72184
73006
  editableTargetCache: editableTargetBlockCache,
72185
73007
  activeStorySize: cachedRenderSnapshot.surface?.storySize,
72186
73008
  textTarget,
72187
- preserveNumberingOnSplit: commandForDispatch.type === "paragraph.split" && targetResolution?.kind === "accepted" && editableTarget?.listAddress?.operationScope === "list-text",
73009
+ preserveNumberingOnSplit: (commandForDispatch.type === "paragraph.split" || commandForDispatch.type === "fragment.insert") && targetResolution?.kind === "accepted" && editableTarget?.listAddress?.operationScope === "list-text",
72188
73010
  rejectTargetlessTableStructureInsert: true
72189
73011
  };
72190
73012
  const baseState = selection === state.selection ? state : {
@@ -72289,6 +73111,27 @@ function createDocumentRuntime(options) {
72289
73111
  newRevisionToken: state.revisionToken
72290
73112
  }));
72291
73113
  }
73114
+ function classifyHotEditTier(ack) {
73115
+ if (ack.kind === "rejected" || ack.refreshClass === "blocked") {
73116
+ return "blocked";
73117
+ }
73118
+ if (ack.refreshClass === "full-projection" || ack.kind === "structural-divergence") {
73119
+ return "full-refresh";
73120
+ }
73121
+ if (ack.refreshClass === "local-text-equivalent" || ack.refreshClass === "selection-only" || ack.refreshClass === "surface-only") {
73122
+ return "patch";
73123
+ }
73124
+ return "full-refresh";
73125
+ }
73126
+ function classifyHotEditPatchMissReason(ack) {
73127
+ if (ack.kind === "rejected" || ack.refreshClass === "blocked") {
73128
+ return "participant-blocked";
73129
+ }
73130
+ if (ack.refreshClass === "full-projection" || ack.kind === "structural-divergence") {
73131
+ return "effect-disqualified";
73132
+ }
73133
+ return "none";
73134
+ }
72292
73135
  function classifyAck(params) {
72293
73136
  const { opId, priorState, transaction, newRevisionToken } = params;
72294
73137
  const meta = transaction.mapping.metadata ?? {};
@@ -73006,7 +73849,7 @@ function canonicalEditableTargetStoryKey(storyTarget) {
73006
73849
  function inferEditableTargetForFragmentInsert(blocks, selection) {
73007
73850
  const position = Math.min(selection.anchor, selection.head);
73008
73851
  const target = findEditableTargetAtSurfacePosition(blocks, position);
73009
- return target && isTableParagraphEditableTarget(target) ? target : void 0;
73852
+ return target && isFragmentInsertEditableTarget(target) ? target : void 0;
73010
73853
  }
73011
73854
  function findEditableTargetAtSurfacePosition(blocks, position) {
73012
73855
  for (const block of blocks) {
@@ -73035,8 +73878,14 @@ function findEditableTargetInSurfaceCell(cell, position) {
73035
73878
  }
73036
73879
  return findEditableTargetAtSurfacePosition(cell.content, position);
73037
73880
  }
73038
- function isTableParagraphEditableTarget(target) {
73039
- return target.editability === "editable" && target.posture.blockers.length === 0 && target.commandFamily === "text-leaf" && (target.kind === "table-cell-paragraph-text" || target.kind === "nested-table-cell-paragraph-text" || target.kind === "sdt-table-cell-paragraph-text");
73881
+ function isFragmentInsertEditableTarget(target) {
73882
+ if (target.editability !== "editable" || target.posture.blockers.length > 0 || target.commandFamily !== "text-leaf") {
73883
+ return false;
73884
+ }
73885
+ if (target.listAddress?.operationScope === "list-text") {
73886
+ return true;
73887
+ }
73888
+ return target.kind === "table-cell-paragraph-text" || target.kind === "nested-table-cell-paragraph-text" || target.kind === "sdt-table-cell-paragraph-text";
73040
73889
  }
73041
73890
  function extractSelectionFragment(document2, selection, activeStory) {
73042
73891
  const from = Math.min(selection.anchor, selection.head);
@@ -91387,6 +92236,9 @@ function createLoadingDebugFacet() {
91387
92236
  },
91388
92237
  getChannels() {
91389
92238
  return bus.getChannels();
92239
+ },
92240
+ getHotEditTraces() {
92241
+ return [];
91390
92242
  }
91391
92243
  };
91392
92244
  }
@@ -116074,6 +116926,16 @@ function resolveSelectionEditableTarget(anchorTarget, headTarget) {
116074
116926
  if (!anchorTarget || !headTarget) return void 0;
116075
116927
  return anchorTarget.targetKey === headTarget.targetKey ? anchorTarget : void 0;
116076
116928
  }
116929
+ function resolveCurrentEditableTarget(state, positionMap) {
116930
+ if (!positionMap) return void 0;
116931
+ if (state.selection instanceof import_prosemirror_state2.NodeSelection) {
116932
+ return positionMap.pmToRuntimeWithContext(state.selection.from).editableTarget;
116933
+ }
116934
+ const { anchor, head } = state.selection;
116935
+ const anchorContext = positionMap.pmToRuntimeWithContext(anchor);
116936
+ const headContext = positionMap.pmToRuntimeWithContext(head);
116937
+ return resolveSelectionEditableTarget(anchorContext.editableTarget, headContext.editableTarget);
116938
+ }
116077
116939
  function createCommandBridgePlugins(callbacks, options) {
116078
116940
  let isComposing = false;
116079
116941
  let pendingCompositionText = null;
@@ -116252,11 +117114,13 @@ function createCommandBridgePlugins(callbacks, options) {
116252
117114
  if (isComposing) return true;
116253
117115
  const dragEvent = event;
116254
117116
  resolveDropSelectionFromCoordinates(_view, dragEvent);
116255
- if (!isPmEditTargetEditable(_view.state, callbacks.getPositionMap())) {
117117
+ const positionMap = callbacks.getPositionMap();
117118
+ if (!isPmEditTargetEditable(_view.state, positionMap)) {
116256
117119
  callbacks.onBlockedInput?.("drop", NON_EDITABLE_INPUT_MESSAGE);
116257
117120
  dragSourceRange = null;
116258
117121
  return true;
116259
117122
  }
117123
+ const editableTarget = resolveCurrentEditableTarget(_view.state, positionMap);
116260
117124
  const dt = dragEvent.dataTransfer;
116261
117125
  if (!dt) {
116262
117126
  callbacks.onBlockedInput?.("drop", "Drop data was not available.");
@@ -116273,6 +117137,7 @@ function createCommandBridgePlugins(callbacks, options) {
116273
117137
  callbacks.onDropFragment({
116274
117138
  fragment: parsed.fragment,
116275
117139
  effect,
117140
+ ...editableTarget ? { editableTarget } : {},
116276
117141
  ...sourceRange ? { sourceRange } : {}
116277
117142
  });
116278
117143
  dragSourceRange = null;
@@ -116403,7 +117268,7 @@ var import_prosemirror_view3 = require("prosemirror-view");
116403
117268
 
116404
117269
  // src/ui-tailwind/editor-surface/pm-decorations.ts
116405
117270
  var import_prosemirror_view2 = require("prosemirror-view");
116406
- function nowMs2() {
117271
+ function nowMs3() {
116407
117272
  return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
116408
117273
  }
116409
117274
  function sanitizeRevisionAuthorColor(raw) {
@@ -116677,7 +117542,7 @@ function buildDecorations(doc, positionMap, commentModel, revisionModel, markupD
116677
117542
  const activeScopeIds = new Set(activeWorkflowScopeIds ?? []);
116678
117543
  const effectiveWorkflowScopes = workflowScopes ?? [];
116679
117544
  const lockedPmRanges = collectLockedPmRanges(workflowLockedZones, activeStory, positionMap);
116680
- const commentsStartMs = nowMs2();
117545
+ const commentsStartMs = nowMs3();
116681
117546
  let commentCount = 0;
116682
117547
  if (commentModel) {
116683
117548
  for (const thread of commentModel.threads) {
@@ -116701,11 +117566,11 @@ function buildDecorations(doc, positionMap, commentModel, revisionModel, markupD
116701
117566
  }
116702
117567
  }
116703
117568
  }
116704
- recordPerfSample("pm.decorations.comments", nowMs2() - commentsStartMs);
117569
+ recordPerfSample("pm.decorations.comments", nowMs3() - commentsStartMs);
116705
117570
  if (commentCount > 0) {
116706
117571
  incrementInvalidationCounter("pm.decorations.comments.count", commentCount);
116707
117572
  }
116708
- const revisionsStartMs = nowMs2();
117573
+ const revisionsStartMs = nowMs3();
116709
117574
  let revisionCount = 0;
116710
117575
  if (revisionModel) {
116711
117576
  for (const rev of revisionModel.revisions) {
@@ -116814,11 +117679,11 @@ function buildDecorations(doc, positionMap, commentModel, revisionModel, markupD
116814
117679
  revisionCount += 1;
116815
117680
  }
116816
117681
  }
116817
- recordPerfSample("pm.decorations.revisions", nowMs2() - revisionsStartMs);
117682
+ recordPerfSample("pm.decorations.revisions", nowMs3() - revisionsStartMs);
116818
117683
  if (revisionCount > 0) {
116819
117684
  incrementInvalidationCounter("pm.decorations.revisions.count", revisionCount);
116820
117685
  }
116821
- const workflowStartMs = nowMs2();
117686
+ const workflowStartMs = nowMs3();
116822
117687
  const workflowDecorationsBefore = decorations.length;
116823
117688
  if (effectiveWorkflowScopes.length > 0) {
116824
117689
  for (const scope of effectiveWorkflowScopes) {
@@ -116936,7 +117801,7 @@ function buildDecorations(doc, positionMap, commentModel, revisionModel, markupD
116936
117801
  }, railRangeCache);
116937
117802
  }
116938
117803
  }
116939
- recordPerfSample("pm.decorations.workflow", nowMs2() - workflowStartMs);
117804
+ recordPerfSample("pm.decorations.workflow", nowMs3() - workflowStartMs);
116940
117805
  const workflowDecorationCount = decorations.length - workflowDecorationsBefore;
116941
117806
  if (workflowDecorationCount > 0) {
116942
117807
  incrementInvalidationCounter(
@@ -117013,11 +117878,11 @@ function applyRuntimeDecorationInputs(view, inputs) {
117013
117878
  const tr = view.state.tr.setMeta(runtimeDecorationPluginKey, {
117014
117879
  inputs
117015
117880
  });
117016
- const startedAt = nowMs3();
117881
+ const startedAt = nowMs4();
117017
117882
  view.dispatch(tr);
117018
- recordPerfSample("pm.decorations.apply", nowMs3() - startedAt);
117883
+ recordPerfSample("pm.decorations.apply", nowMs4() - startedAt);
117019
117884
  }
117020
- function nowMs3() {
117885
+ function nowMs4() {
117021
117886
  return typeof performance !== "undefined" ? performance.now() : Date.now();
117022
117887
  }
117023
117888
 
@@ -122807,6 +123672,7 @@ var LAYER_DEBUG_PANES = [
122807
123672
  snippets: [
122808
123673
  { label: "Selection context", expression: "ref?.getRuntimeContextAnalytics?.()" },
122809
123674
  { label: "Document context", expression: "ref?.getRuntimeContextAnalytics?.({ scopeKind: 'document' })" },
123675
+ { label: "Hot edit trace", expression: "runtime?.debug?.getHotEditTraces?.().at(-1)" },
122810
123676
  { label: "View state", expression: "ref?.getViewState?.()" }
122811
123677
  ],
122812
123678
  routed: [
@@ -122863,6 +123729,7 @@ var LAYER_DEBUG_PANES = [
122863
123729
  snippets: [
122864
123730
  { label: "Navigation", expression: "ref?.getDocumentNavigationSnapshot?.()" },
122865
123731
  { label: "Review surface", expression: "({ comments: ref?.getCommentSidebarSnapshot?.(), changes: ref?.getTrackedChangesSnapshot?.() })" },
123732
+ { label: "Hot edit traces", expression: "runtime?.debug?.getHotEditTraces?.()" },
122866
123733
  { label: "Compatibility", expression: "ref?.getCompatibilityReport?.()" }
122867
123734
  ],
122868
123735
  routed: [
@@ -124288,6 +125155,10 @@ function extractNLHaystack(entry) {
124288
125155
  }
124289
125156
  return out.slice(0, 200).toLowerCase();
124290
125157
  }
125158
+ case "image": {
125159
+ const text = entry.image.type === "image" ? entry.image.altText ?? "" : entry.image.anchor.docPr?.descr ?? entry.image.anchor.docPr?.name ?? "";
125160
+ return text.slice(0, 200).toLowerCase();
125161
+ }
124291
125162
  case "table":
124292
125163
  case "table-row":
124293
125164
  case "table-cell":
@@ -126123,6 +126994,391 @@ function createViewportFamily2(runtime) {
126123
126994
  };
126124
126995
  }
126125
126996
 
126997
+ // src/api/v3/runtime/lists.ts
126998
+ var SUPPORTED_COMMANDS = [
126999
+ "toggle-numbered",
127000
+ "toggle-bulleted",
127001
+ "indent",
127002
+ "outdent",
127003
+ "restart-numbering",
127004
+ "continue-numbering"
127005
+ ];
127006
+ var UNSUPPORTED_COMMANDS = [
127007
+ "create",
127008
+ "attach",
127009
+ "detach",
127010
+ "join",
127011
+ "separate",
127012
+ "split",
127013
+ "set-value",
127014
+ "apply-template",
127015
+ "capture-template",
127016
+ "apply-preset",
127017
+ "set-level-numbering",
127018
+ "set-level-bullet",
127019
+ "set-level-picture-bullet",
127020
+ "set-level-alignment",
127021
+ "set-level-indents",
127022
+ "set-level-trailing-character",
127023
+ "set-level-marker-font",
127024
+ "set-level-text",
127025
+ "set-level-start",
127026
+ "set-level-layout",
127027
+ "convert-to-text",
127028
+ "paste-fragment",
127029
+ "drop-fragment"
127030
+ ];
127031
+ var applyCommandMetadata = {
127032
+ name: "runtime.lists.applyCommand",
127033
+ status: "live-with-adapter",
127034
+ sourceLayer: "runtime-core",
127035
+ liveEvidence: {
127036
+ runnerTest: "test/api/v3/runtime/lists.test.ts",
127037
+ commit: "refactor-07-runtime-lists-namespace"
127038
+ },
127039
+ uxIntent: {
127040
+ uiVisible: true,
127041
+ expectsUxResponse: "surface-refresh",
127042
+ expectedDelta: "list structure changes through the L07 list command surface"
127043
+ },
127044
+ agentMetadata: { readOrMutate: "mutate", boundedScope: "scope", auditCategory: "list-command" },
127045
+ stateClass: "A-canonical",
127046
+ persistsTo: "canonical",
127047
+ broadcastsVia: "crdt",
127048
+ rwdReference: "\xA7Runtime API \xA7 runtime.lists.applyCommand. Dispatches only proven L07 list commands through opaque list targets; future commands return owner-routed blockers until command/export/readback support lands."
127049
+ };
127050
+ function createListsFamily(runtime) {
127051
+ return {
127052
+ list(input = {}) {
127053
+ const document2 = runtime.getCanonicalDocument();
127054
+ const rows = currentListTargets(document2).filter((entry) => input.storyKey === void 0 || entry.target.storyKey === input.storyKey).map((entry) => toReadback(document2, entry.target, entry.paragraph));
127055
+ return input.limit === void 0 ? rows : rows.slice(0, Math.max(0, input.limit));
127056
+ },
127057
+ get(input) {
127058
+ const resolved = resolveCurrentListTarget(runtime.getCanonicalDocument(), input);
127059
+ return resolved.kind === "resolved" ? toReadback(runtime.getCanonicalDocument(), resolved.target, resolved.paragraph) : null;
127060
+ },
127061
+ previewCommand(input) {
127062
+ return previewListCommand(runtime.getCanonicalDocument(), input);
127063
+ },
127064
+ applyCommand(input) {
127065
+ const preview = previewListCommand(runtime.getCanonicalDocument(), input);
127066
+ if (!preview.supported || !preview.target) {
127067
+ return {
127068
+ applied: false,
127069
+ command: input.command,
127070
+ before: preview.target,
127071
+ blockers: preview.blockers
127072
+ };
127073
+ }
127074
+ const resolved = resolveCurrentListTarget(runtime.getCanonicalDocument(), {
127075
+ addressKey: preview.target.addressKey
127076
+ });
127077
+ if (resolved.kind !== "resolved") {
127078
+ return {
127079
+ applied: false,
127080
+ command: input.command,
127081
+ before: preview.target,
127082
+ blockers: [resolved.blocker]
127083
+ };
127084
+ }
127085
+ const command = editorCommandForListCommand(
127086
+ input.command,
127087
+ resolved.target,
127088
+ runtime.now(),
127089
+ input.startAt
127090
+ );
127091
+ if (!command) {
127092
+ return {
127093
+ applied: false,
127094
+ command: input.command,
127095
+ before: preview.target,
127096
+ blockers: [
127097
+ unsupportedCommandBlocker(input.command, {
127098
+ targetKey: preview.target.targetKey,
127099
+ addressKey: preview.target.addressKey
127100
+ })
127101
+ ]
127102
+ };
127103
+ }
127104
+ const beforeDocument = runtime.getCanonicalDocument();
127105
+ runtime.dispatch(command);
127106
+ const afterDocument = runtime.getCanonicalDocument();
127107
+ const after = resolveCurrentListTarget(afterDocument, { targetKey: preview.target.targetKey });
127108
+ emitUxResponse(runtime, {
127109
+ apiFn: applyCommandMetadata.name,
127110
+ intent: applyCommandMetadata.uxIntent.expectedDelta ?? "",
127111
+ mockOrLive: "live",
127112
+ uiVisible: true,
127113
+ expectedDelta: applyCommandMetadata.uxIntent.expectedDelta
127114
+ });
127115
+ return {
127116
+ applied: beforeDocument !== afterDocument,
127117
+ command: input.command,
127118
+ before: preview.target,
127119
+ ...after.kind === "resolved" ? { after: toReadback(afterDocument, after.target, after.paragraph) } : {},
127120
+ blockers: []
127121
+ };
127122
+ }
127123
+ };
127124
+ }
127125
+ function previewListCommand(document2, input) {
127126
+ const resolved = resolveCurrentListTarget(document2, input);
127127
+ if (resolved.kind !== "resolved") {
127128
+ return {
127129
+ command: input.command,
127130
+ supported: false,
127131
+ affectedTargets: [],
127132
+ blockers: [resolved.blocker]
127133
+ };
127134
+ }
127135
+ const target = toReadback(document2, resolved.target, resolved.paragraph);
127136
+ const targetRef = { targetKey: target.targetKey, addressKey: target.addressKey };
127137
+ if (!SUPPORTED_COMMANDS.includes(input.command)) {
127138
+ return {
127139
+ command: input.command,
127140
+ supported: false,
127141
+ target,
127142
+ affectedTargets: [target],
127143
+ blockers: [unsupportedCommandBlocker(input.command, targetRef)]
127144
+ };
127145
+ }
127146
+ const canContinuePrevious = canContinuePreviousSequence(document2, resolved.paragraphIndex);
127147
+ const canJoin = canJoinPreviousSequence(document2, resolved.paragraphIndex);
127148
+ const blockers = [];
127149
+ if (input.command === "continue-numbering" && !canContinuePrevious) {
127150
+ blockers.push({
127151
+ code: "list-continue-target-missing",
127152
+ ownerLayer: "L07",
127153
+ message: "No previous compatible list sequence is available for continue-numbering.",
127154
+ ...targetRef
127155
+ });
127156
+ }
127157
+ return {
127158
+ command: input.command,
127159
+ supported: blockers.length === 0,
127160
+ target,
127161
+ affectedTargets: [target],
127162
+ blockers,
127163
+ canJoin,
127164
+ canContinuePrevious
127165
+ };
127166
+ }
127167
+ function editorCommandForListCommand(command, editableTarget, timestamp, startAt) {
127168
+ const origin = { source: "api", timestamp };
127169
+ switch (command) {
127170
+ case "toggle-numbered":
127171
+ return { type: "list.toggle", kind: "numbered", editableTargets: [editableTarget], origin };
127172
+ case "toggle-bulleted":
127173
+ return { type: "list.toggle", kind: "bulleted", editableTargets: [editableTarget], origin };
127174
+ case "indent":
127175
+ return { type: "list.indent", editableTargets: [editableTarget], origin };
127176
+ case "outdent":
127177
+ return { type: "list.outdent", editableTargets: [editableTarget], origin };
127178
+ case "restart-numbering":
127179
+ return {
127180
+ type: "list.restart-numbering",
127181
+ editableTarget,
127182
+ ...startAt !== void 0 ? { startAt } : {},
127183
+ origin
127184
+ };
127185
+ case "continue-numbering":
127186
+ return { type: "list.continue-numbering", editableTarget, origin };
127187
+ default:
127188
+ return void 0;
127189
+ }
127190
+ }
127191
+ function resolveCurrentListTarget(document2, input) {
127192
+ if (input.editableTarget) {
127193
+ const shapeIssues = validateEditableTargetRef(input.editableTarget);
127194
+ if (shapeIssues.length > 0) {
127195
+ return {
127196
+ kind: "blocked",
127197
+ blocker: {
127198
+ code: "list-target-malformed",
127199
+ ownerLayer: "L07",
127200
+ message: `List target is malformed: ${shapeIssues[0]?.path ?? "$"}.`,
127201
+ targetKey: input.editableTarget.targetKey,
127202
+ addressKey: input.editableTarget.listAddress?.addressKey
127203
+ }
127204
+ };
127205
+ }
127206
+ }
127207
+ const requestedTargetKey = input.editableTarget?.targetKey ?? input.targetKey;
127208
+ const requestedAddressKey = input.editableTarget?.listAddress?.addressKey ?? input.addressKey;
127209
+ if (!requestedTargetKey && !requestedAddressKey) {
127210
+ return {
127211
+ kind: "blocked",
127212
+ blocker: {
127213
+ code: "list-target-required",
127214
+ ownerLayer: "L07",
127215
+ message: "runtime.lists requires a targetKey, addressKey, or editableTarget."
127216
+ }
127217
+ };
127218
+ }
127219
+ const currentTargets = currentListTargets(document2);
127220
+ const resolved = currentTargets.find(
127221
+ ({ target }) => requestedTargetKey !== void 0 && target.targetKey === requestedTargetKey || requestedAddressKey !== void 0 && target.listAddress?.addressKey === requestedAddressKey
127222
+ );
127223
+ if (!resolved) {
127224
+ return {
127225
+ kind: "blocked",
127226
+ blocker: {
127227
+ code: "list-target-not-found",
127228
+ ownerLayer: "L07",
127229
+ message: "List target no longer resolves in the current canonical document.",
127230
+ ...requestedTargetKey !== void 0 ? { targetKey: requestedTargetKey } : {},
127231
+ ...requestedAddressKey !== void 0 ? { addressKey: requestedAddressKey } : {}
127232
+ }
127233
+ };
127234
+ }
127235
+ if (input.editableTarget && !sameTargetStaleHash(input.editableTarget, resolved.target)) {
127236
+ return {
127237
+ kind: "blocked",
127238
+ blocker: {
127239
+ code: "list-target-stale",
127240
+ ownerLayer: "L07",
127241
+ message: "List target resolved by identity but stale discriminators changed.",
127242
+ targetKey: input.editableTarget.targetKey,
127243
+ addressKey: input.editableTarget.listAddress?.addressKey
127244
+ }
127245
+ };
127246
+ }
127247
+ if (resolved.target.editability !== "editable" || resolved.target.posture.blockers.length > 0) {
127248
+ return {
127249
+ kind: "blocked",
127250
+ blocker: {
127251
+ code: "list-target-non-editable",
127252
+ ownerLayer: "L07",
127253
+ message: resolved.target.posture.blockers.length > 0 ? `List target is not editable: ${resolved.target.posture.blockers.join(", ")}.` : "List target is not editable.",
127254
+ targetKey: resolved.target.targetKey,
127255
+ addressKey: resolved.target.listAddress?.addressKey
127256
+ }
127257
+ };
127258
+ }
127259
+ return { kind: "resolved", ...resolved };
127260
+ }
127261
+ function currentListTargets(document2) {
127262
+ const paragraphs = collectParagraphEntries(document2.content.children, "main");
127263
+ const targets = collectEditableTargetRefs(document2).filter(isListTextTarget);
127264
+ const byBlockPath = /* @__PURE__ */ new Map();
127265
+ for (const target of targets) byBlockPath.set(target.blockPath, target);
127266
+ const out = [];
127267
+ for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex += 1) {
127268
+ const entry = paragraphs[paragraphIndex];
127269
+ if (!entry?.paragraph.numbering) continue;
127270
+ const target = byBlockPath.get(entry.blockPath);
127271
+ if (!target) continue;
127272
+ out.push({ target, paragraph: entry.paragraph, paragraphIndex });
127273
+ }
127274
+ return out;
127275
+ }
127276
+ function collectParagraphEntries(blocks, basePath) {
127277
+ const out = [];
127278
+ collectParagraphEntriesInto(blocks, basePath, out);
127279
+ return out;
127280
+ }
127281
+ function collectParagraphEntriesInto(blocks, basePath, out) {
127282
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
127283
+ const block = blocks[blockIndex];
127284
+ if (!block) continue;
127285
+ const blockPath = `${basePath}/block[${blockIndex}]`;
127286
+ switch (block.type) {
127287
+ case "paragraph":
127288
+ out.push({ paragraph: block, blockPath });
127289
+ break;
127290
+ case "table":
127291
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
127292
+ const row2 = block.rows[rowIndex];
127293
+ if (!row2) continue;
127294
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
127295
+ const cell = row2.cells[cellIndex];
127296
+ if (!cell) continue;
127297
+ collectParagraphEntriesInto(
127298
+ cell.children,
127299
+ `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`,
127300
+ out
127301
+ );
127302
+ }
127303
+ }
127304
+ break;
127305
+ case "sdt":
127306
+ collectParagraphEntriesInto(block.children, blockPath, out);
127307
+ break;
127308
+ case "custom_xml":
127309
+ break;
127310
+ default:
127311
+ break;
127312
+ }
127313
+ }
127314
+ }
127315
+ function isListTextTarget(target) {
127316
+ return target.commandFamily === "text-leaf" && target.listAddress?.operationScope === "list-text" && target.listAddress.addressKind === "list-item-text";
127317
+ }
127318
+ function sameTargetStaleHash(left, right) {
127319
+ return left.targetKey === right.targetKey && left.listAddress?.addressKey === right.listAddress?.addressKey && left.listAddress?.resolver?.staleHash === right.listAddress?.resolver?.staleHash && left.staleCheck.paragraphTextHash === right.staleCheck.paragraphTextHash && left.staleCheck.paragraphTextLength === right.staleCheck.paragraphTextLength && left.staleCheck.inlineCount === right.staleCheck.inlineCount;
127320
+ }
127321
+ function toReadback(document2, target, paragraph) {
127322
+ const numbering = paragraph.numbering;
127323
+ const instance = document2.numbering.instances[numbering.numberingInstanceId];
127324
+ const listKind = instance ? getListKind(document2.numbering, numbering.numberingInstanceId) : void 0;
127325
+ return {
127326
+ targetKey: target.targetKey,
127327
+ actionHandle: `list-action:${target.listAddress.addressKey}`,
127328
+ kind: target.kind,
127329
+ storyKey: target.storyKey,
127330
+ blockPath: target.blockPath,
127331
+ leafPath: target.leafPath,
127332
+ addressKey: target.listAddress.addressKey,
127333
+ numberingInstanceId: numbering.numberingInstanceId,
127334
+ ...instance?.abstractNumberingId ? { abstractNumberingId: instance.abstractNumberingId } : {},
127335
+ level: numbering.level,
127336
+ ...listKind ? { listKind } : {},
127337
+ editability: target.editability,
127338
+ blockers: target.posture.blockers,
127339
+ supportedCommands: SUPPORTED_COMMANDS,
127340
+ unsupportedCommands: UNSUPPORTED_COMMANDS,
127341
+ staleDiscriminators: {
127342
+ paragraphTextHash: target.staleCheck.paragraphTextHash,
127343
+ paragraphTextLength: target.staleCheck.paragraphTextLength,
127344
+ inlineCount: target.staleCheck.inlineCount,
127345
+ listAddressStaleHash: target.listAddress?.resolver?.staleHash
127346
+ }
127347
+ };
127348
+ }
127349
+ function canContinuePreviousSequence(document2, paragraphIndex) {
127350
+ const paragraphs = collectParagraphEntries(document2.content.children, "main");
127351
+ const current = paragraphs[paragraphIndex]?.paragraph;
127352
+ if (!current?.numbering) return false;
127353
+ const currentKind = getListKind(document2.numbering, current.numbering.numberingInstanceId);
127354
+ if (!currentKind) return false;
127355
+ for (let index = paragraphIndex - 1; index >= 0; index -= 1) {
127356
+ const previous = paragraphs[index]?.paragraph;
127357
+ if (!previous?.numbering) continue;
127358
+ const previousKind = getListKind(document2.numbering, previous.numbering.numberingInstanceId);
127359
+ return previousKind === currentKind && previous.numbering.numberingInstanceId !== current.numbering.numberingInstanceId;
127360
+ }
127361
+ return false;
127362
+ }
127363
+ function canJoinPreviousSequence(document2, paragraphIndex) {
127364
+ const paragraphs = collectParagraphEntries(document2.content.children, "main");
127365
+ const current = paragraphs[paragraphIndex]?.paragraph;
127366
+ const previous = paragraphs[paragraphIndex - 1]?.paragraph;
127367
+ if (!current?.numbering || !previous?.numbering) return false;
127368
+ const currentKind = getListKind(document2.numbering, current.numbering.numberingInstanceId);
127369
+ const previousKind = getListKind(document2.numbering, previous.numbering.numberingInstanceId);
127370
+ return Boolean(currentKind) && currentKind === previousKind && current.numbering.numberingInstanceId !== previous.numbering.numberingInstanceId;
127371
+ }
127372
+ function unsupportedCommandBlocker(command, target) {
127373
+ return {
127374
+ code: "list-command-unsupported",
127375
+ ownerLayer: "L07",
127376
+ message: `runtime.lists.${command} is reserved but not implemented by the L07 command surface yet.`,
127377
+ ...target.targetKey !== void 0 ? { targetKey: target.targetKey } : {},
127378
+ ...target.addressKey !== void 0 ? { addressKey: target.addressKey } : {}
127379
+ };
127380
+ }
127381
+
126126
127382
  // src/api/v3/ai/_pe2-evidence.ts
126127
127383
  function copyCoverage(coverage) {
126128
127384
  return {
@@ -127850,6 +129106,17 @@ function createTableActionFamily(runtime) {
127850
129106
  operationScope: target.table?.operationScope
127851
129107
  });
127852
129108
  }
129109
+ if (fragmentContent && fragmentContent.blocks.length === 0) {
129110
+ return blockedResult(input, proposalId, {
129111
+ code: `table-action-structured-fragment-empty:${input.operation.kind}`,
129112
+ category: "unsupported-operation",
129113
+ message: "Structured table text actions require a canonical document fragment with at least one block.",
129114
+ nextStep: 'Retry with operation.content.kind="structured" and a CanonicalDocumentFragment whose blocks array contains the paragraph or table content to paste/drop.',
129115
+ actionHandle: input.actionHandle,
129116
+ operation: input.operation.kind,
129117
+ operationScope: target.table?.operationScope
129118
+ });
129119
+ }
127853
129120
  const resolution2 = resolveEditableTextTarget({
127854
129121
  document: runtime.getCanonicalDocument(),
127855
129122
  surface: runtime.getRenderSnapshot().surface?.blocks ?? [],
@@ -127872,6 +129139,7 @@ function createTableActionFamily(runtime) {
127872
129139
  runtime.dispatch({
127873
129140
  type: "fragment.insert",
127874
129141
  fragment: fragmentContent,
129142
+ selection: createSelectionSnapshot(resolution2.range.to, resolution2.range.to),
127875
129143
  editableTarget: target,
127876
129144
  origin: { source: "api", timestamp: nowUtc }
127877
129145
  });
@@ -127884,6 +129152,17 @@ function createTableActionFamily(runtime) {
127884
129152
  });
127885
129153
  }
127886
129154
  const changed2 = runtime.getCanonicalDocument() !== before2;
129155
+ if (!changed2) {
129156
+ return blockedResult(input, proposalId, {
129157
+ code: `table-action-noop:${input.operation.kind}:${input.actionHandle}`,
129158
+ category: "runtime-noop",
129159
+ message: "The runtime accepted the table text target but the operation produced no document change.",
129160
+ nextStep: "Refresh the table action list and verify the target is still editable, the payload is non-empty when required, and structured fragments are dispatched through a command-safe table text action.",
129161
+ actionHandle: input.actionHandle,
129162
+ operation: input.operation.kind,
129163
+ operationScope: target.table?.operationScope
129164
+ });
129165
+ }
127887
129166
  const afterReadback = tableTextReadback(readEditableTargetText(runtime.getCanonicalDocument(), target));
127888
129167
  return {
127889
129168
  proposalId,
@@ -128462,6 +129741,31 @@ var hyperlinkTextEditMetadata = actionMethodMetadata(
128462
129741
  expectedDelta: "hyperlink display text changes"
128463
129742
  }
128464
129743
  );
129744
+ var validateTemplateTargetsMetadata = actionMethodMetadata(
129745
+ "validateTemplateTargets",
129746
+ "read",
129747
+ "actions-template-targets",
129748
+ "Validate template field/clause targets against current document readback, duplicate ranges, and exact action/scope handles before fill.",
129749
+ { uiVisible: false, expectsUxResponse: "none" }
129750
+ );
129751
+ var templateTargetReadMetadata = actionMethodMetadata(
129752
+ "templateTargetRead",
129753
+ "read",
129754
+ "actions-template-targets",
129755
+ "Read a template field/clause target through its exact scope/action handle when present, or diagnostic placeholder occurrence evidence otherwise.",
129756
+ { uiVisible: false, expectsUxResponse: "none" }
129757
+ );
129758
+ var templateFieldFillMetadata = actionMethodMetadata(
129759
+ "templateFieldFill",
129760
+ "mutate",
129761
+ "actions-template-targets",
129762
+ "Fill one template field only through an exact scope/action handle after same-target readback validation; raw ranges are diagnostics only.",
129763
+ {
129764
+ uiVisible: true,
129765
+ expectsUxResponse: "inline-change",
129766
+ expectedDelta: "the exact template field target text changes"
129767
+ }
129768
+ );
128465
129769
  var listOperationMetadata = actionMethodMetadata(
128466
129770
  "listOperation",
128467
129771
  "mutate",
@@ -128522,6 +129826,9 @@ var ACTION_METHODS = Object.freeze([
128522
129826
  "bookmarkEdit",
128523
129827
  "hyperlinkDestinationEdit",
128524
129828
  "hyperlinkTextEdit",
129829
+ "validateTemplateTargets",
129830
+ "templateTargetRead",
129831
+ "templateFieldFill",
128525
129832
  "listOperation",
128526
129833
  "tableFragment",
128527
129834
  "tableSelection",
@@ -128890,6 +130197,25 @@ function createActionsFamily(runtime) {
128890
130197
  origin: input.origin
128891
130198
  });
128892
130199
  },
130200
+ validateTemplateTargets(input) {
130201
+ return validateTemplateTargets(runtime, input);
130202
+ },
130203
+ templateTargetRead(input) {
130204
+ const item = validateTemplateTarget(runtime, input.target, {
130205
+ duplicateRanges: /* @__PURE__ */ new Set(),
130206
+ allowDuplicateRanges: true
130207
+ });
130208
+ return {
130209
+ status: item.status === "blocked" ? "blocked" : "read",
130210
+ ...item.target ? { target: item.target } : {},
130211
+ ...item.readback ? { readback: item.readback } : {},
130212
+ ...item.blockers ? { blockers: item.blockers } : {},
130213
+ ...item.blockerDetails ? { blockerDetails: item.blockerDetails } : {}
130214
+ };
130215
+ },
130216
+ templateFieldFill(input) {
130217
+ return applyTemplateFieldFill(runtime, input);
130218
+ },
128893
130219
  listOperation(input) {
128894
130220
  return applyListOperation(runtime, input);
128895
130221
  },
@@ -128959,6 +130285,9 @@ function runPlanStep(runtime, mode, step, plan) {
128959
130285
  if (step.kind === "tableAction" || step.kind === "tableFragment" || step.kind === "tableSelection") {
128960
130286
  return runPlanTableActionStep(runtime, mode, step, plan);
128961
130287
  }
130288
+ if (step.kind === "templateFieldFill") {
130289
+ return runPlanTemplateFieldFillStep(runtime, mode, step, plan);
130290
+ }
128962
130291
  const before = step.target ? readPlanTarget(runtime, step.target) : readDocumentPlanTarget(runtime);
128963
130292
  if (!before.ok) {
128964
130293
  return blockedPlanStepFromDetails(step.id, step.kind, before.blockerDetails);
@@ -129118,6 +130447,72 @@ function runPlanTableActionStep(runtime, mode, step, plan) {
129118
130447
  ...result.commandReference ? { commandReference: result.commandReference } : {}
129119
130448
  };
129120
130449
  }
130450
+ function runPlanTemplateFieldFillStep(runtime, mode, step, plan) {
130451
+ const validation = validateTemplateTarget(runtime, step.field, {
130452
+ duplicateRanges: /* @__PURE__ */ new Set(),
130453
+ allowDuplicateRanges: true
130454
+ });
130455
+ if (validation.status === "blocked" || !validation.canFill) {
130456
+ return blockedPlanStepFromDetails(
130457
+ step.id,
130458
+ step.kind,
130459
+ validation.blockerDetails ?? [
130460
+ blocker(
130461
+ `actions:template-field-fill:not-fillable:${templateTargetDebugId(step.field)}`,
130462
+ "blocked",
130463
+ "The template field target is not backed by an exact fill handle.",
130464
+ "Plant the field through editor APIs and pass the returned scope handle or actionHandle; raw ranges are diagnostics only."
130465
+ )
130466
+ ],
130467
+ {
130468
+ ...validation.target ? { target: validation.target } : {},
130469
+ ...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {}
130470
+ }
130471
+ );
130472
+ }
130473
+ const precondition = checkPlanPreconditions(step, templateReadbackToPlanReadback(validation.readback));
130474
+ if (precondition) {
130475
+ return blockedPlanStepFromDetails(step.id, step.kind, [precondition], {
130476
+ ...validation.target ? { target: validation.target } : {},
130477
+ ...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {}
130478
+ });
130479
+ }
130480
+ if (mode === "preview") {
130481
+ return {
130482
+ id: step.id,
130483
+ kind: step.kind,
130484
+ status: "planned",
130485
+ applied: false,
130486
+ changed: false,
130487
+ ...validation.target ? { target: validation.target } : {},
130488
+ ...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {}
130489
+ };
130490
+ }
130491
+ const applied = applyTemplateFieldFill(runtime, {
130492
+ field: step.field,
130493
+ text: step.text,
130494
+ actorId: step.actorId ?? plan.actorId,
130495
+ origin: step.origin ?? plan.origin,
130496
+ ...step.proposalId ? { proposalId: step.proposalId } : {}
130497
+ });
130498
+ const after = step.field.target ? readPlanTarget(runtime, step.field.target) : null;
130499
+ return {
130500
+ id: step.id,
130501
+ kind: step.kind,
130502
+ status: applied.status === "unsupported" ? "unsupported" : applied.applied ? "applied" : "blocked",
130503
+ applied: applied.applied,
130504
+ changed: applied.changed,
130505
+ ...applied.target ?? validation.target ? { target: applied.target ?? validation.target } : {},
130506
+ ...validation.readback ? { beforeReadback: templateReadbackToPlanReadback(validation.readback) } : {},
130507
+ ...after?.ok && after.readback ? { afterReadback: after.readback } : {},
130508
+ ...applied.proposalId ? { proposalId: applied.proposalId } : {},
130509
+ ...applied.posture ? { posture: applied.posture } : {},
130510
+ ...applied.blockers ? { blockers: applied.blockers } : {},
130511
+ ...applied.blockerDetails ? { blockerDetails: applied.blockerDetails } : {},
130512
+ ...applied.auditReference ? { auditReference: applied.auditReference } : {},
130513
+ ...applied.commandReference ? { commandReference: applied.commandReference } : {}
130514
+ };
130515
+ }
129121
130516
  function locateAll(runtime, input) {
129122
130517
  if (!input.query) {
129123
130518
  const detail = blocker(
@@ -129200,6 +130595,310 @@ function locateAll(runtime, input) {
129200
130595
  ...matches.length === 0 ? { blockers: Object.freeze([`actions:locate:not-found:${input.query}`]) } : {}
129201
130596
  };
129202
130597
  }
130598
+ function validateTemplateTargets(runtime, input) {
130599
+ if (!Array.isArray(input.targets) || input.targets.length === 0) {
130600
+ const detail = blocker(
130601
+ "actions:template-targets:empty",
130602
+ "input",
130603
+ "Template target validation requires at least one field or clause target.",
130604
+ "Pass the analyzer targets before saving the template."
130605
+ );
130606
+ return {
130607
+ status: "blocked",
130608
+ targets: Object.freeze([]),
130609
+ blockers: Object.freeze([detail.code]),
130610
+ blockerDetails: Object.freeze([detail])
130611
+ };
130612
+ }
130613
+ const duplicateRanges = /* @__PURE__ */ new Set();
130614
+ const items = input.targets.map(
130615
+ (target) => validateTemplateTarget(runtime, target, {
130616
+ duplicateRanges,
130617
+ allowDuplicateRanges: input.allowDuplicateRanges === true
130618
+ })
130619
+ );
130620
+ const blockers = items.flatMap((item) => item.blockers ?? []);
130621
+ const blockerDetails = items.flatMap((item) => item.blockerDetails ?? []);
130622
+ return {
130623
+ status: blockerDetails.length === 0 ? "valid" : items.some((item) => item.status !== "blocked") ? "partial" : "blocked",
130624
+ targets: Object.freeze(items),
130625
+ ...blockers.length > 0 ? { blockers: Object.freeze(blockers) } : {},
130626
+ ...blockerDetails.length > 0 ? { blockerDetails: Object.freeze(blockerDetails) } : {}
130627
+ };
130628
+ }
130629
+ function validateTemplateTarget(runtime, target, context) {
130630
+ const targetKind = templateTargetKind(target);
130631
+ const details = [];
130632
+ const warnings = [];
130633
+ const expected = templateExpectedText(target);
130634
+ const occurrenceCount = expected ? countOccurrences(documentText(runtime.getCanonicalDocument()), expected) : void 0;
130635
+ const rangeKey = templateLocationKey(target.location);
130636
+ if (target.fieldId && target.clauseId) {
130637
+ details.push(
130638
+ blocker(
130639
+ `actions:template-targets:mixed-field-clause:${templateTargetDebugId(target)}`,
130640
+ "input",
130641
+ "A template target cannot be both a field and a clause.",
130642
+ "Split clause boundaries from fillable fields and save them as separate template targets."
130643
+ )
130644
+ );
130645
+ }
130646
+ if (!expected && !target.target) {
130647
+ details.push(
130648
+ blocker(
130649
+ `actions:template-targets:expected-text-required:${templateTargetDebugId(target)}`,
130650
+ "input",
130651
+ "A template target without an exact handle requires placeholderText or expectedText for validation.",
130652
+ "Store the visible placeholder/current text with the target before saving the template."
130653
+ )
130654
+ );
130655
+ }
130656
+ if (rangeKey && !context.allowDuplicateRanges) {
130657
+ if (context.duplicateRanges.has(rangeKey)) {
130658
+ details.push(
130659
+ blocker(
130660
+ `actions:template-targets:duplicate-range:${rangeKey}`,
130661
+ "ambiguous-target",
130662
+ "More than one template target claims the same document range.",
130663
+ "Create one shared grouped field target, or give each field a distinct occurrence identity."
130664
+ )
130665
+ );
130666
+ } else {
130667
+ context.duplicateRanges.add(rangeKey);
130668
+ }
130669
+ }
130670
+ if (isTableTemplateLocation(target.location) && !hasTableCellIdentity(target.location)) {
130671
+ details.push(
130672
+ blocker(
130673
+ `actions:template-targets:table-cell-identity-required:${templateTargetDebugId(target)}`,
130674
+ "input",
130675
+ "A table template target must carry stable cell identity.",
130676
+ "Include cellSourceRef/cellRefId or row and column identity plus the exact actionHandle returned for the cell text."
130677
+ )
130678
+ );
130679
+ }
130680
+ if (expected && occurrenceCount !== void 0 && occurrenceCount > 1 && !hasOccurrenceIdentity(target) && !target.target) {
130681
+ details.push(
130682
+ blocker(
130683
+ `actions:template-targets:ambiguous-placeholder:${templateTargetDebugId(target)}`,
130684
+ "ambiguous-target",
130685
+ "The placeholder/current text appears more than once and the target has no occurrence identity or exact handle.",
130686
+ "Persist an occurrence refId/index or the exact scope/action handle returned by ai.actions.locateAll."
130687
+ )
130688
+ );
130689
+ }
130690
+ let summary;
130691
+ let readback = occurrenceCount !== void 0 && expected !== void 0 ? { text: expected, excerpt: excerpt(expected), isEmpty: expected.trim().length === 0, occurrenceCount } : void 0;
130692
+ if (target.target) {
130693
+ const read = readPlanTarget(runtime, target.target);
130694
+ if (!read.ok) {
130695
+ details.push(...read.blockerDetails);
130696
+ } else {
130697
+ summary = read.target;
130698
+ readback = {
130699
+ text: read.readback?.text,
130700
+ excerpt: read.readback?.excerpt,
130701
+ isEmpty: read.readback?.isEmpty,
130702
+ ...occurrenceCount !== void 0 ? { occurrenceCount } : {}
130703
+ };
130704
+ const text = read.readback?.text ?? "";
130705
+ if (expected && !text.includes(expected)) {
130706
+ details.push(
130707
+ blocker(
130708
+ `actions:template-targets:stale-readback:${templateTargetDebugId(target)}`,
130709
+ "blocked",
130710
+ "The exact handle readback no longer contains the analyzer's expected text.",
130711
+ "Re-run template analysis against the current document and save fresh targets before filling."
130712
+ )
130713
+ );
130714
+ }
130715
+ }
130716
+ }
130717
+ const canFill = targetKind === "template-field" && target.target !== void 0 && details.length === 0;
130718
+ if (targetKind === "template-field" && !target.target) {
130719
+ details.push(
130720
+ blocker(
130721
+ `actions:template-field-fill:exact-target-required:${templateTargetDebugId(target)}`,
130722
+ "blocked",
130723
+ "Template field fill requires an exact scope handle or opaque actionHandle.",
130724
+ "Plant fields through editor APIs and store the returned handle; raw offsets and YAML ranges are diagnostics only."
130725
+ )
130726
+ );
130727
+ }
130728
+ if (targetKind === "template-clause") {
130729
+ warnings.push("template-clause targets are boundary evidence; fillable placeholders must be separate template-field targets.");
130730
+ }
130731
+ const status = details.length > 0 ? "blocked" : warnings.length > 0 ? "warning" : "valid";
130732
+ return {
130733
+ status,
130734
+ targetKind,
130735
+ ...target.fieldId ? { fieldId: target.fieldId } : {},
130736
+ ...target.clauseId ? { clauseId: target.clauseId } : {},
130737
+ ...target.name ? { name: target.name } : {},
130738
+ ...target.groupId ? { groupId: target.groupId } : {},
130739
+ canFill,
130740
+ ...summary ? { target: summary } : {},
130741
+ ...readback ? { readback } : {},
130742
+ ...details.length > 0 ? { blockers: Object.freeze(details.map((detail) => detail.code)) } : {},
130743
+ ...details.length > 0 ? { blockerDetails: Object.freeze(details) } : {},
130744
+ ...warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}
130745
+ };
130746
+ }
130747
+ function applyTemplateFieldFill(runtime, input) {
130748
+ if (input.text === void 0) {
130749
+ return blockedApply(
130750
+ "actions:template-field-fill:text-required",
130751
+ "input",
130752
+ "Template field fill requires a text value.",
130753
+ "Retry with the field fill text."
130754
+ );
130755
+ }
130756
+ if (templateTargetKind(input.field) !== "template-field") {
130757
+ return blockedApply(
130758
+ `actions:template-field-fill:field-target-required:${templateTargetDebugId(input.field)}`,
130759
+ "input",
130760
+ "Template field fill accepts only template-field targets.",
130761
+ "Split clause boundaries from fields and call templateFieldFill only for fillable fields."
130762
+ );
130763
+ }
130764
+ const validation = validateTemplateTarget(runtime, input.field, {
130765
+ duplicateRanges: /* @__PURE__ */ new Set(),
130766
+ allowDuplicateRanges: true
130767
+ });
130768
+ if (validation.status === "blocked" || !validation.canFill || !input.field.target) {
130769
+ return blockedApply(
130770
+ validation.blockerDetails?.[0]?.code ?? `actions:template-field-fill:exact-target-required:${templateTargetDebugId(input.field)}`,
130771
+ validation.blockerDetails?.[0]?.category ?? "blocked",
130772
+ validation.blockerDetails?.[0]?.message ?? "Template field fill requires a validated exact scope handle or opaque actionHandle.",
130773
+ validation.blockerDetails?.[0]?.nextStep ?? "Plant the field through editor APIs and pass the returned handle; raw ranges are diagnostics only.",
130774
+ validation.blockerDetails
130775
+ );
130776
+ }
130777
+ const exactnessBlocker = templateFillExactnessBlocker(input.field, validation);
130778
+ if (exactnessBlocker) {
130779
+ return blockedApply(
130780
+ exactnessBlocker.code,
130781
+ exactnessBlocker.category,
130782
+ exactnessBlocker.message,
130783
+ exactnessBlocker.nextStep,
130784
+ [exactnessBlocker]
130785
+ );
130786
+ }
130787
+ const resolved = resolveTarget(runtime, input.field.target);
130788
+ if (!resolved.ok) return blockedApplyFromResolution(resolved);
130789
+ const result = applyRewrite(runtime, resolved.target, {
130790
+ target: input.field.target,
130791
+ text: input.text,
130792
+ actorId: input.actorId,
130793
+ origin: input.origin,
130794
+ ...input.proposalId ? { proposalId: input.proposalId } : {}
130795
+ });
130796
+ if (!result.applied) return result;
130797
+ const after = readPlanTarget(runtime, input.field.target);
130798
+ if (!after.ok || after.readback?.text !== input.text) {
130799
+ const detail = blockerWithOwner(
130800
+ `actions:template-field-fill:readback-mismatch:${templateTargetDebugId(input.field)}`,
130801
+ "blocked",
130802
+ "The field fill reported applied, but same-target readback did not match the requested text.",
130803
+ "Treat this as failed, inspect export/reopen evidence, and route the target lowering to L08/L07 before retrying.",
130804
+ "L08 semantic scopes and L07 runtime text commands"
130805
+ );
130806
+ return {
130807
+ ...result,
130808
+ status: "blocked",
130809
+ applied: false,
130810
+ changed: result.changed,
130811
+ posture: "suspect-readback",
130812
+ blockers: Object.freeze([...result.blockers ?? [], detail.code]),
130813
+ blockerDetails: Object.freeze([...result.blockerDetails ?? [], detail])
130814
+ };
130815
+ }
130816
+ return result;
130817
+ }
130818
+ function templateFillExactnessBlocker(target, validation) {
130819
+ const readback = validation.readback?.text ?? "";
130820
+ const expected = templateExpectedText(target);
130821
+ if (!expected) return null;
130822
+ if (readback === expected) return null;
130823
+ return blocker(
130824
+ `actions:template-field-fill:exact-target-not-isolated:${templateTargetDebugId(target)}`,
130825
+ "blocked",
130826
+ "The exact handle readback contains surrounding document text, not just the template field text.",
130827
+ "Plant an isolated template-field scope/action handle for the placeholder; do not fill by broad paragraph, clause, or raw range."
130828
+ );
130829
+ }
130830
+ function templateReadbackToPlanReadback(readback) {
130831
+ if (!readback) return void 0;
130832
+ return {
130833
+ ...readback.text !== void 0 ? { text: readback.text } : {},
130834
+ ...readback.excerpt !== void 0 ? { excerpt: readback.excerpt } : {},
130835
+ ...readback.isEmpty !== void 0 ? { isEmpty: readback.isEmpty } : {}
130836
+ };
130837
+ }
130838
+ function templateTargetKind(target) {
130839
+ return target.kind ?? (target.clauseId && !target.fieldId ? "template-clause" : "template-field");
130840
+ }
130841
+ function templateExpectedText(target) {
130842
+ const text = target.expectedText ?? target.placeholderText;
130843
+ return text && text.length > 0 ? text : void 0;
130844
+ }
130845
+ function templateTargetDebugId(target) {
130846
+ return target.fieldId ?? target.clauseId ?? target.name ?? target.placeholderText ?? "unknown";
130847
+ }
130848
+ function templateLocationKey(location) {
130849
+ if (!location?.refId && location?.start === void 0 && location?.end === void 0) return null;
130850
+ return [
130851
+ location.story ?? "main",
130852
+ location.refId ?? "no-ref",
130853
+ location.start ?? "no-start",
130854
+ location.end ?? "no-end"
130855
+ ].join(":");
130856
+ }
130857
+ function isTableTemplateLocation(location) {
130858
+ return Boolean(
130859
+ location?.blockKind === "table-cell" || location?.tableRefId || location?.rowRefId || location?.cellRefId
130860
+ );
130861
+ }
130862
+ function hasTableCellIdentity(location) {
130863
+ return Boolean(
130864
+ location?.cellRefId || location?.rowRefId && location.columnIndex !== void 0 || location?.rowIndex !== void 0 && location?.columnIndex !== void 0
130865
+ );
130866
+ }
130867
+ function hasOccurrenceIdentity(target) {
130868
+ return Boolean(
130869
+ target.occurrence?.refId || target.occurrence?.occurrenceIndexInRef !== void 0 || target.occurrence?.occurrenceIndexGlobal !== void 0 || target.location?.refId || target.location?.cellRefId
130870
+ );
130871
+ }
130872
+ function countOccurrences(text, query) {
130873
+ if (!query) return 0;
130874
+ let count = 0;
130875
+ let index = 0;
130876
+ while (index <= text.length) {
130877
+ const found = text.indexOf(query, index);
130878
+ if (found === -1) break;
130879
+ count += 1;
130880
+ index = found + Math.max(1, query.length);
130881
+ }
130882
+ return count;
130883
+ }
130884
+ function documentText(document2) {
130885
+ return document2.content.children.map((block) => blockText(block)).join("\n");
130886
+ }
130887
+ function blockText(block) {
130888
+ switch (block.type) {
130889
+ case "paragraph":
130890
+ return collectInlineText3(block.children);
130891
+ case "table":
130892
+ return block.rows.map(
130893
+ (row2) => row2.cells.map((cell) => cell.children.map((child) => blockText(child)).join("\n")).join(" ")
130894
+ ).join("\n");
130895
+ case "sdt":
130896
+ case "custom_xml":
130897
+ return block.children.map((child) => blockText(child)).join("\n");
130898
+ default:
130899
+ return "";
130900
+ }
130901
+ }
129203
130902
  function resolveTarget(runtime, target) {
129204
130903
  if ("actionHandle" in target) {
129205
130904
  const action = findTableAction(runtime, target.actionHandle);
@@ -129910,6 +131609,14 @@ function applyPlanStep(runtime, step, plan) {
129910
131609
  actorId: step.actorId ?? plan.actorId,
129911
131610
  origin: step.origin ?? plan.origin
129912
131611
  });
131612
+ case "templateFieldFill":
131613
+ return createActionsFamily(runtime).actions.templateFieldFill({
131614
+ field: step.field,
131615
+ text: step.text,
131616
+ actorId: step.actorId ?? plan.actorId,
131617
+ origin: step.origin ?? plan.origin,
131618
+ ...step.proposalId ? { proposalId: step.proposalId } : {}
131619
+ });
129913
131620
  case "listOperation":
129914
131621
  return createActionsFamily(runtime).actions.listOperation({
129915
131622
  target: step.target,
@@ -130558,7 +132265,8 @@ function createApiV3(handle, opts) {
130558
132265
  chart: createChartFamily(handle),
130559
132266
  search: createSearchFamily(handle),
130560
132267
  table: createTableFamily(handle),
130561
- viewport: createViewportFamily2(handle)
132268
+ viewport: createViewportFamily2(handle),
132269
+ lists: createListsFamily(handle)
130562
132270
  };
130563
132271
  const ui = opts?.ui ? createUiApi(handle, opts.ui) : void 0;
130564
132272
  const api = ui ? { runtime, ai, ui } : { runtime, ai };
@@ -132924,6 +134632,7 @@ var WordReviewEditor = (0, import_react71.forwardRef)(
132924
134632
  // auto-bracketing in insertFragment + our explicit startAction around
132925
134633
  // the delete, so the undo history sees a single atomic action.
132926
134634
  onDropFragment: (meta) => {
134635
+ const dropEditableTarget = meta.editableTarget ?? activeRuntime.getRenderSnapshot().selection.editableTarget;
132927
134636
  if (meta.effect === "move" && meta.sourceRange) {
132928
134637
  activeRuntime.startAction("drag-move");
132929
134638
  try {
@@ -132933,12 +134642,22 @@ var WordReviewEditor = (0, import_react71.forwardRef)(
132933
134642
  to: meta.sourceRange.to,
132934
134643
  assoc: { start: -1, end: 1 }
132935
134644
  });
132936
- activeRuntime.insertFragment(meta.fragment);
134645
+ const currentEditableTarget = activeRuntime.getRenderSnapshot().selection.editableTarget;
134646
+ const editableTarget = currentEditableTarget?.targetKey === dropEditableTarget?.targetKey ? currentEditableTarget : dropEditableTarget;
134647
+ activeRuntime.insertFragment(
134648
+ meta.fragment,
134649
+ void 0,
134650
+ editableTarget ? { editableTarget } : void 0
134651
+ );
132937
134652
  } finally {
132938
134653
  activeRuntime.endAction();
132939
134654
  }
132940
134655
  } else {
132941
- activeRuntime.insertFragment(meta.fragment);
134656
+ activeRuntime.insertFragment(
134657
+ meta.fragment,
134658
+ void 0,
134659
+ dropEditableTarget ? { editableTarget: dropEditableTarget } : void 0
134660
+ );
132942
134661
  }
132943
134662
  },
132944
134663
  onInsertHardBreak: () => dispatchTextCommand(activeRuntime, { type: "insert-hard-break" }, DISPATCH_CONTEXT),
@@ -132963,7 +134682,12 @@ var WordReviewEditor = (0, import_react71.forwardRef)(
132963
134682
  // insertFragment auto-bracket (R.5.a Phase 2) makes the paste a
132964
134683
  // single-undo action.
132965
134684
  onPasteFragment: (meta) => {
132966
- activeRuntime.insertFragment(meta.fragment);
134685
+ const editableTarget = activeRuntime.getRenderSnapshot().selection.editableTarget;
134686
+ activeRuntime.insertFragment(
134687
+ meta.fragment,
134688
+ void 0,
134689
+ editableTarget ? { editableTarget } : void 0
134690
+ );
132967
134691
  },
132968
134692
  // v5 close-out: image paste via existing insertImage ref method.
132969
134693
  // Width/height are omitted so the renderer picks sensible defaults