@beyondwork/docx-react-component 1.0.135 → 1.0.137

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 (62) hide show
  1. package/dist/api/public-types.d.cts +2 -2
  2. package/dist/api/public-types.d.ts +2 -2
  3. package/dist/api/v3.cjs +827 -59
  4. package/dist/api/v3.d.cts +3 -3
  5. package/dist/api/v3.d.ts +3 -3
  6. package/dist/api/v3.js +2 -2
  7. package/dist/{canonical-document-CfZIc-fC.d.cts → canonical-document-COmM7v11.d.cts} +1 -1
  8. package/dist/{canonical-document-CfZIc-fC.d.ts → canonical-document-COmM7v11.d.ts} +1 -1
  9. package/dist/{chunk-EPFVMUKF.js → chunk-M3AEVSKU.js} +793 -56
  10. package/dist/{chunk-5CCYF333.js → chunk-NYIMPM3Z.js} +143 -1
  11. package/dist/{chunk-GIFXKIM5.js → chunk-SMBDQV73.js} +688 -57
  12. package/dist/compare.d.cts +1 -1
  13. package/dist/compare.d.ts +1 -1
  14. package/dist/core/commands/formatting-commands.d.cts +2 -2
  15. package/dist/core/commands/formatting-commands.d.ts +2 -2
  16. package/dist/core/commands/image-commands.d.cts +2 -2
  17. package/dist/core/commands/image-commands.d.ts +2 -2
  18. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  19. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  20. package/dist/core/commands/style-commands.d.cts +2 -2
  21. package/dist/core/commands/style-commands.d.ts +2 -2
  22. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  23. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  24. package/dist/core/commands/text-commands.d.cts +2 -2
  25. package/dist/core/commands/text-commands.d.ts +2 -2
  26. package/dist/core/selection/mapping.d.cts +2 -2
  27. package/dist/core/selection/mapping.d.ts +2 -2
  28. package/dist/core/state/editor-state.d.cts +2 -2
  29. package/dist/core/state/editor-state.d.ts +2 -2
  30. package/dist/index.cjs +1808 -190
  31. package/dist/index.d.cts +5 -5
  32. package/dist/index.d.ts +5 -5
  33. package/dist/index.js +144 -32
  34. package/dist/io/docx-session.d.cts +4 -4
  35. package/dist/io/docx-session.d.ts +4 -4
  36. package/dist/legal.d.cts +1 -1
  37. package/dist/legal.d.ts +1 -1
  38. package/dist/{loader-BQ7AB-0v.d.cts → loader-BB7tRkY2.d.cts} +3 -3
  39. package/dist/{loader-Cy6OYBfn.d.ts → loader-DGPbaboy.d.ts} +3 -3
  40. package/dist/{public-types-D31xKNGc.d.cts → public-types-CIvw1GQa.d.cts} +142 -9
  41. package/dist/{public-types-DqYt8GdP.d.ts → public-types-COCDrgVX.d.ts} +142 -9
  42. package/dist/public-types.d.cts +2 -2
  43. package/dist/public-types.d.ts +2 -2
  44. package/dist/runtime/collab.d.cts +3 -3
  45. package/dist/runtime/collab.d.ts +3 -3
  46. package/dist/runtime/document-runtime.cjs +825 -54
  47. package/dist/runtime/document-runtime.d.cts +2 -2
  48. package/dist/runtime/document-runtime.d.ts +2 -2
  49. package/dist/runtime/document-runtime.js +2 -2
  50. package/dist/{session-DA-F2fCw.d.cts → session-CVU-rtCd.d.cts} +3 -3
  51. package/dist/{session-DqL8H0oZ.d.ts → session-DOqy1-Lf.d.ts} +3 -3
  52. package/dist/session.d.cts +5 -5
  53. package/dist/session.d.ts +5 -5
  54. package/dist/tailwind.d.cts +2 -2
  55. package/dist/tailwind.d.ts +2 -2
  56. package/dist/{types-SllbCtGs.d.ts → types-CB_tOnVp.d.ts} +2 -2
  57. package/dist/{types-B2y94n5t.d.cts → types-CZAll7OS.d.cts} +2 -2
  58. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  59. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  60. package/dist/ui-tailwind.d.cts +3 -3
  61. package/dist/ui-tailwind.d.ts +3 -3
  62. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -24380,6 +24380,106 @@ function setStartOverride(catalog, numberingInstanceId, level, startAt) {
24380
24380
  overrides: mergeOverride(instance.overrides, { level, startAt })
24381
24381
  };
24382
24382
  }
24383
+ function mergeFragmentNumberingCatalog(target, fragment) {
24384
+ const catalog = cloneNumberingCatalog(target);
24385
+ const abstractIdMap = /* @__PURE__ */ new Map();
24386
+ const instanceIdMap = /* @__PURE__ */ new Map();
24387
+ const picBulletIdMap = /* @__PURE__ */ new Map();
24388
+ if (!fragment) {
24389
+ return { catalog, abstractIdMap, instanceIdMap, picBulletIdMap };
24390
+ }
24391
+ for (const [picBulletId, entry] of Object.entries(fragment.numPicBullets ?? {})) {
24392
+ const mappedId = mapPicBulletId(catalog, picBulletId, entry);
24393
+ picBulletIdMap.set(picBulletId, mappedId);
24394
+ }
24395
+ for (const [abstractId, definition] of Object.entries(fragment.abstractDefinitions)) {
24396
+ const mappedId = mapAbstractDefinition(catalog, definition, picBulletIdMap);
24397
+ abstractIdMap.set(abstractId, mappedId);
24398
+ }
24399
+ for (const [instanceId, instance] of Object.entries(fragment.instances)) {
24400
+ const mappedAbstractId = abstractIdMap.get(instance.abstractNumberingId) ?? instance.abstractNumberingId;
24401
+ const mappedId = mapNumberingInstance(
24402
+ catalog,
24403
+ instance,
24404
+ mappedAbstractId,
24405
+ picBulletIdMap
24406
+ );
24407
+ instanceIdMap.set(instanceId, mappedId);
24408
+ }
24409
+ return { catalog, abstractIdMap, instanceIdMap, picBulletIdMap };
24410
+ }
24411
+ function mapPicBulletId(catalog, picBulletId, entry) {
24412
+ const existing = catalog.numPicBullets?.[picBulletId];
24413
+ if (existing && existing.rawXml === entry.rawXml) return picBulletId;
24414
+ const mappedId = existing ? nextNumericString(Object.keys(catalog.numPicBullets ?? {})) : picBulletId;
24415
+ const numPicBullets = { ...catalog.numPicBullets ?? {} };
24416
+ numPicBullets[mappedId] = {
24417
+ ...stripSourceRef(structuredClone(entry)),
24418
+ numPicBulletId: mappedId
24419
+ };
24420
+ catalog.numPicBullets = numPicBullets;
24421
+ return mappedId;
24422
+ }
24423
+ function mapAbstractDefinition(catalog, definition, picBulletIdMap) {
24424
+ const existing = catalog.abstractDefinitions[definition.abstractNumberingId];
24425
+ if (existing && sameJson(comparableAbstract(existing), comparableAbstract(definition))) {
24426
+ return definition.abstractNumberingId;
24427
+ }
24428
+ const mappedId = existing ? nextCanonicalNumericId("abstract-num:", Object.keys(catalog.abstractDefinitions)) : definition.abstractNumberingId;
24429
+ catalog.abstractDefinitions[mappedId] = {
24430
+ ...stripSourceRef(structuredClone(definition)),
24431
+ abstractNumberingId: mappedId,
24432
+ nsid: freshLongHex(catalog, mappedId, "nsid"),
24433
+ tplc: freshLongHex(catalog, mappedId, "tmpl"),
24434
+ levels: definition.levels.map((level) => remapLevelPicBullet(level, picBulletIdMap))
24435
+ };
24436
+ return mappedId;
24437
+ }
24438
+ function mapNumberingInstance(catalog, instance, abstractNumberingId, picBulletIdMap) {
24439
+ const existing = catalog.instances[instance.numberingInstanceId];
24440
+ const candidate = {
24441
+ ...instance,
24442
+ abstractNumberingId,
24443
+ overrides: instance.overrides.map(
24444
+ (override) => remapOverridePicBullet(override, picBulletIdMap)
24445
+ )
24446
+ };
24447
+ if (existing && sameJson(comparableInstance(existing), comparableInstance(candidate))) {
24448
+ return instance.numberingInstanceId;
24449
+ }
24450
+ const mappedId = existing ? nextCanonicalNumericId("num:", Object.keys(catalog.instances)) : instance.numberingInstanceId;
24451
+ catalog.instances[mappedId] = {
24452
+ ...stripSourceRef(structuredClone(instance)),
24453
+ overrides: candidate.overrides.map((override) => stripOverrideSourceRefs(override)),
24454
+ numberingInstanceId: mappedId,
24455
+ abstractNumberingId
24456
+ };
24457
+ return mappedId;
24458
+ }
24459
+ function remapLevelPicBullet(level, picBulletIdMap) {
24460
+ const cloned = stripSourceRef(structuredClone(level));
24461
+ if (!level.picBulletId) return cloned;
24462
+ return {
24463
+ ...cloned,
24464
+ picBulletId: picBulletIdMap.get(level.picBulletId) ?? level.picBulletId
24465
+ };
24466
+ }
24467
+ function remapOverridePicBullet(override, picBulletIdMap) {
24468
+ const cloned = stripOverrideSourceRefs(structuredClone(override));
24469
+ if (!override.levelDefinition) return cloned;
24470
+ return {
24471
+ ...cloned,
24472
+ levelDefinition: remapLevelPicBullet(override.levelDefinition, picBulletIdMap)
24473
+ };
24474
+ }
24475
+ function stripOverrideSourceRefs(override) {
24476
+ const cloned = stripSourceRef(override);
24477
+ if (!override.levelDefinition) return cloned;
24478
+ return {
24479
+ ...cloned,
24480
+ levelDefinition: stripSourceRef(override.levelDefinition)
24481
+ };
24482
+ }
24383
24483
  function mergeOverride(overrides, nextOverride) {
24384
24484
  return [
24385
24485
  ...overrides.filter((override) => override.level !== nextOverride.level),
@@ -24451,6 +24551,28 @@ function hashLongHex(input) {
24451
24551
  }
24452
24552
  return hash.toString(16).toUpperCase().padStart(8, "0").slice(-8);
24453
24553
  }
24554
+ function stripSourceRef(value) {
24555
+ const { sourceRef: _sourceRef, ...rest } = value;
24556
+ return rest;
24557
+ }
24558
+ function comparableAbstract(definition) {
24559
+ return {
24560
+ ...stripSourceRef(definition),
24561
+ levels: definition.levels.map((level) => stripSourceRef(level))
24562
+ };
24563
+ }
24564
+ function comparableInstance(instance) {
24565
+ return {
24566
+ ...stripSourceRef(instance),
24567
+ overrides: instance.overrides.map((override) => ({
24568
+ ...stripSourceRef(override),
24569
+ ...override.levelDefinition ? { levelDefinition: stripSourceRef(override.levelDefinition) } : {}
24570
+ }))
24571
+ };
24572
+ }
24573
+ function sameJson(left, right) {
24574
+ return JSON.stringify(left) === JSON.stringify(right);
24575
+ }
24454
24576
 
24455
24577
  // src/core/commands/list-commands.ts
24456
24578
  function toggleNumberedList(document2, paragraphIndexes, context, options = {}) {
@@ -24498,7 +24620,7 @@ function splitListParagraph(document2, paragraphIndex, paragraphIsEmpty, context
24498
24620
  action: "split"
24499
24621
  };
24500
24622
  }
24501
- const target = paragraphs[resolvedParagraphIndex];
24623
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
24502
24624
  if (!target?.numbering) {
24503
24625
  return {
24504
24626
  document: working,
@@ -24550,7 +24672,7 @@ function backspaceAtListStart(document2, paragraphIndex, context, options = {})
24550
24672
  handled: false
24551
24673
  };
24552
24674
  }
24553
- const target = paragraphs[resolvedParagraphIndex];
24675
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
24554
24676
  if (!target?.numbering) {
24555
24677
  return {
24556
24678
  document: working,
@@ -24596,7 +24718,7 @@ function restartNumbering(document2, paragraphIndex, context, startAt = 1, optio
24596
24718
  affectedParagraphIndexes: []
24597
24719
  };
24598
24720
  }
24599
- const target = paragraphs[resolvedParagraphIndex];
24721
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
24600
24722
  if (!target?.numbering) {
24601
24723
  return {
24602
24724
  document: working,
@@ -24618,8 +24740,13 @@ function restartNumbering(document2, paragraphIndex, context, startAt = 1, optio
24618
24740
  );
24619
24741
  setStartOverride(catalog, numberingInstanceId, target.numbering.level, startAt);
24620
24742
  const affectedParagraphIndexes = [];
24743
+ const targetStoryKey = paragraphs[resolvedParagraphIndex]?.storyKey;
24621
24744
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
24622
- const paragraph = paragraphs[index];
24745
+ const entry = paragraphs[index];
24746
+ if (entry?.storyKey !== targetStoryKey) {
24747
+ break;
24748
+ }
24749
+ const paragraph = entry.paragraph;
24623
24750
  if (!paragraph?.numbering) {
24624
24751
  break;
24625
24752
  }
@@ -24663,7 +24790,7 @@ function continueNumbering(document2, paragraphIndex, context, options = {}) {
24663
24790
  affectedParagraphIndexes: []
24664
24791
  };
24665
24792
  }
24666
- const target = paragraphs[resolvedParagraphIndex];
24793
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
24667
24794
  if (!target?.numbering) {
24668
24795
  return {
24669
24796
  document: working,
@@ -24692,8 +24819,13 @@ function continueNumbering(document2, paragraphIndex, context, options = {}) {
24692
24819
  };
24693
24820
  }
24694
24821
  const affectedParagraphIndexes = [];
24822
+ const targetStoryKey = paragraphs[resolvedParagraphIndex]?.storyKey;
24695
24823
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
24696
- const paragraph = paragraphs[index];
24824
+ const entry = paragraphs[index];
24825
+ if (entry?.storyKey !== targetStoryKey) {
24826
+ break;
24827
+ }
24828
+ const paragraph = entry.paragraph;
24697
24829
  if (!paragraph?.numbering) {
24698
24830
  break;
24699
24831
  }
@@ -24739,12 +24871,13 @@ function toggleListKind(document2, paragraphIndexes, kind, context, options) {
24739
24871
  }
24740
24872
  const catalog = cloneNumberingCatalog(working.numbering);
24741
24873
  const allAlreadyKind = normalizedIndexes.every((index) => {
24742
- const paragraph = paragraphs[index];
24743
- return paragraph.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
24874
+ const paragraph = paragraphs[index]?.paragraph;
24875
+ return paragraph?.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
24744
24876
  });
24745
24877
  if (allAlreadyKind) {
24746
24878
  for (const index of normalizedIndexes) {
24747
- delete paragraphs[index].numbering;
24879
+ const paragraph = paragraphs[index]?.paragraph;
24880
+ if (paragraph) delete paragraph.numbering;
24748
24881
  }
24749
24882
  working.numbering = catalog;
24750
24883
  return {
@@ -24754,7 +24887,8 @@ function toggleListKind(document2, paragraphIndexes, kind, context, options) {
24754
24887
  }
24755
24888
  const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultListInstance(catalog, kind);
24756
24889
  for (const index of normalizedIndexes) {
24757
- const paragraph = paragraphs[index];
24890
+ const paragraph = paragraphs[index]?.paragraph;
24891
+ if (!paragraph) continue;
24758
24892
  paragraph.numbering = {
24759
24893
  numberingInstanceId,
24760
24894
  level: clampLevel(paragraph.numbering?.level ?? 0)
@@ -24785,10 +24919,11 @@ function adjustListLevels(document2, paragraphIndexes, delta, context, options)
24785
24919
  };
24786
24920
  }
24787
24921
  const affectedParagraphIndexes = resolved.paragraphIndexes.filter(
24788
- (index) => Boolean(paragraphs[index]?.numbering)
24922
+ (index) => Boolean(paragraphs[index]?.paragraph.numbering)
24789
24923
  );
24790
24924
  for (const index of affectedParagraphIndexes) {
24791
- const paragraph = paragraphs[index];
24925
+ const paragraph = paragraphs[index]?.paragraph;
24926
+ if (!paragraph) continue;
24792
24927
  if (!paragraph.numbering) {
24793
24928
  continue;
24794
24929
  }
@@ -24808,17 +24943,21 @@ function normalizeListCommandTargets(options) {
24808
24943
  }
24809
24944
  function resolveListCommandParagraphIndexes(document2, paragraphs, paragraphIndexes, context, editableTargets) {
24810
24945
  if (editableTargets.length === 0) {
24811
- return { paragraphIndexes: normalizeParagraphIndexes(paragraphs, paragraphIndexes) };
24946
+ return {
24947
+ paragraphIndexes: normalizeParagraphIndexesForStory(
24948
+ paragraphs,
24949
+ paragraphIndexes,
24950
+ context.activeStoryKey
24951
+ )
24952
+ };
24812
24953
  }
24813
24954
  const currentTargets = collectEditableTargetRefs(document2, context.editableTargetCache);
24814
- const paragraphIndexByTargetKey = /* @__PURE__ */ new Map();
24815
- let paragraphIndex = 0;
24816
- for (const target of currentTargets) {
24817
- if (!isParagraphTextTarget(target)) continue;
24818
- if (!paragraphIndexByTargetKey.has(target.targetKey)) {
24819
- paragraphIndexByTargetKey.set(target.targetKey, paragraphIndex);
24820
- paragraphIndex += 1;
24821
- }
24955
+ const paragraphIndexByAddress = /* @__PURE__ */ new Map();
24956
+ for (let index = 0; index < paragraphs.length; index += 1) {
24957
+ const entry = paragraphs[index];
24958
+ if (!entry) continue;
24959
+ paragraphIndexByAddress.set(`${entry.storyKey}
24960
+ ${entry.blockPath}`, index);
24822
24961
  }
24823
24962
  const resolvedIndexes = [];
24824
24963
  for (const target of editableTargets) {
@@ -24843,7 +24982,8 @@ function resolveListCommandParagraphIndexes(document2, paragraphs, paragraphInde
24843
24982
  }
24844
24983
  };
24845
24984
  }
24846
- const currentIndex = paragraphIndexByTargetKey.get(current.targetKey);
24985
+ const currentIndex = paragraphIndexByAddress.get(`${current.storyKey}
24986
+ ${current.blockPath}`);
24847
24987
  if (currentIndex === void 0) {
24848
24988
  return {
24849
24989
  paragraphIndexes: [],
@@ -24918,18 +25058,28 @@ function sortJson(value) {
24918
25058
  return value;
24919
25059
  }
24920
25060
  function findAdjacentCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
25061
+ const current = paragraphs[fromIndex];
24921
25062
  const previous = paragraphs[fromIndex - 1];
24922
- if (previous?.numbering) {
24923
- const previousKind = getListKind(catalog, previous.numbering.numberingInstanceId);
25063
+ if (previous?.storyKey !== current?.storyKey) {
25064
+ return void 0;
25065
+ }
25066
+ const previousParagraph = previous?.paragraph;
25067
+ if (previousParagraph?.numbering) {
25068
+ const previousKind = getListKind(catalog, previousParagraph.numbering.numberingInstanceId);
24924
25069
  if (previousKind === kind) {
24925
- return previous.numbering.numberingInstanceId;
25070
+ return previousParagraph.numbering.numberingInstanceId;
24926
25071
  }
24927
25072
  }
24928
25073
  return void 0;
24929
25074
  }
24930
25075
  function findPreviousCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
25076
+ const storyKey2 = paragraphs[fromIndex]?.storyKey;
24931
25077
  for (let index = fromIndex - 1; index >= 0; index -= 1) {
24932
- const paragraph = paragraphs[index];
25078
+ const entry = paragraphs[index];
25079
+ if (entry?.storyKey !== storyKey2) {
25080
+ break;
25081
+ }
25082
+ const paragraph = entry.paragraph;
24933
25083
  if (!paragraph?.numbering) {
24934
25084
  continue;
24935
25085
  }
@@ -24948,7 +25098,14 @@ function cloneEnvelope(document2, timestamp) {
24948
25098
  function captureEditableParagraphs(document2) {
24949
25099
  if (isDocumentRoot(document2.content)) {
24950
25100
  const paragraphs = [];
24951
- collectEditableParagraphs(document2.content.children, paragraphs);
25101
+ for (const context of collectStoryBlockContexts(document2)) {
25102
+ collectEditableParagraphs(
25103
+ context.blocks,
25104
+ paragraphs,
25105
+ context.storyKey,
25106
+ context.basePath
25107
+ );
25108
+ }
24952
25109
  return paragraphs;
24953
25110
  }
24954
25111
  const fallback = {
@@ -24956,23 +25113,39 @@ function captureEditableParagraphs(document2) {
24956
25113
  children: [{ type: "paragraph", children: [] }]
24957
25114
  };
24958
25115
  document2.content = fallback;
24959
- return fallback.children;
25116
+ return [{
25117
+ paragraph: fallback.children[0],
25118
+ storyKey: "main",
25119
+ blockPath: "main/block[0]"
25120
+ }];
24960
25121
  }
24961
- function collectEditableParagraphs(blocks, output) {
24962
- for (const block of blocks) {
25122
+ function collectEditableParagraphs(blocks, output, storyKey2, basePath) {
25123
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
25124
+ const block = blocks[blockIndex];
25125
+ if (!block) continue;
25126
+ const blockPath = `${basePath}/block[${blockIndex}]`;
24963
25127
  switch (block.type) {
24964
25128
  case "paragraph":
24965
- output.push(block);
25129
+ output.push({ paragraph: block, storyKey: storyKey2, blockPath });
24966
25130
  break;
24967
25131
  case "table":
24968
- for (const row2 of block.rows) {
24969
- for (const cell of row2.cells) {
24970
- collectEditableParagraphs(cell.children, output);
25132
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
25133
+ const row2 = block.rows[rowIndex];
25134
+ if (!row2) continue;
25135
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
25136
+ const cell = row2.cells[cellIndex];
25137
+ if (!cell) continue;
25138
+ collectEditableParagraphs(
25139
+ cell.children,
25140
+ output,
25141
+ storyKey2,
25142
+ `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`
25143
+ );
24971
25144
  }
24972
25145
  }
24973
25146
  break;
24974
25147
  case "sdt":
24975
- collectEditableParagraphs(block.children, output);
25148
+ collectEditableParagraphs(block.children, output, storyKey2, blockPath);
24976
25149
  break;
24977
25150
  case "custom_xml":
24978
25151
  break;
@@ -24984,6 +25157,18 @@ function collectEditableParagraphs(blocks, output) {
24984
25157
  function normalizeParagraphIndexes(paragraphs, paragraphIndexes) {
24985
25158
  return [...new Set(paragraphIndexes)].filter((index) => Number.isInteger(index) && index >= 0 && index < paragraphs.length).sort((left, right) => left - right);
24986
25159
  }
25160
+ function normalizeParagraphIndexesForStory(paragraphs, paragraphIndexes, storyKey2) {
25161
+ if (storyKey2 === void 0) {
25162
+ return normalizeParagraphIndexes(paragraphs, paragraphIndexes);
25163
+ }
25164
+ const storyParagraphIndexes = [];
25165
+ for (let index = 0; index < paragraphs.length; index += 1) {
25166
+ if (paragraphs[index]?.storyKey === storyKey2) {
25167
+ storyParagraphIndexes.push(index);
25168
+ }
25169
+ }
25170
+ return [...new Set(paragraphIndexes)].filter((index) => Number.isInteger(index) && index >= 0 && index < storyParagraphIndexes.length).map((index) => storyParagraphIndexes[index]).sort((left, right) => left - right);
25171
+ }
24987
25172
  function clampLevel(level) {
24988
25173
  return Math.max(0, Math.min(8, level));
24989
25174
  }
@@ -31279,9 +31464,9 @@ function findTableStructureTargetForSelection(document2, descriptor, operation2,
31279
31464
  if (descriptor.editability === "non-editable" && descriptor.nonEditableReason !== "nested-table-not-editable") {
31280
31465
  return null;
31281
31466
  }
31282
- const activeStoryKey = editableTargetStoryKey(activeStory);
31467
+ const activeStoryKey2 = editableTargetStoryKey(activeStory);
31283
31468
  const targets = collectEditableTargetRefs(document2).filter(
31284
- (target) => target.commandFamily === "table-structure" && target.table !== void 0 && target.storyKey === activeStoryKey && tableStructureTargetMatchesDescriptor2(target, descriptor)
31469
+ (target) => target.commandFamily === "table-structure" && target.table !== void 0 && target.storyKey === activeStoryKey2 && tableStructureTargetMatchesDescriptor2(target, descriptor)
31285
31470
  );
31286
31471
  const scope = preferredTableStructureScope(operation2);
31287
31472
  return targets.find((target) => {
@@ -36544,8 +36729,9 @@ function applyFragmentInsert(document2, selection, fragment, context) {
36544
36729
  workingDocument = collapseResult.document;
36545
36730
  workingSelection = collapseResult.selection;
36546
36731
  if (context.textTarget?.kind === "table-paragraph" || context.textTarget?.kind === "text-leaf") {
36732
+ const { precomputedSurface: _precomputedSurface, ...contextWithoutPrecomputedSurface } = context;
36547
36733
  workingContext = {
36548
- ...context,
36734
+ ...contextWithoutPrecomputedSurface,
36549
36735
  textTarget: {
36550
36736
  ...context.textTarget,
36551
36737
  paragraphEnd: Math.max(
@@ -36557,7 +36743,11 @@ function applyFragmentInsert(document2, selection, fragment, context) {
36557
36743
  }
36558
36744
  }
36559
36745
  const splitResult = splitParagraph(workingDocument, workingSelection, workingContext);
36560
- const splitRoot = splitResult.document.content;
36746
+ const preparedFragment = prepareFragmentNumberingForInsertion(
36747
+ splitResult.document,
36748
+ fragment
36749
+ );
36750
+ const splitRoot = preparedFragment.document.content;
36561
36751
  if (!splitRoot || splitRoot.type !== "doc") {
36562
36752
  return {
36563
36753
  changed: false,
@@ -36568,9 +36758,9 @@ function applyFragmentInsert(document2, selection, fragment, context) {
36568
36758
  const targetedBlockPath = workingContext.textTarget?.kind === "table-paragraph" || workingContext.textTarget?.kind === "text-leaf" ? workingContext.textTarget.blockPath : void 0;
36569
36759
  if (targetedBlockPath) {
36570
36760
  const targeted = insertFragmentBlocksAfterPath(
36571
- splitResult.document,
36761
+ preparedFragment.document,
36572
36762
  targetedBlockPath,
36573
- fragment.blocks
36763
+ preparedFragment.blocks
36574
36764
  );
36575
36765
  if (targeted) {
36576
36766
  return {
@@ -36602,7 +36792,7 @@ function applyFragmentInsert(document2, selection, fragment, context) {
36602
36792
  const rightHalfIndex = scope.blockIndex + 1;
36603
36793
  const splicedChildren = [
36604
36794
  ...splitRoot.children.slice(0, rightHalfIndex),
36605
- ...fragment.blocks.map((block) => cloneBlock(block)),
36795
+ ...preparedFragment.blocks.map((block) => cloneBlock(block)),
36606
36796
  ...splitRoot.children.slice(rightHalfIndex)
36607
36797
  ];
36608
36798
  const nextRoot = {
@@ -36610,7 +36800,7 @@ function applyFragmentInsert(document2, selection, fragment, context) {
36610
36800
  children: splicedChildren
36611
36801
  };
36612
36802
  const nextDocument = {
36613
- ...splitResult.document,
36803
+ ...preparedFragment.document,
36614
36804
  updatedAt: context.timestamp,
36615
36805
  content: nextRoot
36616
36806
  };
@@ -36622,14 +36812,47 @@ function applyFragmentInsert(document2, selection, fragment, context) {
36622
36812
  mapping: createEmptyMapping()
36623
36813
  };
36624
36814
  }
36625
- function cloneBlock(block) {
36626
- if (block.type === "paragraph") {
36627
- return {
36628
- ...block,
36629
- children: block.children.map((child) => ({ ...child }))
36815
+ function prepareFragmentNumberingForInsertion(document2, fragment) {
36816
+ if (!fragment.numbering) {
36817
+ return { document: document2, blocks: fragment.blocks };
36818
+ }
36819
+ const merged = mergeFragmentNumberingCatalog(document2.numbering, fragment.numbering);
36820
+ return {
36821
+ document: {
36822
+ ...document2,
36823
+ numbering: merged.catalog
36824
+ },
36825
+ blocks: fragment.blocks.map((block) => cloneBlock(block, merged.instanceIdMap))
36826
+ };
36827
+ }
36828
+ function cloneBlock(block, numberingInstanceIdMap) {
36829
+ const cloned = structuredClone(block);
36830
+ remapNumberingReferences(cloned, numberingInstanceIdMap);
36831
+ return cloned;
36832
+ }
36833
+ function remapNumberingReferences(value, numberingInstanceIdMap) {
36834
+ if (!numberingInstanceIdMap?.size || !value || typeof value !== "object") {
36835
+ return;
36836
+ }
36837
+ if (Array.isArray(value)) {
36838
+ for (const entry of value) {
36839
+ remapNumberingReferences(entry, numberingInstanceIdMap);
36840
+ }
36841
+ return;
36842
+ }
36843
+ const record = value;
36844
+ if (record.numbering?.numberingInstanceId) {
36845
+ const mappedId = numberingInstanceIdMap.get(record.numbering.numberingInstanceId) ?? record.numbering.numberingInstanceId;
36846
+ record.numbering = {
36847
+ ...record.numbering,
36848
+ numberingInstanceId: mappedId
36630
36849
  };
36631
36850
  }
36632
- return JSON.parse(JSON.stringify(block));
36851
+ remapNumberingReferences(record.children, numberingInstanceIdMap);
36852
+ remapNumberingReferences(record.rows, numberingInstanceIdMap);
36853
+ remapNumberingReferences(record.cells, numberingInstanceIdMap);
36854
+ remapNumberingReferences(record.txbxBlocks, numberingInstanceIdMap);
36855
+ remapNumberingReferences(record.content, numberingInstanceIdMap);
36633
36856
  }
36634
36857
  function insertFragmentBlocksAfterPath(document2, blockPath, fragmentBlocks) {
36635
36858
  const tokens = parseCanonicalBlockPath2(blockPath);
@@ -50035,13 +50258,32 @@ function storyKeyFromHandle(handle) {
50035
50258
  function textLeafEditableTargetHint(entry, semanticBlockRange) {
50036
50259
  const storyKey2 = storyKeyFromHandle(entry.handle);
50037
50260
  if (!storyKey2) return void 0;
50261
+ const semanticBlockPath = textLeafBlockPathFromSemanticPath(entry.handle.semanticPath, storyKey2);
50038
50262
  return {
50039
50263
  kind: "text-leaf",
50040
50264
  storyKey: storyKey2,
50041
- blockPath: `${storyKey2}/block[${entry.blockIndex}]`,
50265
+ blockPath: semanticBlockPath ?? `${storyKey2}/block[${entry.blockIndex}]`,
50042
50266
  semanticBlockRange
50043
50267
  };
50044
50268
  }
50269
+ function textLeafBlockPathFromSemanticPath(semanticPath, storyKey2) {
50270
+ if (!semanticPath) return null;
50271
+ const tableIndex = semanticPath.indexOf("table");
50272
+ const rowIndex = semanticPath.indexOf("row", tableIndex + 1);
50273
+ const cellIndex = semanticPath.indexOf("cell", rowIndex + 1);
50274
+ const paragraphIndex = semanticPath.indexOf("paragraph", cellIndex + 1);
50275
+ if (tableIndex < 0 || rowIndex < 0 || cellIndex < 0 || paragraphIndex < 0) {
50276
+ return null;
50277
+ }
50278
+ const table = Number(semanticPath[tableIndex + 1]);
50279
+ const row2 = Number(semanticPath[rowIndex + 1]);
50280
+ const cell = Number(semanticPath[cellIndex + 1]);
50281
+ const paragraph = Number(semanticPath[paragraphIndex + 1]);
50282
+ if (!Number.isInteger(table) || !Number.isInteger(row2) || !Number.isInteger(cell) || !Number.isInteger(paragraph)) {
50283
+ return null;
50284
+ }
50285
+ return `${storyKey2}/block[${table}]/row[${row2}]/cell[${cell}]/block[${paragraph}]`;
50286
+ }
50045
50287
  function compileParagraphReplacement(entry, proposed, options) {
50046
50288
  if (proposed.operation !== "replace" && proposed.operation !== "insert-before" && proposed.operation !== "insert-after") {
50047
50289
  return null;
@@ -56476,6 +56718,16 @@ function coerceIssueValue2(value) {
56476
56718
  function insertScopeMarkers(document2, params) {
56477
56719
  const { scopeId } = params;
56478
56720
  const root = document2.content;
56721
+ if (!Number.isFinite(params.from) || !Number.isFinite(params.to)) {
56722
+ const from = Number.isFinite(params.from) ? params.from : 0;
56723
+ const to = Number.isFinite(params.to) ? params.to : from;
56724
+ return {
56725
+ status: "non-finite-range",
56726
+ scopeId,
56727
+ from,
56728
+ to
56729
+ };
56730
+ }
56479
56731
  const normalizedFrom = Math.min(params.from, params.to);
56480
56732
  const normalizedTo = Math.max(params.from, params.to);
56481
56733
  if (!root || root.type !== "doc" || root.children.length === 0) {
@@ -56928,6 +57180,14 @@ function isRecord3(value) {
56928
57180
  }
56929
57181
 
56930
57182
  // src/runtime/workflow/coordinator.ts
57183
+ function createScopeMarkerMutationMapping() {
57184
+ return {
57185
+ steps: [],
57186
+ metadata: {
57187
+ layoutNeutralScopeMarkers: true
57188
+ }
57189
+ };
57190
+ }
56931
57191
  var MODE_RESTRICTIVENESS = {
56932
57192
  edit: 0,
56933
57193
  suggest: 1,
@@ -57119,12 +57379,12 @@ function createWorkflowCoordinator(deps) {
57119
57379
  function getCachedInteractionGuardSnapshot() {
57120
57380
  const state = deps.getState();
57121
57381
  const activeStory = deps.getActiveStory();
57122
- const activeStoryKey = storyTargetKey(activeStory);
57382
+ const activeStoryKey2 = storyTargetKey(activeStory);
57123
57383
  const protectionSnapshot = deps.getProtectionSnapshot();
57124
57384
  const documentMode = deps.getDocumentMode();
57125
57385
  const overlay = overlayStore.getOverlay();
57126
57386
  const sharedWorkflowState = overlayStore.getSharedWorkflowState();
57127
- if (cachedInteractionGuardSnapshot && cachedInteractionGuardSnapshot.activeStoryKey === activeStoryKey && cachedInteractionGuardSnapshot.selection === state.selection && cachedInteractionGuardSnapshot.readOnly === state.readOnly && cachedInteractionGuardSnapshot.documentMode === documentMode && cachedInteractionGuardSnapshot.protectionSnapshot === protectionSnapshot && cachedInteractionGuardSnapshot.overlay === overlay && cachedInteractionGuardSnapshot.sharedWorkflowState === sharedWorkflowState) {
57387
+ if (cachedInteractionGuardSnapshot && cachedInteractionGuardSnapshot.activeStoryKey === activeStoryKey2 && cachedInteractionGuardSnapshot.selection === state.selection && cachedInteractionGuardSnapshot.readOnly === state.readOnly && cachedInteractionGuardSnapshot.documentMode === documentMode && cachedInteractionGuardSnapshot.protectionSnapshot === protectionSnapshot && cachedInteractionGuardSnapshot.overlay === overlay && cachedInteractionGuardSnapshot.sharedWorkflowState === sharedWorkflowState) {
57128
57388
  return cachedInteractionGuardSnapshot.snapshot;
57129
57389
  }
57130
57390
  const blockedReasons = evaluateBlockedReasons(state.selection);
@@ -57165,7 +57425,7 @@ function createWorkflowCoordinator(deps) {
57165
57425
  blockedReasons
57166
57426
  };
57167
57427
  cachedInteractionGuardSnapshot = {
57168
- activeStoryKey,
57428
+ activeStoryKey: activeStoryKey2,
57169
57429
  selection: state.selection,
57170
57430
  readOnly: state.readOnly,
57171
57431
  documentMode,
@@ -57194,13 +57454,13 @@ function createWorkflowCoordinator(deps) {
57194
57454
  function getCachedWorkflowMarkupSnapshot() {
57195
57455
  const state = deps.getState();
57196
57456
  const activeStory = deps.getActiveStory();
57197
- const activeStoryKey = storyTargetKey(activeStory);
57457
+ const activeStoryKey2 = storyTargetKey(activeStory);
57198
57458
  const protectionSnapshot = deps.getProtectionSnapshot();
57199
57459
  const preservation = deps.getDocument().preservation;
57200
57460
  const overlay = overlayStore.getOverlay();
57201
57461
  const metadataDefinitions = overlayStore.getMetadataDefinitions();
57202
57462
  const metadataEntries = overlayStore.getMetadataEntries();
57203
- if (cachedWorkflowMarkupSnapshot && cachedWorkflowMarkupSnapshot.activeStoryKey === activeStoryKey && cachedWorkflowMarkupSnapshot.protectionSnapshot === protectionSnapshot && cachedWorkflowMarkupSnapshot.preservation === preservation && cachedWorkflowMarkupSnapshot.overlay === overlay && cachedWorkflowMarkupSnapshot.metadataDefinitions === metadataDefinitions && cachedWorkflowMarkupSnapshot.metadataEntries === metadataEntries) {
57463
+ if (cachedWorkflowMarkupSnapshot && cachedWorkflowMarkupSnapshot.activeStoryKey === activeStoryKey2 && cachedWorkflowMarkupSnapshot.protectionSnapshot === protectionSnapshot && cachedWorkflowMarkupSnapshot.preservation === preservation && cachedWorkflowMarkupSnapshot.overlay === overlay && cachedWorkflowMarkupSnapshot.metadataDefinitions === metadataDefinitions && cachedWorkflowMarkupSnapshot.metadataEntries === metadataEntries) {
57204
57464
  return cachedWorkflowMarkupSnapshot.snapshot;
57205
57465
  }
57206
57466
  const snapshot = collectWorkflowMarkupSnapshot({
@@ -57211,7 +57471,7 @@ function createWorkflowCoordinator(deps) {
57211
57471
  workflowMetadataSnapshot: overlayStore.getMetadataSnapshot()
57212
57472
  });
57213
57473
  cachedWorkflowMarkupSnapshot = {
57214
- activeStoryKey,
57474
+ activeStoryKey: activeStoryKey2,
57215
57475
  protectionSnapshot,
57216
57476
  preservation,
57217
57477
  overlay,
@@ -57235,6 +57495,60 @@ function createWorkflowCoordinator(deps) {
57235
57495
  activeStory: deps.getActiveStory()
57236
57496
  };
57237
57497
  }
57498
+ function createPlantFailureResult(input) {
57499
+ const { scopeId, anchor, assoc, plantResult } = input;
57500
+ return {
57501
+ scopeId: "",
57502
+ anchor: {
57503
+ kind: "range",
57504
+ from: anchor.from,
57505
+ to: anchor.to,
57506
+ assoc
57507
+ },
57508
+ plantStatus: {
57509
+ planted: false,
57510
+ reason: plantResult.status,
57511
+ ...plantResult.status === "non-paragraph-target" ? {
57512
+ blockIndex: plantResult.blockIndex,
57513
+ blockKind: plantResult.blockKind
57514
+ } : {},
57515
+ ...plantResult.status === "range-out-of-bounds" ? { storyLength: plantResult.storyLength } : {},
57516
+ requestedFrom: plantResult.from,
57517
+ requestedTo: plantResult.to
57518
+ }
57519
+ };
57520
+ }
57521
+ function buildWorkflowScope(input) {
57522
+ const { params, scopeId, publicAnchor } = input;
57523
+ return {
57524
+ scopeId,
57525
+ mode: params.mode ?? "comment",
57526
+ anchor: publicAnchor,
57527
+ ...params.storyTarget ? { storyTarget: params.storyTarget } : {},
57528
+ ...params.label ? { label: params.label } : {},
57529
+ ...params.visibility ? { visibility: params.visibility } : {},
57530
+ ...params.guardPolicy ? { guardPolicy: params.guardPolicy } : {},
57531
+ ...params.scopeMetadataFields && params.scopeMetadataFields.length > 0 ? { metadata: [...params.scopeMetadataFields] } : {}
57532
+ };
57533
+ }
57534
+ function buildWorkflowMetadataEntry(input) {
57535
+ const { params, scopeId, publicAnchor } = input;
57536
+ if (!params.persistence || params.persistence === "runtime-only") return null;
57537
+ const requestedMetadata = params.metadata ?? {};
57538
+ const entryPersistence = requestedMetadata.metadataPersistence ?? (params.persistence === "session" ? "external" : "internal");
57539
+ return {
57540
+ entryId: requestedMetadata.entryId ?? `scope-metadata-${scopeId}`,
57541
+ metadataId: requestedMetadata.metadataId ?? "workflow.scope",
57542
+ anchor: publicAnchor,
57543
+ ...params.storyTarget ? { storyTarget: params.storyTarget } : {},
57544
+ scopeId,
57545
+ ...requestedMetadata.workItemId ? { workItemId: requestedMetadata.workItemId } : {},
57546
+ ...requestedMetadata.value !== void 0 ? { value: requestedMetadata.value } : params.persistence === "document-metadata" && params.label ? { value: { label: params.label } } : {},
57547
+ metadataPersistence: entryPersistence,
57548
+ ...requestedMetadata.storageRef !== void 0 ? { storageRef: requestedMetadata.storageRef } : {},
57549
+ ...requestedMetadata.metadataVersion !== void 0 ? { metadataVersion: requestedMetadata.metadataVersion } : {}
57550
+ };
57551
+ }
57238
57552
  function addScope(params) {
57239
57553
  const state = deps.getState();
57240
57554
  const scopeId = params.scopeId ?? `scope-${clock().replace(/[^0-9]/gu, "")}-${Math.floor(Math.random() * 1e6)}`;
@@ -57277,6 +57591,7 @@ function createWorkflowCoordinator(deps) {
57277
57591
  deps.dispatch({
57278
57592
  type: "document.replace",
57279
57593
  document: nextDocument,
57594
+ mapping: createScopeMarkerMutationMapping(),
57280
57595
  origin: { source: "api", at: clock() }
57281
57596
  });
57282
57597
  const callerAssoc = params.anchor.kind === "range" ? params.anchor.assoc : { start: -1, end: 1 };
@@ -57333,6 +57648,86 @@ function createWorkflowCoordinator(deps) {
57333
57648
  }
57334
57649
  return { scopeId, anchor: publicAnchor };
57335
57650
  }
57651
+ function addScopes(paramsList) {
57652
+ if (paramsList.length === 0) return [];
57653
+ return deps.runInRuntimeBatch("workflow.addScopes", () => {
57654
+ let nextDocument = deps.getDocument();
57655
+ let documentChanged = false;
57656
+ const results = [];
57657
+ const scopesToAdd = [];
57658
+ const metadataEntriesToAdd = [];
57659
+ const newScopeIds = /* @__PURE__ */ new Set();
57660
+ for (const params of paramsList) {
57661
+ const scopeId = params.scopeId ?? `scope-${clock().replace(/[^0-9]/gu, "")}-${Math.floor(Math.random() * 1e6)}`;
57662
+ const anchor = params.anchor.kind === "range" ? { from: params.anchor.from, to: params.anchor.to } : null;
57663
+ if (!anchor) {
57664
+ results.push({ scopeId, anchor: params.anchor });
57665
+ continue;
57666
+ }
57667
+ const callerAssoc = params.anchor.kind === "range" ? params.anchor.assoc : { start: -1, end: 1 };
57668
+ const plantResult = insertScopeMarkers(nextDocument, {
57669
+ scopeId,
57670
+ from: anchor.from,
57671
+ to: anchor.to
57672
+ });
57673
+ if (plantResult.status !== "planted") {
57674
+ results.push(
57675
+ createPlantFailureResult({
57676
+ scopeId,
57677
+ anchor,
57678
+ assoc: callerAssoc,
57679
+ plantResult
57680
+ })
57681
+ );
57682
+ continue;
57683
+ }
57684
+ nextDocument = plantResult.document;
57685
+ documentChanged = true;
57686
+ const publicAnchor = {
57687
+ kind: "range",
57688
+ from: plantResult.plantedRange.from,
57689
+ to: plantResult.plantedRange.to,
57690
+ assoc: callerAssoc
57691
+ };
57692
+ newScopeIds.add(scopeId);
57693
+ scopesToAdd.push(buildWorkflowScope({ params, scopeId, publicAnchor }));
57694
+ const entry = buildWorkflowMetadataEntry({ params, scopeId, publicAnchor });
57695
+ if (entry) metadataEntriesToAdd.push(entry);
57696
+ results.push({ scopeId, anchor: publicAnchor });
57697
+ }
57698
+ if (documentChanged) {
57699
+ deps.dispatch({
57700
+ type: "document.replace",
57701
+ document: nextDocument,
57702
+ mapping: createScopeMarkerMutationMapping(),
57703
+ origin: { source: "api", at: clock() }
57704
+ });
57705
+ }
57706
+ if (scopesToAdd.length > 0) {
57707
+ const currentOverlay = overlayStore.getOverlay() ?? {
57708
+ overlayVersion: "workflow-overlay/1",
57709
+ scopes: []
57710
+ };
57711
+ const existingScopes = currentOverlay.scopes.filter(
57712
+ (existing) => !newScopeIds.has(existing.scopeId)
57713
+ );
57714
+ deps.dispatch({
57715
+ type: "workflow.set-overlay",
57716
+ overlay: { ...currentOverlay, scopes: [...existingScopes, ...scopesToAdd] },
57717
+ origin: { source: "api", at: clock() }
57718
+ });
57719
+ }
57720
+ if (metadataEntriesToAdd.length > 0) {
57721
+ const priorEntries = overlayStore.getMetadataEntries();
57722
+ deps.dispatch({
57723
+ type: "workflow.set-metadata-entries",
57724
+ entries: [...priorEntries, ...metadataEntriesToAdd],
57725
+ origin: { source: "api", at: clock() }
57726
+ });
57727
+ }
57728
+ return results;
57729
+ });
57730
+ }
57336
57731
  function removeScope(scopeId) {
57337
57732
  const overlay = overlayStore.getOverlay();
57338
57733
  if (overlay) {
@@ -57350,6 +57745,7 @@ function createWorkflowCoordinator(deps) {
57350
57745
  deps.dispatch({
57351
57746
  type: "document.replace",
57352
57747
  document: nextDocument,
57748
+ mapping: createScopeMarkerMutationMapping(),
57353
57749
  origin: { source: "api", at: clock() }
57354
57750
  });
57355
57751
  }
@@ -57743,6 +58139,7 @@ function createWorkflowCoordinator(deps) {
57743
58139
  }
57744
58140
  return {
57745
58141
  addScope,
58142
+ addScopes,
57746
58143
  removeScope,
57747
58144
  addInvisibleScope,
57748
58145
  setScopeVisibility,
@@ -69724,8 +70121,8 @@ function resolveEditableTextTarget(input) {
69724
70121
  `Editable target ref is malformed: ${shapeIssues[0]?.path ?? "$"}.`
69725
70122
  );
69726
70123
  }
69727
- const activeStoryKey = input.activeStoryKey ?? "main";
69728
- if (input.target.storyKey !== activeStoryKey) {
70124
+ const activeStoryKey2 = input.activeStoryKey ?? "main";
70125
+ if (input.target.storyKey !== activeStoryKey2) {
69729
70126
  return reject(
69730
70127
  "editable_target_wrong_story",
69731
70128
  "Editable target ref does not belong to the active story."
@@ -69821,8 +70218,8 @@ function resolveEditableCommandTarget(input) {
69821
70218
  `Editable target ref is malformed: ${shapeIssues[0]?.path ?? "$"}.`
69822
70219
  );
69823
70220
  }
69824
- const activeStoryKey = input.activeStoryKey ?? input.target.storyKey;
69825
- if (input.target.storyKey !== activeStoryKey) {
70221
+ const activeStoryKey2 = input.activeStoryKey ?? input.target.storyKey;
70222
+ if (input.target.storyKey !== activeStoryKey2) {
69826
70223
  return rejectCommand(
69827
70224
  "editable_target_wrong_story",
69828
70225
  "Editable target ref does not belong to the active story."
@@ -70237,8 +70634,8 @@ function resolveEditableTableStructureTarget(input) {
70237
70634
  `Editable target ref is malformed: ${shapeIssues[0]?.path ?? "$"}.`
70238
70635
  );
70239
70636
  }
70240
- const activeStoryKey = input.activeStoryKey ?? input.target.storyKey;
70241
- if (input.target.storyKey !== activeStoryKey) {
70637
+ const activeStoryKey2 = input.activeStoryKey ?? input.target.storyKey;
70638
+ if (input.target.storyKey !== activeStoryKey2) {
70242
70639
  return reject2(
70243
70640
  "editable_target_wrong_story",
70244
70641
  "Editable target ref does not belong to the active story."
@@ -70480,6 +70877,10 @@ function createDocumentRuntime(options) {
70480
70877
  const sessionId = createSessionId(options.documentId, clock());
70481
70878
  const listeners = /* @__PURE__ */ new Set();
70482
70879
  const eventListeners = /* @__PURE__ */ new Set();
70880
+ let runtimeNotificationBatchDepth = 0;
70881
+ let pendingRuntimeListenerNotify = false;
70882
+ let pendingRenderSnapshotRefresh = false;
70883
+ const pendingRuntimeEvents = [];
70483
70884
  const loadScheduler = options.loadScheduler ?? createLoadScheduler({ backendOverride: "sync" });
70484
70885
  let effectiveMarkupModeProvider;
70485
70886
  const perfCounters = new PerfCounters();
@@ -70853,7 +71254,7 @@ function createDocumentRuntime(options) {
70853
71254
  if (cached) {
70854
71255
  return cached;
70855
71256
  }
70856
- const activeStoryKey = storyTargetKey(nextActiveStory);
71257
+ const activeStoryKey2 = storyTargetKey(nextActiveStory);
70857
71258
  const snapshot = createEditorSurfaceSnapshot(document2, state.selection, nextActiveStory, {
70858
71259
  viewportBlockRanges: null,
70859
71260
  editableTargetsByBlockPath: getEditableTargetsByBlockPath(document2),
@@ -70871,31 +71272,31 @@ function createDocumentRuntime(options) {
70871
71272
  preservation: document2.preservation,
70872
71273
  review: document2.review,
70873
71274
  effectiveMarkupModeProvider,
70874
- activeStoryKey,
71275
+ activeStoryKey: activeStoryKey2,
70875
71276
  snapshot
70876
71277
  };
70877
71278
  return snapshot;
70878
71279
  }
70879
71280
  function getReusableCachedFullSurface(document2, nextActiveStory) {
70880
- const activeStoryKey = storyTargetKey(nextActiveStory);
70881
- if (cachedFullSurface && cachedFullSurface.content === document2.content && cachedFullSurface.subParts === document2.subParts && cachedFullSurface.styles === document2.styles && cachedFullSurface.numbering === document2.numbering && cachedFullSurface.media === document2.media && cachedFullSurface.preservation === document2.preservation && cachedFullSurface.review === document2.review && cachedFullSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider && cachedFullSurface.activeStoryKey === activeStoryKey) {
71281
+ const activeStoryKey2 = storyTargetKey(nextActiveStory);
71282
+ if (cachedFullSurface && cachedFullSurface.content === document2.content && cachedFullSurface.subParts === document2.subParts && cachedFullSurface.styles === document2.styles && cachedFullSurface.numbering === document2.numbering && cachedFullSurface.media === document2.media && cachedFullSurface.preservation === document2.preservation && cachedFullSurface.review === document2.review && cachedFullSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider && cachedFullSurface.activeStoryKey === activeStoryKey2) {
70882
71283
  return cachedFullSurface.snapshot;
70883
71284
  }
70884
71285
  return void 0;
70885
71286
  }
70886
71287
  function getCachedSurface(document2, nextActiveStory, options2 = {}) {
70887
- const activeStoryKey = storyTargetKey(nextActiveStory);
71288
+ const activeStoryKey2 = storyTargetKey(nextActiveStory);
70888
71289
  const surfaceViewportRanges = "viewportBlockRangesOverride" in options2 ? options2.viewportBlockRangesOverride ?? null : viewportBlockRanges;
70889
71290
  const surfaceViewportRangesKey = "viewportBlockRangesOverride" in options2 ? serializeViewportRanges(surfaceViewportRanges) : viewportRangesKey;
70890
71291
  const surfaceCacheKey = options2.enrichCulledPlaceholders === false ? `${surfaceViewportRangesKey}|raw-placeholders` : surfaceViewportRangesKey;
70891
- if (cachedSurface && cachedSurface.content === document2.content && cachedSurface.subParts === document2.subParts && cachedSurface.styles === document2.styles && cachedSurface.numbering === document2.numbering && cachedSurface.media === document2.media && cachedSurface.preservation === document2.preservation && cachedSurface.review === document2.review && cachedSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider && cachedSurface.activeStoryKey === activeStoryKey && cachedSurface.viewportRangesKey === surfaceCacheKey) {
71292
+ if (cachedSurface && cachedSurface.content === document2.content && cachedSurface.subParts === document2.subParts && cachedSurface.styles === document2.styles && cachedSurface.numbering === document2.numbering && cachedSurface.media === document2.media && cachedSurface.preservation === document2.preservation && cachedSurface.review === document2.review && cachedSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider && cachedSurface.activeStoryKey === activeStoryKey2 && cachedSurface.viewportRangesKey === surfaceCacheKey) {
70892
71293
  return cachedSurface.snapshot;
70893
71294
  }
70894
71295
  const snapshot = createEditorSurfaceSnapshot(document2, state.selection, nextActiveStory, {
70895
71296
  viewportBlockRanges: surfaceViewportRanges,
70896
71297
  editableTargetsByBlockPath: options2.editableTargetsByBlockPathOverride ?? getEditableTargetsByBlockPathForRanges(
70897
71298
  document2,
70898
- activeStoryKey,
71299
+ activeStoryKey2,
70899
71300
  surfaceViewportRanges
70900
71301
  ),
70901
71302
  paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document2.styles),
@@ -70918,7 +71319,7 @@ function createDocumentRuntime(options) {
70918
71319
  preservation: document2.preservation,
70919
71320
  review: document2.review,
70920
71321
  effectiveMarkupModeProvider,
70921
- activeStoryKey,
71322
+ activeStoryKey: activeStoryKey2,
70922
71323
  snapshot: enrichedSnapshot
70923
71324
  };
70924
71325
  }
@@ -70931,11 +71332,11 @@ function createDocumentRuntime(options) {
70931
71332
  preservation: document2.preservation,
70932
71333
  review: document2.review,
70933
71334
  effectiveMarkupModeProvider,
70934
- activeStoryKey,
71335
+ activeStoryKey: activeStoryKey2,
70935
71336
  viewportRangesKey: surfaceCacheKey,
70936
71337
  snapshot: enrichedSnapshot
70937
71338
  };
70938
- cachedSurfaceFingerprint = `${activeStoryKey}|${surfaceCacheKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
71339
+ cachedSurfaceFingerprint = `${activeStoryKey2}|${surfaceCacheKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
70939
71340
  return enrichedSnapshot;
70940
71341
  }
70941
71342
  function getSelectionCorridorViewportRanges(previousSurface) {
@@ -70966,7 +71367,7 @@ function createDocumentRuntime(options) {
70966
71367
  return -1;
70967
71368
  }
70968
71369
  function cachePatchedLocalTextSurface(surface, fullSurfaceForCache) {
70969
- const activeStoryKey = storyTargetKey(activeStory);
71370
+ const activeStoryKey2 = storyTargetKey(activeStory);
70970
71371
  const rangesKey = serializeViewportRanges(surface.viewportBlockRanges);
70971
71372
  cachedSurface = {
70972
71373
  content: state.document.content,
@@ -70977,7 +71378,7 @@ function createDocumentRuntime(options) {
70977
71378
  preservation: state.document.preservation,
70978
71379
  review: state.document.review,
70979
71380
  effectiveMarkupModeProvider,
70980
- activeStoryKey,
71381
+ activeStoryKey: activeStoryKey2,
70981
71382
  viewportRangesKey: rangesKey,
70982
71383
  snapshot: surface
70983
71384
  };
@@ -70992,11 +71393,11 @@ function createDocumentRuntime(options) {
70992
71393
  preservation: state.document.preservation,
70993
71394
  review: state.document.review,
70994
71395
  effectiveMarkupModeProvider,
70995
- activeStoryKey,
71396
+ activeStoryKey: activeStoryKey2,
70996
71397
  snapshot: fullSurface
70997
71398
  };
70998
71399
  }
70999
- cachedSurfaceFingerprint = `${activeStoryKey}|${rangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
71400
+ cachedSurfaceFingerprint = `${activeStoryKey2}|${rangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
71000
71401
  }
71001
71402
  function createLocalTextCorridorSurfaceFromFullSurface(fullSurface) {
71002
71403
  const ranges = getSelectionCorridorViewportRanges(fullSurface);
@@ -71391,7 +71792,7 @@ function createDocumentRuntime(options) {
71391
71792
  return snapshot.suggestions.find((suggestion) => suggestion.changeIds.includes(changeId));
71392
71793
  }
71393
71794
  function getCachedDocumentNavigationSnapshot(nextState, nextActiveStory) {
71394
- const activeStoryKey = storyTargetKey(nextActiveStory);
71795
+ const activeStoryKey2 = storyTargetKey(nextActiveStory);
71395
71796
  const buildSnapshot = () => layoutEngine.getNavigationSnapshot(
71396
71797
  {
71397
71798
  document: nextState.document,
@@ -71404,7 +71805,7 @@ function createDocumentRuntime(options) {
71404
71805
  nextState.selection,
71405
71806
  nextActiveStory
71406
71807
  );
71407
- if (cachedNavigation && cachedNavigation.document === nextState.document && cachedNavigation.activeStoryKey === activeStoryKey && cachedNavigation.workspaceMode === viewState.workspaceMode && cachedNavigation.zoomLevel === viewState.zoomLevel) {
71808
+ if (cachedNavigation && cachedNavigation.document === nextState.document && cachedNavigation.activeStoryKey === activeStoryKey2 && cachedNavigation.workspaceMode === viewState.workspaceMode && cachedNavigation.zoomLevel === viewState.zoomLevel) {
71408
71809
  if (cachedNavigation.selectionHead === nextState.selection.head) {
71409
71810
  return cachedNavigation.snapshot;
71410
71811
  }
@@ -71412,7 +71813,7 @@ function createDocumentRuntime(options) {
71412
71813
  if (snapshot2.activePageIndex === cachedNavigation.snapshot.activePageIndex && snapshot2.activeSectionIndex === cachedNavigation.snapshot.activeSectionIndex) {
71413
71814
  cachedNavigation = {
71414
71815
  document: nextState.document,
71415
- activeStoryKey,
71816
+ activeStoryKey: activeStoryKey2,
71416
71817
  workspaceMode: viewState.workspaceMode,
71417
71818
  zoomLevel: viewState.zoomLevel,
71418
71819
  selectionHead: nextState.selection.head,
@@ -71422,7 +71823,7 @@ function createDocumentRuntime(options) {
71422
71823
  }
71423
71824
  cachedNavigation = {
71424
71825
  document: nextState.document,
71425
- activeStoryKey,
71826
+ activeStoryKey: activeStoryKey2,
71426
71827
  workspaceMode: viewState.workspaceMode,
71427
71828
  zoomLevel: viewState.zoomLevel,
71428
71829
  selectionHead: nextState.selection.head,
@@ -71435,7 +71836,7 @@ function createDocumentRuntime(options) {
71435
71836
  incrementInvalidationCounter("runtime.snapshot.navigationMisses");
71436
71837
  cachedNavigation = {
71437
71838
  document: nextState.document,
71438
- activeStoryKey,
71839
+ activeStoryKey: activeStoryKey2,
71439
71840
  workspaceMode: viewState.workspaceMode,
71440
71841
  zoomLevel: viewState.zoomLevel,
71441
71842
  selectionHead: nextState.selection.head,
@@ -71453,18 +71854,18 @@ function createDocumentRuntime(options) {
71453
71854
  return storyTargetKey(nextActiveStory);
71454
71855
  }
71455
71856
  function getCachedPageLayoutSnapshot(nextState, nextActiveStory) {
71456
- const activeStoryKey = storyTargetKey(nextActiveStory);
71857
+ const activeStoryKey2 = storyTargetKey(nextActiveStory);
71457
71858
  const activeSectionIndex = resolvePageLayoutActiveSectionIndex(
71458
71859
  nextState,
71459
71860
  nextActiveStory
71460
71861
  );
71461
- if (cachedPageLayout && cachedPageLayout.revisionToken === nextState.revisionToken && cachedPageLayout.activeStoryKey === activeStoryKey && cachedPageLayout.activeSectionIndex === activeSectionIndex) {
71862
+ if (cachedPageLayout && cachedPageLayout.revisionToken === nextState.revisionToken && cachedPageLayout.activeStoryKey === activeStoryKey2 && cachedPageLayout.activeSectionIndex === activeSectionIndex) {
71462
71863
  return cachedPageLayout.snapshot;
71463
71864
  }
71464
71865
  const snapshot = derivePageLayoutSnapshot(nextState, nextActiveStory, storySelections);
71465
71866
  cachedPageLayout = {
71466
71867
  revisionToken: nextState.revisionToken,
71467
- activeStoryKey,
71868
+ activeStoryKey: activeStoryKey2,
71468
71869
  activeSectionIndex,
71469
71870
  snapshot
71470
71871
  };
@@ -71534,8 +71935,8 @@ function createDocumentRuntime(options) {
71534
71935
  if (activeStory.kind === "main") {
71535
71936
  return surface.blocks;
71536
71937
  }
71537
- const activeStoryKey = storyTargetKey(activeStory);
71538
- return surface.secondaryStories.find((story) => storyTargetKey(story.target) === activeStoryKey)?.blocks ?? null;
71938
+ const activeStoryKey2 = storyTargetKey(activeStory);
71939
+ return surface.secondaryStories.find((story) => storyTargetKey(story.target) === activeStoryKey2)?.blocks ?? null;
71539
71940
  }
71540
71941
  function findSurfaceOpaqueTargetIntersectingRange(blocks, range) {
71541
71942
  for (const block of blocks) {
@@ -71691,6 +72092,7 @@ function createDocumentRuntime(options) {
71691
72092
  deriveOpaqueWorkflowBlockedReason,
71692
72093
  isBlockedByProtection,
71693
72094
  dispatch: (command) => dispatchToRuntime(command),
72095
+ runInRuntimeBatch: runRuntimeNotificationBatch,
71694
72096
  emitEvent: (event) => emit2(event),
71695
72097
  editorStateChannel,
71696
72098
  suggestingUnsupportedCommands: SUGGESTING_UNSUPPORTED_COMMANDS
@@ -71710,12 +72112,12 @@ function createDocumentRuntime(options) {
71710
72112
  };
71711
72113
  }
71712
72114
  function getCachedRuntimeContextAnalytics(query) {
71713
- const activeStoryKey = storyTargetKey(activeStory);
72115
+ const activeStoryKey2 = storyTargetKey(activeStory);
71714
72116
  const queryKey = getRuntimeContextAnalyticsQueryKey(query);
71715
72117
  const cachedEntry = cachedContextAnalyticsSnapshots.get(queryKey);
71716
72118
  const effectiveScopeKind = query?.scopeKind ?? "selection";
71717
72119
  const selectionCacheKey = effectiveScopeKind === "selection" ? state.selection : null;
71718
- if (cachedEntry && cachedEntry.revisionToken === state.revisionToken && cachedEntry.activeStoryKey === activeStoryKey && cachedEntry.selection === selectionCacheKey && cachedEntry.readOnly === state.readOnly && cachedEntry.documentMode === viewState.documentMode && cachedEntry.workflowOverlay === overlayStore.getOverlay() && cachedEntry.protectionSnapshot === protectionSnapshot && cachedEntry.warnings === state.warnings && cachedEntry.fatalError === state.fatalError) {
72120
+ if (cachedEntry && cachedEntry.revisionToken === state.revisionToken && cachedEntry.activeStoryKey === activeStoryKey2 && cachedEntry.selection === selectionCacheKey && cachedEntry.readOnly === state.readOnly && cachedEntry.documentMode === viewState.documentMode && cachedEntry.workflowOverlay === overlayStore.getOverlay() && cachedEntry.protectionSnapshot === protectionSnapshot && cachedEntry.warnings === state.warnings && cachedEntry.fatalError === state.fatalError) {
71719
72121
  return cachedEntry.snapshot;
71720
72122
  }
71721
72123
  const tWf = performance.now();
@@ -71772,7 +72174,7 @@ function createDocumentRuntime(options) {
71772
72174
  perfCounters.increment("ctxa.build.us", Math.round((performance.now() - tBuild) * 1e3));
71773
72175
  cachedContextAnalyticsSnapshots.set(queryKey, {
71774
72176
  revisionToken: state.revisionToken,
71775
- activeStoryKey,
72177
+ activeStoryKey: activeStoryKey2,
71776
72178
  // L7 Phase 1.6: store the selectionCacheKey we tested against, so the
71777
72179
  // same scopeKind invariant applies to future reads.
71778
72180
  selection: selectionCacheKey,
@@ -71970,7 +72372,7 @@ function createDocumentRuntime(options) {
71970
72372
  }
71971
72373
  let cachedSurfaceFingerprint = null;
71972
72374
  function refreshSurfaceOnly(options2 = {}) {
71973
- const activeStoryKey = storyTargetKey(activeStory);
72375
+ const activeStoryKey2 = storyTargetKey(activeStory);
71974
72376
  if (options2.forceProjection) {
71975
72377
  cachedFullSurface = void 0;
71976
72378
  }
@@ -71987,7 +72389,7 @@ function createDocumentRuntime(options) {
71987
72389
  viewportBlockRanges,
71988
72390
  editableTargetsByBlockPath: getEditableTargetsByBlockPathForRanges(
71989
72391
  state.document,
71990
- activeStoryKey,
72392
+ activeStoryKey2,
71991
72393
  viewportBlockRanges
71992
72394
  ),
71993
72395
  paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(
@@ -72017,7 +72419,7 @@ function createDocumentRuntime(options) {
72017
72419
  preservation: state.document.preservation,
72018
72420
  review: state.document.review,
72019
72421
  effectiveMarkupModeProvider,
72020
- activeStoryKey,
72422
+ activeStoryKey: activeStoryKey2,
72021
72423
  snapshot: newSurface
72022
72424
  };
72023
72425
  }
@@ -72032,7 +72434,7 @@ function createDocumentRuntime(options) {
72032
72434
  preservation: state.document.preservation,
72033
72435
  review: state.document.review,
72034
72436
  effectiveMarkupModeProvider,
72035
- activeStoryKey,
72437
+ activeStoryKey: activeStoryKey2,
72036
72438
  viewportRangesKey,
72037
72439
  snapshot: newSurface
72038
72440
  };
@@ -72040,9 +72442,7 @@ function createDocumentRuntime(options) {
72040
72442
  ...cachedRenderSnapshot,
72041
72443
  surface: newSurface
72042
72444
  };
72043
- for (const listener of listeners) {
72044
- listener();
72045
- }
72445
+ notifyRuntimeListeners();
72046
72446
  }
72047
72447
  function maybeRefreshSurfaceForViewport() {
72048
72448
  const fingerprint = `${storyTargetKey(activeStory)}|${viewportRangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
@@ -72093,10 +72493,10 @@ function createDocumentRuntime(options) {
72093
72493
  return true;
72094
72494
  }
72095
72495
  function getCachedViewStateSnapshot() {
72096
- const activeStoryKey = storyTargetKey(activeStory);
72496
+ const activeStoryKey2 = storyTargetKey(activeStory);
72097
72497
  const surface = cachedRenderSnapshot.surface;
72098
72498
  const pageLayout = cachedRenderSnapshot.pageLayout;
72099
- if (cachedViewStateSnapshot && cachedViewStateSnapshot.activeStoryKey === activeStoryKey && cachedViewStateSnapshot.selection === state.selection && cachedViewStateSnapshot.viewStateRef === viewState && cachedViewStateSnapshot.surface === surface && cachedViewStateSnapshot.pageLayout === pageLayout && cachedViewStateSnapshot.numbering === state.document.numbering) {
72499
+ if (cachedViewStateSnapshot && cachedViewStateSnapshot.activeStoryKey === activeStoryKey2 && cachedViewStateSnapshot.selection === state.selection && cachedViewStateSnapshot.viewStateRef === viewState && cachedViewStateSnapshot.surface === surface && cachedViewStateSnapshot.pageLayout === pageLayout && cachedViewStateSnapshot.numbering === state.document.numbering) {
72100
72500
  return cachedViewStateSnapshot.snapshot;
72101
72501
  }
72102
72502
  const mainSurface = activeStory.kind === "main" ? surface : getCachedSurface(state.document, MAIN_STORY_TARGET);
@@ -72110,7 +72510,7 @@ function createDocumentRuntime(options) {
72110
72510
  state.document.numbering
72111
72511
  );
72112
72512
  cachedViewStateSnapshot = {
72113
- activeStoryKey,
72513
+ activeStoryKey: activeStoryKey2,
72114
72514
  selection: state.selection,
72115
72515
  viewStateRef: viewState,
72116
72516
  surface,
@@ -72644,6 +73044,17 @@ function createDocumentRuntime(options) {
72644
73044
  };
72645
73045
  resolvedReplayTextTarget = prepared.textTarget;
72646
73046
  } else {
73047
+ const listBoundaryJoinCommand = createListItemBoundaryJoinReplayCommand({
73048
+ command,
73049
+ document: replayState.document,
73050
+ selection: replayState.selection,
73051
+ surface: replaySnapshot.surface?.blocks ?? [],
73052
+ storyTarget: replayStory,
73053
+ timestamp: context.timestamp
73054
+ });
73055
+ if (listBoundaryJoinCommand) {
73056
+ executableCommand = listBoundaryJoinCommand;
73057
+ }
72647
73058
  const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
72648
73059
  command,
72649
73060
  document: replayState.document,
@@ -72801,6 +73212,17 @@ function createDocumentRuntime(options) {
72801
73212
  };
72802
73213
  resolvedReplayTextTarget = prepared.textTarget;
72803
73214
  } else {
73215
+ const listBoundaryJoinCommand = createListItemBoundaryJoinReplayCommand({
73216
+ command,
73217
+ document: stateForCommand.document,
73218
+ selection: stateForCommand.selection,
73219
+ surface: snapshotForCommand.surface?.blocks ?? [],
73220
+ storyTarget: replayStory,
73221
+ timestamp: context.timestamp
73222
+ });
73223
+ if (listBoundaryJoinCommand) {
73224
+ executableCommand = listBoundaryJoinCommand;
73225
+ }
72804
73226
  const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
72805
73227
  command,
72806
73228
  document: stateForCommand.document,
@@ -73110,8 +73532,8 @@ function createDocumentRuntime(options) {
73110
73532
  applyScopeReplacement(plan) {
73111
73533
  const resolveEditableTargetHint = (hint) => {
73112
73534
  if (!hint) return void 0;
73113
- const activeStoryKey = storyTargetKey(activeStory);
73114
- if (hint.storyKey !== activeStoryKey) return null;
73535
+ const activeStoryKey2 = storyTargetKey(activeStory);
73536
+ if (hint.storyKey !== activeStoryKey2) return null;
73115
73537
  const currentTargets = collectEditableTargetRefs(
73116
73538
  state.document,
73117
73539
  editableTargetBlockCache
@@ -73130,7 +73552,7 @@ function createDocumentRuntime(options) {
73130
73552
  document: state.document,
73131
73553
  surface: cachedRenderSnapshot.surface?.blocks ?? [],
73132
73554
  target,
73133
- activeStoryKey,
73555
+ activeStoryKey: activeStoryKey2,
73134
73556
  editableTargetCache: editableTargetBlockCache
73135
73557
  });
73136
73558
  if (resolved.kind === "rejected") {
@@ -73830,6 +74252,9 @@ function createDocumentRuntime(options) {
73830
74252
  addScope(params) {
73831
74253
  return workflowCoordinator.addScope(params);
73832
74254
  },
74255
+ addScopes(params) {
74256
+ return workflowCoordinator.addScopes(params);
74257
+ },
73833
74258
  getScope(scopeId) {
73834
74259
  return workflowCoordinator.getScope(scopeId);
73835
74260
  },
@@ -74813,6 +75238,9 @@ function createDocumentRuntime(options) {
74813
75238
  if (transaction.mapping.metadata?.scopeTagTouches) return false;
74814
75239
  return getLocalTextPatchMetadata(transaction.mapping) !== null;
74815
75240
  }
75241
+ function isLayoutNeutralScopeMarkerCommit(previous, next, transaction) {
75242
+ return transaction.markDirty && previous.document !== next.document && transaction.mapping.steps.length === 0 && transaction.mapping.metadata?.layoutNeutralScopeMarkers === true;
75243
+ }
74816
75244
  function applyTransactionToState(transaction, options2 = {}) {
74817
75245
  const effects = transaction.effects;
74818
75246
  const selectionUnchanged = transaction.nextState.selection === state.selection;
@@ -74841,6 +75269,11 @@ function createDocumentRuntime(options) {
74841
75269
  transaction,
74842
75270
  transaction.effects
74843
75271
  );
75272
+ const layoutNeutralScopeMarkerCommit = isLayoutNeutralScopeMarkerCommit(
75273
+ previous,
75274
+ state,
75275
+ transaction
75276
+ );
74844
75277
  perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
74845
75278
  const tOverlay0 = performance.now();
74846
75279
  const skipOverlaySync = useLocalTextCommitSnapshot && canSkipOverlaySyncForLocalText(transaction);
@@ -74889,9 +75322,12 @@ function createDocumentRuntime(options) {
74889
75322
  ...detachedWorkflowScopeWarnings.cleared
74890
75323
  ]
74891
75324
  };
74892
- if (!useLocalTextCommitSnapshot && transaction.markDirty && previous.document !== state.document) {
75325
+ if (!useLocalTextCommitSnapshot && !layoutNeutralScopeMarkerCommit && transaction.markDirty && previous.document !== state.document) {
74893
75326
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
74894
75327
  }
75328
+ if (layoutNeutralScopeMarkerCommit && viewportBlockRanges !== null) {
75329
+ getCachedFullSurface(state.document, activeStory);
75330
+ }
74895
75331
  const tValidation0 = performance.now();
74896
75332
  const patchSourceSurface = getReusableCachedFullSurface(previous.document, activeStory) ?? cachedRenderSnapshot.surface;
74897
75333
  const patchedFullLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(patchSourceSurface, transaction.mapping) : null;
@@ -75139,9 +75575,7 @@ function createDocumentRuntime(options) {
75139
75575
  code: cleared.code
75140
75576
  });
75141
75577
  }
75142
- for (const listener of listeners) {
75143
- listener();
75144
- }
75578
+ notifyRuntimeListeners();
75145
75579
  }
75146
75580
  function applyTextCommandInActiveStory(command, textOptions = {}) {
75147
75581
  emitStageToken(telemetryBus, "command", "command.dispatch.start", {
@@ -75260,6 +75694,39 @@ function createDocumentRuntime(options) {
75260
75694
  const preSelection = selection;
75261
75695
  const preActiveStory = activeStory;
75262
75696
  const priorDocument = state.document;
75697
+ const listBoundaryJoin = createListItemBoundaryJoinReplacement({
75698
+ command: commandForDispatch,
75699
+ document: state.document,
75700
+ editableTarget,
75701
+ selection,
75702
+ storyTarget: activeStory,
75703
+ targetResolution,
75704
+ timestamp
75705
+ });
75706
+ if (listBoundaryJoin && context.documentMode !== "suggesting") {
75707
+ const replacementCommand = {
75708
+ type: "document.replace",
75709
+ document: listBoundaryJoin.document,
75710
+ selection: listBoundaryJoin.selection,
75711
+ mapping: listBoundaryJoin.mapping,
75712
+ protectionSelection: selection,
75713
+ origin: commandForDispatch.origin
75714
+ };
75715
+ const transaction = executeEditorCommand(baseState, replacementCommand, context);
75716
+ commit(transaction);
75717
+ options.onCommandApplied?.(commandForDispatch, transaction, context, {
75718
+ preSelection,
75719
+ activeStory: preActiveStory,
75720
+ priorDocument
75721
+ });
75722
+ return completeDispatch(classifyAck({
75723
+ command: commandForDispatch,
75724
+ opId,
75725
+ priorState: baseState,
75726
+ transaction,
75727
+ newRevisionToken: state.revisionToken
75728
+ }));
75729
+ }
75263
75730
  const selectedListItemDelete = createSelectedListItemDeleteReplacement({
75264
75731
  command: commandForDispatch,
75265
75732
  document: state.document,
@@ -75701,7 +76168,7 @@ function createDocumentRuntime(options) {
75701
76168
  const warningDelta = workflowCoordinator.applyOverlayCommand(
75702
76169
  command,
75703
76170
  () => {
75704
- cachedRenderSnapshot = refreshRenderSnapshot();
76171
+ requestRuntimeRenderSnapshotRefresh();
75705
76172
  }
75706
76173
  );
75707
76174
  if (warningDelta) {
@@ -75759,11 +76226,69 @@ function createDocumentRuntime(options) {
75759
76226
  });
75760
76227
  }
75761
76228
  }
76229
+ notifyRuntimeListeners();
76230
+ }
76231
+ function runRuntimeNotificationBatch(label, fn) {
76232
+ runtimeNotificationBatchDepth += 1;
76233
+ perfCounters.increment(`runtime.notificationBatch.${label}.calls`);
76234
+ try {
76235
+ return fn();
76236
+ } finally {
76237
+ runtimeNotificationBatchDepth -= 1;
76238
+ if (runtimeNotificationBatchDepth === 0) {
76239
+ flushRuntimeNotificationBatch();
76240
+ }
76241
+ }
76242
+ }
76243
+ function requestRuntimeRenderSnapshotRefresh() {
76244
+ if (runtimeNotificationBatchDepth > 0) {
76245
+ pendingRenderSnapshotRefresh = true;
76246
+ perfCounters.increment("runtime.notificationBatch.renderRefreshDeferred");
76247
+ return;
76248
+ }
76249
+ cachedRenderSnapshot = refreshRenderSnapshot();
76250
+ }
76251
+ function notifyRuntimeListeners() {
76252
+ if (runtimeNotificationBatchDepth > 0) {
76253
+ pendingRuntimeListenerNotify = true;
76254
+ perfCounters.increment("runtime.notificationBatch.listenerNotifyDeferred");
76255
+ return;
76256
+ }
76257
+ notifyRuntimeListenersNow();
76258
+ }
76259
+ function notifyRuntimeListenersNow() {
75762
76260
  for (const listener of listeners) {
75763
76261
  listener();
75764
76262
  }
75765
76263
  }
76264
+ function flushRuntimeNotificationBatch() {
76265
+ if (pendingRenderSnapshotRefresh) {
76266
+ pendingRenderSnapshotRefresh = false;
76267
+ cachedRenderSnapshot = refreshRenderSnapshot();
76268
+ perfCounters.increment("runtime.notificationBatch.renderRefreshFlushed");
76269
+ }
76270
+ if (pendingRuntimeEvents.length > 0) {
76271
+ const queuedEvents = pendingRuntimeEvents.splice(0);
76272
+ perfCounters.increment("runtime.notificationBatch.eventsFlushed", queuedEvents.length);
76273
+ for (const event of queuedEvents) {
76274
+ emitInternalNow(event);
76275
+ }
76276
+ }
76277
+ if (pendingRuntimeListenerNotify) {
76278
+ pendingRuntimeListenerNotify = false;
76279
+ perfCounters.increment("runtime.notificationBatch.listenerNotifyFlushed");
76280
+ notifyRuntimeListenersNow();
76281
+ }
76282
+ }
75766
76283
  function emitInternal(event) {
76284
+ if (runtimeNotificationBatchDepth > 0) {
76285
+ pendingRuntimeEvents.push(event);
76286
+ perfCounters.increment("runtime.notificationBatch.eventsQueued");
76287
+ return;
76288
+ }
76289
+ emitInternalNow(event);
76290
+ }
76291
+ function emitInternalNow(event) {
75767
76292
  options.onEvent?.(event);
75768
76293
  for (const listener of eventListeners) {
75769
76294
  listener(event);
@@ -78167,6 +78692,56 @@ function stripStoryTarget2(selection) {
78167
78692
  function isTopLevelMainStoryBlockPath(blockPath) {
78168
78693
  return typeof blockPath === "string" && /^main\/block\[\d+\]$/u.test(blockPath);
78169
78694
  }
78695
+ function createListItemBoundaryJoinReplacement(input) {
78696
+ const { command, document: document2, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
78697
+ const direction = listItemBoundaryJoinDirection(command, selection, targetResolution);
78698
+ if (!direction || editableTarget?.listAddress?.operationScope !== "list-text" || targetResolution?.kind !== "accepted") {
78699
+ return null;
78700
+ }
78701
+ const storyBlocks = getStoryBlocks(document2, storyTarget);
78702
+ const replacement = joinNumberedParagraphAtStoryPath(
78703
+ storyBlocks,
78704
+ editableTarget.blockPath,
78705
+ storyTarget,
78706
+ direction
78707
+ );
78708
+ if (!replacement) {
78709
+ return null;
78710
+ }
78711
+ const nextDocument = replaceStoryBlocks({
78712
+ ...document2,
78713
+ updatedAt: timestamp
78714
+ }, storyTarget, replacement.blocks);
78715
+ const deletedFrom = direction === "backward" ? Math.max(0, selection.anchor - 1) : selection.anchor;
78716
+ const deletedTo = direction === "backward" ? selection.anchor : selection.anchor + 1;
78717
+ const nextAnchor = direction === "backward" ? deletedFrom : selection.anchor;
78718
+ return {
78719
+ document: nextDocument,
78720
+ selection: createSelectionSnapshot(nextAnchor, nextAnchor),
78721
+ mapping: {
78722
+ steps: [{
78723
+ from: deletedFrom,
78724
+ to: deletedTo,
78725
+ insertSize: 0
78726
+ }],
78727
+ metadata: {
78728
+ invalidatesStructures: true
78729
+ }
78730
+ }
78731
+ };
78732
+ }
78733
+ function listItemBoundaryJoinDirection(command, selection, targetResolution) {
78734
+ if (selection.isCollapsed !== true || targetResolution?.kind !== "accepted") {
78735
+ return null;
78736
+ }
78737
+ if (command.type === "text.delete-backward" && selection.anchor === targetResolution.range.from) {
78738
+ return "backward";
78739
+ }
78740
+ if (command.type === "text.delete-forward" && selection.anchor === targetResolution.range.to) {
78741
+ return "forward";
78742
+ }
78743
+ return null;
78744
+ }
78170
78745
  function createSelectedListItemDeleteReplacement(input) {
78171
78746
  const { command, document: document2, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
78172
78747
  if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
@@ -78214,6 +78789,152 @@ function removeNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget) {
78214
78789
  if (!tokens) return null;
78215
78790
  return removeNumberedParagraphFromBlocks(blocks, tokens);
78216
78791
  }
78792
+ function joinNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget, direction) {
78793
+ const tokens = parseStoryBlockPathTokens(blockPath, storyTarget);
78794
+ if (!tokens) return null;
78795
+ return joinNumberedParagraphFromBlocks(blocks, tokens, direction);
78796
+ }
78797
+ function joinNumberedParagraphFromBlocks(blocks, tokens, direction) {
78798
+ const [token, ...rest] = tokens;
78799
+ if (!token || token.kind !== "block") return null;
78800
+ const block = blocks[token.index];
78801
+ if (!block) return null;
78802
+ if (rest.length === 0) {
78803
+ return joinAdjacentNumberedParagraphs(blocks, token.index, direction);
78804
+ }
78805
+ const next = rest[0];
78806
+ if (block.type === "table" && next?.kind === "row") {
78807
+ const updatedTable = joinNumberedParagraphInTable(block, rest, direction);
78808
+ if (!updatedTable) return null;
78809
+ return {
78810
+ blocks: [
78811
+ ...blocks.slice(0, token.index),
78812
+ updatedTable,
78813
+ ...blocks.slice(token.index + 1)
78814
+ ]
78815
+ };
78816
+ }
78817
+ if ((block.type === "sdt" || block.type === "custom_xml") && next?.kind === "block") {
78818
+ const updatedChildren = joinNumberedParagraphFromBlocks(block.children, rest, direction);
78819
+ if (!updatedChildren) return null;
78820
+ return {
78821
+ blocks: [
78822
+ ...blocks.slice(0, token.index),
78823
+ { ...block, children: updatedChildren.blocks },
78824
+ ...blocks.slice(token.index + 1)
78825
+ ]
78826
+ };
78827
+ }
78828
+ if (block.type === "paragraph" && next?.kind === "inline") {
78829
+ const updatedParagraph = joinNumberedParagraphInTextBoxInline(block, rest, direction);
78830
+ if (!updatedParagraph) return null;
78831
+ return {
78832
+ blocks: [
78833
+ ...blocks.slice(0, token.index),
78834
+ updatedParagraph,
78835
+ ...blocks.slice(token.index + 1)
78836
+ ]
78837
+ };
78838
+ }
78839
+ return null;
78840
+ }
78841
+ function joinAdjacentNumberedParagraphs(blocks, targetIndex, direction) {
78842
+ const target = blocks[targetIndex];
78843
+ if (target?.type !== "paragraph" || !target.numbering) {
78844
+ return null;
78845
+ }
78846
+ if (direction === "backward") {
78847
+ const previousIndex = targetIndex - 1;
78848
+ const previous = blocks[previousIndex];
78849
+ if (previous?.type !== "paragraph" || !previous.numbering) {
78850
+ return null;
78851
+ }
78852
+ const merged2 = {
78853
+ ...previous,
78854
+ children: [...previous.children, ...target.children]
78855
+ };
78856
+ return {
78857
+ blocks: [
78858
+ ...blocks.slice(0, previousIndex),
78859
+ merged2,
78860
+ ...blocks.slice(targetIndex + 1)
78861
+ ]
78862
+ };
78863
+ }
78864
+ const nextIndex = targetIndex + 1;
78865
+ const next = blocks[nextIndex];
78866
+ if (next?.type !== "paragraph" || !next.numbering) {
78867
+ return null;
78868
+ }
78869
+ const merged = {
78870
+ ...target,
78871
+ children: [...target.children, ...next.children]
78872
+ };
78873
+ return {
78874
+ blocks: [
78875
+ ...blocks.slice(0, targetIndex),
78876
+ merged,
78877
+ ...blocks.slice(nextIndex + 1)
78878
+ ]
78879
+ };
78880
+ }
78881
+ function joinNumberedParagraphInTable(table, tokens, direction) {
78882
+ const [rowToken, cellToken, ...childTokens] = tokens;
78883
+ if (rowToken?.kind !== "row" || cellToken?.kind !== "cell" || childTokens[0]?.kind !== "block") {
78884
+ return null;
78885
+ }
78886
+ const row2 = table.rows[rowToken.index];
78887
+ const cell = row2?.cells[cellToken.index];
78888
+ if (!row2 || !cell) return null;
78889
+ const updatedChildren = joinNumberedParagraphFromBlocks(cell.children, childTokens, direction);
78890
+ if (!updatedChildren) return null;
78891
+ const nextCells = [
78892
+ ...row2.cells.slice(0, cellToken.index),
78893
+ { ...cell, children: updatedChildren.blocks },
78894
+ ...row2.cells.slice(cellToken.index + 1)
78895
+ ];
78896
+ const nextRows = [
78897
+ ...table.rows.slice(0, rowToken.index),
78898
+ { ...row2, cells: nextCells },
78899
+ ...table.rows.slice(rowToken.index + 1)
78900
+ ];
78901
+ return { ...table, rows: nextRows };
78902
+ }
78903
+ function joinNumberedParagraphInTextBoxInline(paragraph, tokens, direction) {
78904
+ const [inlineToken, textBoxToken, ...childTokens] = tokens;
78905
+ if (inlineToken?.kind !== "inline" || textBoxToken?.kind !== "txbx" || childTokens[0]?.kind !== "block") {
78906
+ return null;
78907
+ }
78908
+ const inline = paragraph.children[inlineToken.index];
78909
+ if (!inline) return null;
78910
+ const updatedInline = joinNumberedParagraphInInlineTextBox(inline, childTokens, direction);
78911
+ if (!updatedInline) return null;
78912
+ return {
78913
+ ...paragraph,
78914
+ children: [
78915
+ ...paragraph.children.slice(0, inlineToken.index),
78916
+ updatedInline,
78917
+ ...paragraph.children.slice(inlineToken.index + 1)
78918
+ ]
78919
+ };
78920
+ }
78921
+ function joinNumberedParagraphInInlineTextBox(inline, tokens, direction) {
78922
+ if (inline.type === "shape" && inline.txbxBlocks) {
78923
+ const updatedBlocks = joinNumberedParagraphFromBlocks(inline.txbxBlocks, tokens, direction);
78924
+ return updatedBlocks ? { ...inline, txbxBlocks: updatedBlocks.blocks } : null;
78925
+ }
78926
+ if (inline.type === "drawing_frame" && inline.content.type === "shape" && inline.content.txbxBlocks) {
78927
+ const updatedBlocks = joinNumberedParagraphFromBlocks(inline.content.txbxBlocks, tokens, direction);
78928
+ return updatedBlocks ? {
78929
+ ...inline,
78930
+ content: {
78931
+ ...inline.content,
78932
+ txbxBlocks: updatedBlocks.blocks
78933
+ }
78934
+ } : null;
78935
+ }
78936
+ return null;
78937
+ }
78217
78938
  function removeNumberedParagraphFromBlocks(blocks, tokens) {
78218
78939
  const [token, ...rest] = tokens;
78219
78940
  if (!token || token.kind !== "block") return null;
@@ -78376,6 +79097,56 @@ function createSelectedListItemDeleteReplayCommand(input) {
78376
79097
  origin: command.origin
78377
79098
  };
78378
79099
  }
79100
+ function createListItemBoundaryJoinReplayCommand(input) {
79101
+ const { command, document: document2, selection, surface, storyTarget, timestamp } = input;
79102
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
79103
+ return null;
79104
+ }
79105
+ const editableTarget = command.editableTarget;
79106
+ if (!editableTarget) {
79107
+ return null;
79108
+ }
79109
+ const targetResolution = resolveEditableTextTarget({
79110
+ document: document2,
79111
+ selection,
79112
+ surface,
79113
+ target: editableTarget,
79114
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
79115
+ });
79116
+ const resolvedEditableTarget = targetResolution.kind === "accepted" ? editableTarget : storyTarget.kind !== "main" && blockPathBelongsToStoryTarget(editableTarget.blockPath, storyTarget) ? resolveEditableCommandTarget({
79117
+ document: document2,
79118
+ target: editableTarget,
79119
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
79120
+ commandFamilies: ["text-leaf"]
79121
+ }) : null;
79122
+ const selectedRange = {
79123
+ from: Math.min(selection.anchor, selection.head),
79124
+ to: Math.max(selection.anchor, selection.head)
79125
+ };
79126
+ const replacement = createListItemBoundaryJoinReplacement({
79127
+ command,
79128
+ document: document2,
79129
+ editableTarget: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? resolvedEditableTarget.target : editableTarget,
79130
+ selection,
79131
+ storyTarget,
79132
+ targetResolution: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? {
79133
+ kind: "accepted",
79134
+ range: selectedRange
79135
+ } : targetResolution,
79136
+ timestamp
79137
+ });
79138
+ if (!replacement) {
79139
+ return null;
79140
+ }
79141
+ return {
79142
+ type: "document.replace",
79143
+ document: replacement.document,
79144
+ selection: replacement.selection,
79145
+ mapping: replacement.mapping,
79146
+ protectionSelection: selection,
79147
+ origin: command.origin
79148
+ };
79149
+ }
78379
79150
  function parseStoryBlockPathTokens(blockPath, storyTarget) {
78380
79151
  if (!blockPath) {
78381
79152
  return null;
@@ -94542,6 +95313,9 @@ function createLoadingRuntimeBridge(input) {
94542
95313
  addScope: () => {
94543
95314
  throw createLoadingBoundaryError(input.snapshot.documentId, "scope");
94544
95315
  },
95316
+ addScopes: () => {
95317
+ throw createLoadingBoundaryError(input.snapshot.documentId, "scope");
95318
+ },
94545
95319
  getScope: () => null,
94546
95320
  compileScopeBundleById: () => null,
94547
95321
  compileScopeList: () => [],
@@ -126809,7 +127583,8 @@ var LAYER_DEBUG_PANES = [
126809
127583
  snippets: [
126810
127584
  { label: "Selection context", expression: "ref?.getRuntimeContextAnalytics?.()" },
126811
127585
  { label: "Document context", expression: "ref?.getRuntimeContextAnalytics?.({ scopeKind: 'document' })" },
126812
- { label: "Hot edit trace", expression: "runtime?.debug?.getHotEditTraces?.().at(-1)" },
127586
+ { label: "API families", expression: "api ? Object.keys(api).sort() : null" },
127587
+ { label: "Hot edit trace", expression: "runtime?.debug?.getHotEditTraces?.()?.at(-1)" },
126813
127588
  { label: "View state", expression: "ref?.getViewState?.()" }
126814
127589
  ],
126815
127590
  routed: [
@@ -126823,8 +127598,9 @@ var LAYER_DEBUG_PANES = [
126823
127598
  focus: "Workflow scopes, markup, metadata, candidates, and scope-derived context.",
126824
127599
  snippets: [
126825
127600
  { label: "Scope snapshot", expression: "ref?.getWorkflowScopeSnapshot?.()" },
126826
- { label: "Query scopes", expression: "ref?.queryScopes?.({ includeHidden: true, includeInvisible: true })" },
126827
- { label: "Workflow markup", expression: "ref?.getWorkflowMarkupSnapshot?.()" }
127601
+ { label: "Query scopes", expression: "api?.runtime.workflow.queryScopes({ includeHidden: true, includeInvisible: true, limit: 50 }) ?? ref?.queryScopes?.({ includeHidden: true, includeInvisible: true, limit: 50 })" },
127602
+ { label: "Bulk placeholder scopes", expression: "(() => { const r = api?.ai.actions.createPlaceholderScopes({ limit: 200 }); if (!r) return { status: 'api-unavailable' }; return { status: r.status, totalHits: r.totalHits, created: r.created, blocked: r.blocked, scopeIds: r.scopes.slice(0, 50).map((s) => s.scopeId ?? null), blockers: r.blockers?.slice(0, 20) ?? [] }; })()" },
127603
+ { label: "Workflow markup", expression: "(() => { const m = ref?.getWorkflowMarkupSnapshot?.(); return m ? { itemCount: m.items?.length ?? 0, items: m.items?.slice(0, 50) ?? [] } : m; })()" }
126828
127604
  ],
126829
127605
  routed: [
126830
127606
  "Compiler replacement planning and semantic scope normalization remain Layer 08-owned."
@@ -126838,7 +127614,8 @@ var LAYER_DEBUG_PANES = [
126838
127614
  snippets: [
126839
127615
  { label: "Document analytics", expression: "ref?.getRuntimeContextAnalytics?.({ scopeKind: 'document' })" },
126840
127616
  { label: "Workflow analytics", expression: "ref?.getRuntimeContextAnalytics?.({ scopeKind: 'workflow_scope', scopeId: ref?.getInteractionGuardSnapshot?.()?.matchedScopeId })" },
126841
- { label: "Available scopes", expression: "ref?.queryScopes?.({ includeHidden: true, includeInvisible: true })" }
127617
+ { label: "Available scopes", expression: "api?.ai.listScopes({ limit: 50 }) ?? ref?.queryScopes?.({ includeHidden: true, includeInvisible: true, limit: 50 })" },
127618
+ { label: "Placeholder scope action", expression: "api?.ai.actions.createPlaceholderScopes({ limit: 200 })" }
126842
127619
  ],
126843
127620
  routed: [
126844
127621
  "AI audit references and action policy payloads are Layer 09-owned."
@@ -126866,7 +127643,7 @@ var LAYER_DEBUG_PANES = [
126866
127643
  snippets: [
126867
127644
  { label: "Navigation", expression: "ref?.getDocumentNavigationSnapshot?.()" },
126868
127645
  { label: "Review surface", expression: "({ comments: ref?.getCommentSidebarSnapshot?.(), changes: ref?.getTrackedChangesSnapshot?.() })" },
126869
- { label: "Hot edit traces", expression: "runtime?.debug?.getHotEditTraces?.()" },
127646
+ { label: "Hot edit traces", expression: "runtime?.debug?.getHotEditTraces?.()?.slice?.(-10)" },
126870
127647
  { label: "Compatibility", expression: "ref?.getCompatibilityReport?.()" }
126871
127648
  ],
126872
127649
  routed: [
@@ -126899,6 +127676,11 @@ var import_jsx_runtime83 = require("react/jsx-runtime");
126899
127676
  var MAX_HISTORY = 30;
126900
127677
  var MAX_ENTRIES = 50;
126901
127678
  var MAX_OUTPUT_CHARS = 8e3;
127679
+ var MAX_SERIALIZE_DEPTH = 6;
127680
+ var MAX_SERIALIZE_STRING_CHARS = 1e3;
127681
+ var MAX_SERIALIZE_ARRAY_ITEMS = 40;
127682
+ var MAX_SERIALIZE_OBJECT_KEYS = 80;
127683
+ var MAX_SERIALIZE_NODES = 2500;
126902
127684
  var HISTORY_STORAGE_KEY = "wre-runtime-repl-history";
126903
127685
  var HISTORY_STORAGE_VERSION = 1;
126904
127686
  function TwRuntimeReplDialog(props) {
@@ -126996,10 +127778,12 @@ function TwRuntimeReplDialog(props) {
126996
127778
  return;
126997
127779
  }
126998
127780
  try {
127781
+ const refValue = editorRef?.current ?? null;
126999
127782
  const value = await evaluateReplExpression(
127000
127783
  code,
127001
127784
  runtime,
127002
- editorRef?.current ?? null
127785
+ refValue,
127786
+ resolveReplApi(refValue)
127003
127787
  );
127004
127788
  pushEntry({
127005
127789
  input: code,
@@ -127104,9 +127888,10 @@ function TwRuntimeReplDialog(props) {
127104
127888
  "evaluates against ",
127105
127889
  /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: "runtime" }),
127106
127890
  editorRef ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
127107
- " ",
127108
- "and ",
127109
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: "ref" })
127891
+ ", ",
127892
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: "ref" }),
127893
+ ", and ",
127894
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: "api" })
127110
127895
  ] }) : null
127111
127896
  ] })
127112
127897
  ] }),
@@ -127253,10 +128038,10 @@ function TwRuntimeReplDialog(props) {
127253
128038
  "data-testid": "tw-runtime-repl__output",
127254
128039
  children: entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("p", { className: "text-[var(--color-text-tertiary)]", children: [
127255
128040
  "Evaluate JavaScript against the active runtime",
127256
- editorRef ? " and editor ref" : "",
128041
+ editorRef ? ", editor ref, and API" : "",
127257
128042
  ". Example:",
127258
128043
  " ",
127259
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: editorRef ? "ref.getRenderSnapshot().surface?.blocks.length" : "runtime.getRenderSnapshot().surface?.blocks.length" })
128044
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: editorRef ? "api.ai.listScopes({ limit: 5 })" : "runtime.getRenderSnapshot().surface?.blocks.length" })
127260
128045
  ] }) : entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "mb-3 last:mb-0", children: [
127261
128046
  /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-start gap-2", children: [
127262
128047
  /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
@@ -127306,7 +128091,7 @@ function TwRuntimeReplDialog(props) {
127306
128091
  onKeyDown: handleKeyDown,
127307
128092
  rows: 3,
127308
128093
  spellCheck: false,
127309
- placeholder: editorRef ? "ref.getRenderSnapshot().selection" : "runtime.getRenderSnapshot().selection",
128094
+ placeholder: editorRef ? "api.runtime.workflow.queryScopes({ limit: 10 })" : "runtime.getRenderSnapshot().selection",
127310
128095
  className: [
127311
128096
  "w-full resize-y rounded-[var(--radius-sm)] bg-[var(--color-bg-muted)]",
127312
128097
  "px-3 py-2 font-mono text-xs leading-relaxed",
@@ -127339,12 +128124,13 @@ function isReplToggleShortcut(event) {
127339
128124
  if (event.shiftKey) return false;
127340
128125
  return event.metaKey || event.ctrlKey;
127341
128126
  }
127342
- async function evaluateReplExpression(code, runtime, ref = null) {
128127
+ async function evaluateReplExpression(code, runtime, ref = null, api = resolveReplApi(ref)) {
127343
128128
  let fn = null;
127344
128129
  try {
127345
128130
  fn = new Function(
127346
128131
  "runtime",
127347
128132
  "ref",
128133
+ "api",
127348
128134
  `return (async () => { return (${code}); })();`
127349
128135
  );
127350
128136
  } catch (exprError) {
@@ -127354,17 +128140,22 @@ async function evaluateReplExpression(code, runtime, ref = null) {
127354
128140
  fn = new Function(
127355
128141
  "runtime",
127356
128142
  "ref",
128143
+ "api",
127357
128144
  `return (async () => { ${code}
127358
128145
  })();`
127359
128146
  );
127360
128147
  }
127361
- return await fn(runtime, ref);
128148
+ return await fn(runtime, ref, api);
128149
+ }
128150
+ function resolveReplApi(ref) {
128151
+ if (!ref || typeof ref.getApiV3 !== "function") return null;
128152
+ return ref.getApiV3();
127362
128153
  }
127363
128154
  function formatReplValue(value) {
127364
128155
  if (value === void 0) return "undefined";
127365
128156
  if (value === null) return "null";
127366
128157
  const type = typeof value;
127367
- if (type === "string") return JSON.stringify(value);
128158
+ if (type === "string") return truncate2(JSON.stringify(value), MAX_OUTPUT_CHARS);
127368
128159
  if (type === "number" || type === "boolean" || type === "bigint") {
127369
128160
  return String(value);
127370
128161
  }
@@ -127374,7 +128165,7 @@ function formatReplValue(value) {
127374
128165
  return `[Function${fn.name ? `: ${fn.name}` : ""}]`;
127375
128166
  }
127376
128167
  try {
127377
- const serialized = JSON.stringify(value, createCircularReplacer(), 2);
128168
+ const serialized = JSON.stringify(createReplPreview(value), null, 2);
127378
128169
  if (serialized === void 0) {
127379
128170
  return String(value);
127380
128171
  }
@@ -127390,21 +128181,113 @@ function formatReplError(error) {
127390
128181
  }
127391
128182
  return truncate2(String(error), MAX_OUTPUT_CHARS);
127392
128183
  }
127393
- function createCircularReplacer() {
127394
- const seen = /* @__PURE__ */ new WeakSet();
127395
- return function replacer(_key, value) {
127396
- if (typeof value === "bigint") return `${value.toString()}n`;
127397
- if (typeof value === "function") {
127398
- const fn = value;
127399
- return `[Function${fn.name ? `: ${fn.name}` : ""}]`;
128184
+ function createReplPreview(value) {
128185
+ return createReplPreviewValue(value, 0, {
128186
+ seen: /* @__PURE__ */ new WeakSet(),
128187
+ nodes: 0
128188
+ });
128189
+ }
128190
+ function createReplPreviewValue(value, depth, state) {
128191
+ if (value === null || typeof value === "number" || typeof value === "boolean") {
128192
+ return value;
128193
+ }
128194
+ if (typeof value === "string") {
128195
+ return value.length > MAX_SERIALIZE_STRING_CHARS ? `${value.slice(0, MAX_SERIALIZE_STRING_CHARS)}... [truncated ${value.length - MAX_SERIALIZE_STRING_CHARS} chars]` : value;
128196
+ }
128197
+ if (typeof value === "bigint") return `${value.toString()}n`;
128198
+ if (typeof value === "symbol") return value.toString();
128199
+ if (typeof value === "function") {
128200
+ const fn = value;
128201
+ return `[Function${fn.name ? `: ${fn.name}` : ""}]`;
128202
+ }
128203
+ if (typeof value !== "object") return String(value);
128204
+ state.nodes += 1;
128205
+ if (state.nodes > MAX_SERIALIZE_NODES) {
128206
+ return "[Max REPL preview nodes reached]";
128207
+ }
128208
+ const objectValue = value;
128209
+ if (state.seen.has(objectValue)) return "[Circular]";
128210
+ state.seen.add(objectValue);
128211
+ if (depth >= MAX_SERIALIZE_DEPTH) {
128212
+ return summarizePreviewBoundary(objectValue);
128213
+ }
128214
+ const domPreview = summarizeDomNode(objectValue);
128215
+ if (domPreview) return domPreview;
128216
+ if (Array.isArray(value)) {
128217
+ const preview = value.slice(0, MAX_SERIALIZE_ARRAY_ITEMS).map((item) => createReplPreviewValue(item, depth + 1, state));
128218
+ if (value.length > MAX_SERIALIZE_ARRAY_ITEMS) {
128219
+ preview.push(`[... ${value.length - MAX_SERIALIZE_ARRAY_ITEMS} more items]`);
127400
128220
  }
127401
- if (typeof value === "symbol") return value.toString();
127402
- if (value !== null && typeof value === "object") {
127403
- if (seen.has(value)) return "[Circular]";
127404
- seen.add(value);
128221
+ return preview;
128222
+ }
128223
+ if (value instanceof Date) {
128224
+ return Number.isNaN(value.getTime()) ? "[Invalid Date]" : value.toISOString();
128225
+ }
128226
+ if (value instanceof Map) {
128227
+ const entries = [];
128228
+ let index = 0;
128229
+ for (const [key, entryValue] of value.entries()) {
128230
+ if (index >= MAX_SERIALIZE_OBJECT_KEYS) {
128231
+ entries.push("[additional map entries omitted]");
128232
+ break;
128233
+ }
128234
+ entries.push([
128235
+ createReplPreviewValue(key, depth + 1, state),
128236
+ createReplPreviewValue(entryValue, depth + 1, state)
128237
+ ]);
128238
+ index += 1;
127405
128239
  }
127406
- return value;
127407
- };
128240
+ return { "[Map]": entries };
128241
+ }
128242
+ if (value instanceof Set) {
128243
+ const entries = [];
128244
+ let index = 0;
128245
+ for (const entryValue of value.values()) {
128246
+ if (index >= MAX_SERIALIZE_OBJECT_KEYS) {
128247
+ entries.push("[additional set entries omitted]");
128248
+ break;
128249
+ }
128250
+ entries.push(createReplPreviewValue(entryValue, depth + 1, state));
128251
+ index += 1;
128252
+ }
128253
+ return { "[Set]": entries };
128254
+ }
128255
+ const output = {};
128256
+ let count = 0;
128257
+ for (const key in value) {
128258
+ if (!Object.prototype.propertyIsEnumerable.call(value, key)) continue;
128259
+ if (count >= MAX_SERIALIZE_OBJECT_KEYS) {
128260
+ output["..."] = "[additional properties omitted]";
128261
+ break;
128262
+ }
128263
+ try {
128264
+ output[key] = createReplPreviewValue(
128265
+ value[key],
128266
+ depth + 1,
128267
+ state
128268
+ );
128269
+ } catch (error) {
128270
+ output[key] = `[unreadable property: ${formatReplError(error)}]`;
128271
+ }
128272
+ count += 1;
128273
+ }
128274
+ return output;
128275
+ }
128276
+ function summarizePreviewBoundary(value) {
128277
+ if (Array.isArray(value)) return `[Array(${value.length}) depth limit]`;
128278
+ const domPreview = summarizeDomNode(value);
128279
+ if (domPreview) return domPreview;
128280
+ const constructorName = value.constructor?.name;
128281
+ return constructorName && constructorName !== "Object" ? `[${constructorName} depth limit]` : "[Object depth limit]";
128282
+ }
128283
+ function summarizeDomNode(value) {
128284
+ const maybeNode = value;
128285
+ if (typeof maybeNode.nodeType !== "number" || typeof maybeNode.nodeName !== "string") {
128286
+ return null;
128287
+ }
128288
+ const id = typeof maybeNode.id === "string" && maybeNode.id.length > 0 ? `#${maybeNode.id}` : "";
128289
+ const className = typeof maybeNode.className === "string" && maybeNode.className.length > 0 ? `.${maybeNode.className.trim().replace(/\s+/g, ".")}` : "";
128290
+ return `[DOM ${maybeNode.nodeName.toLowerCase()}${id}${className}]`;
127408
128291
  }
127409
128292
  function truncate2(text, max) {
127410
128293
  if (text.length <= max) return text;
@@ -128754,9 +129637,23 @@ function findSurfaceBlockById(blocks, blockId) {
128754
129637
  }
128755
129638
  function createScopeFromAnchor(runtime, input) {
128756
129639
  const doc = runtime.getCanonicalDocument();
128757
- const storyTarget = input.anchor.storyTarget ?? { kind: "main" };
129640
+ const normalizedInputAnchor = normalizeCreateScopeAnchor(input.anchor);
129641
+ const storyTarget = normalizedInputAnchor.storyTarget ?? { kind: "main" };
128758
129642
  const storyLength = storyTarget.kind === "main" ? computeMainStoryLength(doc) : Number.MAX_SAFE_INTEGER;
128759
- const { from, to } = input.anchor;
129643
+ const { from, to } = normalizedInputAnchor;
129644
+ if (!Number.isFinite(from) || !Number.isFinite(to)) {
129645
+ const diagnosticFrom = Number.isFinite(from) ? from : 0;
129646
+ const diagnosticTo = Number.isFinite(to) ? to : diagnosticFrom;
129647
+ return {
129648
+ status: "range-invalid",
129649
+ reason: "non-finite-range",
129650
+ from: diagnosticFrom,
129651
+ to: diagnosticTo,
129652
+ storyLength,
129653
+ message: `createScopeFromAnchor requires finite numeric from/to offsets. Pass selection.activeRange or an object shaped as {from, to}; do not pass a malformed range.`,
129654
+ nextStep: "pass-selection-activeRange-or-finite-from-to"
129655
+ };
129656
+ }
128760
129657
  if (from < 0) {
128761
129658
  return {
128762
129659
  status: "range-invalid",
@@ -128854,6 +129751,29 @@ function createScopeFromAnchor(runtime, input) {
128854
129751
  }
128855
129752
  return { status: "created", scopeId: result.scopeId, anchor: result.anchor };
128856
129753
  }
129754
+ function normalizeCreateScopeAnchor(anchor) {
129755
+ const candidate = anchor;
129756
+ const activeRange = candidate.activeRange;
129757
+ if (activeRange?.kind === "range") {
129758
+ return {
129759
+ from: activeRange.from,
129760
+ to: activeRange.to,
129761
+ storyTarget: candidate.storyTarget
129762
+ };
129763
+ }
129764
+ if (candidate.kind === "range") {
129765
+ return {
129766
+ from: candidate.from ?? Number.NaN,
129767
+ to: candidate.to ?? Number.NaN,
129768
+ storyTarget: candidate.storyTarget
129769
+ };
129770
+ }
129771
+ return {
129772
+ from: candidate.from ?? Number.NaN,
129773
+ to: candidate.to ?? Number.NaN,
129774
+ storyTarget: candidate.storyTarget
129775
+ };
129776
+ }
128857
129777
 
128858
129778
  // src/api/v3/runtime/workflow.ts
128859
129779
  var createScopeMetadata = {
@@ -128894,6 +129814,29 @@ var createScopeFromAnchorMetadata = {
128894
129814
  broadcastsVia: "crdt",
128895
129815
  rwdReference: "\xA7Runtime API \xA7 runtime.workflow.createScopeFromAnchor. Companion to createScope({blockId}) for sub-block ranges. Consumes from/to once to plant inline scope_marker_start/end; the returned scopeId is the durable reference (KI-P9)."
128896
129816
  };
129817
+ var createScopesMetadata = {
129818
+ name: "runtime.workflow.createScopes",
129819
+ status: "live-with-adapter",
129820
+ sourceLayer: "workflow-review",
129821
+ liveEvidence: {
129822
+ runnerTest: "test/api/v3/workflow-create-scope-live.test.ts",
129823
+ commit: "pending"
129824
+ },
129825
+ uxIntent: {
129826
+ uiVisible: true,
129827
+ expectsUxResponse: "scope-created",
129828
+ expectedDelta: "rail shows new scope chips; editor surface refreshes once after the bulk scope batch"
129829
+ },
129830
+ agentMetadata: {
129831
+ readOrMutate: "mutate",
129832
+ boundedScope: "selection",
129833
+ auditCategory: "scope-creation"
129834
+ },
129835
+ stateClass: "A-canonical",
129836
+ persistsTo: "customXml",
129837
+ broadcastsVia: "crdt",
129838
+ rwdReference: "\xA7Runtime API \xA7 runtime.workflow.createScopes. Bulk companion to createScope/createScopeFromAnchor; resolves blockId/range inputs, plants marker-backed scopes via one runtime addScopes batch, and returns per-item results."
129839
+ };
128897
129840
  var setScopeGuardPolicyMetadata = {
128898
129841
  name: "runtime.workflow.setScopeGuardPolicy",
128899
129842
  status: "live",
@@ -128989,6 +129932,228 @@ var setMarkupModePolicyMetadata = {
128989
129932
  broadcastsVia: "crdt",
128990
129933
  rwdReference: "\xA7Runtime API \xA7 runtime.workflow.setMarkupModePolicy"
128991
129934
  };
129935
+ function isAnchorScopeInput(input) {
129936
+ return "anchor" in input;
129937
+ }
129938
+ function normalizeCreateScopesAnchor(anchor) {
129939
+ const candidate = anchor;
129940
+ const activeRange = candidate.activeRange;
129941
+ if (activeRange?.kind === "range") {
129942
+ return {
129943
+ from: activeRange.from,
129944
+ to: activeRange.to,
129945
+ storyTarget: candidate.storyTarget
129946
+ };
129947
+ }
129948
+ if (candidate.kind === "range") {
129949
+ return {
129950
+ from: candidate.from ?? Number.NaN,
129951
+ to: candidate.to ?? Number.NaN,
129952
+ storyTarget: candidate.storyTarget
129953
+ };
129954
+ }
129955
+ return {
129956
+ from: candidate.from ?? Number.NaN,
129957
+ to: candidate.to ?? Number.NaN,
129958
+ storyTarget: candidate.storyTarget
129959
+ };
129960
+ }
129961
+ function stableRefMetadataFields(stableRefHint) {
129962
+ if (stableRefHint === void 0) return void 0;
129963
+ return [{
129964
+ key: "stableRefHint",
129965
+ valueType: "string",
129966
+ value: stableRefHint
129967
+ }];
129968
+ }
129969
+ function createRangeInvalidResult(inputIndex, reason, from, to, storyLength, detail) {
129970
+ const base = {
129971
+ inputIndex,
129972
+ scopeId: "",
129973
+ status: "range-invalid",
129974
+ reason,
129975
+ from,
129976
+ to,
129977
+ storyLength,
129978
+ ...detail?.blockIndex !== void 0 ? { blockIndex: detail.blockIndex } : {},
129979
+ ...detail?.blockKind !== void 0 ? { blockKind: detail.blockKind } : {}
129980
+ };
129981
+ switch (reason) {
129982
+ case "non-finite-range":
129983
+ return {
129984
+ ...base,
129985
+ message: `createScopes requires finite numeric from/to values (received from=${from}, to=${to}). Pass selection.activeRange or an object shaped as {from, to}.`,
129986
+ nextStep: "pass-selection-activeRange-or-finite-from-to"
129987
+ };
129988
+ case "from-negative":
129989
+ return {
129990
+ ...base,
129991
+ message: `createScopes requires from >= 0 (received from=${from}). Clamp negative values to 0 before calling.`,
129992
+ nextStep: "clamp-from-to-zero"
129993
+ };
129994
+ case "to-less-than-from":
129995
+ return {
129996
+ ...base,
129997
+ message: `createScopes requires to >= from (received from=${from}, to=${to}). Swap the two values before calling.`,
129998
+ nextStep: "swap-from-and-to"
129999
+ };
130000
+ case "range-exceeds-story-length":
130001
+ return {
130002
+ ...base,
130003
+ message: `createScopes requires to <= storyLength (received to=${to}, storyLength=${storyLength}). Re-derive positions from the current document and retry.`,
130004
+ nextStep: "clamp-to-to-storyLength-or-pick-a-different-range"
130005
+ };
130006
+ case "non-paragraph-target":
130007
+ return {
130008
+ ...base,
130009
+ message: `createScopes refused range [${from}, ${to}]: it targets a ${detail?.blockKind ?? "non-paragraph"} block. Pick a paragraph target or use a structural workflow scope.`,
130010
+ nextStep: "pick-a-paragraph-target"
130011
+ };
130012
+ case "empty-document":
130013
+ return {
130014
+ ...base,
130015
+ message: "createScopes refused: the target document has no blocks; initialize a document before creating scopes.",
130016
+ nextStep: "initialize-document-before-creating-scopes"
130017
+ };
130018
+ }
130019
+ }
130020
+ function plantFailureToCreateScopesResult(pending, result) {
130021
+ const status = result.plantStatus;
130022
+ if (!status || status.planted !== false) {
130023
+ return {
130024
+ inputIndex: pending.inputIndex,
130025
+ status: "created",
130026
+ scopeId: result.scopeId
130027
+ };
130028
+ }
130029
+ if (status.reason === "non-paragraph-target") {
130030
+ return createRangeInvalidResult(
130031
+ pending.inputIndex,
130032
+ "non-paragraph-target",
130033
+ pending.from,
130034
+ pending.to,
130035
+ status.storyLength ?? pending.storyLength,
130036
+ {
130037
+ blockIndex: status.blockIndex ?? -1,
130038
+ blockKind: status.blockKind ?? "unknown"
130039
+ }
130040
+ );
130041
+ }
130042
+ if (status.reason === "range-out-of-bounds") {
130043
+ return createRangeInvalidResult(
130044
+ pending.inputIndex,
130045
+ "range-exceeds-story-length",
130046
+ pending.from,
130047
+ pending.to,
130048
+ status.storyLength ?? pending.storyLength
130049
+ );
130050
+ }
130051
+ return createRangeInvalidResult(
130052
+ pending.inputIndex,
130053
+ "empty-document",
130054
+ pending.from,
130055
+ pending.to,
130056
+ status.storyLength ?? pending.storyLength
130057
+ );
130058
+ }
130059
+ function createScopesBulk(runtime, input) {
130060
+ const doc = runtime.getCanonicalDocument();
130061
+ const storyLength = runtime.getRenderSnapshot().surface?.storySize ?? 0;
130062
+ const results = [];
130063
+ const pending = [];
130064
+ input.scopes.forEach((item, inputIndex) => {
130065
+ const assoc = item.assoc ?? { start: 1, end: -1 };
130066
+ const scopeMetadataFields = stableRefMetadataFields(item.stableRefHint);
130067
+ if (isAnchorScopeInput(item)) {
130068
+ const normalizedAnchor = normalizeCreateScopesAnchor(item.anchor);
130069
+ const { from, to } = normalizedAnchor;
130070
+ const itemStoryLength = normalizedAnchor.storyTarget?.kind === void 0 || normalizedAnchor.storyTarget.kind === "main" ? storyLength : Number.MAX_SAFE_INTEGER;
130071
+ if (!Number.isFinite(from) || !Number.isFinite(to)) {
130072
+ results.push(createRangeInvalidResult(inputIndex, "non-finite-range", from, to, itemStoryLength));
130073
+ return;
130074
+ }
130075
+ if (from < 0) {
130076
+ results.push(createRangeInvalidResult(inputIndex, "from-negative", from, to, itemStoryLength));
130077
+ return;
130078
+ }
130079
+ if (to < from) {
130080
+ results.push(createRangeInvalidResult(inputIndex, "to-less-than-from", from, to, itemStoryLength));
130081
+ return;
130082
+ }
130083
+ if (to > itemStoryLength) {
130084
+ results.push(createRangeInvalidResult(inputIndex, "range-exceeds-story-length", from, to, itemStoryLength));
130085
+ return;
130086
+ }
130087
+ const anchor2 = {
130088
+ kind: "range",
130089
+ from,
130090
+ to,
130091
+ assoc
130092
+ };
130093
+ pending.push({
130094
+ inputIndex,
130095
+ request: {
130096
+ anchor: anchor2,
130097
+ scopeId: item.scopeId,
130098
+ mode: item.mode,
130099
+ persistence: item.persistence,
130100
+ metadata: item.metadata,
130101
+ label: item.label,
130102
+ storyTarget: normalizedAnchor.storyTarget ?? { kind: "main" },
130103
+ ...item.visibility ? { visibility: item.visibility } : {},
130104
+ ...item.guardPolicy ? { guardPolicy: item.guardPolicy } : {},
130105
+ ...scopeMetadataFields ? { scopeMetadataFields } : {}
130106
+ },
130107
+ from,
130108
+ to,
130109
+ storyLength: itemStoryLength
130110
+ });
130111
+ return;
130112
+ }
130113
+ const anchor = resolveBlockAnchorFromCanonical(doc, item.blockId, assoc);
130114
+ if (!anchor || anchor.kind !== "range") {
130115
+ results.push({
130116
+ inputIndex,
130117
+ scopeId: "",
130118
+ status: "block-not-found"
130119
+ });
130120
+ return;
130121
+ }
130122
+ pending.push({
130123
+ inputIndex,
130124
+ request: {
130125
+ anchor,
130126
+ scopeId: item.scopeId,
130127
+ mode: item.mode,
130128
+ persistence: item.persistence,
130129
+ metadata: item.metadata,
130130
+ label: item.label,
130131
+ ...item.visibility ? { visibility: item.visibility } : {},
130132
+ ...item.guardPolicy ? { guardPolicy: item.guardPolicy } : {},
130133
+ ...scopeMetadataFields ? { scopeMetadataFields } : {}
130134
+ },
130135
+ from: anchor.from,
130136
+ to: anchor.to,
130137
+ storyLength
130138
+ });
130139
+ });
130140
+ const created = runtime.addScopes(pending.map((item) => item.request));
130141
+ created.forEach((result, index) => {
130142
+ const item = pending[index];
130143
+ if (!item) return;
130144
+ results.push(plantFailureToCreateScopesResult(item, result));
130145
+ });
130146
+ const sorted = results.sort((a, b) => a.inputIndex - b.inputIndex);
130147
+ const createdCount = sorted.filter((item) => item.status === "created").length;
130148
+ const blocked2 = sorted.length - createdCount;
130149
+ return {
130150
+ status: blocked2 === 0 ? "created" : createdCount > 0 ? "partial" : "blocked",
130151
+ total: input.scopes.length,
130152
+ created: createdCount,
130153
+ blocked: blocked2,
130154
+ scopes: Object.freeze(sorted)
130155
+ };
130156
+ }
128992
130157
  function createWorkflowFamily(runtime) {
128993
130158
  return {
128994
130159
  queryScopes(filter) {
@@ -129003,7 +130168,10 @@ function createWorkflowFamily(runtime) {
129003
130168
  createScope(input) {
129004
130169
  const adapterResult = createScopeFromBlockId(runtime, {
129005
130170
  blockId: input.blockId,
130171
+ scopeId: input.scopeId,
129006
130172
  mode: input.mode,
130173
+ persistence: input.persistence,
130174
+ metadata: input.metadata,
129007
130175
  label: input.label,
129008
130176
  ...input.visibility ? { visibility: input.visibility } : {},
129009
130177
  ...input.guardPolicy ? { guardPolicy: input.guardPolicy } : {},
@@ -129037,6 +130205,25 @@ function createWorkflowFamily(runtime) {
129037
130205
  }
129038
130206
  return { scopeId: adapterResult.scopeId, status: "created" };
129039
130207
  },
130208
+ createScopes(input) {
130209
+ const result = createScopesBulk(runtime, input);
130210
+ emitUxResponse(runtime, {
130211
+ apiFn: createScopesMetadata.name,
130212
+ intent: createScopesMetadata.uxIntent.expectedDelta ?? "",
130213
+ mockOrLive: "live",
130214
+ uiVisible: true,
130215
+ expectedDelta: createScopesMetadata.uxIntent.expectedDelta,
130216
+ actualDelta: result.created > 0 ? {
130217
+ kind: "inline-change",
130218
+ payload: {
130219
+ created: result.created,
130220
+ blocked: result.blocked,
130221
+ scopeIds: result.scopes.filter((scope) => scope.status === "created").map((scope) => scope.scopeId)
130222
+ }
130223
+ } : void 0
130224
+ });
130225
+ return result;
130226
+ },
129040
130227
  getScopeGuardPolicy(scopeId) {
129041
130228
  return runtime.getScopeGuardPolicy(scopeId);
129042
130229
  },
@@ -129072,7 +130259,10 @@ function createWorkflowFamily(runtime) {
129072
130259
  createScopeFromAnchor(input) {
129073
130260
  const adapterResult = createScopeFromAnchor(runtime, {
129074
130261
  anchor: input.anchor,
130262
+ scopeId: input.scopeId,
129075
130263
  mode: input.mode,
130264
+ persistence: input.persistence,
130265
+ metadata: input.metadata,
129076
130266
  label: input.label,
129077
130267
  ...input.visibility ? { visibility: input.visibility } : {},
129078
130268
  ...input.guardPolicy ? { guardPolicy: input.guardPolicy } : {},
@@ -130100,7 +131290,8 @@ var SUPPORTED_COMMANDS2 = [
130100
131290
  "indent",
130101
131291
  "outdent",
130102
131292
  "restart-numbering",
130103
- "continue-numbering"
131293
+ "continue-numbering",
131294
+ "set-value"
130104
131295
  ];
130105
131296
  var UNSUPPORTED_COMMANDS2 = [
130106
131297
  "create",
@@ -130109,7 +131300,6 @@ var UNSUPPORTED_COMMANDS2 = [
130109
131300
  "join",
130110
131301
  "separate",
130111
131302
  "split",
130112
- "set-value",
130113
131303
  "apply-template",
130114
131304
  "capture-template",
130115
131305
  "apply-preset",
@@ -130157,11 +131347,17 @@ function createListsFamily2(runtime) {
130157
131347
  const resolved = resolveCurrentListTarget(runtime.getCanonicalDocument(), input);
130158
131348
  return resolved.kind === "resolved" ? toReadback(runtime.getCanonicalDocument(), resolved.target, resolved.paragraph) : null;
130159
131349
  },
131350
+ canJoin(input) {
131351
+ return sequencePreflight(runtime.getCanonicalDocument(), input, activeStoryKey(runtime));
131352
+ },
131353
+ canContinuePrevious(input) {
131354
+ return sequencePreflight(runtime.getCanonicalDocument(), input, activeStoryKey(runtime));
131355
+ },
130160
131356
  previewCommand(input) {
130161
- return previewListCommand(runtime.getCanonicalDocument(), input);
131357
+ return previewListCommand(runtime.getCanonicalDocument(), input, activeStoryKey(runtime));
130162
131358
  },
130163
131359
  applyCommand(input) {
130164
- const preview = previewListCommand(runtime.getCanonicalDocument(), input);
131360
+ const preview = previewListCommand(runtime.getCanonicalDocument(), input, activeStoryKey(runtime));
130165
131361
  if (!preview.supported || !preview.target) {
130166
131362
  return {
130167
131363
  applied: false,
@@ -130221,7 +131417,38 @@ function createListsFamily2(runtime) {
130221
131417
  }
130222
131418
  };
130223
131419
  }
130224
- function previewListCommand(document2, input) {
131420
+ function sequencePreflight(document2, input, activeStoryKey2) {
131421
+ const resolved = resolveCurrentListTarget(document2, input);
131422
+ if (resolved.kind !== "resolved") {
131423
+ return {
131424
+ canJoin: false,
131425
+ canContinuePrevious: false,
131426
+ blockers: [resolved.blocker]
131427
+ };
131428
+ }
131429
+ const target = toReadback(document2, resolved.target, resolved.paragraph);
131430
+ const targetRef = { targetKey: target.targetKey, addressKey: target.addressKey };
131431
+ if (activeStoryKey2 !== void 0 && target.storyKey !== activeStoryKey2) {
131432
+ return {
131433
+ target,
131434
+ canJoin: false,
131435
+ canContinuePrevious: false,
131436
+ blockers: [{
131437
+ code: "list-target-wrong-story",
131438
+ ownerLayer: "L07",
131439
+ message: "List target does not belong to the runtime active story.",
131440
+ ...targetRef
131441
+ }]
131442
+ };
131443
+ }
131444
+ return {
131445
+ target,
131446
+ canJoin: canJoinPreviousSequence(document2, resolved.paragraphIndex),
131447
+ canContinuePrevious: canContinuePreviousSequence(document2, resolved.paragraphIndex),
131448
+ blockers: []
131449
+ };
131450
+ }
131451
+ function previewListCommand(document2, input, activeStoryKey2) {
130225
131452
  const resolved = resolveCurrentListTarget(document2, input);
130226
131453
  if (resolved.kind !== "resolved") {
130227
131454
  return {
@@ -130233,6 +131460,20 @@ function previewListCommand(document2, input) {
130233
131460
  }
130234
131461
  const target = toReadback(document2, resolved.target, resolved.paragraph);
130235
131462
  const targetRef = { targetKey: target.targetKey, addressKey: target.addressKey };
131463
+ if (activeStoryKey2 !== void 0 && target.storyKey !== activeStoryKey2) {
131464
+ return {
131465
+ command: input.command,
131466
+ supported: false,
131467
+ target,
131468
+ affectedTargets: [target],
131469
+ blockers: [{
131470
+ code: "list-target-wrong-story",
131471
+ ownerLayer: "L07",
131472
+ message: "List target does not belong to the runtime active story.",
131473
+ ...targetRef
131474
+ }]
131475
+ };
131476
+ }
130236
131477
  if (!SUPPORTED_COMMANDS2.includes(input.command)) {
130237
131478
  return {
130238
131479
  command: input.command,
@@ -130245,6 +131486,17 @@ function previewListCommand(document2, input) {
130245
131486
  const canContinuePrevious = canContinuePreviousSequence(document2, resolved.paragraphIndex);
130246
131487
  const canJoin = canJoinPreviousSequence(document2, resolved.paragraphIndex);
130247
131488
  const blockers = [];
131489
+ if (input.command === "set-value") {
131490
+ const value = input.startAt;
131491
+ if (!Number.isInteger(value) || value === void 0 || value < 1) {
131492
+ blockers.push({
131493
+ code: "list-command-preflight-blocked",
131494
+ ownerLayer: "L07",
131495
+ message: "runtime.lists.set-value requires a positive integer startAt value.",
131496
+ ...targetRef
131497
+ });
131498
+ }
131499
+ }
130248
131500
  if (input.command === "continue-numbering" && !canContinuePrevious) {
130249
131501
  blockers.push({
130250
131502
  code: "list-continue-target-missing",
@@ -130275,6 +131527,7 @@ function editorCommandForListCommand(command, editableTarget, timestamp, startAt
130275
131527
  case "outdent":
130276
131528
  return { type: "list.outdent", editableTargets: [editableTarget], origin };
130277
131529
  case "restart-numbering":
131530
+ case "set-value":
130278
131531
  return {
130279
131532
  type: "list.restart-numbering",
130280
131533
  editableTarget,
@@ -130358,33 +131611,35 @@ function resolveCurrentListTarget(document2, input) {
130358
131611
  return { kind: "resolved", ...resolved };
130359
131612
  }
130360
131613
  function currentListTargets(document2) {
130361
- const paragraphs = collectParagraphEntries(document2.content.children, "main");
131614
+ const paragraphs = collectParagraphEntries(document2);
130362
131615
  const targets = collectEditableTargetRefs(document2).filter(isListTextTarget);
130363
- const byBlockPath = /* @__PURE__ */ new Map();
130364
- for (const target of targets) byBlockPath.set(target.blockPath, target);
131616
+ const byStoryBlockPath = /* @__PURE__ */ new Map();
131617
+ for (const target of targets) byStoryBlockPath.set(storyBlockPathKey(target.storyKey, target.blockPath), target);
130365
131618
  const out = [];
130366
131619
  for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex += 1) {
130367
131620
  const entry = paragraphs[paragraphIndex];
130368
131621
  if (!entry?.paragraph.numbering) continue;
130369
- const target = byBlockPath.get(entry.blockPath);
131622
+ const target = byStoryBlockPath.get(storyBlockPathKey(entry.storyKey, entry.blockPath));
130370
131623
  if (!target) continue;
130371
- out.push({ target, paragraph: entry.paragraph, paragraphIndex });
131624
+ out.push({ target, paragraph: entry.paragraph, paragraphIndex, storyKey: entry.storyKey });
130372
131625
  }
130373
131626
  return out;
130374
131627
  }
130375
- function collectParagraphEntries(blocks, basePath) {
131628
+ function collectParagraphEntries(document2) {
130376
131629
  const out = [];
130377
- collectParagraphEntriesInto(blocks, basePath, out);
131630
+ for (const context of collectStoryBlockContexts(document2)) {
131631
+ collectParagraphEntriesInto(context.blocks, context.storyKey, context.basePath, out);
131632
+ }
130378
131633
  return out;
130379
131634
  }
130380
- function collectParagraphEntriesInto(blocks, basePath, out) {
131635
+ function collectParagraphEntriesInto(blocks, storyKey2, basePath, out) {
130381
131636
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
130382
131637
  const block = blocks[blockIndex];
130383
131638
  if (!block) continue;
130384
131639
  const blockPath = `${basePath}/block[${blockIndex}]`;
130385
131640
  switch (block.type) {
130386
131641
  case "paragraph":
130387
- out.push({ paragraph: block, blockPath });
131642
+ out.push({ paragraph: block, storyKey: storyKey2, blockPath, containerPath: basePath });
130388
131643
  break;
130389
131644
  case "table":
130390
131645
  for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
@@ -130395,6 +131650,7 @@ function collectParagraphEntriesInto(blocks, basePath, out) {
130395
131650
  if (!cell) continue;
130396
131651
  collectParagraphEntriesInto(
130397
131652
  cell.children,
131653
+ storyKey2,
130398
131654
  `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`,
130399
131655
  out
130400
131656
  );
@@ -130402,7 +131658,7 @@ function collectParagraphEntriesInto(blocks, basePath, out) {
130402
131658
  }
130403
131659
  break;
130404
131660
  case "sdt":
130405
- collectParagraphEntriesInto(block.children, blockPath, out);
131661
+ collectParagraphEntriesInto(block.children, storyKey2, blockPath, out);
130406
131662
  break;
130407
131663
  case "custom_xml":
130408
131664
  break;
@@ -130446,13 +131702,17 @@ function toReadback(document2, target, paragraph) {
130446
131702
  };
130447
131703
  }
130448
131704
  function canContinuePreviousSequence(document2, paragraphIndex) {
130449
- const paragraphs = collectParagraphEntries(document2.content.children, "main");
130450
- const current = paragraphs[paragraphIndex]?.paragraph;
131705
+ const paragraphs = collectParagraphEntries(document2);
131706
+ const currentEntry = paragraphs[paragraphIndex];
131707
+ const current = currentEntry?.paragraph;
130451
131708
  if (!current?.numbering) return false;
130452
131709
  const currentKind = getListKind(document2.numbering, current.numbering.numberingInstanceId);
130453
131710
  if (!currentKind) return false;
130454
131711
  for (let index = paragraphIndex - 1; index >= 0; index -= 1) {
130455
- const previous = paragraphs[index]?.paragraph;
131712
+ const previousEntry = paragraphs[index];
131713
+ if (previousEntry?.storyKey !== currentEntry.storyKey) break;
131714
+ if (previousEntry.containerPath !== currentEntry.containerPath) break;
131715
+ const previous = previousEntry.paragraph;
130456
131716
  if (!previous?.numbering) continue;
130457
131717
  const previousKind = getListKind(document2.numbering, previous.numbering.numberingInstanceId);
130458
131718
  return previousKind === currentKind && previous.numbering.numberingInstanceId !== current.numbering.numberingInstanceId;
@@ -130460,14 +131720,26 @@ function canContinuePreviousSequence(document2, paragraphIndex) {
130460
131720
  return false;
130461
131721
  }
130462
131722
  function canJoinPreviousSequence(document2, paragraphIndex) {
130463
- const paragraphs = collectParagraphEntries(document2.content.children, "main");
130464
- const current = paragraphs[paragraphIndex]?.paragraph;
130465
- const previous = paragraphs[paragraphIndex - 1]?.paragraph;
131723
+ const paragraphs = collectParagraphEntries(document2);
131724
+ const currentEntry = paragraphs[paragraphIndex];
131725
+ const previousEntry = paragraphs[paragraphIndex - 1];
131726
+ if (previousEntry?.storyKey !== currentEntry?.storyKey) return false;
131727
+ if (previousEntry?.containerPath !== currentEntry?.containerPath) return false;
131728
+ const current = currentEntry?.paragraph;
131729
+ const previous = previousEntry?.paragraph;
130466
131730
  if (!current?.numbering || !previous?.numbering) return false;
130467
131731
  const currentKind = getListKind(document2.numbering, current.numbering.numberingInstanceId);
130468
131732
  const previousKind = getListKind(document2.numbering, previous.numbering.numberingInstanceId);
130469
131733
  return Boolean(currentKind) && currentKind === previousKind && current.numbering.numberingInstanceId !== previous.numbering.numberingInstanceId;
130470
131734
  }
131735
+ function storyBlockPathKey(storyKey2, blockPath) {
131736
+ return `${storyKey2}
131737
+ ${blockPath}`;
131738
+ }
131739
+ function activeStoryKey(runtime) {
131740
+ const activeStory = runtime.getRenderSnapshot()?.activeStory;
131741
+ return activeStory ? storyTargetKey(activeStory) : void 0;
131742
+ }
130471
131743
  function unsupportedCommandBlocker(command, target) {
130472
131744
  return {
130473
131745
  code: "list-command-unsupported",
@@ -134762,33 +136034,51 @@ function createPlaceholderScopes(runtime, input) {
134762
136034
  blockerDetails: Object.freeze([detail])
134763
136035
  };
134764
136036
  }
134765
- const compiler = createScopeCompilerService(runtime);
134766
136037
  const byOriginalIndex = /* @__PURE__ */ new Map();
134767
- for (const item of orderedHits) {
136038
+ const createdScopeIds = [];
136039
+ const scopeRequests = orderedHits.map((item) => {
134768
136040
  const text = item.text || query;
134769
136041
  const label = input.labelPrefix === void 0 ? text : `${input.labelPrefix} ${item.originalIndex + 1}`;
134770
- const result = createScopeFromAnchor(runtime, {
134771
- anchor: { from: item.hit.from, to: item.hit.to },
136042
+ return {
136043
+ anchor: {
136044
+ kind: "range",
136045
+ from: item.hit.from,
136046
+ to: item.hit.to,
136047
+ assoc: input.assoc ?? { start: 1, end: -1 }
136048
+ },
134772
136049
  mode: input.mode ?? "edit",
134773
136050
  label,
134774
136051
  ...input.visibility ? { visibility: input.visibility } : {},
134775
136052
  ...input.guardPolicy ? { guardPolicy: input.guardPolicy } : {},
134776
136053
  ...input.assoc ? { assoc: input.assoc } : {},
134777
- ...input.stableRefHint ? { stableRefHint: input.stableRefHint } : {}
134778
- });
134779
- if (result.status === "created") {
134780
- const compiled = compiler.compileScopeById(result.scopeId)?.scope;
136054
+ ...input.stableRefHint ? {
136055
+ scopeMetadataFields: [
136056
+ {
136057
+ key: "stableRefHint",
136058
+ valueType: "string",
136059
+ value: input.stableRefHint
136060
+ }
136061
+ ]
136062
+ } : {}
136063
+ };
136064
+ });
136065
+ const scopeResults = runtime.addScopes(scopeRequests);
136066
+ orderedHits.forEach((item, requestIndex) => {
136067
+ const text = item.text || query;
136068
+ const result = scopeResults[requestIndex];
136069
+ if (result && result.scopeId && result.plantStatus?.planted !== false) {
136070
+ createdScopeIds.push(result.scopeId);
134781
136071
  byOriginalIndex.set(item.originalIndex, {
134782
136072
  status: "created",
134783
136073
  text,
134784
136074
  excerpt: excerpt(text),
134785
- scopeId: result.scopeId,
134786
- ...compiled?.handle ? { handle: compiled.handle } : {}
136075
+ scopeId: result.scopeId
134787
136076
  });
134788
- continue;
136077
+ return;
134789
136078
  }
136079
+ const reason = result?.plantStatus?.reason ?? "unknown";
134790
136080
  const detail = blockerWithOwner(
134791
- `actions:placeholder-scopes:create-refused:${result.reason}`,
136081
+ `actions:placeholder-scopes:create-refused:${reason}`,
134792
136082
  "blocked",
134793
136083
  "The placeholder match could not be converted into a workflow scope.",
134794
136084
  "Refresh the document and retry; if it still refuses, route the target to the workflow/scope writer owner.",
@@ -134801,6 +136091,38 @@ function createPlaceholderScopes(runtime, input) {
134801
136091
  blockers: Object.freeze([detail.code]),
134802
136092
  blockerDetails: Object.freeze([detail])
134803
136093
  });
136094
+ });
136095
+ if (createdScopeIds.length > 0) {
136096
+ const createdScopeIdSet = new Set(createdScopeIds);
136097
+ const handlesByScopeId = new Map(
136098
+ createScopeCompilerService(runtime).compileAllScopes().filter((scope) => createdScopeIdSet.has(scope.handle.scopeId)).map((scope) => [scope.handle.scopeId, scope.handle])
136099
+ );
136100
+ for (const [originalIndex, item] of byOriginalIndex) {
136101
+ if (item.status !== "created" || !item.scopeId) continue;
136102
+ const handle = handlesByScopeId.get(item.scopeId);
136103
+ if (!handle) {
136104
+ const detail = blockerWithOwner(
136105
+ `actions:placeholder-scopes:create-unresolved:${item.scopeId}`,
136106
+ "blocked",
136107
+ "The placeholder scope marker was planted but did not enumerate as a current semantic scope handle.",
136108
+ "Treat this target as unresolved, refresh scope enumeration, and route persistent misses to the semantic-scope compiler owner.",
136109
+ "L08"
136110
+ );
136111
+ byOriginalIndex.set(originalIndex, {
136112
+ status: "blocked",
136113
+ text: item.text,
136114
+ excerpt: item.excerpt,
136115
+ scopeId: item.scopeId,
136116
+ blockers: Object.freeze([detail.code]),
136117
+ blockerDetails: Object.freeze([detail])
136118
+ });
136119
+ continue;
136120
+ }
136121
+ byOriginalIndex.set(originalIndex, {
136122
+ ...item,
136123
+ handle
136124
+ });
136125
+ }
134804
136126
  }
134805
136127
  const scopes = orderedHits.map((item) => byOriginalIndex.get(item.originalIndex)).filter((value) => value !== void 0);
134806
136128
  const created = scopes.filter((scope) => scope.status === "created").length;
@@ -135263,6 +136585,9 @@ function applyRewrite(runtime, target, input) {
135263
136585
  if (target.kind === "editable-text") {
135264
136586
  return applyEditableTextRewrite(runtime, target, input);
135265
136587
  }
136588
+ if (target.handle.provenance === "marker-backed" && (target.scope.kind === "paragraph" || target.scope.kind === "list-item")) {
136589
+ return applyMarkerBackedRangeRewrite(runtime, target, input);
136590
+ }
135266
136591
  if (target.scope.kind === "list-item") {
135267
136592
  const listTextTarget = uniqueListTextActionForScope(runtime, target.handle);
135268
136593
  if (!listTextTarget.ok) return blockedApplyFromResolution(listTextTarget);
@@ -135409,13 +136734,97 @@ function applyEditableTextRewrite(runtime, target, input) {
135409
136734
  afterReadback
135410
136735
  };
135411
136736
  }
136737
+ function applyMarkerBackedRangeRewrite(runtime, target, input) {
136738
+ const range = buildScopePositionMap(runtime.getCanonicalDocument()).markerScopes.get(
136739
+ target.handle.scopeId
136740
+ );
136741
+ if (!range) {
136742
+ return blockedApply(
136743
+ `actions:rewrite:marker-range-unresolved:${target.handle.scopeId}`,
136744
+ "unresolved-target",
136745
+ "The marker-backed scope could not be joined to its current marker range.",
136746
+ "Refresh placeholder scopes and retry; route persistent failures to L06 marker scope tracking."
136747
+ );
136748
+ }
136749
+ const beforeReadback = markerScopeReadback(runtime, target.handle.scopeId) ?? {
136750
+ text: target.scope.content.text,
136751
+ isEmpty: target.scope.content.text.length === 0
136752
+ };
136753
+ const before = runtime.getCanonicalDocument();
136754
+ const origin = actionOrigin(runtime, input);
136755
+ runtime.dispatch({
136756
+ type: "selection.set",
136757
+ selection: {
136758
+ anchor: range.from,
136759
+ head: range.to,
136760
+ isCollapsed: range.from === range.to,
136761
+ activeRange: {
136762
+ kind: "range",
136763
+ from: range.from,
136764
+ to: range.to,
136765
+ assoc: { start: -1, end: 1 }
136766
+ }
136767
+ },
136768
+ origin
136769
+ });
136770
+ const ack = runtime.applyActiveStoryTextCommand({
136771
+ type: "text.insert",
136772
+ text: input.text,
136773
+ origin
136774
+ });
136775
+ const changed = runtime.getCanonicalDocument() !== before;
136776
+ const afterReadback = markerScopeReadback(runtime, target.handle.scopeId);
136777
+ const compiledAfter = createScopeCompilerService(runtime).compileScopeById(target.handle.scopeId);
136778
+ if (!changed || afterReadback?.text !== input.text) {
136779
+ return {
136780
+ status: "blocked",
136781
+ applied: false,
136782
+ changed,
136783
+ target: summarizeTarget(
136784
+ compiledAfter ? { ...target, scope: compiledAfter.scope, handle: compiledAfter.scope.handle } : target
136785
+ ),
136786
+ posture: "suspect-readback",
136787
+ blockers: Object.freeze([
136788
+ `actions:rewrite:marker-range-readback-mismatch:${target.handle.scopeId}`
136789
+ ]),
136790
+ blockerDetails: Object.freeze([
136791
+ blocker(
136792
+ `actions:rewrite:marker-range-readback-mismatch:${target.handle.scopeId}`,
136793
+ "blocked",
136794
+ ack.kind === "rejected" ? "The marker-backed rewrite command was rejected or did not produce the requested marker readback." : "The marker-backed rewrite command did not produce the requested marker readback.",
136795
+ "Treat the mutation as suspect. Re-read the target and export before claiming success."
136796
+ )
136797
+ ]),
136798
+ ...afterReadback ? { afterReadback } : {}
136799
+ };
136800
+ }
136801
+ return {
136802
+ status: "applied",
136803
+ applied: true,
136804
+ changed: true,
136805
+ target: summarizeTarget(
136806
+ compiledAfter ? { ...target, scope: compiledAfter.scope, handle: compiledAfter.scope.handle } : target
136807
+ ),
136808
+ commandReference: {
136809
+ command: "text.insert",
136810
+ actorId: input.actorId ?? "v3-ai-api",
136811
+ origin: input.origin ?? "agent",
136812
+ emittedAtUtc: currentAuditTimestamp(runtime)
136813
+ },
136814
+ beforeReadback,
136815
+ afterReadback
136816
+ };
136817
+ }
135412
136818
  function applyTableScopedMarkerRewrite(runtime, target, action, input) {
135413
136819
  const workflowScope = runtime.getScope(target.handle.scopeId);
136820
+ const markerRange = buildScopePositionMap(runtime.getCanonicalDocument()).markerScopes.get(
136821
+ target.handle.scopeId
136822
+ );
135414
136823
  const editableTarget = tableEditableTargetForActionHandle(
135415
136824
  runtime,
135416
136825
  action.actionHandle
135417
136826
  );
135418
- if (!workflowScope || workflowScope.anchor.kind !== "range" || !editableTarget) {
136827
+ if (!workflowScope || !markerRange || !editableTarget) {
135419
136828
  return blockedApply(
135420
136829
  `actions:rewrite:table-marker-target-unresolved:${target.handle.scopeId}`,
135421
136830
  "unresolved-target",
@@ -135423,19 +136832,23 @@ function applyTableScopedMarkerRewrite(runtime, target, action, input) {
135423
136832
  "Refresh placeholder scopes and retry; route persistent failures to L08 table scope target mapping."
135424
136833
  );
135425
136834
  }
136835
+ const beforeReadback = markerScopeReadback(runtime, target.handle.scopeId) ?? {
136836
+ text: target.scope.content.text,
136837
+ isEmpty: target.scope.content.text.length === 0
136838
+ };
135426
136839
  const before = runtime.getCanonicalDocument();
135427
136840
  try {
135428
136841
  runtime.dispatch({
135429
136842
  type: "selection.set",
135430
136843
  selection: {
135431
- anchor: workflowScope.anchor.from,
135432
- head: workflowScope.anchor.to,
135433
- isCollapsed: workflowScope.anchor.from === workflowScope.anchor.to,
136844
+ anchor: markerRange.from,
136845
+ head: markerRange.to,
136846
+ isCollapsed: markerRange.from === markerRange.to,
135434
136847
  activeRange: {
135435
136848
  kind: "range",
135436
- from: workflowScope.anchor.from,
135437
- to: workflowScope.anchor.to,
135438
- assoc: workflowScope.anchor.assoc ?? { start: -1, end: 1 }
136849
+ from: markerRange.from,
136850
+ to: markerRange.to,
136851
+ assoc: { start: -1, end: 1 }
135439
136852
  }
135440
136853
  },
135441
136854
  origin: actionOrigin(runtime, input)
@@ -135470,12 +136883,19 @@ function applyTableScopedMarkerRewrite(runtime, target, action, input) {
135470
136883
  );
135471
136884
  const afterText = paragraph ? collectInlineText4(paragraph.children) : void 0;
135472
136885
  const afterReadback = afterText === void 0 ? void 0 : { text: afterText, isEmpty: afterText.length === 0 };
135473
- if (!changed || afterReadback?.text !== input.text) {
136886
+ const compiledAfter = createScopeCompilerService(runtime).compileScopeById(target.handle.scopeId);
136887
+ const scopeReadback = markerScopeReadback(runtime, target.handle.scopeId) ?? (compiledAfter ? {
136888
+ text: compiledAfter.scope.content.text,
136889
+ isEmpty: compiledAfter.scope.content.text.length === 0
136890
+ } : void 0);
136891
+ if (!changed || scopeReadback?.text !== input.text) {
135474
136892
  return {
135475
136893
  status: "blocked",
135476
136894
  applied: false,
135477
136895
  changed,
135478
- target: summarizeTarget({ kind: "table-text", action }),
136896
+ target: summarizeTarget(
136897
+ compiledAfter ? { ...target, scope: compiledAfter.scope, handle: compiledAfter.scope.handle } : target
136898
+ ),
135479
136899
  posture: "suspect-readback",
135480
136900
  blockers: Object.freeze([
135481
136901
  `actions:rewrite:table-marker-readback-mismatch:${target.handle.scopeId}`
@@ -135488,25 +136908,24 @@ function applyTableScopedMarkerRewrite(runtime, target, action, input) {
135488
136908
  "Treat the mutation as suspect. Re-read the target and export before claiming success."
135489
136909
  )
135490
136910
  ]),
135491
- ...afterReadback ? { afterReadback } : {}
136911
+ ...scopeReadback ? { afterReadback: scopeReadback } : afterReadback ? { afterReadback } : {}
135492
136912
  };
135493
136913
  }
135494
136914
  return {
135495
136915
  status: "applied",
135496
136916
  applied: true,
135497
136917
  changed: true,
135498
- target: summarizeTarget({
135499
- kind: "table-text",
135500
- action: { ...action, readback: afterReadback }
135501
- }),
136918
+ target: summarizeTarget(
136919
+ compiledAfter ? { ...target, scope: compiledAfter.scope, handle: compiledAfter.scope.handle } : { kind: "table-text", action: { ...action, readback: scopeReadback } }
136920
+ ),
135502
136921
  commandReference: {
135503
136922
  command: "text.insert",
135504
136923
  actorId: input.actorId ?? "v3-ai-api",
135505
136924
  origin: input.origin ?? "agent",
135506
136925
  emittedAtUtc: currentAuditTimestamp(runtime)
135507
136926
  },
135508
- ...action.readback ? { beforeReadback: action.readback } : {},
135509
- afterReadback
136927
+ beforeReadback,
136928
+ afterReadback: scopeReadback
135510
136929
  };
135511
136930
  }
135512
136931
  function projectRewriteScopeResult(runtime, result, target, beforeText, proposedText, documentMutated) {
@@ -135600,7 +137019,7 @@ function summarizeTarget(target) {
135600
137019
  if (target.kind === "editable-text") {
135601
137020
  return {
135602
137021
  kind: target.targetKind,
135603
- handle: target.ownerHandle,
137022
+ handle: publicActionScopeHandle(target.ownerHandle),
135604
137023
  actionHandle: target.actionHandle,
135605
137024
  readback: target.readback,
135606
137025
  canRewriteText: true,
@@ -135611,13 +137030,21 @@ function summarizeTarget(target) {
135611
137030
  }
135612
137031
  return {
135613
137032
  kind: target.scope.kind,
135614
- handle: target.handle,
137033
+ handle: publicActionScopeHandle(target.handle),
135615
137034
  canRewriteText: canRewriteScopeText(target.scope),
135616
137035
  canInsertAdjacentText: canInsertAdjacentScopeText(target.scope),
135617
137036
  canFlag: true,
135618
137037
  canMark: canMarkScope(target.scope)
135619
137038
  };
135620
137039
  }
137040
+ function publicActionScopeHandle(handle) {
137041
+ const parentScopeId = handle.parentScopeId;
137042
+ if (!parentScopeId || !/^(cell|table|row|column|span):/u.test(parentScopeId)) {
137043
+ return handle;
137044
+ }
137045
+ const { parentScopeId: _parentScopeId, ...rest } = handle;
137046
+ return rest;
137047
+ }
135621
137048
  function tableTextActionsForScope(runtime, handle) {
135622
137049
  const result = createTableActionFamily(runtime).listTableActions({
135623
137050
  handle,
@@ -135670,6 +137097,13 @@ function tableEditableTargetForActionHandle(runtime, actionHandle) {
135670
137097
  }
135671
137098
  return null;
135672
137099
  }
137100
+ function markerScopeReadback(runtime, scopeId) {
137101
+ const document2 = runtime.getCanonicalDocument();
137102
+ const range = buildScopePositionMap(document2).markerScopes.get(scopeId);
137103
+ if (!range) return null;
137104
+ const text = textForCanonicalRange(document2, range.from, range.to);
137105
+ return { text, isEmpty: text.length === 0 };
137106
+ }
135673
137107
  function editableTextActionsForScope(runtime, handle) {
135674
137108
  const bundle = createScopeCompilerService(runtime).compileBundleById(
135675
137109
  handle.scopeId,
@@ -137022,6 +138456,86 @@ function blockTextLength(block) {
137022
138456
  return 0;
137023
138457
  }
137024
138458
  }
138459
+ function textForCanonicalRange(document2, from, to) {
138460
+ let cursor = 0;
138461
+ let text = "";
138462
+ const append = (value, start, end) => {
138463
+ const clippedFrom = Math.max(from, start);
138464
+ const clippedTo = Math.min(to, end);
138465
+ if (clippedTo <= clippedFrom) return;
138466
+ const localFrom = clippedFrom - start;
138467
+ const localTo = clippedTo - start;
138468
+ text += Array.from(value).slice(localFrom, localTo).join("");
138469
+ };
138470
+ const walkInline = (inline) => {
138471
+ const start = cursor;
138472
+ switch (inline.type) {
138473
+ case "text": {
138474
+ const length = Array.from(inline.text).length;
138475
+ cursor += length;
138476
+ append(inline.text, start, cursor);
138477
+ return length;
138478
+ }
138479
+ case "tab":
138480
+ cursor += 1;
138481
+ append(" ", start, cursor);
138482
+ return 1;
138483
+ case "hard_break":
138484
+ cursor += 1;
138485
+ append("\n", start, cursor);
138486
+ return 1;
138487
+ case "hyperlink":
138488
+ case "field": {
138489
+ const before = cursor;
138490
+ for (const child of inline.children) {
138491
+ walkInline(child);
138492
+ }
138493
+ return cursor - before;
138494
+ }
138495
+ case "bookmark_start":
138496
+ case "bookmark_end":
138497
+ case "scope_marker_start":
138498
+ case "scope_marker_end":
138499
+ return 0;
138500
+ default:
138501
+ cursor += 1;
138502
+ return 1;
138503
+ }
138504
+ };
138505
+ const walkBlock = (block) => {
138506
+ if (!block) return 0;
138507
+ const before = cursor;
138508
+ switch (block.type) {
138509
+ case "paragraph":
138510
+ for (const child of block.children) walkInline(child);
138511
+ break;
138512
+ case "table":
138513
+ for (const row2 of block.rows) {
138514
+ for (const cell of row2.cells) {
138515
+ for (const child of cell.children) walkBlock(child);
138516
+ }
138517
+ }
138518
+ break;
138519
+ case "sdt":
138520
+ case "custom_xml":
138521
+ for (const child of block.children) walkBlock(child);
138522
+ break;
138523
+ default:
138524
+ cursor += 1;
138525
+ break;
138526
+ }
138527
+ return cursor - before;
138528
+ };
138529
+ const blocks = document2.content.children;
138530
+ for (let index = 0; index < blocks.length; index += 1) {
138531
+ walkBlock(blocks[index]);
138532
+ if (index < blocks.length - 1 && blocks[index + 1]?.type === "paragraph") {
138533
+ cursor += 1;
138534
+ append("\n", cursor - 1, cursor);
138535
+ }
138536
+ }
138537
+ return text;
138538
+ }
137025
138539
  function inlineTextLength(inline) {
137026
138540
  if (!inline) return 0;
137027
138541
  switch (inline.type) {
@@ -137177,6 +138691,109 @@ function summarizePlanResult(mode, steps) {
137177
138691
  };
137178
138692
  }
137179
138693
 
138694
+ // src/api/v3/ai/agent.ts
138695
+ function createAgentFamily(runtime, pe2Evidence) {
138696
+ const inspect = createInspectFamily(runtime, pe2Evidence);
138697
+ const resolve = createResolveFamily(runtime);
138698
+ const bundle = createBundleFamily(runtime, pe2Evidence);
138699
+ const actions2 = createActionsFamily(runtime).actions;
138700
+ const table = createTableActionFamily(runtime);
138701
+ const object = createObjectActionFamily(runtime);
138702
+ const policy = createPolicyFamily(runtime);
138703
+ const evaluate = createEvaluateFamily(runtime);
138704
+ const outline = createOutlineFamily(runtime);
138705
+ const stats = createStatsFamily(runtime);
138706
+ const explain = createExplainFamily(runtime);
138707
+ const review = createReviewFamily2(runtime);
138708
+ const exportFamily = createExportFamily(runtime);
138709
+ const read = Object.freeze({
138710
+ inspectDocument: inspect.inspectDocument,
138711
+ listScopes: inspect.listScopes,
138712
+ getScope: bundle.getScope,
138713
+ getScopeBundle: bundle.getScopeBundle,
138714
+ resolveReference: resolve.resolveReference,
138715
+ queryScopeAtPosition: resolve.queryScopeAtPosition,
138716
+ queryScopeInRange: resolve.queryScopeInRange,
138717
+ brief: actions2.brief,
138718
+ getDocumentOutline: outline.getDocumentOutline,
138719
+ getDocumentStatistics: stats.getDocumentStatistics,
138720
+ explainFormatting: explain.explainFormatting
138721
+ });
138722
+ const target = Object.freeze({
138723
+ discover: actions2.discover,
138724
+ locate: actions2.locate,
138725
+ locateAll: actions2.locateAll,
138726
+ createPlaceholderScopes: actions2.createPlaceholderScopes
138727
+ });
138728
+ const edit = Object.freeze({
138729
+ rewrite: actions2.rewrite,
138730
+ runPlan: actions2.runPlan,
138731
+ insertText: actions2.insertText,
138732
+ mark: actions2.mark,
138733
+ flag: actions2.flag,
138734
+ flagMany: actions2.flagMany,
138735
+ fieldRefresh: actions2.fieldRefresh,
138736
+ tocRefresh: actions2.tocRefresh,
138737
+ bookmarkEdit: actions2.bookmarkEdit,
138738
+ hyperlinkDestinationEdit: actions2.hyperlinkDestinationEdit,
138739
+ hyperlinkTextEdit: actions2.hyperlinkTextEdit
138740
+ });
138741
+ const template = Object.freeze({
138742
+ validateTargets: actions2.validateTemplateTargets,
138743
+ readTarget: actions2.templateTargetRead,
138744
+ fillField: actions2.templateFieldFill
138745
+ });
138746
+ const tableGroup = Object.freeze({
138747
+ replaceContent: actions2.tableContent,
138748
+ applyFragment: actions2.tableFragment,
138749
+ applySelection: actions2.tableSelection,
138750
+ listActions: table.listTableActions,
138751
+ applyAction: table.applyTableAction
138752
+ });
138753
+ const list = Object.freeze({
138754
+ applyOperation: actions2.listOperation
138755
+ });
138756
+ const objectGroup = Object.freeze({
138757
+ listActions: object.listObjectActions,
138758
+ applyAction: object.applyObjectAction
138759
+ });
138760
+ const reviewGroup = Object.freeze({
138761
+ acceptRevision: review.acceptRevision,
138762
+ rejectRevision: review.rejectRevision,
138763
+ resolveCommentThread: review.resolveCommentThread,
138764
+ resolveIssue: review.resolveIssue,
138765
+ reopenIssue: review.reopenIssue
138766
+ });
138767
+ const policyGroup = Object.freeze({
138768
+ getPolicy: policy.getPolicy,
138769
+ listActions: policy.listAIActions,
138770
+ evaluateAction: evaluate.evaluateAction
138771
+ });
138772
+ const exportGroup = Object.freeze({
138773
+ reviewedDocument: exportFamily.exportReviewedDocument
138774
+ });
138775
+ const category = Object.freeze({
138776
+ read,
138777
+ target,
138778
+ edit,
138779
+ template,
138780
+ table: tableGroup,
138781
+ list,
138782
+ object: objectGroup,
138783
+ review: reviewGroup,
138784
+ policy: policyGroup,
138785
+ export: exportGroup
138786
+ });
138787
+ const family = {
138788
+ agent() {
138789
+ return category;
138790
+ }
138791
+ };
138792
+ return {
138793
+ agent: family.agent()
138794
+ };
138795
+ }
138796
+
137180
138797
  // src/api/v3/_create.ts
137181
138798
  function createApiV3(handle, opts) {
137182
138799
  const ai = {
@@ -137194,7 +138811,8 @@ function createApiV3(handle, opts) {
137194
138811
  ...createOutlineFamily(handle),
137195
138812
  ...createTableActionFamily(handle),
137196
138813
  ...createObjectActionFamily(handle),
137197
- ...createActionsFamily(handle)
138814
+ ...createActionsFamily(handle),
138815
+ ...createAgentFamily(handle, opts?.pe2Evidence)
137198
138816
  };
137199
138817
  const runtime = {
137200
138818
  document: createDocumentFamily(handle),