@superdoc/mcp 1.0.0-next.6 → 1.0.0-next.8

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 (2) hide show
  1. package/dist/index.js +1424 -457
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -199498,6 +199498,93 @@ var init_contract = __esm(() => {
199498
199498
  revisionGroupId: {
199499
199499
  type: "string"
199500
199500
  },
199501
+ reviewGroup: {
199502
+ type: "object",
199503
+ properties: {
199504
+ kind: {
199505
+ const: "text-rewrite"
199506
+ },
199507
+ role: {
199508
+ enum: [
199509
+ "parent",
199510
+ "child"
199511
+ ]
199512
+ },
199513
+ parentId: {
199514
+ type: "string"
199515
+ },
199516
+ childChangeIds: {
199517
+ type: "array",
199518
+ items: {
199519
+ type: "string"
199520
+ }
199521
+ },
199522
+ members: {
199523
+ type: "array",
199524
+ items: {
199525
+ type: "object",
199526
+ properties: {
199527
+ id: {
199528
+ type: "string"
199529
+ },
199530
+ type: {
199531
+ enum: [
199532
+ "insertion",
199533
+ "deletion",
199534
+ "replacement"
199535
+ ]
199536
+ },
199537
+ subtype: {
199538
+ type: "string"
199539
+ },
199540
+ sourceIds: {
199541
+ type: "object",
199542
+ properties: {
199543
+ wordIdInsert: {
199544
+ type: "string",
199545
+ description: "Word `w:id` value from the insertion side of this logical change."
199546
+ },
199547
+ wordIdDelete: {
199548
+ type: "string",
199549
+ description: "Word `w:id` value from the deletion side of this logical change."
199550
+ },
199551
+ wordIdOther: {
199552
+ type: "array",
199553
+ items: {
199554
+ type: "string"
199555
+ },
199556
+ description: "Word `w:id` values from other wrappers (for example moveFrom/moveTo)."
199557
+ },
199558
+ rsids: {
199559
+ type: "array",
199560
+ items: {
199561
+ type: "string"
199562
+ },
199563
+ description: "Word revision-save ids (`w:rsidR` / `w:rsidDel`) seen on contributing wrappers."
199564
+ }
199565
+ },
199566
+ additionalProperties: false,
199567
+ description: "Canonical multi-side source provenance. Provenance metadata only; never the canonical SuperDoc tracked-change id."
199568
+ }
199569
+ },
199570
+ additionalProperties: false,
199571
+ required: [
199572
+ "id",
199573
+ "type",
199574
+ "subtype",
199575
+ "sourceIds"
199576
+ ]
199577
+ }
199578
+ }
199579
+ },
199580
+ additionalProperties: false,
199581
+ required: [
199582
+ "kind",
199583
+ "role",
199584
+ "childChangeIds",
199585
+ "members"
199586
+ ]
199587
+ },
199501
199588
  author: {
199502
199589
  type: "string"
199503
199590
  },
@@ -200406,6 +200493,93 @@ var init_contract = __esm(() => {
200406
200493
  revisionGroupId: {
200407
200494
  type: "string"
200408
200495
  },
200496
+ reviewGroup: {
200497
+ type: "object",
200498
+ properties: {
200499
+ kind: {
200500
+ const: "text-rewrite"
200501
+ },
200502
+ role: {
200503
+ enum: [
200504
+ "parent",
200505
+ "child"
200506
+ ]
200507
+ },
200508
+ parentId: {
200509
+ type: "string"
200510
+ },
200511
+ childChangeIds: {
200512
+ type: "array",
200513
+ items: {
200514
+ type: "string"
200515
+ }
200516
+ },
200517
+ members: {
200518
+ type: "array",
200519
+ items: {
200520
+ type: "object",
200521
+ properties: {
200522
+ id: {
200523
+ type: "string"
200524
+ },
200525
+ type: {
200526
+ enum: [
200527
+ "insertion",
200528
+ "deletion",
200529
+ "replacement"
200530
+ ]
200531
+ },
200532
+ subtype: {
200533
+ type: "string"
200534
+ },
200535
+ sourceIds: {
200536
+ type: "object",
200537
+ properties: {
200538
+ wordIdInsert: {
200539
+ type: "string",
200540
+ description: "Word `w:id` value from the insertion side of this logical change."
200541
+ },
200542
+ wordIdDelete: {
200543
+ type: "string",
200544
+ description: "Word `w:id` value from the deletion side of this logical change."
200545
+ },
200546
+ wordIdOther: {
200547
+ type: "array",
200548
+ items: {
200549
+ type: "string"
200550
+ },
200551
+ description: "Word `w:id` values from other wrappers (for example moveFrom/moveTo)."
200552
+ },
200553
+ rsids: {
200554
+ type: "array",
200555
+ items: {
200556
+ type: "string"
200557
+ },
200558
+ description: "Word revision-save ids (`w:rsidR` / `w:rsidDel`) seen on contributing wrappers."
200559
+ }
200560
+ },
200561
+ additionalProperties: false,
200562
+ description: "Canonical multi-side source provenance. Provenance metadata only; never the canonical SuperDoc tracked-change id."
200563
+ }
200564
+ },
200565
+ additionalProperties: false,
200566
+ required: [
200567
+ "id",
200568
+ "type",
200569
+ "subtype",
200570
+ "sourceIds"
200571
+ ]
200572
+ }
200573
+ }
200574
+ },
200575
+ additionalProperties: false,
200576
+ required: [
200577
+ "kind",
200578
+ "role",
200579
+ "childChangeIds",
200580
+ "members"
200581
+ ]
200582
+ },
200409
200583
  splitFromId: {
200410
200584
  oneOf: [
200411
200585
  {
@@ -349641,7 +349815,7 @@ var init_host = __esm(() => {
349641
349815
  });
349642
349816
 
349643
349817
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
349644
- var SDK_VERSION = "2.13.0-next.8";
349818
+ var SDK_VERSION = "2.13.0-next.10";
349645
349819
 
349646
349820
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
349647
349821
  import { chmodSync, existsSync } from "node:fs";
@@ -389676,7 +389850,6 @@ async function runReplaceTextUnchecked(doc2, args) {
389676
389850
  let skippedEdits = [];
389677
389851
  let steps;
389678
389852
  let applyExpectedRevision;
389679
- const preserveTargets = [];
389680
389853
  if (args.selector) {
389681
389854
  const target = selectorToBlockTarget(args.selector, pre);
389682
389855
  if (!target) {
@@ -389715,13 +389888,6 @@ async function runReplaceTextUnchecked(doc2, args) {
389715
389888
  ];
389716
389889
  applyExpectedRevision = pre.revision;
389717
389890
  selectedTargets.push({ selector: args.selector, matched: [target.nodeId] });
389718
- preserveTargets.push({
389719
- nodeId: target.nodeId,
389720
- nodeType: target.nodeType ?? "paragraph",
389721
- oldText: target.text,
389722
- newText: rewrittenText,
389723
- runs: await captureBlockRuns(doc2, target.nodeId, target.text)
389724
- });
389725
389891
  } else {
389726
389892
  let candidates = args.edits.map((edit, editIndex) => ({
389727
389893
  edit,
@@ -389778,12 +389944,6 @@ async function runReplaceTextUnchecked(doc2, args) {
389778
389944
  steps = candidates.map((candidate) => candidate.step);
389779
389945
  }
389780
389946
  const result = await executeMutations(doc2, steps, args.changeMode, applyExpectedRevision);
389781
- const preserved = [];
389782
- for (const entry of preserveTargets) {
389783
- const restored = await preserveRunPatternAfterRewrite(doc2, entry.nodeId, entry.oldText, entry.runs, entry.newText);
389784
- if (restored)
389785
- preserved.push({ nodeId: entry.nodeId, ...restored });
389786
- }
389787
389947
  if (args.selector && selectedTargets[0]) {
389788
389948
  const post = await buildMutationSnapshot(doc2, { includeDomains: selectorDomains ?? ["blocks"] });
389789
389949
  const blockId = selectedTargets[0].matched[0];
@@ -389812,10 +389972,7 @@ async function runReplaceTextUnchecked(doc2, args) {
389812
389972
  preSnapshot: { revision: pre.revision, counts: pre.counts },
389813
389973
  postSnapshot: { revision: post.revision, counts: post.counts },
389814
389974
  selectedTargets,
389815
- executedOperations: [
389816
- { operationId: "doc.mutations.apply", result },
389817
- ...preserved.length > 0 ? [{ operationId: "doc.format.apply", result: { preserved } }] : []
389818
- ],
389975
+ executedOperations: [{ operationId: "doc.mutations.apply", result }],
389819
389976
  verification: verification2
389820
389977
  };
389821
389978
  }
@@ -389836,8 +389993,7 @@ async function runReplaceTextUnchecked(doc2, args) {
389836
389993
  operationId: "doc.mutations.apply",
389837
389994
  ...skippedEditRationale ? { rationale: skippedEditRationale } : {},
389838
389995
  result
389839
- },
389840
- ...preserved.length > 0 ? [{ operationId: "doc.format.apply", result: { preserved } }] : []
389996
+ }
389841
389997
  ],
389842
389998
  verification
389843
389999
  };
@@ -390811,7 +390967,6 @@ async function runRewriteBlock(doc2, args) {
390811
390967
  throw new Error("selector did not resolve to a body block");
390812
390968
  context.selectedTargets.push({ selector: args.selector, matched: [target.nodeId] });
390813
390969
  const text = normalizeTitleLikeRewriteText(target.text, args.text);
390814
- const runs = await captureBlockRuns(doc2, target.nodeId, target.text);
390815
390970
  await executeMutations(context.document, [
390816
390971
  {
390817
390972
  id: "rewrite-block-1",
@@ -390820,7 +390975,6 @@ async function runRewriteBlock(doc2, args) {
390820
390975
  args: { replacement: { text }, style: preserveRewriteStyle() }
390821
390976
  }
390822
390977
  ], args.changeMode, pre.revision);
390823
- await preserveRunPatternAfterRewrite(context.document, target.nodeId, target.text, runs, text);
390824
390978
  const post = await context.finish();
390825
390979
  const rewritten = await post.block(target.nodeId);
390826
390980
  const verification = [
@@ -390951,57 +391105,6 @@ async function preserveScopedRunPattern(doc2, nodeId, oldText, oldRuns, spans) {
390951
391105
  return { skipped: reasonOf(err) };
390952
391106
  }
390953
391107
  }
390954
- async function preserveRunPatternAfterRewrite(doc2, nodeId, oldText, oldRuns, newText) {
390955
- if (!oldRuns || oldRuns.length === 0)
390956
- return null;
390957
- if (!oldRuns.some((run) => Object.keys(inlineFromSnapshotRun(run, new Set)).length > 0))
390958
- return null;
390959
- const formatFn = maybeMethod2(doc2, ["format", "apply"]);
390960
- if (!formatFn)
390961
- return null;
390962
- const normalize = new Set(RUN_BOOL_MARKS.filter((key) => oldRuns.some((run) => run[key])));
390963
- const oldTrim = oldText.trim();
390964
- const newTrimStart = newText.length - newText.trimStart().length;
390965
- const newTrim = newText.trim();
390966
- let prefix = 0;
390967
- const maxCommon = Math.min(oldTrim.length, newTrim.length);
390968
- while (prefix < maxCommon && oldTrim[prefix] === newTrim[prefix])
390969
- prefix += 1;
390970
- let suffix = 0;
390971
- while (suffix < maxCommon - prefix && oldTrim[oldTrim.length - 1 - suffix] === newTrim[newTrim.length - 1 - suffix])
390972
- suffix += 1;
390973
- const delta = newTrim.length - oldTrim.length;
390974
- let applied = 0;
390975
- const applyRange = async (start, end, inline) => {
390976
- if (end <= start || Object.keys(inline).length === 0)
390977
- return;
390978
- const changed = await applyInlineQuiet(formatFn, {
390979
- blockId: nodeId,
390980
- start: newTrimStart + start,
390981
- end: newTrimStart + end,
390982
- inline
390983
- });
390984
- if (changed)
390985
- applied += 1;
390986
- };
390987
- try {
390988
- for (const run of oldRuns) {
390989
- const inline = inlineFromSnapshotRun(run, normalize);
390990
- await applyRange(run.start, Math.min(run.end, prefix), inline);
390991
- const sufStart = Math.max(run.start, oldTrim.length - suffix);
390992
- if (run.end > sufStart)
390993
- await applyRange(sufStart + delta, run.end + delta, inline);
390994
- }
390995
- const middleEnd = newTrim.length - suffix;
390996
- if (middleEnd > prefix) {
390997
- const anchorRun = oldRuns.find((run) => prefix > run.start && prefix <= run.end) ?? oldRuns[oldRuns.length - 1];
390998
- await applyRange(prefix, middleEnd, inlineFromSnapshotRun(anchorRun, normalize));
390999
- }
391000
- return applied > 0 ? { restoredRunRanges: applied } : null;
391001
- } catch (err) {
391002
- return { skipped: reasonOf(err) };
391003
- }
391004
- }
391005
391108
  function normalizeColor(raw) {
391006
391109
  const trimmed = raw.trim();
391007
391110
  if (trimmed.length === 0)
@@ -394856,7 +394959,7 @@ var init_actions = __esm(() => {
394856
394959
  delete_blocks: 'selectors[] (each resolving to ONE inspected block: list item, paragraph or heading), changeMode? — THE way to DELETE a whole LIST ITEM, paragraph or heading, bullet/number included. Use for "remove the first item under Article II" / "delete that clause". delete_text only strikes the text and leaves an empty numbered item behind. Deletes several blocks in ONE call; use delete_table for a whole table and delete_text to clear a table cell (a cell must keep a paragraph)',
394857
394960
  append_list: 'items[], kind?: ordered|bullet, headingText?, headingLevel?, placement? {at:"after"|"before",selector} builds the list at that block instead of document end',
394858
394961
  create_table: 'rows, columns, cellTexts? (2D: rows of cells; each cell is a plain string OR a STYLED object {runs:[{text,marks}], marks?} to format the cell — marks: bold/italic/underline/strikethrough/fontFamily/fontSize(points)/color(hex)/highlight), placement?, changeMode? — style cells HERE, do not format_text afterward; changeMode:"tracked" makes the table insertion itself a tracked change',
394859
- rewrite_block: "selector, text, changeMode? — REPLACES the whole block text; the block's intra-paragraph run pattern is preserved best-effort over the unchanged prefix/suffix. For appending a NEW paragraph/clause use insert_paragraphs, and for small wording edits prefer replace_text with a minimal find span",
394962
+ rewrite_block: "selector, text, changeMode? — REPLACES the whole block text using the document API's formatting preservation. For appending a NEW paragraph/clause use insert_paragraphs, and for small wording edits prefer replace_text with a minimal find span",
394860
394963
  fill_placeholders: "values[] and/or fields[{label?,value}], changeMode?",
394861
394964
  move_range: `fromText (text in the FIRST block of the range to move), toText? (text in the LAST block — omit to auto-extend across the whole VISUAL SECTION: from fromText up to the next heading-like/ALL-CAPS/bold title), then exactly ONE destination: afterText OR beforeText (text in the block to land after/before). Direct-only today: changeMode:"tracked" fails with no mutation because block-range deletion cannot be tracked. Moves plain paragraph/heading text only; a range containing a table, list, or image is refused with nothing changed. THE way to MOVE a contiguous block range or a visual "section" identified BY TEXT (works on styled-paragraph sections like PREAMBLE / SCHEDULE A that are NOT Word heading nodes). afterText on a heading-like block lands the range after that block's WHOLE section.`,
394862
394965
  comment_paragraphs: "commentText, scope?: all|body, excludeBlockQuotes?",
@@ -407310,7 +407413,7 @@ function refConfigSchemas() {
407310
407413
  failure: refFailureSchema
407311
407414
  };
407312
407415
  }
407313
- var trackChangeTypeValues, sourcePathSchema, diagnosticPathSchema, conversionSourceRangeSchema, conversionSourceSchema, diagnosticProperties, sdDiagnosticSchema, sdConversionDiagnosticSchema, conversionReportSchema, receiptSuccessMetadataProperties, nodeTypeValues, blockNodeTypeValues, deletableBlockNodeTypeValues, inlineNodeTypeValues, knownTargetKindValues, SHARED_DEFS, rangeSchema, positionSchema, inlineAnchorSchema, targetKindSchema, textAddressSchema, textTargetSchema, commentTrackedChangeTargetSchema, textSearchCommentTargetSchema, blockNodeAddressSchema, deletableBlockNodeAddressSchema, tableAddressSchema, tableRowAddressSchema, tableCellAddressSchema, tableOrCellAddressSchema, paragraphAddressSchema, headingAddressSchema, listItemAddressSchema, listsV2BlockTargetSchema, paragraphTargetSchema, sectionAddressSchema, watermarkSlotTargetSchema, watermarkTargetSchema, watermarkAddressSchema, watermarkHorizontalPlacementSchema, watermarkVerticalPlacementSchema, watermarkPlacementSchema, textWatermarkSchema, pictureWatermarkInputSchema, pictureWatermarkInfoSchema, watermarkInfoSchema, inlineNodeAddressSchema, nodeAddressSchema, commentAddressSchema, trackedChangeAddressSchema, entityAddressSchema, selectionTargetSchema, commentTrackedChangeLinkSchema, targetLocatorSchema, deleteBehaviorSchema, resolvedHandleSchema, pageInfoSchema, receiptSuccessSchema, commentsCreateSuccessSchema, textMutationRangeSchema, textMutationResolutionSchema, textMutationSuccessSchema, matchRunSchema, matchBlockSchema, storyLocatorSchema, bodyStoryLocatorSchema, markRunColorRefSchema, markRunFontsSchema, markRunLanguagesSchema, markRunUnderlineSchema, markRunShadingSchema, markRunBorderSchema, markRunPropsSchema, trackChangeRefSchema, createParagraphSuccessSchema, createHeadingSuccessSchema, createHeadingLevelSchema, semanticHeadingLevelSchema, listsInsertSuccessSchema, listsMutateItemSuccessSchema, listsExitSuccessSchema, nodeSummarySchema, nodeInfoSchema, matchContextSchema, unknownNodeDiagnosticSchema, textSelectorSchema, planTextSelectorSchema, nodeSelectorSchema, selectorShorthandSchema, sdTextSelectorSchema, sdNodeSelectorSchema, sdSelectorSchema, sdReadOptionsSchema, sdFindInputSchema, sdNodeResultSchema, sdFindResultSchema, sdMutationResolutionSchema, evaluatedRevisionSchema, sdMutationSuccessSchema, documentInfoCountsSchema, documentInfoOutlineItemSchema, documentInfoCapabilitiesSchema, documentStyleInfoSchema, documentStylesSchema, documentDefaultsSchema, documentInfoSchema, listKindSchema, listInsertPositionSchema, listItemInfoSchema, listItemDomainItemSchema, listsListResultSchema, sectionBreakTypeSchema, sectionOrientationSchema, sectionVerticalAlignSchema, sectionDirectionSchema, sectionHeaderFooterKindSchema, sectionHeaderFooterVariantSchema, sectionLineNumberRestartSchema, sectionPageNumberFormatSchema, sectionRangeDomainSchema, sectionPageMarginsSchema, sectionHeaderFooterMarginsSchema, sectionPageSetupSchema, sectionColumnsSchema, sectionLineNumberingSchema, sectionPageNumberingSchema, sectionHeaderFooterRefsSchema, sectionBorderSpecSchema, sectionPageBordersSchema, sectionInfoSchema, sectionResolvedHandleSchema, sectionDomainItemSchema, sectionsListResultSchema, sectionMutationSuccessSchema, documentMutationSuccessSchema, paragraphMutationTargetSchema, paragraphMutationSuccessSchema, createSectionBreakSuccessSchema, commentMetadataSchema, commentInfoSchema, commentDomainItemSchema, commentsListResultSchema, trackChangeWordRevisionIdsSchema, trackChangeSourceIdsSchema, trackChangeBroadTypeEnum, trackChangeGroupingEnum, trackChangeCanonicalizationKindEnum, trackChangeAddressKindEnum, trackChangeSourcePlatformEnum, trackChangeReplacementSideSchema, trackChangeReplacementSchema, trackChangeOverlapRelationshipSchema, trackChangeOverlapLayerSchema, trackChangeOverlapInfoSchema, trackChangeFormattingSnapshotSchema, trackChangeListDeltaKindEnum, trackChangeListDeltaSideSchema, trackChangeListMemberDeltaSchema, trackChangeListDeltaSummarySchema, trackChangeTargetSchema, trackChangeSnapshotSchema, trackChangeCustomAttributeSchema, trackChangeInfoSchema, trackChangeDomainItemSchema, trackChangesListResultSchema, reviewDecideRangeTargetOptions, historyActionCollaborationSchema, capabilityReasonCodeSchema, capabilityReasonsSchema, capabilityFlagSchema, operationRuntimeCapabilitySchema, operationCapabilitiesSchema, inlinePropertyCapabilitySchema, inlinePropertyCapabilitiesByKeySchema, formatCapabilitiesSchema, planEngineCapabilitiesSchema, capabilitiesOutputSchema, strictEmptyObjectSchema, tableBorderColorPattern, tableBorderSpecSchema, nullableTableBorderSpecSchema, sdFragmentSchema, conversionFragmentSchema, placementSchema, nestingPolicySchema, insertInputSchema, supportCheckRichInsertInputSchema, supportCheckRichReplaceInputSchema, supportCheckProjectionInputSchema, supportCheckInputSchema, supportCheckFailureSchema, supportCheckGuardSchema, supportCheckCommonProperties, supportCheckOutputSchema, tableLocatorSchema, cellLocatorSchema, cellOrTableScopedCellLocatorSchema, tableOrCellLocatorSchema, mergeRangeLocatorSchema, tableAnchorLocationMembers, tableAnchorLocationSchema, tableCreateLocationSchema, tableMutationSuccessSchema, createTableSuccessSchema, tableMutationFailureCodes, tableMutationFailureSchema, tableMutationResultSchema, createTableResultSchema, historyActionSuccessSchema, historyActionFailureSchema, formatInlineAliasOperationSchemas, tocMutationFailureCodes, tocMutationFailureSchema, tocMutationSuccessSchema, tocEntryMutationFailureCodes, tocEntryMutationFailureSchema, tocEntryMutationSuccessSchema, hyperlinkTargetSchema, hyperlinkReadPropertiesSchema, hyperlinkDestinationSchema, hyperlinkSpecSchema, hyperlinkPatchSchema, hyperlinkDomainSchema, hyperlinkMutationSuccessSchema, hyperlinkMutationFailureCodes, hyperlinkMutationFailureSchema, hyperlinkInfoSchema, contentControlTargetSchema, contentControlMoveDestinationSchema, contentControlMutationSuccessSchema, contentControlMutationFailureSchema, ccInfoSchema, ccListResultSchema, refListQueryProperties, refListQuerySchema, discoveryOutputSchema, receiptFailureSchema, refFailureSchema, bookmarkAddressSchema, bookmarkMutation, customXmlPartTargetSchema, customXmlPartMutation, customXmlPartCreateMutation, anchoredMetadataAttachMutation, anchoredMetadataMutation, footnoteAddressSchema, footnoteConfigScopeSchema, footnoteNumberingSchema, footnoteMutation, footnoteConfig, crossRefAddressSchema, crossRefTargetSchema, crossRefDisplaySchema, crossRefMutation, indexAddressSchema, indexEntryAddressSchema, indexConfigSchema, indexEntryDataSchema, indexEntryPatchSchema, indexMutation, indexEntryMutation, captionAddressSchema, captionMutation, captionConfig, fieldAddressSchema, fieldMutation, citationAddressSchema, citationSourceAddressSchema, bibliographyAddressSchema, citationMutation, citationSourceMutation, bibliographyMutation, citationPersonSchema, citationSourceFieldsSchema, tocCreateLocationSchema, authoritiesAddressSchema, authorityEntryAddressSchema, authoritiesConfigSchema, authorityEntryDataSchema, authorityEntryPatchSchema, authoritiesMutation, authorityEntryMutation, diffCoverageSchema, diffSummarySchema, diffSnapshotSchema, diffApplyEligibilityBlockerSchema, diffApplyModeEligibilitySchema, diffApplyEligibilitySchema, diffPayloadSchema, diffApplyResultSchema, operationSchemas;
407416
+ var trackChangeTypeValues, sourcePathSchema, diagnosticPathSchema, conversionSourceRangeSchema, conversionSourceSchema, diagnosticProperties, sdDiagnosticSchema, sdConversionDiagnosticSchema, conversionReportSchema, receiptSuccessMetadataProperties, nodeTypeValues, blockNodeTypeValues, deletableBlockNodeTypeValues, inlineNodeTypeValues, knownTargetKindValues, SHARED_DEFS, rangeSchema, positionSchema, inlineAnchorSchema, targetKindSchema, textAddressSchema, textTargetSchema, commentTrackedChangeTargetSchema, textSearchCommentTargetSchema, blockNodeAddressSchema, deletableBlockNodeAddressSchema, tableAddressSchema, tableRowAddressSchema, tableCellAddressSchema, tableOrCellAddressSchema, paragraphAddressSchema, headingAddressSchema, listItemAddressSchema, listsV2BlockTargetSchema, paragraphTargetSchema, sectionAddressSchema, watermarkSlotTargetSchema, watermarkTargetSchema, watermarkAddressSchema, watermarkHorizontalPlacementSchema, watermarkVerticalPlacementSchema, watermarkPlacementSchema, textWatermarkSchema, pictureWatermarkInputSchema, pictureWatermarkInfoSchema, watermarkInfoSchema, inlineNodeAddressSchema, nodeAddressSchema, commentAddressSchema, trackedChangeAddressSchema, entityAddressSchema, selectionTargetSchema, commentTrackedChangeLinkSchema, targetLocatorSchema, deleteBehaviorSchema, resolvedHandleSchema, pageInfoSchema, receiptSuccessSchema, commentsCreateSuccessSchema, textMutationRangeSchema, textMutationResolutionSchema, textMutationSuccessSchema, matchRunSchema, matchBlockSchema, storyLocatorSchema, bodyStoryLocatorSchema, markRunColorRefSchema, markRunFontsSchema, markRunLanguagesSchema, markRunUnderlineSchema, markRunShadingSchema, markRunBorderSchema, markRunPropsSchema, trackChangeRefSchema, createParagraphSuccessSchema, createHeadingSuccessSchema, createHeadingLevelSchema, semanticHeadingLevelSchema, listsInsertSuccessSchema, listsMutateItemSuccessSchema, listsExitSuccessSchema, nodeSummarySchema, nodeInfoSchema, matchContextSchema, unknownNodeDiagnosticSchema, textSelectorSchema, planTextSelectorSchema, nodeSelectorSchema, selectorShorthandSchema, sdTextSelectorSchema, sdNodeSelectorSchema, sdSelectorSchema, sdReadOptionsSchema, sdFindInputSchema, sdNodeResultSchema, sdFindResultSchema, sdMutationResolutionSchema, evaluatedRevisionSchema, sdMutationSuccessSchema, documentInfoCountsSchema, documentInfoOutlineItemSchema, documentInfoCapabilitiesSchema, documentStyleInfoSchema, documentStylesSchema, documentDefaultsSchema, documentInfoSchema, listKindSchema, listInsertPositionSchema, listItemInfoSchema, listItemDomainItemSchema, listsListResultSchema, sectionBreakTypeSchema, sectionOrientationSchema, sectionVerticalAlignSchema, sectionDirectionSchema, sectionHeaderFooterKindSchema, sectionHeaderFooterVariantSchema, sectionLineNumberRestartSchema, sectionPageNumberFormatSchema, sectionRangeDomainSchema, sectionPageMarginsSchema, sectionHeaderFooterMarginsSchema, sectionPageSetupSchema, sectionColumnsSchema, sectionLineNumberingSchema, sectionPageNumberingSchema, sectionHeaderFooterRefsSchema, sectionBorderSpecSchema, sectionPageBordersSchema, sectionInfoSchema, sectionResolvedHandleSchema, sectionDomainItemSchema, sectionsListResultSchema, sectionMutationSuccessSchema, documentMutationSuccessSchema, paragraphMutationTargetSchema, paragraphMutationSuccessSchema, createSectionBreakSuccessSchema, commentMetadataSchema, commentInfoSchema, commentDomainItemSchema, commentsListResultSchema, trackChangeWordRevisionIdsSchema, trackChangeSourceIdsSchema, trackChangeBroadTypeEnum, trackChangeGroupingEnum, trackChangeCanonicalizationKindEnum, trackChangeAddressKindEnum, trackChangeSourcePlatformEnum, trackChangeReplacementSideSchema, trackChangeReplacementSchema, trackChangeOverlapRelationshipSchema, trackChangeOverlapLayerSchema, trackChangeOverlapInfoSchema, trackChangeFormattingSnapshotSchema, trackChangeListDeltaKindEnum, trackChangeListDeltaSideSchema, trackChangeListMemberDeltaSchema, trackChangeListDeltaSummarySchema, trackChangeTargetSchema, trackChangeSnapshotSchema, trackChangeCustomAttributeSchema, trackChangeRewriteReviewGroupSchema, trackChangeInfoSchema, trackChangeDomainItemSchema, trackChangesListResultSchema, reviewDecideRangeTargetOptions, historyActionCollaborationSchema, capabilityReasonCodeSchema, capabilityReasonsSchema, capabilityFlagSchema, operationRuntimeCapabilitySchema, operationCapabilitiesSchema, inlinePropertyCapabilitySchema, inlinePropertyCapabilitiesByKeySchema, formatCapabilitiesSchema, planEngineCapabilitiesSchema, capabilitiesOutputSchema, strictEmptyObjectSchema, tableBorderColorPattern, tableBorderSpecSchema, nullableTableBorderSpecSchema, sdFragmentSchema, conversionFragmentSchema, placementSchema, nestingPolicySchema, insertInputSchema, supportCheckRichInsertInputSchema, supportCheckRichReplaceInputSchema, supportCheckProjectionInputSchema, supportCheckInputSchema, supportCheckFailureSchema, supportCheckGuardSchema, supportCheckCommonProperties, supportCheckOutputSchema, tableLocatorSchema, cellLocatorSchema, cellOrTableScopedCellLocatorSchema, tableOrCellLocatorSchema, mergeRangeLocatorSchema, tableAnchorLocationMembers, tableAnchorLocationSchema, tableCreateLocationSchema, tableMutationSuccessSchema, createTableSuccessSchema, tableMutationFailureCodes, tableMutationFailureSchema, tableMutationResultSchema, createTableResultSchema, historyActionSuccessSchema, historyActionFailureSchema, formatInlineAliasOperationSchemas, tocMutationFailureCodes, tocMutationFailureSchema, tocMutationSuccessSchema, tocEntryMutationFailureCodes, tocEntryMutationFailureSchema, tocEntryMutationSuccessSchema, hyperlinkTargetSchema, hyperlinkReadPropertiesSchema, hyperlinkDestinationSchema, hyperlinkSpecSchema, hyperlinkPatchSchema, hyperlinkDomainSchema, hyperlinkMutationSuccessSchema, hyperlinkMutationFailureCodes, hyperlinkMutationFailureSchema, hyperlinkInfoSchema, contentControlTargetSchema, contentControlMoveDestinationSchema, contentControlMutationSuccessSchema, contentControlMutationFailureSchema, ccInfoSchema, ccListResultSchema, refListQueryProperties, refListQuerySchema, discoveryOutputSchema, receiptFailureSchema, refFailureSchema, bookmarkAddressSchema, bookmarkMutation, customXmlPartTargetSchema, customXmlPartMutation, customXmlPartCreateMutation, anchoredMetadataAttachMutation, anchoredMetadataMutation, footnoteAddressSchema, footnoteConfigScopeSchema, footnoteNumberingSchema, footnoteMutation, footnoteConfig, crossRefAddressSchema, crossRefTargetSchema, crossRefDisplaySchema, crossRefMutation, indexAddressSchema, indexEntryAddressSchema, indexConfigSchema, indexEntryDataSchema, indexEntryPatchSchema, indexMutation, indexEntryMutation, captionAddressSchema, captionMutation, captionConfig, fieldAddressSchema, fieldMutation, citationAddressSchema, citationSourceAddressSchema, bibliographyAddressSchema, citationMutation, citationSourceMutation, bibliographyMutation, citationPersonSchema, citationSourceFieldsSchema, tocCreateLocationSchema, authoritiesAddressSchema, authorityEntryAddressSchema, authoritiesConfigSchema, authorityEntryDataSchema, authorityEntryPatchSchema, authoritiesMutation, authorityEntryMutation, diffCoverageSchema, diffSummarySchema, diffSnapshotSchema, diffApplyEligibilityBlockerSchema, diffApplyModeEligibilitySchema, diffApplyEligibilitySchema, diffPayloadSchema, diffApplyResultSchema, operationSchemas;
407314
407417
  var init_schemas4 = __esm(() => {
407315
407418
  init_command_catalog();
407316
407419
  init_types4();
@@ -408827,6 +408930,21 @@ var init_schemas4 = __esm(() => {
408827
408930
  localName: { type: "string" },
408828
408931
  value: { type: "string" }
408829
408932
  }, ["name", "namespaceUri", "localName", "value"]);
408933
+ trackChangeRewriteReviewGroupSchema = objectSchema2({
408934
+ kind: { const: "text-rewrite" },
408935
+ role: { enum: ["parent", "child"] },
408936
+ parentId: { type: "string" },
408937
+ childChangeIds: { type: "array", items: { type: "string" } },
408938
+ members: {
408939
+ type: "array",
408940
+ items: objectSchema2({
408941
+ id: { type: "string" },
408942
+ type: { enum: ["insertion", "deletion", "replacement"] },
408943
+ subtype: { type: "string" },
408944
+ sourceIds: trackChangeSourceIdsSchema
408945
+ }, ["id", "type", "subtype", "sourceIds"])
408946
+ }
408947
+ }, ["kind", "role", "childChangeIds", "members"]);
408830
408948
  trackChangeInfoSchema = objectSchema2({
408831
408949
  address: trackedChangeAddressSchema,
408832
408950
  id: { type: "string" },
@@ -408839,6 +408957,7 @@ var init_schemas4 = __esm(() => {
408839
408957
  sourceIds: trackChangeSourceIdsSchema,
408840
408958
  wordRevisionIds: trackChangeWordRevisionIdsSchema,
408841
408959
  revisionGroupId: { type: "string" },
408960
+ reviewGroup: trackChangeRewriteReviewGroupSchema,
408842
408961
  splitFromId: { oneOf: [{ type: "string" }, { type: "null" }] },
408843
408962
  replacement: trackChangeReplacementSchema,
408844
408963
  author: { type: "string" },
@@ -408889,6 +409008,7 @@ var init_schemas4 = __esm(() => {
408889
409008
  sourceIds: trackChangeSourceIdsSchema,
408890
409009
  wordRevisionIds: trackChangeWordRevisionIdsSchema,
408891
409010
  revisionGroupId: { type: "string" },
409011
+ reviewGroup: trackChangeRewriteReviewGroupSchema,
408892
409012
  author: { type: "string" },
408893
409013
  authorEmail: { type: "string" },
408894
409014
  authorImage: { type: "string" },
@@ -469788,6 +469908,214 @@ var init_review_groups = __esm(() => {
469788
469908
  init_numbering_catalog();
469789
469909
  });
469790
469910
 
469911
+ // ../../../v2/editor-core/dist/document/transactions/tracked-changes/rewrite-groups.js
469912
+ function readRewriteGroupId(carrier) {
469913
+ const values = carrier.customAttributes?.filter((attribute) => attribute.namespaceUri === REWRITE_NAMESPACE && attribute.localName === "id");
469914
+ if (values?.length !== 1)
469915
+ return null;
469916
+ const value = values[0].value;
469917
+ return /^[\w.:-]{1,200}$/.test(value) ? value : null;
469918
+ }
469919
+ function stampRewriteGroups(xml, groupsByRsid, source) {
469920
+ if (groupsByRsid.size === 0)
469921
+ return xml;
469922
+ if ([...groupsByRsid.values()].some((id) => !/^[\w.:-]{1,200}$/.test(id)))
469923
+ return null;
469924
+ const raw = buildTrackedChangeCatalogFromPartXml({ xml, ...source });
469925
+ const independentOrigins = new Set;
469926
+ for (const fragment2 of collectIndependentRewriteFragments(raw.byPart.get(source.partUri) ?? [], xml)) {
469927
+ const origin = fragment2.rsid ? groupsByRsid.get(fragment2.rsid) : undefined;
469928
+ if (origin)
469929
+ independentOrigins.add(origin);
469930
+ }
469931
+ const replacements = [];
469932
+ const parsed = walkXmlElements(xml, {
469933
+ fragment: true,
469934
+ additionalNamespaces: xmlFragmentAdditionalNamespaces(xml, new Map, { w: NS_W }),
469935
+ onOpenTag: ({ tag, end, namespaceBindings }) => {
469936
+ if (tag.namespaceUri !== NS_W || tag.isSelfClosing || tag.localName !== "ins" && tag.localName !== "del")
469937
+ return;
469938
+ const rsid = tag.attributes.find((attribute) => attribute.namespaceUri === NS_W && attribute.localName === (tag.localName === "ins" ? "rsidR" : "rsidDel"))?.value;
469939
+ const id = rsid ? groupsByRsid.get(rsid) : undefined;
469940
+ if (!id)
469941
+ return;
469942
+ const availablePrefix = (seed) => {
469943
+ let prefix2 = seed;
469944
+ for (let index = 1;namespaceBindings[prefix2]; index += 1)
469945
+ prefix2 = `${seed}${index}`;
469946
+ return prefix2;
469947
+ };
469948
+ const prefix = availablePrefix("sdRewrite");
469949
+ const mc = availablePrefix("sdRewriteMc");
469950
+ replacements.push({
469951
+ at: end - 1,
469952
+ text: ` xmlns:${prefix}="${REWRITE_NAMESPACE}" xmlns:${mc}="${MC_NAMESPACE}" ${mc}:Ignorable="${prefix}" ${prefix}:id="${id}"${independentOrigins.has(id) ? ` ${prefix}:display="children"` : ""}`
469953
+ });
469954
+ }
469955
+ });
469956
+ if (parsed.errors.length > 0)
469957
+ return null;
469958
+ let cursor = 0;
469959
+ const chunks = [];
469960
+ for (const replacement of replacements) {
469961
+ chunks.push(xml.slice(cursor, replacement.at), replacement.text);
469962
+ cursor = replacement.at;
469963
+ }
469964
+ chunks.push(xml.slice(cursor));
469965
+ return chunks.join("");
469966
+ }
469967
+ function buildTextRewriteReviewGroupId(storyId, origin, noteId) {
469968
+ return buildLogicalId(storyId, "rewrite-group", `${noteId ?? ""}:${origin}`);
469969
+ }
469970
+ function projectRewriteGroups(input) {
469971
+ const groups = new Map;
469972
+ for (const entry of input.byId.values()) {
469973
+ if (entry.reviewGroup || entry.fragments.length === 0 || !["insertion", "deletion", "replacement"].includes(entry.type))
469974
+ continue;
469975
+ const origin = readRewriteGroupId(entry.fragments[0]);
469976
+ if (!origin || entry.fragments.some((fragment2) => readRewriteGroupId(fragment2) !== origin))
469977
+ continue;
469978
+ const id = buildTextRewriteReviewGroupId(entry.storyId, origin, entry.noteId);
469979
+ const members = groups.get(id) ?? [];
469980
+ members.push(entry);
469981
+ groups.set(id, members);
469982
+ }
469983
+ for (const [id, children] of groups) {
469984
+ children.sort((a, b) => a.documentOrderStart - b.documentOrderStart || a.id.localeCompare(b.id));
469985
+ const first = children[0];
469986
+ const display = children.some((child) => child.fragments.some((fragment2) => fragment2.customAttributes?.some((attribute) => attribute.namespaceUri === REWRITE_NAMESPACE && attribute.localName === "display" && attribute.value === "children"))) ? { display: "children" } : {};
469987
+ const fragments = children.flatMap((child) => child.fragments).sort((a, b) => a.byteStart - b.byteStart);
469988
+ const inserted = fragments.filter((fragment2) => fragment2.kind === "ins");
469989
+ const deleted = fragments.filter((fragment2) => fragment2.kind === "del");
469990
+ const type = inserted.length === 0 ? "deletion" : deleted.length === 0 ? "insertion" : "replacement";
469991
+ const wordIdInsert = inserted.find((fragment2) => fragment2.wId)?.wId;
469992
+ const wordIdDelete = deleted.find((fragment2) => fragment2.wId)?.wId;
469993
+ const rsids = [
469994
+ ...new Set(fragments.map((fragment2) => fragment2.rsid).filter((value) => Boolean(value)))
469995
+ ];
469996
+ const parent = {
469997
+ ...first,
469998
+ id,
469999
+ type,
470000
+ subtype: type === "replacement" ? "text-replacement" : type === "insertion" ? "text-insertion" : "text-deletion",
470001
+ revisionGroupId: id,
470002
+ splitFromId: null,
470003
+ documentOrderStart: children.reduce((start, child) => Math.min(start, child.documentOrderStart), first.documentOrderStart),
470004
+ documentOrderEnd: children.reduce((end, child) => Math.max(end, child.documentOrderEnd), first.documentOrderEnd),
470005
+ before: { text: children.map((child) => child.before.text ?? "").join("") },
470006
+ after: { text: children.map((child) => child.after.text ?? "").join("") },
470007
+ sides: null,
470008
+ contributingRsids: rsids,
470009
+ sourceIds: {
470010
+ wordIdInsert,
470011
+ wordIdDelete,
470012
+ wordIdOther: [
470013
+ ...new Set(fragments.map((fragment2) => fragment2.wId).filter((value) => Boolean(value) && value !== wordIdInsert && value !== wordIdDelete))
470014
+ ],
470015
+ rsids
470016
+ },
470017
+ fragments,
470018
+ reviewGroup: {
470019
+ kind: "text-rewrite",
470020
+ ...display,
470021
+ role: "parent",
470022
+ parentId: null,
470023
+ ownedChildIds: children.map((child) => child.id),
470024
+ duplicateDisplayPolicy: "subsumed",
470025
+ members: children.flatMap((child) => child.fragments.map((fragment2) => ({
470026
+ logicalId: child.id,
470027
+ carrier: "text",
470028
+ partUri: fragment2.partUri,
470029
+ storyId: fragment2.storyId,
470030
+ rsid: fragment2.rsid,
470031
+ wordId: fragment2.wId,
470032
+ subtype: child.subtype,
470033
+ byteStart: fragment2.byteStart,
470034
+ byteEnd: fragment2.byteEnd
470035
+ })))
470036
+ }
470037
+ };
470038
+ for (const child of children)
470039
+ child.reviewGroup = {
470040
+ kind: "text-rewrite",
470041
+ ...display,
470042
+ role: "child",
470043
+ parentId: id,
470044
+ ownedChildIds: [],
470045
+ duplicateDisplayPolicy: "subsumed",
470046
+ members: []
470047
+ };
470048
+ input.byId.set(id, parent);
470049
+ input.byStory.get(first.storyId).push(parent);
470050
+ }
470051
+ }
470052
+ function projectTextRewriteReviewGroup(entry, logical) {
470053
+ if (entry.reviewGroup?.kind !== "text-rewrite")
470054
+ return;
470055
+ const group = entry.reviewGroup;
470056
+ return {
470057
+ kind: "text-rewrite",
470058
+ role: group.role,
470059
+ ...group.parentId ? { parentId: group.parentId } : {},
470060
+ childChangeIds: group.ownedChildIds,
470061
+ members: group.ownedChildIds.flatMap((id) => {
470062
+ const child = logical.byId.get(id);
470063
+ return child ? [
470064
+ {
470065
+ id,
470066
+ type: child.type,
470067
+ subtype: child.subtype,
470068
+ sourceIds: child.sourceIds
470069
+ }
470070
+ ] : [];
470071
+ })
470072
+ };
470073
+ }
470074
+ function isVisibleLogicalTrackedChange(entry) {
470075
+ const group = entry.reviewGroup;
470076
+ if (group?.display === "children" ? group.role === "parent" : group?.role === "child")
470077
+ return false;
470078
+ return entry.subsumption?.role !== "child";
470079
+ }
470080
+ function reviewGroupDisplayParentId(entry) {
470081
+ return entry.reviewGroup?.role === "child" && entry.reviewGroup.display !== "children" ? entry.reviewGroup.parentId : null;
470082
+ }
470083
+ var REWRITE_NAMESPACE = "urn:superdoc:tracked-rewrite:1", MC_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006";
470084
+ var init_rewrite_groups = __esm(() => {
470085
+ init_xml_sax();
470086
+ init_catalog3();
470087
+ init_logical_catalog();
470088
+ });
470089
+
470090
+ // ../../../v2/editor-core/dist/document/transactions/tracked-changes/table-split-paragraph.js
470091
+ function isEmptyTableSplitParagraph(xml, excludedStart, excludedEnd) {
470092
+ const shell = /\s+|<[\w.-]+:(?:p|r)\b(?:"[^"]*"|'[^']*'|[^>"'])*>|<\/[\w.-]+:(?:p|r)>/y;
470093
+ const property = /<(?:[\w.-]+:)?(pPr|rPr)(?=[\s/>])/y;
470094
+ let cursor = 0;
470095
+ while (cursor < xml.length) {
470096
+ if (cursor === excludedStart) {
470097
+ cursor = excludedEnd;
470098
+ continue;
470099
+ }
470100
+ property.lastIndex = cursor;
470101
+ const propertyMatch = property.exec(xml);
470102
+ if (propertyMatch) {
470103
+ const element = matchLeadingElement(xml.slice(cursor), propertyMatch[1]);
470104
+ if (!element)
470105
+ return false;
470106
+ cursor += element.length;
470107
+ continue;
470108
+ }
470109
+ shell.lastIndex = cursor;
470110
+ const shellMatch = shell.exec(xml);
470111
+ if (!shellMatch)
470112
+ return false;
470113
+ cursor += shellMatch[0].length;
470114
+ }
470115
+ return true;
470116
+ }
470117
+ var init_table_split_paragraph = () => {};
470118
+
469791
470119
  // ../../../v2/editor-core/dist/document/transactions/tracked-changes/list-deltas.js
469792
470120
  function createListEffectiveSideResolver(input) {
469793
470121
  return (pPrInnerXml) => {
@@ -470456,6 +470784,7 @@ function buildLogicalCatalog(raw, replacementMode, partXmlByUri, splitLineage, o
470456
470784
  structuralKeyToLogicalId,
470457
470785
  partXmlByUri
470458
470786
  });
470787
+ projectRewriteGroups({ byId, byStory });
470459
470788
  projectWordFormattingGroups({
470460
470789
  byId,
470461
470790
  byStory,
@@ -470820,6 +471149,8 @@ function projectOverlapRelationships(byId, partXmlByUri) {
470820
471149
  return;
470821
471150
  const fragmentsByPart = new Map;
470822
471151
  for (const logical of byId.values()) {
471152
+ if (logical.reviewGroup?.kind === "text-rewrite" && logical.reviewGroup.role === "parent")
471153
+ continue;
470823
471154
  if (!isOverlapEligibleType(logical.type))
470824
471155
  continue;
470825
471156
  for (const fragment2 of logical.fragments) {
@@ -471519,6 +471850,10 @@ function resolveReplacementMode(override) {
471519
471850
  return "paired";
471520
471851
  }
471521
471852
  function isReplacementPairCandidate(a, b, noteIdA, noteIdB) {
471853
+ const originA = readRewriteGroupId(a);
471854
+ const originB = readRewriteGroupId(b);
471855
+ if (originA !== originB || originA !== null && a.rsid !== b.rsid)
471856
+ return false;
471522
471857
  const opposites = a.kind === "del" && b.kind === "ins" || a.kind === "ins" && b.kind === "del";
471523
471858
  if (!opposites)
471524
471859
  return false;
@@ -471538,6 +471873,33 @@ function isReplacementPairCandidate(a, b, noteIdA, noteIdB) {
471538
471873
  return false;
471539
471874
  return true;
471540
471875
  }
471876
+ function collectIndependentRewriteFragments(fragments, partXml) {
471877
+ const ordered = [...fragments].sort((a, b) => a.byteStart - b.byteStart || b.byteEnd - a.byteEnd);
471878
+ const independent = new Set;
471879
+ const ancestors = [];
471880
+ const unconsumed = new Set;
471881
+ for (const [index, first] of ordered.entries()) {
471882
+ while (ancestors.length && !isStrictlyNestedIn(first, ancestors[ancestors.length - 1]))
471883
+ ancestors.pop();
471884
+ if (ancestors.some((parent) => parent.author.name !== first.author.name))
471885
+ independent.add(first);
471886
+ ancestors.push(first);
471887
+ const second = findAdjacentTrackedSiblingAfter(ordered, index, partXml, unconsumed);
471888
+ if (!second || !isReplacementPairCandidate(first, second, null, null))
471889
+ continue;
471890
+ const secondIndex = ordered.indexOf(second, index + 1);
471891
+ if (!isChildReplacementInsideDeletion({
471892
+ previous: findAdjacentTrackedSiblingBefore(ordered, index, partXml, unconsumed),
471893
+ first,
471894
+ second,
471895
+ next: findAdjacentTrackedSiblingAfter(ordered, secondIndex, partXml, unconsumed)
471896
+ }))
471897
+ continue;
471898
+ independent.add(first);
471899
+ independent.add(second);
471900
+ }
471901
+ return independent;
471902
+ }
471541
471903
  function isChildReplacementInsideDeletion(input) {
471542
471904
  const childAuthor = input.first.author.name || "";
471543
471905
  const touchesDifferentAuthorDeletionBefore = input.previous?.kind === "del" && (input.previous.author.name || "") !== childAuthor;
@@ -471681,6 +472043,8 @@ function collectAdjacentSameRevisionRun(head, index, fragmentsInPart, partXml, c
471681
472043
  if (run.some((fragment2) => isStrictlyNestedIn(candidate, fragment2)))
471682
472044
  continue;
471683
472045
  const candidateNoteId = noteIdFor(candidate);
472046
+ if ((readRewriteGroupId(head) || readRewriteGroupId(candidate)) && (readRewriteGroupId(head) !== readRewriteGroupId(candidate) || head.wId !== candidate.wId))
472047
+ break;
471684
472048
  if (isSameRevisionFragment(head, candidate, headNoteId, candidateNoteId)) {
471685
472049
  if (maybeBuildDerivedStructuralLogical(candidate, candidateNoteId, partXml))
471686
472050
  break;
@@ -473755,9 +474119,7 @@ function isTableSplitTextInsertion(fragment2, partXml) {
473755
474119
  const paragraphXml2 = partXml.slice(localStart, localEnd);
473756
474120
  const relativeStart2 = fragment2.byteStart - localStart;
473757
474121
  const relativeEnd2 = fragment2.byteEnd - localStart;
473758
- const paragraphWithoutFragment2 = paragraphXml2.slice(0, relativeStart2) + paragraphXml2.slice(relativeEnd2);
473759
- const stripped2 = stripElements(stripElements(paragraphWithoutFragment2, "pPr"), "rPr").replace(/<[\w.-]+:p\b[^>]*>/g, "").replace(/<\/[\w.-]+:p>/g, "").replace(/<[\w.-]+:r\b[^>]*>/g, "").replace(/<\/[\w.-]+:r>/g, "").replace(/\s+/g, "");
473760
- if (stripped2.length !== 0)
474122
+ if (!isEmptyTableSplitParagraph(paragraphXml2, relativeStart2, relativeEnd2))
473761
474123
  return false;
473762
474124
  }
473763
474125
  }
@@ -473782,9 +474144,7 @@ function isTableSplitTextInsertion(fragment2, partXml) {
473782
474144
  const paragraphXml = partXml.slice(paragraph.start, paragraph.end);
473783
474145
  const relativeStart = fragment2.byteStart - paragraph.start;
473784
474146
  const relativeEnd = fragment2.byteEnd - paragraph.start;
473785
- const paragraphWithoutFragment = paragraphXml.slice(0, relativeStart) + paragraphXml.slice(relativeEnd);
473786
- const stripped = stripElements(stripElements(paragraphWithoutFragment, "pPr"), "rPr").replace(/<[\w.-]+:p\b[^>]*>/g, "").replace(/<\/[\w.-]+:p>/g, "").replace(/<[\w.-]+:r\b[^>]*>/g, "").replace(/<\/[\w.-]+:r>/g, "").replace(/\s+/g, "");
473787
- return stripped.length === 0;
474147
+ return isEmptyTableSplitParagraph(paragraphXml, relativeStart, relativeEnd);
473788
474148
  }
473789
474149
  function isSingleParagraphXml(xml) {
473790
474150
  return /^<[\w.-]+:p\b[^>]*\/>$/.test(xml) || /^<[\w.-]+:p\b[\s\S]*<\/[\w.-]+:p>$/.test(xml);
@@ -474045,6 +474405,14 @@ function enrichLogicalChangeExcerpts(catalog, partXmlByUri) {
474045
474405
  const before = logical.before.text ?? "";
474046
474406
  logical.excerpt = after || before;
474047
474407
  }
474408
+ for (const parent of catalog.byId.values()) {
474409
+ if (parent.reviewGroup?.kind !== "text-rewrite" || parent.reviewGroup.role !== "parent")
474410
+ continue;
474411
+ const children = parent.reviewGroup.ownedChildIds.map((id) => catalog.byId.get(id));
474412
+ parent.before = { text: children.map((child) => child.before.text).filter(Boolean).join(" … ") };
474413
+ parent.after = { text: children.map((child) => child.after.text).filter(Boolean).join(" … ") };
474414
+ parent.excerpt = parent.after.text || parent.before.text || "";
474415
+ }
474048
474416
  }
474049
474417
  function decodePartXmlForLogicalCatalog(raw, readPartBytes2) {
474050
474418
  const out = new Map;
@@ -474194,6 +474562,8 @@ var init_logical_catalog = __esm(() => {
474194
474562
  init_structural_groups();
474195
474563
  init_numbering_catalog();
474196
474564
  init_review_groups();
474565
+ init_rewrite_groups();
474566
+ init_table_split_paragraph();
474197
474567
  init_list_deltas();
474198
474568
  init_comment_range_invariance();
474199
474569
  PARAGRAPH_SEMANTIC_KEYS = [
@@ -476281,6 +476651,32 @@ function reviewReplicaChainIsContiguous(commits, previousPackageRevision, nextPa
476281
476651
  }
476282
476652
  return expected === nextPackageRevision;
476283
476653
  }
476654
+ function textEditDirtyBlock(op) {
476655
+ if (!op.edits) {
476656
+ return {
476657
+ storyId: op.on.storyId,
476658
+ blockId: op.on.startBlockId,
476659
+ targetRange: { start: op.on.startOffset, end: op.on.endOffset },
476660
+ insertedTextLength: op.newText.length
476661
+ };
476662
+ }
476663
+ let start = Infinity;
476664
+ let end = 0;
476665
+ let delta = 0;
476666
+ for (const edit of op.edits) {
476667
+ if (edit.on.storyId !== op.on.storyId || edit.on.startBlockId !== op.on.startBlockId || edit.on.endBlockId !== op.on.startBlockId || edit.on.coordinateSpace === "tracked")
476668
+ return;
476669
+ start = Math.min(start, edit.on.startOffset);
476670
+ end = Math.max(end, edit.on.endOffset);
476671
+ delta += edit.newText.length - (edit.on.endOffset - edit.on.startOffset);
476672
+ }
476673
+ return {
476674
+ storyId: op.on.storyId,
476675
+ blockId: op.on.startBlockId,
476676
+ targetRange: { start, end },
476677
+ insertedTextLength: end - start + delta
476678
+ };
476679
+ }
476284
476680
  function buildBaseEnvelope(txId, prepared, result, dirtyBlockOverride) {
476285
476681
  if (result.status !== "committed" || result.documentEpoch == null || result.commitSequence == null || result.previousPackageRevision == null || result.packageRevision == null) {
476286
476682
  return null;
@@ -476288,12 +476684,7 @@ function buildBaseEnvelope(txId, prepared, result, dirtyBlockOverride) {
476288
476684
  const semantic = prepared.semanticDelta;
476289
476685
  const trackedAnnotations = captureTrackedAnnotationDelta(prepared);
476290
476686
  const op = prepared.source;
476291
- const dirtyBlock = dirtyBlockOverride ?? (op.kind === "editText" ? {
476292
- storyId: op.on.storyId,
476293
- blockId: op.on.startBlockId,
476294
- targetRange: { start: op.on.startOffset, end: op.on.endOffset },
476295
- insertedTextLength: op.newText.length
476296
- } : op.kind === "paragraphSplit" ? {
476687
+ const dirtyBlock = dirtyBlockOverride ?? (op.kind === "editText" ? textEditDirtyBlock(op) : op.kind === "paragraphSplit" ? {
476297
476688
  storyId: op.target.storyId,
476298
476689
  blockId: op.target.paraId,
476299
476690
  targetRange: { start: op.offset, end: op.offset },
@@ -491658,7 +492049,6 @@ function runDirectEditTextBatchCommit(input, edits) {
491658
492049
  });
491659
492050
  if (!commentCascade.ok)
491660
492051
  return rejected2(txId, commentCascade.reason);
491661
- const { edits: _edits, ...retainedSource } = op;
491662
492052
  const storiesTouched = [...new Set([
491663
492053
  ...textEditTouchedStories(state, storyId, partUri),
491664
492054
  ...commentCascade.storiesTouched
@@ -491699,6 +492089,8 @@ function runDirectEditTextBatchCommit(input, edits) {
491699
492089
  wId: revision.wId
491700
492090
  }))
491701
492091
  ]);
492092
+ const { edits: _edits, ...primarySource } = op;
492093
+ const retainedSource = { ...primarySource, batchSpanCount: edits.length };
491702
492094
  const forwardPatchGroup = {
491703
492095
  source: retainedSource,
491704
492096
  baseRevisions: {
@@ -491726,7 +492118,7 @@ function runDirectEditTextBatchCommit(input, edits) {
491726
492118
  };
491727
492119
  const prepared = {
491728
492120
  txId,
491729
- source: retainedSource,
492121
+ source: op,
491730
492122
  resolvedTargets: {
491731
492123
  partUris: Object.keys(perPart),
491732
492124
  stories: storiesTouched,
@@ -491842,6 +492234,34 @@ function rewritePlainTrackedTextBatch(paragraphBytes, edits, stampByEdit, stampi
491842
492234
  rewritten = rewritten.slice(0, op.start) + op.xml + rewritten.slice(op.end);
491843
492235
  return TE16.encode(rewritten);
491844
492236
  }
492237
+ function captureBatchTrackedAnnotations(paragraphBytes, createdIds) {
492238
+ if (createdIds.size === 0)
492239
+ return [];
492240
+ const pending = [...parseParagraphInlineMap(TD38.decode(paragraphBytes)).pieces];
492241
+ const seen = new Set;
492242
+ const annotations = [];
492243
+ while (pending.length > 0) {
492244
+ const piece = pending.pop();
492245
+ if ("children" in piece) {
492246
+ for (const child of piece.children)
492247
+ pending.push(child);
492248
+ }
492249
+ if (piece.kind !== "tracked" || piece.trackedKind !== "ins" && piece.trackedKind !== "del" || !piece.rsid || !createdIds.has(piece.rsid) || piece.revisionId == null || piece.author == null || piece.date == null)
492250
+ continue;
492251
+ const key2 = `${piece.rsid}:${piece.revisionId}:${piece.trackedKind}`;
492252
+ if (seen.has(key2))
492253
+ continue;
492254
+ seen.add(key2);
492255
+ annotations.push({
492256
+ changeId: piece.rsid,
492257
+ wId: piece.revisionId,
492258
+ kind: piece.trackedKind === "ins" ? "insert" : "delete",
492259
+ author: { name: piece.author, initials: piece.initials, email: piece.email },
492260
+ date: piece.date
492261
+ });
492262
+ }
492263
+ return annotations;
492264
+ }
491845
492265
  function runTrackedEditTextBatchCommit(input, edits) {
491846
492266
  const { state, txId, op } = input;
491847
492267
  const stamping = pickStamping(input);
@@ -491951,7 +492371,9 @@ function runTrackedEditTextBatchCommit(input, edits) {
491951
492371
  on: edit.on,
491952
492372
  newText: edit.newText,
491953
492373
  rsid: stamp.rsid,
491954
- insRsid: stamp.insRsid
492374
+ insRsid: stamp.insRsid,
492375
+ rewriteGroupId: edit.rewriteGroupId,
492376
+ preserveExistingRevisions: edit.preserveExistingRevisions
491955
492377
  };
491956
492378
  const paragraphWindow = { byteStart: 0, byteEnd: afterBytes.byteLength, isSelfClosing: false };
491957
492379
  const localized = edit.on.coordinateSpace === "tracked" ? null : rewriteLocalizedTracked(afterBytes, paragraphWindow, batchOp, {
@@ -491963,7 +492385,7 @@ function runTrackedEditTextBatchCommit(input, edits) {
491963
492385
  newText: edit.newText,
491964
492386
  allocateWIdBlock: () => null
491965
492387
  });
491966
- if (localized?.ok) {
492388
+ if (localized?.ok && !(edit.preserveExistingRevisions && localized.foldedInsRsid)) {
491967
492389
  afterBytes = localized.bytes;
491968
492390
  if (localized.foldedInsRsid) {
491969
492391
  emittedByEdit.set(edit, []);
@@ -491990,7 +492412,7 @@ function runTrackedEditTextBatchCommit(input, edits) {
491990
492412
  }
491991
492413
  continue;
491992
492414
  }
491993
- if (localized && localized.reason !== "text-range-in-unsupported-tracked-wrapper") {
492415
+ if (localized && !localized.ok && localized.reason !== "text-range-in-unsupported-tracked-wrapper") {
491994
492416
  return rejected2(txId, localized.reason);
491995
492417
  }
491996
492418
  const overlap = tryOverlapRewriteTracked({ ...input, op: batchOp }, afterBytes, paragraphWindow, paragraph.byteStart, {
@@ -492008,19 +492430,6 @@ function runTrackedEditTextBatchCommit(input, edits) {
492008
492430
  for (const rsid of overlap.updatedRsids)
492009
492431
  updatedRsids.add(rsid);
492010
492432
  resolvedInsertionRevisions.push(...overlap.resolvedInsertionRevisions);
492011
- for (const revision of overlap.authoredTrackedRevisions ?? []) {
492012
- trackedAnnotations.push({
492013
- changeId: revision.rsid,
492014
- wId: revision.wId,
492015
- kind: revision.kind,
492016
- author: {
492017
- name: stamping.author.name,
492018
- initials: stamping.author.initials ?? null,
492019
- email: stamping.author.email ?? null
492020
- },
492021
- date: stamping.date
492022
- });
492023
- }
492024
492433
  }
492025
492434
  }
492026
492435
  for (const edit of blockEdits) {
@@ -492051,7 +492460,21 @@ function runTrackedEditTextBatchCommit(input, edits) {
492051
492460
  });
492052
492461
  }
492053
492462
  }
492463
+ const rewriteGroups = new Map;
492464
+ for (const edit of blockEdits) {
492465
+ if (!edit.rewriteGroupId)
492466
+ continue;
492467
+ for (const rsid of emittedByEdit.get(edit) ?? [])
492468
+ rewriteGroups.set(rsid, edit.rewriteGroupId);
492469
+ }
492470
+ if (rewriteGroups.size > 0) {
492471
+ const stamped = stampRewriteGroups(TD38.decode(afterBytes), rewriteGroups, { partUri, storyId });
492472
+ if (stamped === null)
492473
+ return rejected2(txId, "invalid-input");
492474
+ afterBytes = TE16.encode(stamped);
492475
+ }
492054
492476
  if (!bytesEqual5(beforeBytes, afterBytes)) {
492477
+ trackedAnnotations.push(...captureBatchTrackedAnnotations(afterBytes, new Set(blockEdits.flatMap((edit) => emittedByEdit.get(edit) ?? []))));
492055
492478
  patches.push({
492056
492479
  kind: "replaceBytes",
492057
492480
  order: patches.length,
@@ -492069,7 +492492,6 @@ function runTrackedEditTextBatchCommit(input, edits) {
492069
492492
  patches.forEach((patch, order) => {
492070
492493
  patch.order = order;
492071
492494
  });
492072
- const { edits: _edits, ...retainedSource } = op;
492073
492495
  const storiesTouched = textEditTouchedStories(state, storyId, partUri);
492074
492496
  const storyPartOwnership = storyPartOwnershipForTouchedStories(state, storiesTouched, partUri);
492075
492497
  const perPart = {
@@ -492078,6 +492500,8 @@ function runTrackedEditTextBatchCommit(input, edits) {
492078
492500
  const patchMaps = {
492079
492501
  [partUri]: { partUri, ranges: [] }
492080
492502
  };
492503
+ const { edits: _edits, ...primarySource } = op;
492504
+ const retainedSource = { ...primarySource, batchSpanCount: edits.length };
492081
492505
  const forwardPatchGroup = {
492082
492506
  source: retainedSource,
492083
492507
  baseRevisions: {
@@ -492105,7 +492529,7 @@ function runTrackedEditTextBatchCommit(input, edits) {
492105
492529
  };
492106
492530
  const prepared = {
492107
492531
  txId,
492108
- source: retainedSource,
492532
+ source: op,
492109
492533
  resolvedTargets: {
492110
492534
  partUris: [partUri],
492111
492535
  stories: storiesTouched,
@@ -493940,6 +494364,7 @@ function tryOverlapRewriteTracked(input, bytes, window2, byteBase, stamp, inline
493940
494364
  newText: op.newText,
493941
494365
  changeMode: "tracked",
493942
494366
  currentAuthor: stamp.author,
494367
+ ...op.preserveExistingRevisions ? { existingRevisionOwnership: "foreign" } : {},
493943
494368
  txTimestamp: stamp.date,
493944
494369
  rsid: stamp.rsid,
493945
494370
  insRsid: stamp.insRsid,
@@ -496669,6 +497094,7 @@ function collectPerPartRevisions(state, partUris) {
496669
497094
  }
496670
497095
  var TD38, TE16, TRACKED_WRAPPER_OPEN_RE, INLINE_CONTROL_PLACEHOLDER = "";
496671
497096
  var init_compile_edit_text = __esm(() => {
497097
+ init_rewrite_groups();
496672
497098
  init_word_text_payload();
496673
497099
  init_textbox_atom_replacement();
496674
497100
  init_sd_document_state();
@@ -504324,6 +504750,8 @@ function buildLogicalIdByTextFragmentKey(logical) {
504324
504750
  }
504325
504751
  const out = new Map;
504326
504752
  for (const entry of logical.byId.values()) {
504753
+ if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent")
504754
+ continue;
504327
504755
  for (const fragment2 of entry.fragments) {
504328
504756
  if ((logicalIdsByRsid.get(fragment2.rsid)?.size ?? 0) <= 1)
504329
504757
  continue;
@@ -504335,6 +504763,8 @@ function buildLogicalIdByTextFragmentKey(logical) {
504335
504763
  function buildExactLogicalIdByTextFragmentKey(logical) {
504336
504764
  const out = new Map;
504337
504765
  for (const entry of logical.byId.values()) {
504766
+ if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent")
504767
+ continue;
504338
504768
  for (const fragment2 of entry.fragments) {
504339
504769
  out.set(trackedChangeFragmentKey(fragment2), entry.id);
504340
504770
  }
@@ -532531,7 +532961,7 @@ function buildProjectionFact(change, tableCatalogs) {
532531
532961
  return {
532532
532962
  logicalId: change.id,
532533
532963
  reviewOwnerId: reviewOwnerId(change),
532534
- visible: change.reviewGroup?.role !== "child" && change.subsumption?.role !== "child",
532964
+ visible: isVisibleLogicalTrackedChange(change),
532535
532965
  type: change.type,
532536
532966
  subtype: change.subtype,
532537
532967
  storyId: change.storyId,
@@ -532549,8 +532979,9 @@ function buildProjectionFact(change, tableCatalogs) {
532549
532979
  };
532550
532980
  }
532551
532981
  function reviewOwnerId(change) {
532552
- if (change.reviewGroup?.role === "child" && change.reviewGroup.parentId) {
532553
- return change.reviewGroup.parentId;
532982
+ const groupParentId = reviewGroupDisplayParentId(change);
532983
+ if (groupParentId) {
532984
+ return groupParentId;
532554
532985
  }
532555
532986
  if (change.subsumption?.role === "child")
532556
532987
  return change.subsumption.parentId;
@@ -532769,6 +533200,7 @@ function rangesOverlap5(leftStart, leftEnd, rightStart, rightEnd) {
532769
533200
  return leftStart < rightEnd && rightStart < leftEnd;
532770
533201
  }
532771
533202
  var init_review_projection_overlay = __esm(() => {
533203
+ init_rewrite_groups();
532772
533204
  init_review_decision_semantics();
532773
533205
  });
532774
533206
 
@@ -539297,6 +539729,8 @@ function prepareExactHistoryRenderInput(state, prepared, entry, direction) {
539297
539729
  }
539298
539730
  if (source.kind !== "editText" && source.kind !== "formatRunRange" || source.changeMode !== "direct")
539299
539731
  return null;
539732
+ if (source.kind === "editText" && (source.edits || source.batchSpanCount != null))
539733
+ return null;
539300
539734
  if (source.kind === "formatRunRange" && entry.semanticDelta.textRangeShifts.length !== 0)
539301
539735
  return null;
539302
539736
  const index = state.paragraphIndexes.get(source.on.storyId);
@@ -550593,7 +551027,7 @@ function refConfigSchemas2() {
550593
551027
  failure: refFailureSchema2
550594
551028
  };
550595
551029
  }
550596
- var trackChangeTypeValues2, sourcePathSchema2, diagnosticPathSchema2, conversionSourceRangeSchema2, conversionSourceSchema2, diagnosticProperties2, sdDiagnosticSchema2, sdConversionDiagnosticSchema2, conversionReportSchema2, receiptSuccessMetadataProperties2, nodeTypeValues2, blockNodeTypeValues2, deletableBlockNodeTypeValues2, inlineNodeTypeValues2, knownTargetKindValues2, SHARED_DEFS2, rangeSchema2, positionSchema2, inlineAnchorSchema2, targetKindSchema2, textAddressSchema2, textTargetSchema2, commentTrackedChangeTargetSchema2, textSearchCommentTargetSchema2, blockNodeAddressSchema2, deletableBlockNodeAddressSchema2, tableAddressSchema2, tableRowAddressSchema2, tableCellAddressSchema2, tableOrCellAddressSchema2, paragraphAddressSchema2, headingAddressSchema2, listItemAddressSchema2, listsV2BlockTargetSchema2, paragraphTargetSchema2, sectionAddressSchema2, watermarkSlotTargetSchema2, watermarkTargetSchema2, watermarkAddressSchema2, watermarkHorizontalPlacementSchema2, watermarkVerticalPlacementSchema2, watermarkPlacementSchema2, textWatermarkSchema2, pictureWatermarkInputSchema2, pictureWatermarkInfoSchema2, watermarkInfoSchema2, inlineNodeAddressSchema2, nodeAddressSchema2, commentAddressSchema2, trackedChangeAddressSchema2, entityAddressSchema2, selectionTargetSchema2, commentTrackedChangeLinkSchema2, targetLocatorSchema2, deleteBehaviorSchema2, resolvedHandleSchema2, pageInfoSchema2, receiptSuccessSchema2, commentsCreateSuccessSchema2, textMutationRangeSchema2, textMutationResolutionSchema2, textMutationSuccessSchema2, matchRunSchema2, matchBlockSchema2, storyLocatorSchema2, bodyStoryLocatorSchema2, markRunColorRefSchema2, markRunFontsSchema2, markRunLanguagesSchema2, markRunUnderlineSchema2, markRunShadingSchema2, markRunBorderSchema2, markRunPropsSchema2, trackChangeRefSchema2, createParagraphSuccessSchema2, createHeadingSuccessSchema2, createHeadingLevelSchema2, semanticHeadingLevelSchema2, listsInsertSuccessSchema2, listsMutateItemSuccessSchema2, listsExitSuccessSchema2, nodeSummarySchema2, nodeInfoSchema2, matchContextSchema2, unknownNodeDiagnosticSchema2, textSelectorSchema2, planTextSelectorSchema2, nodeSelectorSchema2, selectorShorthandSchema2, sdTextSelectorSchema2, sdNodeSelectorSchema2, sdSelectorSchema2, sdReadOptionsSchema2, sdFindInputSchema2, sdNodeResultSchema2, sdFindResultSchema2, sdMutationResolutionSchema2, evaluatedRevisionSchema2, sdMutationSuccessSchema2, documentInfoCountsSchema2, documentInfoOutlineItemSchema2, documentInfoCapabilitiesSchema2, documentStyleInfoSchema2, documentStylesSchema2, documentDefaultsSchema2, documentInfoSchema2, listKindSchema2, listInsertPositionSchema2, listItemInfoSchema2, listItemDomainItemSchema2, listsListResultSchema2, sectionBreakTypeSchema2, sectionOrientationSchema2, sectionVerticalAlignSchema2, sectionDirectionSchema2, sectionHeaderFooterKindSchema2, sectionHeaderFooterVariantSchema2, sectionLineNumberRestartSchema2, sectionPageNumberFormatSchema2, sectionRangeDomainSchema2, sectionPageMarginsSchema2, sectionHeaderFooterMarginsSchema2, sectionPageSetupSchema2, sectionColumnsSchema2, sectionLineNumberingSchema2, sectionPageNumberingSchema2, sectionHeaderFooterRefsSchema2, sectionBorderSpecSchema2, sectionPageBordersSchema2, sectionInfoSchema2, sectionResolvedHandleSchema2, sectionDomainItemSchema2, sectionsListResultSchema2, sectionMutationSuccessSchema2, documentMutationSuccessSchema2, paragraphMutationTargetSchema2, paragraphMutationSuccessSchema2, createSectionBreakSuccessSchema2, commentMetadataSchema2, commentInfoSchema2, commentDomainItemSchema2, commentsListResultSchema2, trackChangeWordRevisionIdsSchema2, trackChangeSourceIdsSchema2, trackChangeBroadTypeEnum2, trackChangeGroupingEnum2, trackChangeCanonicalizationKindEnum2, trackChangeAddressKindEnum2, trackChangeSourcePlatformEnum2, trackChangeReplacementSideSchema2, trackChangeReplacementSchema2, trackChangeOverlapRelationshipSchema2, trackChangeOverlapLayerSchema2, trackChangeOverlapInfoSchema2, trackChangeFormattingSnapshotSchema2, trackChangeListDeltaKindEnum2, trackChangeListDeltaSideSchema2, trackChangeListMemberDeltaSchema2, trackChangeListDeltaSummarySchema2, trackChangeTargetSchema2, trackChangeSnapshotSchema2, trackChangeCustomAttributeSchema2, trackChangeInfoSchema2, trackChangeDomainItemSchema2, trackChangesListResultSchema2, reviewDecideRangeTargetOptions2, historyActionCollaborationSchema2, capabilityReasonCodeSchema2, capabilityReasonsSchema2, capabilityFlagSchema2, operationRuntimeCapabilitySchema2, operationCapabilitiesSchema2, inlinePropertyCapabilitySchema2, inlinePropertyCapabilitiesByKeySchema2, formatCapabilitiesSchema2, planEngineCapabilitiesSchema2, capabilitiesOutputSchema2, strictEmptyObjectSchema2, tableBorderColorPattern2, tableBorderSpecSchema2, nullableTableBorderSpecSchema2, sdFragmentSchema2, conversionFragmentSchema2, placementSchema2, nestingPolicySchema2, insertInputSchema2, supportCheckRichInsertInputSchema2, supportCheckRichReplaceInputSchema2, supportCheckProjectionInputSchema2, supportCheckInputSchema2, supportCheckFailureSchema2, supportCheckGuardSchema2, supportCheckCommonProperties2, supportCheckOutputSchema2, tableLocatorSchema2, cellLocatorSchema2, cellOrTableScopedCellLocatorSchema2, tableOrCellLocatorSchema2, mergeRangeLocatorSchema2, tableAnchorLocationMembers2, tableAnchorLocationSchema2, tableCreateLocationSchema2, tableMutationSuccessSchema2, createTableSuccessSchema2, tableMutationFailureCodes2, tableMutationFailureSchema2, tableMutationResultSchema2, createTableResultSchema2, historyActionSuccessSchema2, historyActionFailureSchema2, formatInlineAliasOperationSchemas2, tocMutationFailureCodes2, tocMutationFailureSchema2, tocMutationSuccessSchema2, tocEntryMutationFailureCodes2, tocEntryMutationFailureSchema2, tocEntryMutationSuccessSchema2, hyperlinkTargetSchema2, hyperlinkReadPropertiesSchema2, hyperlinkDestinationSchema2, hyperlinkSpecSchema2, hyperlinkPatchSchema2, hyperlinkDomainSchema2, hyperlinkMutationSuccessSchema2, hyperlinkMutationFailureCodes2, hyperlinkMutationFailureSchema2, hyperlinkInfoSchema2, contentControlTargetSchema2, contentControlMoveDestinationSchema2, contentControlMutationSuccessSchema2, contentControlMutationFailureSchema2, ccInfoSchema2, ccListResultSchema2, refListQueryProperties2, refListQuerySchema2, discoveryOutputSchema2, receiptFailureSchema2, refFailureSchema2, bookmarkAddressSchema2, bookmarkMutation2, customXmlPartTargetSchema2, customXmlPartMutation2, customXmlPartCreateMutation2, anchoredMetadataAttachMutation2, anchoredMetadataMutation2, footnoteAddressSchema2, footnoteConfigScopeSchema2, footnoteNumberingSchema2, footnoteMutation2, footnoteConfig2, crossRefAddressSchema2, crossRefTargetSchema2, crossRefDisplaySchema2, crossRefMutation2, indexAddressSchema2, indexEntryAddressSchema2, indexConfigSchema2, indexEntryDataSchema2, indexEntryPatchSchema2, indexMutation2, indexEntryMutation2, captionAddressSchema2, captionMutation2, captionConfig2, fieldAddressSchema2, fieldMutation2, citationAddressSchema2, citationSourceAddressSchema2, bibliographyAddressSchema2, citationMutation2, citationSourceMutation2, bibliographyMutation2, citationPersonSchema2, citationSourceFieldsSchema2, tocCreateLocationSchema2, authoritiesAddressSchema2, authorityEntryAddressSchema2, authoritiesConfigSchema2, authorityEntryDataSchema2, authorityEntryPatchSchema2, authoritiesMutation2, authorityEntryMutation2, diffCoverageSchema2, diffSummarySchema2, diffSnapshotSchema2, diffApplyEligibilityBlockerSchema2, diffApplyModeEligibilitySchema2, diffApplyEligibilitySchema2, diffPayloadSchema2, diffApplyResultSchema2, operationSchemas2;
551030
+ var trackChangeTypeValues2, sourcePathSchema2, diagnosticPathSchema2, conversionSourceRangeSchema2, conversionSourceSchema2, diagnosticProperties2, sdDiagnosticSchema2, sdConversionDiagnosticSchema2, conversionReportSchema2, receiptSuccessMetadataProperties2, nodeTypeValues2, blockNodeTypeValues2, deletableBlockNodeTypeValues2, inlineNodeTypeValues2, knownTargetKindValues2, SHARED_DEFS2, rangeSchema2, positionSchema2, inlineAnchorSchema2, targetKindSchema2, textAddressSchema2, textTargetSchema2, commentTrackedChangeTargetSchema2, textSearchCommentTargetSchema2, blockNodeAddressSchema2, deletableBlockNodeAddressSchema2, tableAddressSchema2, tableRowAddressSchema2, tableCellAddressSchema2, tableOrCellAddressSchema2, paragraphAddressSchema2, headingAddressSchema2, listItemAddressSchema2, listsV2BlockTargetSchema2, paragraphTargetSchema2, sectionAddressSchema2, watermarkSlotTargetSchema2, watermarkTargetSchema2, watermarkAddressSchema2, watermarkHorizontalPlacementSchema2, watermarkVerticalPlacementSchema2, watermarkPlacementSchema2, textWatermarkSchema2, pictureWatermarkInputSchema2, pictureWatermarkInfoSchema2, watermarkInfoSchema2, inlineNodeAddressSchema2, nodeAddressSchema2, commentAddressSchema2, trackedChangeAddressSchema2, entityAddressSchema2, selectionTargetSchema2, commentTrackedChangeLinkSchema2, targetLocatorSchema2, deleteBehaviorSchema2, resolvedHandleSchema2, pageInfoSchema2, receiptSuccessSchema2, commentsCreateSuccessSchema2, textMutationRangeSchema2, textMutationResolutionSchema2, textMutationSuccessSchema2, matchRunSchema2, matchBlockSchema2, storyLocatorSchema2, bodyStoryLocatorSchema2, markRunColorRefSchema2, markRunFontsSchema2, markRunLanguagesSchema2, markRunUnderlineSchema2, markRunShadingSchema2, markRunBorderSchema2, markRunPropsSchema2, trackChangeRefSchema2, createParagraphSuccessSchema2, createHeadingSuccessSchema2, createHeadingLevelSchema2, semanticHeadingLevelSchema2, listsInsertSuccessSchema2, listsMutateItemSuccessSchema2, listsExitSuccessSchema2, nodeSummarySchema2, nodeInfoSchema2, matchContextSchema2, unknownNodeDiagnosticSchema2, textSelectorSchema2, planTextSelectorSchema2, nodeSelectorSchema2, selectorShorthandSchema2, sdTextSelectorSchema2, sdNodeSelectorSchema2, sdSelectorSchema2, sdReadOptionsSchema2, sdFindInputSchema2, sdNodeResultSchema2, sdFindResultSchema2, sdMutationResolutionSchema2, evaluatedRevisionSchema2, sdMutationSuccessSchema2, documentInfoCountsSchema2, documentInfoOutlineItemSchema2, documentInfoCapabilitiesSchema2, documentStyleInfoSchema2, documentStylesSchema2, documentDefaultsSchema2, documentInfoSchema2, listKindSchema2, listInsertPositionSchema2, listItemInfoSchema2, listItemDomainItemSchema2, listsListResultSchema2, sectionBreakTypeSchema2, sectionOrientationSchema2, sectionVerticalAlignSchema2, sectionDirectionSchema2, sectionHeaderFooterKindSchema2, sectionHeaderFooterVariantSchema2, sectionLineNumberRestartSchema2, sectionPageNumberFormatSchema2, sectionRangeDomainSchema2, sectionPageMarginsSchema2, sectionHeaderFooterMarginsSchema2, sectionPageSetupSchema2, sectionColumnsSchema2, sectionLineNumberingSchema2, sectionPageNumberingSchema2, sectionHeaderFooterRefsSchema2, sectionBorderSpecSchema2, sectionPageBordersSchema2, sectionInfoSchema2, sectionResolvedHandleSchema2, sectionDomainItemSchema2, sectionsListResultSchema2, sectionMutationSuccessSchema2, documentMutationSuccessSchema2, paragraphMutationTargetSchema2, paragraphMutationSuccessSchema2, createSectionBreakSuccessSchema2, commentMetadataSchema2, commentInfoSchema2, commentDomainItemSchema2, commentsListResultSchema2, trackChangeWordRevisionIdsSchema2, trackChangeSourceIdsSchema2, trackChangeBroadTypeEnum2, trackChangeGroupingEnum2, trackChangeCanonicalizationKindEnum2, trackChangeAddressKindEnum2, trackChangeSourcePlatformEnum2, trackChangeReplacementSideSchema2, trackChangeReplacementSchema2, trackChangeOverlapRelationshipSchema2, trackChangeOverlapLayerSchema2, trackChangeOverlapInfoSchema2, trackChangeFormattingSnapshotSchema2, trackChangeListDeltaKindEnum2, trackChangeListDeltaSideSchema2, trackChangeListMemberDeltaSchema2, trackChangeListDeltaSummarySchema2, trackChangeTargetSchema2, trackChangeSnapshotSchema2, trackChangeCustomAttributeSchema2, trackChangeRewriteReviewGroupSchema2, trackChangeInfoSchema2, trackChangeDomainItemSchema2, trackChangesListResultSchema2, reviewDecideRangeTargetOptions2, historyActionCollaborationSchema2, capabilityReasonCodeSchema2, capabilityReasonsSchema2, capabilityFlagSchema2, operationRuntimeCapabilitySchema2, operationCapabilitiesSchema2, inlinePropertyCapabilitySchema2, inlinePropertyCapabilitiesByKeySchema2, formatCapabilitiesSchema2, planEngineCapabilitiesSchema2, capabilitiesOutputSchema2, strictEmptyObjectSchema2, tableBorderColorPattern2, tableBorderSpecSchema2, nullableTableBorderSpecSchema2, sdFragmentSchema2, conversionFragmentSchema2, placementSchema2, nestingPolicySchema2, insertInputSchema2, supportCheckRichInsertInputSchema2, supportCheckRichReplaceInputSchema2, supportCheckProjectionInputSchema2, supportCheckInputSchema2, supportCheckFailureSchema2, supportCheckGuardSchema2, supportCheckCommonProperties2, supportCheckOutputSchema2, tableLocatorSchema2, cellLocatorSchema2, cellOrTableScopedCellLocatorSchema2, tableOrCellLocatorSchema2, mergeRangeLocatorSchema2, tableAnchorLocationMembers2, tableAnchorLocationSchema2, tableCreateLocationSchema2, tableMutationSuccessSchema2, createTableSuccessSchema2, tableMutationFailureCodes2, tableMutationFailureSchema2, tableMutationResultSchema2, createTableResultSchema2, historyActionSuccessSchema2, historyActionFailureSchema2, formatInlineAliasOperationSchemas2, tocMutationFailureCodes2, tocMutationFailureSchema2, tocMutationSuccessSchema2, tocEntryMutationFailureCodes2, tocEntryMutationFailureSchema2, tocEntryMutationSuccessSchema2, hyperlinkTargetSchema2, hyperlinkReadPropertiesSchema2, hyperlinkDestinationSchema2, hyperlinkSpecSchema2, hyperlinkPatchSchema2, hyperlinkDomainSchema2, hyperlinkMutationSuccessSchema2, hyperlinkMutationFailureCodes2, hyperlinkMutationFailureSchema2, hyperlinkInfoSchema2, contentControlTargetSchema2, contentControlMoveDestinationSchema2, contentControlMutationSuccessSchema2, contentControlMutationFailureSchema2, ccInfoSchema2, ccListResultSchema2, refListQueryProperties2, refListQuerySchema2, discoveryOutputSchema2, receiptFailureSchema2, refFailureSchema2, bookmarkAddressSchema2, bookmarkMutation2, customXmlPartTargetSchema2, customXmlPartMutation2, customXmlPartCreateMutation2, anchoredMetadataAttachMutation2, anchoredMetadataMutation2, footnoteAddressSchema2, footnoteConfigScopeSchema2, footnoteNumberingSchema2, footnoteMutation2, footnoteConfig2, crossRefAddressSchema2, crossRefTargetSchema2, crossRefDisplaySchema2, crossRefMutation2, indexAddressSchema2, indexEntryAddressSchema2, indexConfigSchema2, indexEntryDataSchema2, indexEntryPatchSchema2, indexMutation2, indexEntryMutation2, captionAddressSchema2, captionMutation2, captionConfig2, fieldAddressSchema2, fieldMutation2, citationAddressSchema2, citationSourceAddressSchema2, bibliographyAddressSchema2, citationMutation2, citationSourceMutation2, bibliographyMutation2, citationPersonSchema2, citationSourceFieldsSchema2, tocCreateLocationSchema2, authoritiesAddressSchema2, authorityEntryAddressSchema2, authoritiesConfigSchema2, authorityEntryDataSchema2, authorityEntryPatchSchema2, authoritiesMutation2, authorityEntryMutation2, diffCoverageSchema2, diffSummarySchema2, diffSnapshotSchema2, diffApplyEligibilityBlockerSchema2, diffApplyModeEligibilitySchema2, diffApplyEligibilitySchema2, diffPayloadSchema2, diffApplyResultSchema2, operationSchemas2;
550597
551031
  var init_schemas5 = __esm(() => {
550598
551032
  init_command_catalog2();
550599
551033
  init_types8();
@@ -552110,6 +552544,21 @@ var init_schemas5 = __esm(() => {
552110
552544
  localName: { type: "string" },
552111
552545
  value: { type: "string" }
552112
552546
  }, ["name", "namespaceUri", "localName", "value"]);
552547
+ trackChangeRewriteReviewGroupSchema2 = objectSchema4({
552548
+ kind: { const: "text-rewrite" },
552549
+ role: { enum: ["parent", "child"] },
552550
+ parentId: { type: "string" },
552551
+ childChangeIds: { type: "array", items: { type: "string" } },
552552
+ members: {
552553
+ type: "array",
552554
+ items: objectSchema4({
552555
+ id: { type: "string" },
552556
+ type: { enum: ["insertion", "deletion", "replacement"] },
552557
+ subtype: { type: "string" },
552558
+ sourceIds: trackChangeSourceIdsSchema2
552559
+ }, ["id", "type", "subtype", "sourceIds"])
552560
+ }
552561
+ }, ["kind", "role", "childChangeIds", "members"]);
552113
552562
  trackChangeInfoSchema2 = objectSchema4({
552114
552563
  address: trackedChangeAddressSchema2,
552115
552564
  id: { type: "string" },
@@ -552122,6 +552571,7 @@ var init_schemas5 = __esm(() => {
552122
552571
  sourceIds: trackChangeSourceIdsSchema2,
552123
552572
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
552124
552573
  revisionGroupId: { type: "string" },
552574
+ reviewGroup: trackChangeRewriteReviewGroupSchema2,
552125
552575
  splitFromId: { oneOf: [{ type: "string" }, { type: "null" }] },
552126
552576
  replacement: trackChangeReplacementSchema2,
552127
552577
  author: { type: "string" },
@@ -552172,6 +552622,7 @@ var init_schemas5 = __esm(() => {
552172
552622
  sourceIds: trackChangeSourceIdsSchema2,
552173
552623
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
552174
552624
  revisionGroupId: { type: "string" },
552625
+ reviewGroup: trackChangeRewriteReviewGroupSchema2,
552175
552626
  author: { type: "string" },
552176
552627
  authorEmail: { type: "string" },
552177
552628
  authorImage: { type: "string" },
@@ -558284,6 +558735,58 @@ var init_src3 = __esm(() => {
558284
558735
  init_protection_types2();
558285
558736
  });
558286
558737
 
558738
+ // ../../../v2/document-api-v2-adapter/dist/history/rewrite-group-effects.js
558739
+ function applyHistoryGroupEffects(result, effects2, direction) {
558740
+ if (!effects2)
558741
+ return result;
558742
+ const inserted = direction === "undo" ? effects2.removed : effects2.created;
558743
+ const removed = direction === "undo" ? effects2.created : effects2.removed;
558744
+ const refs = (ids) => ids.map((entityId) => ({
558745
+ kind: "entity",
558746
+ entityType: "trackedChange",
558747
+ entityId
558748
+ }));
558749
+ return {
558750
+ ...result,
558751
+ inserted: [...result.inserted ?? [], ...refs(inserted)],
558752
+ updated: [...result.updated ?? [], ...refs(effects2.updated)],
558753
+ removed: [...result.removed ?? [], ...refs(removed)],
558754
+ invalidatedRefs: [...result.invalidatedRefs ?? [], ...refs(removed)]
558755
+ };
558756
+ }
558757
+ function composeHistoryGroupEffects(effects2) {
558758
+ const states = new Map;
558759
+ for (const effect of effects2) {
558760
+ if (!effect)
558761
+ continue;
558762
+ for (const kind of ["created", "updated", "removed"]) {
558763
+ for (const id of effect[kind]) {
558764
+ const previous = states.get(id);
558765
+ states.set(id, {
558766
+ before: previous?.before ?? kind !== "created",
558767
+ after: kind !== "removed"
558768
+ });
558769
+ }
558770
+ }
558771
+ }
558772
+ if (states.size === 0)
558773
+ return;
558774
+ const result = {
558775
+ created: [],
558776
+ updated: [],
558777
+ removed: []
558778
+ };
558779
+ for (const [id, state] of states) {
558780
+ if (state.before && state.after)
558781
+ result.updated.push(id);
558782
+ else if (state.after)
558783
+ result.created.push(id);
558784
+ else if (state.before)
558785
+ result.removed.push(id);
558786
+ }
558787
+ return result;
558788
+ }
558789
+
558287
558790
  // ../../../v2/document-api-v2-adapter/dist/policy/source.js
558288
558791
  function v2Coverage(operationId, wiredVia, workerWired, completenessStatus, completenessReason) {
558289
558792
  return {
@@ -560819,7 +561322,7 @@ class V2HistoryAdapter {
560819
561322
  applied.push({
560820
561323
  entry,
560821
561324
  result,
560822
- projected: projectUndoToHistoryResult(entry, result, this.context.session, priorLogicalIds)
561325
+ projected: applyHistoryGroupEffects(projectUndoToHistoryResult(entry, result, this.context.session, priorLogicalIds), this.context.getHistoryTrackedChangeGroupEffects(entry.txId), "undo")
560823
561326
  });
560824
561327
  }
560825
561328
  return aggregateHistoryResults(this.context, group, applied);
@@ -560849,7 +561352,7 @@ class V2HistoryAdapter {
560849
561352
  applied.push({
560850
561353
  entry,
560851
561354
  result,
560852
- projected: projectRedoToHistoryResult(entry, result, this.context.session, priorLogicalIds)
561355
+ projected: applyHistoryGroupEffects(projectRedoToHistoryResult(entry, result, this.context.session, priorLogicalIds), this.context.getHistoryTrackedChangeGroupEffects(entry.txId), "redo")
560853
561356
  });
560854
561357
  }
560855
561358
  return aggregateHistoryResults(this.context, group, applied);
@@ -561528,45 +562031,65 @@ var init_xml = __esm(() => {
561528
562031
  });
561529
562032
 
561530
562033
  // ../../../v2/document-api-v2-adapter/dist/address/painted-offsets.js
561531
- function paintedRangeContainedObjectOrdinals(paraXml, paintedStart, paintedEnd) {
561532
- if (paintedEnd <= paintedStart)
561533
- return [];
561534
- const contained = [];
561535
- for (const run of paintedRuns(paraXml)) {
561536
- if (run.objectOrdinal !== null && paintedStart <= run.paintedStart && run.paintedStart + 1 <= paintedEnd) {
561537
- contained.push(run.objectOrdinal);
562034
+ function preparePaintedOffsets(paraXml) {
562035
+ const runs = paintedRuns(paraXml);
562036
+ const objects = runs.filter((run) => run.objectOrdinal !== null);
562037
+ return {
562038
+ containedObjectOrdinals(start, end) {
562039
+ const contained = [];
562040
+ for (let i2 = lowerBound(objects, start, "start");i2 < objects.length; i2++) {
562041
+ const run = objects[i2];
562042
+ if (run.paintedStart + 1 > end)
562043
+ break;
562044
+ contained.push(run.objectOrdinal);
562045
+ }
562046
+ return contained;
562047
+ },
562048
+ containsObject(start, end) {
562049
+ const run = objects[lowerBound(objects, start, "start")];
562050
+ return run !== undefined && run.paintedStart + 1 <= end;
562051
+ },
562052
+ toKernelOffset(offset) {
562053
+ if (offset <= 0)
562054
+ return offset;
562055
+ const run = runs[lowerBound(runs, offset, "end")];
562056
+ if (!run) {
562057
+ const last = runs.at(-1);
562058
+ return last ? last.kernelStart + last.kernelLength : 0;
562059
+ }
562060
+ return run.objectOrdinal === null ? run.kernelStart + Math.max(0, offset - run.paintedStart) : run.kernelStart;
562061
+ },
562062
+ caretObjectBoundary(offset) {
562063
+ const run = objects[lowerBound(objects, offset, "end")];
562064
+ if (!run)
562065
+ return;
562066
+ if (offset === run.paintedStart)
562067
+ return { objectOrdinal: run.objectOrdinal, edge: "before" };
562068
+ if (offset === run.paintedStart + 1)
562069
+ return { objectOrdinal: run.objectOrdinal, edge: "after" };
562070
+ return;
561538
562071
  }
562072
+ };
562073
+ }
562074
+ function lowerBound(runs, offset, edge) {
562075
+ let low = 0;
562076
+ let high = runs.length;
562077
+ while (low < high) {
562078
+ const mid = low + Math.floor((high - low) / 2);
562079
+ const run = runs[mid];
562080
+ const boundary = run.paintedStart + (edge === "end" ? run.paintedLength : 0);
562081
+ if (boundary < offset)
562082
+ low = mid + 1;
562083
+ else
562084
+ high = mid;
561539
562085
  }
561540
- return contained;
562086
+ return low;
561541
562087
  }
561542
- function paintedRangeContainsObject(paraXml, paintedStart, paintedEnd) {
561543
- return paintedRangeContainedObjectOrdinals(paraXml, paintedStart, paintedEnd).length > 0;
562088
+ function paintedRangeContainedObjectOrdinals(paraXml, paintedStart, paintedEnd) {
562089
+ return preparePaintedOffsets(paraXml).containedObjectOrdinals(paintedStart, paintedEnd);
561544
562090
  }
561545
562091
  function paintedToKernelOffset(paraXml, paintedOffset) {
561546
- if (paintedOffset <= 0)
561547
- return paintedOffset;
561548
- let kernelLength = 0;
561549
- for (const run of paintedRuns(paraXml)) {
561550
- kernelLength = run.kernelStart + run.kernelLength;
561551
- if (paintedOffset <= run.paintedStart + run.paintedLength) {
561552
- const within = Math.max(0, paintedOffset - run.paintedStart);
561553
- return run.objectOrdinal === null ? run.kernelStart + within : run.kernelStart;
561554
- }
561555
- }
561556
- return kernelLength;
561557
- }
561558
- function paintedCaretObjectBoundary(paraXml, paintedOffset) {
561559
- for (const run of paintedRuns(paraXml)) {
561560
- if (run.objectOrdinal === null)
561561
- continue;
561562
- if (paintedOffset === run.paintedStart) {
561563
- return { objectOrdinal: run.objectOrdinal, edge: "before" };
561564
- }
561565
- if (paintedOffset === run.paintedStart + 1) {
561566
- return { objectOrdinal: run.objectOrdinal, edge: "after" };
561567
- }
561568
- }
561569
- return;
562092
+ return preparePaintedOffsets(paraXml).toKernelOffset(paintedOffset);
561570
562093
  }
561571
562094
  function paintedRuns(paraXml) {
561572
562095
  const runs = [];
@@ -561595,6 +562118,12 @@ var init_painted_offsets = __esm(() => {
561595
562118
 
561596
562119
  // ../../../v2/document-api-v2-adapter/dist/address/selection-target.js
561597
562120
  function resolveSelectionTargetToRange(input) {
562121
+ const prepared = prepareSelectionTargetResolution(input);
562122
+ if ("error" in prepared)
562123
+ return prepared;
562124
+ return prepared.resolveOffsets();
562125
+ }
562126
+ function prepareSelectionTargetResolution(input) {
561598
562127
  const target = input.target;
561599
562128
  if (target.kind !== "selection") {
561600
562129
  return { error: "INVALID_TARGET", message: "expected a SelectionTarget." };
@@ -561642,80 +562171,69 @@ function resolveSelectionTargetToRange(input) {
561642
562171
  totalBytes: () => localOffsetMap.totalBytes()
561643
562172
  };
561644
562173
  const kernelTextLength = coordinateSpace === "tracked" ? offsetMap.totalChars() : entry.textLength;
561645
- let startOffset = target.start.offset;
561646
- let endOffset = target.end.offset;
561647
- let paintedObjectContained = false;
561648
- let collapsedObjectBoundary;
561649
- if (coordinateSpace === "visible" && input.offsetSpace === "selection") {
561650
- const paraXml = SELECTION_TARGET_TD.decode(paragraphBytes);
561651
- const objectRuns = (paraXml.match(/<[\w.-]+:(?:drawing|pict|object)\b/g) ?? []).length;
561652
- if (objectRuns > 0) {
561653
- if (entry.textLength > 0) {
562174
+ const paraXml = coordinateSpace === "visible" && input.offsetSpace === "selection" ? SELECTION_TARGET_TD.decode(paragraphBytes) : "";
562175
+ const objectRuns = (paraXml.match(/<[\w.-]+:(?:drawing|pict|object)\b/g) ?? []).length;
562176
+ const painted = objectRuns > 0 ? preparePaintedOffsets(paraXml) : null;
562177
+ const originalStart = target.start.offset;
562178
+ const originalEnd = target.end.offset;
562179
+ return {
562180
+ resolveOffsets(paintedStartOffset = originalStart, paintedEndOffset = originalEnd) {
562181
+ if (paintedStartOffset > paintedEndOffset) {
562182
+ return { error: "INVALID_TARGET", message: "selection end precedes selection start." };
562183
+ }
562184
+ let startOffset = paintedStartOffset;
562185
+ let endOffset = paintedEndOffset;
562186
+ let paintedObjectContained = false;
562187
+ let collapsedObjectBoundary;
562188
+ if (painted) {
561654
562189
  if (startOffset < 0 || endOffset > entry.textLength + objectRuns) {
561655
- return {
561656
- error: "INVALID_TARGET",
561657
- message: "selection offsets exceed paragraph text."
561658
- };
562190
+ return { error: "INVALID_TARGET", message: "selection offsets exceed paragraph text." };
561659
562191
  }
561660
- paintedObjectContained = paintedRangeContainsObject(paraXml, startOffset, endOffset);
562192
+ paintedObjectContained = painted.containsObject(startOffset, endOffset);
561661
562193
  if (startOffset === endOffset) {
561662
- collapsedObjectBoundary = paintedCaretObjectBoundary(paraXml, startOffset);
562194
+ collapsedObjectBoundary = painted.caretObjectBoundary(startOffset);
561663
562195
  }
561664
- startOffset = paintedToKernelOffset(paraXml, startOffset);
561665
- endOffset = paintedToKernelOffset(paraXml, endOffset);
561666
- } else {
561667
- if (startOffset < 0 || endOffset > objectRuns) {
561668
- return {
561669
- error: "INVALID_TARGET",
561670
- message: "selection offsets exceed paragraph text."
561671
- };
561672
- }
561673
- if (startOffset === endOffset) {
561674
- collapsedObjectBoundary = paintedCaretObjectBoundary(paraXml, startOffset);
561675
- } else {
561676
- paintedObjectContained = paintedRangeContainsObject(paraXml, startOffset, endOffset);
561677
- }
561678
- startOffset = paintedToKernelOffset(paraXml, startOffset);
561679
- endOffset = paintedToKernelOffset(paraXml, endOffset);
562196
+ startOffset = painted.toKernelOffset(startOffset);
562197
+ endOffset = painted.toKernelOffset(endOffset);
562198
+ }
562199
+ if (startOffset < 0 || endOffset > kernelTextLength) {
562200
+ return {
562201
+ error: "INVALID_TARGET",
562202
+ message: "selection offsets exceed paragraph text."
562203
+ };
561680
562204
  }
562205
+ const startByte = offsetMap.charToByte(Math.min(startOffset, kernelTextLength));
562206
+ const endByte = offsetMap.charToByte(Math.min(endOffset, kernelTextLength));
562207
+ if (startByte == null || endByte == null || startByte > endByte) {
562208
+ return {
562209
+ error: "INVALID_TARGET",
562210
+ message: "selection could not be resolved to source bytes."
562211
+ };
562212
+ }
562213
+ return {
562214
+ storyId: entry.storyId,
562215
+ storyRevision: entry.storyRevision,
562216
+ partUri: entry.partUri,
562217
+ partRevision: entry.partRevision,
562218
+ startByte,
562219
+ endByte,
562220
+ paragraphByteStart: entry.byteStart,
562221
+ paragraphByteEnd: entry.byteEnd,
562222
+ startBlockId: startBlock,
562223
+ endBlockId: endBlock,
562224
+ startOffset,
562225
+ endOffset,
562226
+ ...coordinateSpace === "tracked" ? { coordinateSpace } : {},
562227
+ sourceAddress: {
562228
+ blockId: startBlock,
562229
+ range: { start: startOffset, end: endOffset }
562230
+ },
562231
+ paintedStartOffset,
562232
+ paintedEndOffset,
562233
+ paintedObjectContained,
562234
+ ...collapsedObjectBoundary ? { collapsedObjectBoundary } : {}
562235
+ };
561681
562236
  }
561682
- }
561683
- if (startOffset < 0 || endOffset > kernelTextLength) {
561684
- return {
561685
- error: "INVALID_TARGET",
561686
- message: "selection offsets exceed paragraph text."
561687
- };
561688
- }
561689
- const startByte = offsetMap.charToByte(Math.min(startOffset, kernelTextLength));
561690
- const endByte = offsetMap.charToByte(Math.min(endOffset, kernelTextLength));
561691
- if (startByte == null || endByte == null || startByte > endByte) {
561692
- return {
561693
- error: "INVALID_TARGET",
561694
- message: "selection could not be resolved to source bytes."
561695
- };
561696
- }
561697
- return {
561698
- storyId: entry.storyId,
561699
- storyRevision: entry.storyRevision,
561700
- partUri: entry.partUri,
561701
- partRevision: entry.partRevision,
561702
- startByte,
561703
- endByte,
561704
- paragraphByteStart: entry.byteStart,
561705
- paragraphByteEnd: entry.byteEnd,
561706
- startBlockId: startBlock,
561707
- endBlockId: endBlock,
561708
- startOffset,
561709
- endOffset,
561710
- ...coordinateSpace === "tracked" ? { coordinateSpace } : {},
561711
- sourceAddress: {
561712
- blockId: startBlock,
561713
- range: { start: startOffset, end: endOffset }
561714
- },
561715
- paintedStartOffset: target.start.offset,
561716
- paintedEndOffset: target.end.offset,
561717
- paintedObjectContained,
561718
- ...collapsedObjectBoundary ? { collapsedObjectBoundary } : {}
561719
562237
  };
561720
562238
  }
561721
562239
  function selectionTargetCoordinateSpace(target) {
@@ -573942,8 +574460,8 @@ function tocFieldSdtByteSpan(context, field) {
573942
574460
  byteEnd: encodeXml(xml.slice(0, close.sdtEndChar)).length
573943
574461
  };
573944
574462
  }
573945
- function findEnclosingParagraphStart(xml, pos, lowerBound) {
573946
- for (let i2 = Math.min(pos, xml.length - 1);i2 >= lowerBound; i2 -= 1) {
574463
+ function findEnclosingParagraphStart(xml, pos, lowerBound2) {
574464
+ for (let i2 = Math.min(pos, xml.length - 1);i2 >= lowerBound2; i2 -= 1) {
573947
574465
  if (xml.startsWith("<w:p", i2)) {
573948
574466
  const next = xml[i2 + 4];
573949
574467
  if (next === " " || next === ">" || next === "/")
@@ -578562,6 +579080,11 @@ function normalizeTarget(target) {
578562
579080
  };
578563
579081
  }
578564
579082
 
579083
+ // ../../../v2/editor-core/dist/review-read-model.js
579084
+ var init_review_read_model = __esm(() => {
579085
+ init_rewrite_groups();
579086
+ });
579087
+
578565
579088
  // ../../../v2/document-api-v2-adapter/dist/interaction-trace.js
578566
579089
  function safeTraceCollector() {
578567
579090
  try {
@@ -579111,6 +579634,7 @@ function publishCapturedHistory(context, txIds, compositeTxIdPrefix) {
579111
579634
  recordCommittedTxIdForHistory(context, entry.txId);
579112
579635
  return historyEntryToReceipt(entry);
579113
579636
  }
579637
+ const trackedChangeGroupEffects = composeHistoryGroupEffects(txIds.map((txId) => context.getHistoryTrackedChangeGroupEffects(txId)));
579114
579638
  let receipt3;
579115
579639
  try {
579116
579640
  receipt3 = composeSDDocumentSessionInternalCapturedHistory(context.session, {
@@ -579123,7 +579647,8 @@ function publishCapturedHistory(context, txIds, compositeTxIdPrefix) {
579123
579647
  if (!receipt3)
579124
579648
  return null;
579125
579649
  context.invalidate(receipt3);
579126
- recordCommittedTxIdForHistory(context, receipt3.txId);
579650
+ recordCommittedTxIdForHistory(context, receipt3.txId, { trackedChangeGroupEffects });
579651
+ context.discardHistoryMetadata(txIds);
579127
579652
  return receipt3;
579128
579653
  }
579129
579654
  function rollbackCapturedHistory(context, txIds) {
@@ -579131,6 +579656,7 @@ function rollbackCapturedHistory(context, txIds) {
579131
579656
  return;
579132
579657
  try {
579133
579658
  rollbackSDDocumentSessionInternalCapturedHistory(context.session, txIds);
579659
+ context.discardHistoryMetadata(txIds);
579134
579660
  } catch (error48) {
579135
579661
  throw new DocumentApiValidationError2("PRECONDITION_FAILED", error48 instanceof Error ? error48.message : "captured history rollback failed.");
579136
579662
  }
@@ -580324,6 +580850,195 @@ var init_adapter5 = __esm(() => {
580324
580850
  ]);
580325
580851
  });
580326
580852
 
580853
+ // ../../../v2/document-api-v2-adapter/dist/selection-mutation/replacement-span.js
580854
+ function uniqueTokenAnchors(before, after) {
580855
+ const uniquePositions = (tokens) => {
580856
+ const positions = new Map;
580857
+ tokens.forEach((token, index) => positions.set(token, positions.has(token) ? -1 : index));
580858
+ return positions;
580859
+ };
580860
+ const oldPositions = uniquePositions(before);
580861
+ const newPositions = uniquePositions(after);
580862
+ const candidates = [];
580863
+ for (const [token, oldIndex] of oldPositions) {
580864
+ const newIndex = newPositions.get(token);
580865
+ if (oldIndex >= 0 && newIndex !== undefined && newIndex >= 0)
580866
+ candidates.push([oldIndex, newIndex]);
580867
+ }
580868
+ const tails = [];
580869
+ const previous = new Int32Array(candidates.length).fill(-1);
580870
+ candidates.forEach(([, newIndex], index) => {
580871
+ let low = 0;
580872
+ let high = tails.length;
580873
+ while (low < high) {
580874
+ const middle = low + high >>> 1;
580875
+ if (candidates[tails[middle]][1] < newIndex)
580876
+ low = middle + 1;
580877
+ else
580878
+ high = middle;
580879
+ }
580880
+ if (low > 0)
580881
+ previous[index] = tails[low - 1];
580882
+ tails[low] = index;
580883
+ });
580884
+ const anchors = [];
580885
+ for (let index = tails.at(-1) ?? -1;index >= 0; index = previous[index])
580886
+ anchors.push(candidates[index]);
580887
+ return anchors.reverse();
580888
+ }
580889
+ function greedyTokenMatches(before, after, aStart, aEnd, bStart, bEnd) {
580890
+ const positions = new Map;
580891
+ for (let index = bStart;index < bEnd; index += 1) {
580892
+ const token = after[index];
580893
+ const indices = positions.get(token);
580894
+ if (indices)
580895
+ indices.push(index);
580896
+ else
580897
+ positions.set(token, [index]);
580898
+ }
580899
+ const matches = [];
580900
+ let cursor = bStart;
580901
+ for (let index = aStart;index < aEnd && cursor < bEnd; index += 1) {
580902
+ const indices = positions.get(before[index]);
580903
+ if (!indices)
580904
+ continue;
580905
+ let low = 0;
580906
+ let high = indices.length;
580907
+ while (low < high) {
580908
+ const middle = low + high >>> 1;
580909
+ if (indices[middle] < cursor)
580910
+ low = middle + 1;
580911
+ else
580912
+ high = middle;
580913
+ }
580914
+ if (low < indices.length) {
580915
+ matches.push([index, indices[low]]);
580916
+ cursor = indices[low] + 1;
580917
+ }
580918
+ }
580919
+ return matches;
580920
+ }
580921
+ function narrowTextReplacement(before, after) {
580922
+ if (before === after)
580923
+ return null;
580924
+ const tokens = /[\p{L}\p{N}\p{M}_]+|\s+|[^\p{L}\p{N}\p{M}_\s]/gu;
580925
+ const oldTokens = before.match(tokens) ?? [];
580926
+ const newTokens = after.match(tokens) ?? [];
580927
+ let prefix = 0;
580928
+ let start = 0;
580929
+ while (prefix < oldTokens.length && prefix < newTokens.length && oldTokens[prefix] === newTokens[prefix]) {
580930
+ start += oldTokens[prefix].length;
580931
+ prefix += 1;
580932
+ }
580933
+ let oldEnd = oldTokens.length;
580934
+ let newEnd = newTokens.length;
580935
+ let suffixLength = 0;
580936
+ while (oldEnd > prefix && newEnd > prefix && oldTokens[oldEnd - 1] === newTokens[newEnd - 1]) {
580937
+ suffixLength += oldTokens[oldEnd - 1].length;
580938
+ oldEnd -= 1;
580939
+ newEnd -= 1;
580940
+ }
580941
+ return { start, end: before.length - suffixLength, text: after.slice(start, after.length - suffixLength) };
580942
+ }
580943
+ function planTextReplacement(before, after) {
580944
+ const boundary = narrowTextReplacement(before, after);
580945
+ if (!boundary)
580946
+ return [];
580947
+ const tokens = /[\p{L}\p{N}\p{M}_]+|\s+|[^\p{L}\p{N}\p{M}_\s]/gu;
580948
+ const oldTokens = before.slice(boundary.start, boundary.end).match(tokens) ?? [];
580949
+ const newTokens = boundary.text.match(tokens) ?? [];
580950
+ const matches = [];
580951
+ const oldValues = new Set(oldTokens);
580952
+ if (!newTokens.some((token) => oldValues.has(token)))
580953
+ return [boundary];
580954
+ const row = (aStart, aEnd, bStart, bEnd, reverse) => {
580955
+ const lengths = new Uint32Array(bEnd - bStart + 1);
580956
+ for (let i2 = 0;i2 < aEnd - aStart; i2 += 1) {
580957
+ let diagonal = 0;
580958
+ const token = oldTokens[reverse ? aEnd - i2 - 1 : aStart + i2];
580959
+ for (let j = 1;j <= bEnd - bStart; j += 1) {
580960
+ const previous = lengths[j];
580961
+ lengths[j] = token === newTokens[reverse ? bEnd - j : bStart + j - 1] ? diagonal + 1 : Math.max(lengths[j], lengths[j - 1]);
580962
+ diagonal = previous;
580963
+ }
580964
+ }
580965
+ return lengths;
580966
+ };
580967
+ const align = (aStart, aEnd, bStart, bEnd) => {
580968
+ if (aStart === aEnd || bStart === bEnd)
580969
+ return;
580970
+ if (aEnd - aStart === 1) {
580971
+ for (let j = bStart;j < bEnd; j += 1) {
580972
+ if (oldTokens[aStart] === newTokens[j]) {
580973
+ matches.push([aStart, j]);
580974
+ break;
580975
+ }
580976
+ }
580977
+ return;
580978
+ }
580979
+ const middle = Math.floor((aStart + aEnd) / 2);
580980
+ const left = row(aStart, middle, bStart, bEnd, false);
580981
+ const right = row(middle, aEnd, bStart, bEnd, true);
580982
+ let split = 0;
580983
+ let best = -1;
580984
+ for (let j = 0;j <= bEnd - bStart; j += 1) {
580985
+ const score = left[j] + right[bEnd - bStart - j];
580986
+ if (score > best) {
580987
+ best = score;
580988
+ split = j;
580989
+ }
580990
+ }
580991
+ align(aStart, middle, bStart, bStart + split);
580992
+ align(middle, aEnd, bStart + split, bEnd);
580993
+ };
580994
+ let remainingCells = 2000000;
580995
+ const alignGap = (aStart, aEnd, bStart, bEnd) => {
580996
+ if (aStart === aEnd || bStart === bEnd)
580997
+ return;
580998
+ const values = new Set(oldTokens.slice(aStart, aEnd));
580999
+ if (!newTokens.slice(bStart, bEnd).some((token) => values.has(token)))
581000
+ return;
581001
+ const cells = 3 * (aEnd - aStart) * (bEnd - bStart);
581002
+ if (cells <= remainingCells) {
581003
+ remainingCells -= cells;
581004
+ align(aStart, aEnd, bStart, bEnd);
581005
+ } else {
581006
+ for (const match of greedyTokenMatches(oldTokens, newTokens, aStart, aEnd, bStart, bEnd))
581007
+ matches.push(match);
581008
+ }
581009
+ };
581010
+ if (3 * oldTokens.length * newTokens.length <= remainingCells) {
581011
+ alignGap(0, oldTokens.length, 0, newTokens.length);
581012
+ } else {
581013
+ const anchors = uniqueTokenAnchors(oldTokens, newTokens);
581014
+ let oldCursor2 = 0;
581015
+ let newCursor2 = 0;
581016
+ for (const [oldIndex, newIndex] of [...anchors, [oldTokens.length, newTokens.length]]) {
581017
+ alignGap(oldCursor2, oldIndex, newCursor2, newIndex);
581018
+ if (oldIndex < oldTokens.length)
581019
+ matches.push([oldIndex, newIndex]);
581020
+ oldCursor2 = oldIndex + 1;
581021
+ newCursor2 = newIndex + 1;
581022
+ }
581023
+ }
581024
+ matches.push([oldTokens.length, newTokens.length]);
581025
+ const spans = [];
581026
+ let oldCursor = 0;
581027
+ let newCursor = 0;
581028
+ let offset = boundary.start;
581029
+ for (const [oldIndex, newIndex] of matches) {
581030
+ const removed = oldTokens.slice(oldCursor, oldIndex).join("");
581031
+ const inserted = newTokens.slice(newCursor, newIndex).join("");
581032
+ if (removed || inserted) {
581033
+ spans.push({ start: offset, end: offset + removed.length, text: inserted });
581034
+ }
581035
+ offset += removed.length + (oldTokens[oldIndex]?.length ?? 0);
581036
+ oldCursor = oldIndex + 1;
581037
+ newCursor = newIndex + 1;
581038
+ }
581039
+ return spans;
581040
+ }
581041
+
580327
581042
  // ../../../v2/document-api-v2-adapter/dist/ranges/adapter.js
580328
581043
  class V2RangesAdapter {
580329
581044
  constructor(context) {
@@ -581491,23 +582206,66 @@ class V2SelectionMutationAdapter {
581491
582206
  if ("failure" in begun) {
581492
582207
  return { success: false, failure: begun.failure, resolution: edits[0].resolution };
581493
582208
  }
582209
+ const preparedByBlock = new Map;
582210
+ const planned = [];
582211
+ for (const [editIndex, edit] of edits.entries()) {
582212
+ const { on, newText, resolution } = edit;
582213
+ const spans = on.coordinateSpace !== "tracked" && resolution.text.length === on.endOffset - on.startOffset && isPlannableTextPayload(newText) ? planTextReplacement(resolution.text, newText) : [{ start: 0, end: on.endOffset - on.startOffset, text: newText }];
582214
+ const index = isMainStoryId(on.storyId) ? getSDDocumentSessionInternalParagraphIndex(this.context.session) : getSDDocumentSessionInternalStoryParagraphIndex(this.context.session, on.storyId);
582215
+ if (!index)
582216
+ return { success: false, failure: { code: "TARGET_NOT_FOUND", message: "rewrite paragraph index unavailable" }, resolution };
582217
+ const preparedKey = `${on.storyId}:${on.startBlockId}:${on.coordinateSpace ?? "visible"}`;
582218
+ const prepared = preparedByBlock.get(preparedKey) ?? prepareSelectionTargetResolution({
582219
+ target: {
582220
+ kind: "selection",
582221
+ start: { kind: "text", blockId: on.startBlockId, offset: on.startOffset },
582222
+ end: { kind: "text", blockId: on.endBlockId, offset: on.endOffset },
582223
+ ...on.coordinateSpace ? { coordinateSpace: on.coordinateSpace } : {}
582224
+ },
582225
+ index,
582226
+ readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(this.context.session, partUri),
582227
+ readPartRange: (partUri, start, end) => getSDDocumentSessionInternalPartRange(this.context.session, partUri, start, end),
582228
+ buildOffsetMap: buildOffsetMapForCoordinateSpace3
582229
+ });
582230
+ if ("error" in prepared)
582231
+ return { success: false, failure: { code: prepared.error, message: prepared.message }, resolution };
582232
+ preparedByBlock.set(preparedKey, prepared);
582233
+ for (const span of spans) {
582234
+ const narrowed = prepared.resolveOffsets(on.startOffset + span.start, on.startOffset + span.end);
582235
+ if ("error" in narrowed)
582236
+ return { success: false, failure: { code: narrowed.error, message: narrowed.message }, resolution };
582237
+ if (narrowed.paintedObjectContained)
582238
+ return { success: false, failure: { code: "INVALID_CONTEXT", message: "rewrite contains an inline object" }, resolution };
582239
+ planned.push({ on: narrowed, newText: span.text, resolution: { ...resolution, text: resolution.text.slice(span.start, span.end) }, resultKey: String(editIndex), owner: edit.ownerStepId ?? "", rewriteIntent: edit.rewriteIntent === true });
582240
+ }
582241
+ }
582242
+ if (planned.length === 0)
582243
+ return { success: false, failure: { code: "NO_OP", message: "rewrite produced no change" }, resolution: edits[0].resolution };
582244
+ const ownerIds = new Map;
582245
+ for (const edit of planned) {
582246
+ if (!ownerIds.has(edit.owner))
582247
+ ownerIds.set(edit.owner, `${begun.tx.txId}:${ownerIds.size}`);
582248
+ }
581494
582249
  const fieldEntries = listCanonicalFieldEntries(this.context);
581495
582250
  const retiredFieldIds = [];
581496
582251
  const independentTracked = options?.changeMode === "tracked" && this.context.trackedChangesReplacementMode === "independent";
581497
582252
  let trackedFieldDeletion = false;
581498
- const kernelEdits = edits.map(({ on, newText, resolution }, index) => {
581499
- const stamps = independentTracked && on.startOffset < on.endOffset && newText.length > 0 ? {
581500
- rsid: deriveRsid(`${begun.tx.txId}:${index}`, "del"),
581501
- insRsid: deriveRsid(`${begun.tx.txId}:${index}`, "ins")
581502
- } : {};
582253
+ const kernelEdits = planned.map(({ on, newText, resolution, resultKey, owner, rewriteIntent }, index) => {
582254
+ const stamps = {
582255
+ ...options?.changeMode === "tracked" && rewriteIntent ? { rewriteGroupId: ownerIds.get(owner), preserveExistingRevisions: true } : {},
582256
+ ...independentTracked && on.startOffset < on.endOffset && newText.length > 0 ? {
582257
+ rsid: deriveRsid(`${begun.tx.txId}:${index}`, "del"),
582258
+ insRsid: deriveRsid(`${begun.tx.txId}:${index}`, "ins")
582259
+ } : {}
582260
+ };
581503
582261
  if (newText.length !== 0)
581504
- return { on, newText, ...stamps, resultKey: String(index) };
582262
+ return { on, newText, ...stamps, resultKey };
581505
582263
  const matchingFields = fieldEntries.filter((entry) => entry.storyId === on.storyId && entry.blockId === on.startBlockId && entry.descriptor.resultText === resolution.text && rangesOverlap8(on.startByte, on.endByte, entry.descriptor.byteStart, entry.descriptor.byteEnd));
581506
582264
  if (matchingFields.length !== 1)
581507
- return { on, newText, ...stamps, resultKey: String(index) };
582265
+ return { on, newText, ...stamps, resultKey };
581508
582266
  if (options?.changeMode === "tracked") {
581509
582267
  trackedFieldDeletion = true;
581510
- return { on, newText, ...stamps, resultKey: String(index) };
582268
+ return { on, newText, ...stamps, resultKey };
581511
582269
  }
581512
582270
  const field = matchingFields[0];
581513
582271
  retiredFieldIds.push(field.stableFieldId);
@@ -581515,7 +582273,7 @@ class V2SelectionMutationAdapter {
581515
582273
  on,
581516
582274
  newText,
581517
582275
  ...stamps,
581518
- resultKey: String(index),
582276
+ resultKey,
581519
582277
  deleteFieldRange: {
581520
582278
  startByte: field.descriptor.byteStart,
581521
582279
  endByte: field.descriptor.byteEnd
@@ -581551,7 +582309,17 @@ class V2SelectionMutationAdapter {
581551
582309
  for (const stableFieldId of retiredFieldIds) {
581552
582310
  retireStableFieldIdForSession(this.context.session, stableFieldId);
581553
582311
  }
581554
- recordCommittedTxIdForHistory(this.context, receipt3.txId);
582312
+ const createdRewriteGroups = new Set;
582313
+ for (const outcome of receipt3.trackedTextEditOutcomes ?? []) {
582314
+ const source = edits[Number(outcome.resultKey)];
582315
+ const origin = source.rewriteIntent ? ownerIds.get(source.ownerStepId ?? "") : undefined;
582316
+ if (origin && outcome.createdRsids.length > 0) {
582317
+ createdRewriteGroups.add(rewriteReviewId(source.on, source.resolution, origin));
582318
+ }
582319
+ }
582320
+ recordCommittedTxIdForHistory(this.context, receipt3.txId, createdRewriteGroups.size > 0 ? {
582321
+ trackedChangeGroupEffects: { created: [...createdRewriteGroups], updated: [], removed: [] }
582322
+ } : undefined);
581555
582323
  const story = edits[0].resolution.target.story;
581556
582324
  const createdRefs = receipt3.createdRefs ?? [];
581557
582325
  const updatedRefs = receipt3.updatedRefs ?? [];
@@ -581563,7 +582331,10 @@ class V2SelectionMutationAdapter {
581563
582331
  ]));
581564
582332
  const trackedOutcomeLogicalView = trackedOutcomeRawIds.size <= 100 && trackedOutcomeRawIds.size > 0 ? buildCachedTrackedChangeLogicalView(this.context).logical : null;
581565
582333
  const trackedChangeOutcomes = (receipt3.trackedTextEditOutcomes ?? []).map((outcome) => {
581566
- const refs = dedupeTrackedChangeReceiptEntities([...outcome.createdRsids, ...outcome.updatedRsids].map((rawId) => ({
582334
+ const source = edits[Number(outcome.resultKey)];
582335
+ const origin = source.rewriteIntent ? ownerIds.get(source.ownerStepId ?? "") : undefined;
582336
+ const parentId = origin ? rewriteReviewId(source.on, source.resolution, origin) : undefined;
582337
+ const refs = parentId && (outcome.createdRsids.length > 0 || outcome.updatedRsids.length > 0) ? [{ kind: "entity", entityType: "trackedChange", entityId: parentId }] : dedupeTrackedChangeReceiptEntities([...outcome.createdRsids, ...outcome.updatedRsids].map((rawId) => ({
581567
582338
  kind: "entity",
581568
582339
  entityType: "trackedChange",
581569
582340
  entityId: trackedOutcomeLogicalView?.rsidToLogicalId.get(rawId) ?? rawId
@@ -581594,11 +582365,11 @@ class V2SelectionMutationAdapter {
581594
582365
  readEffectiveInlineUniformity(input) {
581595
582366
  return readEffectiveInlineUniformity(this.context, input);
581596
582367
  }
581597
- execute(request, options) {
582368
+ execute(request, options, rewriteIntent = false) {
581598
582369
  const offsetSpace = selectionOffsetSpace(options);
581599
582370
  switch (request.kind) {
581600
582371
  case "replace":
581601
- return this.executeReplace(request, options, offsetSpace);
582372
+ return this.executeReplace(request, options, offsetSpace, rewriteIntent);
581602
582373
  case "insert":
581603
582374
  return this.executeReplace({
581604
582375
  kind: "replace",
@@ -581606,7 +582377,7 @@ class V2SelectionMutationAdapter {
581606
582377
  ref: request.ref,
581607
582378
  text: request.text,
581608
582379
  in: request.in
581609
- }, options, offsetSpace);
582380
+ }, options, offsetSpace, false);
581610
582381
  case "delete":
581611
582382
  return this.executeReplace({
581612
582383
  kind: "replace",
@@ -581614,15 +582385,15 @@ class V2SelectionMutationAdapter {
581614
582385
  ref: request.ref,
581615
582386
  text: "",
581616
582387
  in: request.in
581617
- }, options, offsetSpace);
582388
+ }, options, offsetSpace, false);
581618
582389
  case "format":
581619
582390
  return this.executeFormat(request, options, offsetSpace);
581620
582391
  }
581621
582392
  }
581622
- executeReplace(request, options, offsetSpace) {
582393
+ executeReplace(request, options, offsetSpace, isRewrite = false) {
581623
582394
  const startedAt = nowMs6();
581624
582395
  if (request.ref !== undefined && request.target === undefined) {
581625
- return this.executeRefBasedReplace(request, options);
582396
+ return this.executeRefBasedReplace(request, options, isRewrite);
581626
582397
  }
581627
582398
  const target = request.target;
581628
582399
  if (!target) {
@@ -581644,6 +582415,14 @@ class V2SelectionMutationAdapter {
581644
582415
  const revisionFailure = validateExpectedRevision(this.context, options?.expectedRevision);
581645
582416
  if (revisionFailure)
581646
582417
  return failureWithoutResolution(revisionFailure.code, revisionFailure.message);
582418
+ const policyFailure = this.context.getMutationPolicyFailure();
582419
+ if (policyFailure)
582420
+ return failureWithoutResolution(policyFailure.code, policyFailure.message);
582421
+ if (!options?.dryRun && initialStory.materialization?.sourcePartUri) {
582422
+ const preflight = this.executeReplace(request, { ...options, dryRun: true }, offsetSpace, isRewrite);
582423
+ if (!preflight.success)
582424
+ return preflight;
582425
+ }
581647
582426
  const materialized = options?.dryRun ? { ok: true, resolved: initialStory } : storyLocator ? materializeHeaderFooterSlotIfInherited(this.context, initialStory, storyLocator) : { ok: true, resolved: initialStory };
581648
582427
  if (!materialized.ok) {
581649
582428
  return failureWithoutResolution(materialized.failure.code, materialized.failure.message);
@@ -581724,7 +582503,7 @@ class V2SelectionMutationAdapter {
581724
582503
  });
581725
582504
  }
581726
582505
  const resolveSelectionTargetStartedAt = nowMs6();
581727
- const resolved = resolveSelectionTargetToRange({
582506
+ const prepared = prepareSelectionTargetResolution({
581728
582507
  target,
581729
582508
  index,
581730
582509
  readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(this.context.session, partUri),
@@ -581732,6 +582511,9 @@ class V2SelectionMutationAdapter {
581732
582511
  buildOffsetMap: buildOffsetMapForCoordinateSpace3,
581733
582512
  ...offsetSpace ? { offsetSpace } : {}
581734
582513
  });
582514
+ if ("error" in prepared)
582515
+ return failureWithoutResolution(prepared.error, prepared.message);
582516
+ const resolved = prepared.resolveOffsets();
581735
582517
  if ("error" in resolved) {
581736
582518
  return failureWithoutResolution(resolved.error, resolved.message);
581737
582519
  }
@@ -581760,6 +582542,30 @@ class V2SelectionMutationAdapter {
581760
582542
  resolved
581761
582543
  });
581762
582544
  const buildResolutionMs = nowMs6() - buildResolutionStartedAt;
582545
+ let replacements = resolved.coordinateSpace !== "tracked" && resolved.startOffset < resolved.endOffset && selectedText.length === resolved.endOffset - resolved.startOffset && isPlannableTextPayload(request.text) ? planTextReplacement(selectedText, request.text) : [{ start: 0, end: resolved.endOffset - resolved.startOffset, text: request.text }];
582546
+ if (story.storyKind === "textbox" && replacements.length > 1) {
582547
+ const boundary = narrowTextReplacement(selectedText, request.text);
582548
+ replacements = boundary ? [boundary] : [];
582549
+ }
582550
+ if (replacements.length === 0) {
582551
+ return { success: false, failure: { code: "NO_OP", message: "replace produced no change." }, resolution };
582552
+ }
582553
+ const edits = [];
582554
+ for (const replacement of replacements) {
582555
+ let editRange = resolved;
582556
+ if (replacement.start !== 0 || replacement.end !== selectedText.length) {
582557
+ const baseOffset = offsetSpace === "selection" ? resolved.paintedStartOffset : resolved.startOffset;
582558
+ const narrowed = prepared.resolveOffsets(baseOffset + replacement.start, baseOffset + replacement.end);
582559
+ if ("error" in narrowed)
582560
+ return failureWithoutResolution(narrowed.error, narrowed.message);
582561
+ editRange = {
582562
+ ...narrowed,
582563
+ paintedStartOffset: resolved.paintedStartOffset + replacement.start,
582564
+ paintedEndOffset: resolved.paintedStartOffset + replacement.end
582565
+ };
582566
+ }
582567
+ edits.push({ on: editRange, newText: replacement.text });
582568
+ }
581763
582569
  if (options?.dryRun) {
581764
582570
  return {
581765
582571
  success: true,
@@ -581779,13 +582585,20 @@ class V2SelectionMutationAdapter {
581779
582585
  const tx = begun.tx;
581780
582586
  const editTextStartedAt = nowMs6();
581781
582587
  const collapsedInlineAffinity = selectionCollapsedInlineAffinity(options);
581782
- const resolvedForEdit = collapsedInlineAffinity && resolved.startOffset === resolved.endOffset ? { ...resolved, collapsedInlineAffinity } : resolved;
581783
- tx.editText({
581784
- changeMode: options?.changeMode ?? "direct",
581785
- on: resolvedForEdit,
581786
- newText: request.text,
581787
- ...trackedTextStampForMode(this.context, tx.txId, options, resolved, request.text)
581788
- });
582588
+ const kernelEdits = edits.map((edit, index2) => ({
582589
+ on: collapsedInlineAffinity && edit.on.startOffset === edit.on.endOffset ? { ...edit.on, collapsedInlineAffinity } : edit.on,
582590
+ newText: edit.newText,
582591
+ ...options?.changeMode === "tracked" && (isRewrite || edits.length > 1) && !typingHistoryMetadata(options) && story.storyKind !== "textbox" ? { rewriteGroupId: `${tx.txId}:0`, preserveExistingRevisions: isRewrite } : {},
582592
+ ...trackedTextStampForMode(this.context, `${tx.txId}:${index2}`, options, edit.on, edit.newText)
582593
+ }));
582594
+ if (kernelEdits.length === 1 && !kernelEdits[0].rewriteGroupId) {
582595
+ tx.editText({ changeMode: options?.changeMode ?? "direct", ...kernelEdits[0] });
582596
+ } else {
582597
+ tx.editTextRanges({
582598
+ changeMode: options?.changeMode ?? "direct",
582599
+ edits: kernelEdits
582600
+ });
582601
+ }
581789
582602
  const editTextMs = nowMs6() - editTextStartedAt;
581790
582603
  const txPerf = createSDTxPerfProbe();
581791
582604
  const commitStartedAt = nowMs6();
@@ -581805,7 +582618,17 @@ class V2SelectionMutationAdapter {
581805
582618
  const invalidateStartedAt = nowMs6();
581806
582619
  this.context.invalidate(receipt3);
581807
582620
  const adapterInvalidateMs = nowMs6() - invalidateStartedAt;
581808
- recordCommittedTxIdForHistory(this.context, receipt3.txId, typingHistoryMetadata(options));
582621
+ const createdRewriteOrigin = kernelEdits.find((edit) => edit.rewriteGroupId)?.rewriteGroupId;
582622
+ recordCommittedTxIdForHistory(this.context, receipt3.txId, {
582623
+ ...typingHistoryMetadata(options),
582624
+ ...createdRewriteOrigin && receipt3.createdRefs?.some((ref5) => ref5.kind === "trackedChange") ? {
582625
+ trackedChangeGroupEffects: {
582626
+ created: [rewriteReviewId(resolved, resolution, createdRewriteOrigin)],
582627
+ updated: [],
582628
+ removed: []
582629
+ }
582630
+ } : {}
582631
+ });
581809
582632
  const textRangeShiftsStartedAt = nowMs6();
581810
582633
  const textRangeShifts = projectTextRangeShifts(receipt3.textRangeShifts ?? [], this.context.session, effectiveStory);
581811
582634
  const projectTextRangeShiftsMs = nowMs6() - textRangeShiftsStartedAt;
@@ -581823,20 +582646,32 @@ class V2SelectionMutationAdapter {
581823
582646
  const remappedRefs = projectTrackedTextReviewGroupRemappings(this.context, inserted);
581824
582647
  const projectTrackedTextEntitiesMs = nowMs6() - trackedProjectionStartedAt;
581825
582648
  const effectsStartedAt = nowMs6();
581826
- const effects2 = buildInsertedTextEffect({
581827
- blockId: resolved.startBlockId,
581828
- baseOffset: resolved.startOffset,
581829
- paintedBaseOffset: resolved.paintedStartOffset,
581830
- text: request.text,
581831
- story: effectiveStory,
581832
- changeMode: options?.changeMode ?? "direct",
581833
- coordinateSpace: resolved.coordinateSpace,
581834
- storyId: resolved.storyId,
581835
- createdSpanProof: getSDCreatedVisibleTextSpanProof(receipt3)
582649
+ let offsetDelta = 0;
582650
+ const insertedTextEffects = edits.flatMap((edit) => {
582651
+ const effects3 = buildInsertedTextEffect({
582652
+ blockId: edit.on.startBlockId,
582653
+ baseOffset: edit.on.startOffset + offsetDelta,
582654
+ paintedBaseOffset: edit.on.paintedStartOffset + offsetDelta,
582655
+ text: edit.newText,
582656
+ story: effectiveStory,
582657
+ changeMode: options?.changeMode ?? "direct",
582658
+ coordinateSpace: edit.on.coordinateSpace,
582659
+ storyId: edit.on.storyId,
582660
+ createdSpanProof: getSDCreatedVisibleTextSpanProof(receipt3)
582661
+ });
582662
+ offsetDelta += edit.newText.length - (edit.on.endOffset - edit.on.startOffset);
582663
+ return effects3?.insertedText ?? [];
581836
582664
  });
582665
+ const effects2 = insertedTextEffects.length > 0 ? { insertedText: insertedTextEffects } : undefined;
581837
582666
  const buildInsertedTextEffectMs = nowMs6() - effectsStartedAt;
582667
+ const rewriteOrigin = isRewrite ? kernelEdits.find((edit) => edit.rewriteGroupId)?.rewriteGroupId : undefined;
581838
582668
  const successReceipt = {
581839
582669
  success: true,
582670
+ ...rewriteOrigin ? { trackedChangeCount: 1, trackedChangeRefs: [{
582671
+ kind: "entity",
582672
+ entityType: "trackedChange",
582673
+ entityId: rewriteReviewId(resolved, resolution, rewriteOrigin)
582674
+ }] } : {},
581840
582675
  affectedStories,
581841
582676
  textRangeShifts,
581842
582677
  txId: receipt3.txId,
@@ -582190,7 +583025,7 @@ class V2SelectionMutationAdapter {
582190
583025
  ...remappedRefs ? { remappedRefs } : {}
582191
583026
  };
582192
583027
  }
582193
- executeRefBasedReplace(request, options) {
583028
+ executeRefBasedReplace(request, options, isRewrite = false) {
582194
583029
  const ref5 = request.ref;
582195
583030
  if (isV2RangeRef(ref5)) {
582196
583031
  const resolvedRange = this.resolveRangeRefSelectionTarget(ref5, request.in);
@@ -582204,7 +583039,7 @@ class V2SelectionMutationAdapter {
582204
583039
  target: resolvedRange.target,
582205
583040
  text: request.text,
582206
583041
  in: resolvedRange.story
582207
- }, options, "kernel");
583042
+ }, options, "kernel", isRewrite);
582208
583043
  }
582209
583044
  if (!isV2SearchRef(ref5)) {
582210
583045
  const raw = resolveRawBlockRefTarget(this.context, ref5, request.in);
@@ -582216,7 +583051,7 @@ class V2SelectionMutationAdapter {
582216
583051
  target: raw.target,
582217
583052
  text: request.text,
582218
583053
  in: request.in
582219
- }, options, "kernel");
583054
+ }, options, "kernel", isRewrite);
582220
583055
  }
582221
583056
  const outcome = resolveV2SearchRef({
582222
583057
  ref: ref5,
@@ -582248,75 +583083,12 @@ class V2SelectionMutationAdapter {
582248
583083
  resolution
582249
583084
  };
582250
583085
  }
582251
- if (options?.dryRun) {
582252
- return {
582253
- success: true,
582254
- resolution
582255
- };
582256
- }
582257
- const fieldDelete = tryDeleteMatchedFieldRef(this.context, request.text, outcome, resolution);
582258
- if (fieldDelete) {
582259
- return fieldDelete;
582260
- }
582261
- const begun = this.context.beginMutation({
582262
- expectedRevision: options?.expectedRevision
582263
- });
582264
- if ("failure" in begun) {
582265
- return {
582266
- success: false,
582267
- failure: begun.failure,
582268
- resolution
582269
- };
582270
- }
582271
- const tx = begun.tx;
582272
- tx.editText({
582273
- changeMode: options?.changeMode ?? "direct",
582274
- on: outcome.resolved,
582275
- newText: request.text,
582276
- ...trackedTextStampForMode(this.context, tx.txId, options, outcome.resolved, request.text)
582277
- });
582278
- const receipt3 = tx.commit();
582279
- if (receipt3.status === "rejected") {
582280
- const code = mapRejectionReason(receipt3.rejectedReason ?? "internal-error");
582281
- return {
582282
- success: false,
582283
- failure: {
582284
- code,
582285
- message: receipt3.rejectedReason ?? "internal-error"
582286
- },
582287
- resolution
582288
- };
583086
+ if (!options?.dryRun) {
583087
+ const fieldDelete = tryDeleteMatchedFieldRef(this.context, request.text, outcome, resolution);
583088
+ if (fieldDelete)
583089
+ return fieldDelete;
582289
583090
  }
582290
- this.context.invalidate(receipt3);
582291
- recordCommittedTxIdForHistory(this.context, receipt3.txId);
582292
- const textRangeShifts = projectTextRangeShifts(receipt3.textRangeShifts ?? [], this.context.session, outcome.storyLocator);
582293
- const affectedStories = projectAffectedStories(receipt3.storiesChanged ?? [], this.context.session, receipt3.partsChanged, outcome.storyLocator);
582294
- const inserted = projectTrackedTextEntities(this.context, receipt3.createdRefs ?? []);
582295
- const updated = projectTrackedTextEntities(this.context, receipt3.updatedRefs ?? []);
582296
- const invalidatedRefs = projectAffectedRefs2(receipt3.invalidatedRefs ?? []);
582297
- const remappedRefs = projectTrackedTextReviewGroupRemappings(this.context, inserted);
582298
- const effects2 = buildInsertedTextEffect({
582299
- blockId: outcome.resolved.startBlockId,
582300
- baseOffset: outcome.resolved.startOffset,
582301
- text: request.text,
582302
- story: outcome.storyLocator,
582303
- changeMode: options?.changeMode ?? "direct",
582304
- coordinateSpace: outcome.resolved.coordinateSpace,
582305
- storyId: outcome.resolved.storyId,
582306
- createdSpanProof: getSDCreatedVisibleTextSpanProof(receipt3)
582307
- });
582308
- return {
582309
- success: true,
582310
- affectedStories,
582311
- textRangeShifts,
582312
- txId: receipt3.txId,
582313
- resolution,
582314
- ...inserted ? { inserted } : {},
582315
- ...updated ? { updated } : {},
582316
- ...invalidatedRefs.length > 0 ? { invalidatedRefs } : {},
582317
- ...remappedRefs ? { remappedRefs } : {},
582318
- ...effects2 ? { effects: effects2 } : {}
582319
- };
583091
+ return this.executeReplace({ kind: "replace", target: outcome.selectionTarget, text: request.text, in: outcome.storyLocator }, options, "kernel", isRewrite);
582320
583092
  }
582321
583093
  trackedTextMove(input, options) {
582322
583094
  const destination = input.destination;
@@ -583383,6 +584155,14 @@ function isDirectTextPayload(text) {
583383
584155
  }
583384
584156
  return true;
583385
584157
  }
584158
+ function isPlannableTextPayload(text) {
584159
+ for (let i2 = 0;i2 < text.length; i2 += 1) {
584160
+ const code = text.charCodeAt(i2);
584161
+ if (code < 32 && code !== 9)
584162
+ return false;
584163
+ }
584164
+ return true;
584165
+ }
583386
584166
  function trackedTextStampForMode(context, txId, options, resolved, newText) {
583387
584167
  if (options?.changeMode !== "tracked")
583388
584168
  return {};
@@ -583558,8 +584338,14 @@ function readTrailingBodySectPr(bodyInner) {
583558
584338
  function buildOffsetMapForCoordinateSpace3(bytes, byteStart, byteEnd, coordinateSpace) {
583559
584339
  return coordinateSpace === "tracked" ? buildSDDocumentSessionInternalTrackedParagraphOffsetMap(bytes, byteStart, byteEnd) : buildSDDocumentSessionInternalParagraphOffsetMap(bytes, byteStart, byteEnd);
583560
584340
  }
584341
+ function rewriteReviewId(on, resolution, origin) {
584342
+ const story = resolution.target.story;
584343
+ const noteId = story && "noteId" in story ? story.noteId : undefined;
584344
+ return buildTextRewriteReviewGroupId(on.storyId, origin, noteId);
584345
+ }
583561
584346
  var TD79, TE41, PERMISSION_DENIED_DOC_PROTECTION = "document protection permits edits only within an everyone permission range.", FORMAT_STRADDLE_MARKER_KINDS;
583562
584347
  var init_adapter7 = __esm(() => {
584348
+ init_review_read_model();
583563
584349
  init_src3();
583564
584350
  init_sd_document_session_internal();
583565
584351
  init_logical_view_cache();
@@ -584245,6 +585031,7 @@ function createV2AdapterContext(session, options = {}) {
584245
585031
  const undoGroups = [];
584246
585032
  const redoGroups = [];
584247
585033
  const historyTrackedChangeLogicalIds = new Map;
585034
+ const historyTrackedChangeGroupEffects = new Map;
584248
585035
  const historyCaptureStack = [];
584249
585036
  let historyGeneration = getSDDocumentSessionInternalHistoryGeneration(session);
584250
585037
  const ensureHistoryGeneration = () => {
@@ -584257,6 +585044,7 @@ function createV2AdapterContext(session, options = {}) {
584257
585044
  undoGroups.length = 0;
584258
585045
  redoGroups.length = 0;
584259
585046
  historyTrackedChangeLogicalIds.clear();
585047
+ historyTrackedChangeGroupEffects.clear();
584260
585048
  fieldContext = copyScalarFieldContext(undefined);
584261
585049
  };
584262
585050
  const renderCommitCaptureStack = [];
@@ -584478,6 +585266,13 @@ function createV2AdapterContext(session, options = {}) {
584478
585266
  historyTrackedChangeLogicalIds.delete(oldestTxId);
584479
585267
  }
584480
585268
  }
585269
+ const groupEffects = metadata?.trackedChangeGroupEffects;
585270
+ if (groupEffects)
585271
+ historyTrackedChangeGroupEffects.set(txId, {
585272
+ created: [...groupEffects.created],
585273
+ updated: [...groupEffects.updated],
585274
+ removed: [...groupEffects.removed]
585275
+ });
584481
585276
  const activeCapture = historyCaptureStack[historyCaptureStack.length - 1];
584482
585277
  if (activeCapture) {
584483
585278
  activeCapture.push(txId);
@@ -584497,8 +585292,7 @@ function createV2AdapterContext(session, options = {}) {
584497
585292
  ...logicalGroup ? { logicalGroup: { ...logicalGroup } } : {}
584498
585293
  });
584499
585294
  }
584500
- for (const redoTxId of redoStack)
584501
- historyTrackedChangeLogicalIds.delete(redoTxId);
585295
+ this.discardHistoryMetadata(redoStack);
584502
585296
  redoStack.length = 0;
584503
585297
  redoGroups.length = 0;
584504
585298
  const evicted = [];
@@ -584512,7 +585306,7 @@ function createV2AdapterContext(session, options = {}) {
584512
585306
  }
584513
585307
  for (const dropped of droppedTxIds) {
584514
585308
  evicted.push(dropped);
584515
- historyTrackedChangeLogicalIds.delete(dropped);
585309
+ this.discardHistoryMetadata([dropped]);
584516
585310
  if (onEvict)
584517
585311
  onEvict(dropped);
584518
585312
  }
@@ -584522,6 +585316,15 @@ function createV2AdapterContext(session, options = {}) {
584522
585316
  getHistoryTrackedChangeLogicalIds(txId) {
584523
585317
  return historyTrackedChangeLogicalIds.get(txId) ?? null;
584524
585318
  },
585319
+ getHistoryTrackedChangeGroupEffects(txId) {
585320
+ return historyTrackedChangeGroupEffects.get(txId) ?? null;
585321
+ },
585322
+ discardHistoryMetadata(txIds) {
585323
+ for (const txId of txIds) {
585324
+ historyTrackedChangeLogicalIds.delete(txId);
585325
+ historyTrackedChangeGroupEffects.delete(txId);
585326
+ }
585327
+ },
584525
585328
  captureCommittedHistory(callback) {
584526
585329
  const capturedTxIds = [];
584527
585330
  historyCaptureStack.push(capturedTxIds);
@@ -622169,8 +622972,6 @@ function buildTrackedChangeThreadLookup(context) {
622169
622972
  function buildVisibleLogicalIdByFragment(logical) {
622170
622973
  const out = new WeakMap;
622171
622974
  for (const entry of logical.byId.values()) {
622172
- if (entry.reviewGroup?.role === "child")
622173
- continue;
622174
622975
  const visibleEntry = resolveVisibleLogicalOwner(logical, entry);
622175
622976
  if (!visibleEntry)
622176
622977
  continue;
@@ -622186,15 +622987,15 @@ function buildVisibleLogicalIdByFragment(logical) {
622186
622987
  return out;
622187
622988
  }
622188
622989
  function resolveVisibleLogicalOwner(logical, entry) {
622189
- const reviewParentId = entry.reviewGroup?.role === "child" ? entry.reviewGroup.parentId : null;
622990
+ const reviewParentId = reviewGroupDisplayParentId(entry);
622190
622991
  const subsumptionParentId = entry.subsumption?.role === "child" ? entry.subsumption.parentId : null;
622191
- if (entry.reviewGroup?.role === "child" && !reviewParentId)
622992
+ if (entry.reviewGroup?.role === "child" && !reviewParentId && !isVisibleLogicalTrackedChange(entry))
622192
622993
  return null;
622193
622994
  if (reviewParentId && subsumptionParentId && reviewParentId !== subsumptionParentId)
622194
622995
  return null;
622195
622996
  const ownerId = reviewParentId ?? subsumptionParentId;
622196
622997
  const owner = ownerId ? logical.byId.get(ownerId) : entry;
622197
- if (!owner || owner.reviewGroup?.role === "child" || owner.subsumption?.role === "child")
622998
+ if (!owner || !isVisibleLogicalTrackedChange(owner))
622198
622999
  return null;
622199
623000
  return owner;
622200
623001
  }
@@ -622968,6 +623769,7 @@ function structuredError3(code2, message) {
622968
623769
  }
622969
623770
  var LIVE_TRACKED_CHANGE_COMMENT_ID_PREFIX = "tc-comment:", trackedChangeAssociationCache, commentLinksCache;
622970
623771
  var init_read = __esm(() => {
623772
+ init_review_read_model();
622971
623773
  init_src3();
622972
623774
  init_sd_document_session_internal();
622973
623775
  init_logical_view_cache();
@@ -629710,7 +630512,7 @@ class V2InfoAdapter {
629710
630512
  const commentsCatalog = getSDDocumentSessionInternalCommentsCatalog(this.context.session);
629711
630513
  const comments = commentsCatalog?.orderedWIds.length ?? 0;
629712
630514
  const tcCatalog = getSDDocumentSessionInternalTrackedChangeCatalog(this.context.session);
629713
- const trackedChanges = tcCatalog ? Array.from(buildCachedTrackedChangeLogicalView(this.context).logical.byId.values()).filter((entry) => entry.reviewGroup?.role !== "child" && entry.subsumption?.role !== "child").length : 0;
630515
+ const trackedChanges = tcCatalog ? Array.from(buildCachedTrackedChangeLogicalView(this.context).logical.byId.values()).filter(isVisibleLogicalTrackedChange).length : 0;
629714
630516
  const lists2 = countDistinctLists(paragraphs);
629715
630517
  const outline = paragraphs.filter((p) => p.headingLevel > 0).map((p) => ({ level: p.headingLevel, text: p.text, nodeId: p.blockId }));
629716
630518
  return {
@@ -630214,6 +631016,7 @@ function findTrackedParagraphEntry(context, storyId, partUri, start, end) {
630214
631016
  }
630215
631017
  var WORD_RE;
630216
631018
  var init_read_adapters = __esm(() => {
631019
+ init_review_read_model();
630217
631020
  init_src3();
630218
631021
  init_sd_document_session_internal();
630219
631022
  init_story_locator();
@@ -636541,6 +637344,8 @@ class V2TrackedChangesAdapter {
636541
637344
  continue;
636542
637345
  }
636543
637346
  if (entry.reviewGroup?.role === "parent") {
637347
+ if (entry.reviewGroup.kind === "text-rewrite")
637348
+ cascadeChildRefs.push({ kind: "trackedChange", entityId: entry.id, storyId: entry.storyId });
636544
637349
  for (const fragment3 of entry.structuralFragments) {
636545
637350
  if (seenStructuralKeys.has(fragment3.entityKey))
636546
637351
  continue;
@@ -636784,9 +637589,7 @@ class V2TrackedChangesAdapter {
636784
637589
  withSpan("documentApi.trackChanges.adapter.invalidate", "document-api", {
636785
637590
  txId: receipt3.txId
636786
637591
  }, () => {
636787
- const trackedChangeLogicalIds = collectHistoryTrackedChangeLogicalIds(receipt3, logical);
636788
637592
  this.context.invalidate(receipt3);
636789
- recordCommittedTxIdForHistory(this.context, receipt3.txId, trackedChangeLogicalIds.size > 0 ? { trackedChangeLogicalIds } : undefined);
636790
637593
  });
636791
637594
  let postLogical = null;
636792
637595
  const getPostLogical = () => {
@@ -636803,11 +637606,36 @@ class V2TrackedChangesAdapter {
636803
637606
  createdRefCount: receipt3.createdRefs?.length ?? 0
636804
637607
  }, () => {
636805
637608
  const mergedInvalidated = mergeInvalidatedRefs(receipt3.invalidatedRefs ?? [], cascadeChildRefs);
637609
+ const touchedGroups = new Set;
637610
+ for (const ref5 of mergedInvalidated) {
637611
+ if (ref5.kind !== "trackedChange")
637612
+ continue;
637613
+ const id = logical.rsidToLogicalId.get(ref5.entityId) ?? ref5.entityId;
637614
+ const group = logical.byId.get(id)?.reviewGroup;
637615
+ if (group?.kind === "text-rewrite")
637616
+ touchedGroups.add(group.parentId ?? id);
637617
+ }
637618
+ const survivingGroups = [...touchedGroups].filter((id) => getPostLogical().byId.has(id));
637619
+ for (const id of touchedGroups) {
637620
+ if (!getPostLogical().byId.has(id) && !mergedInvalidated.some((ref5) => ref5.kind === "trackedChange" && ref5.entityId === id)) {
637621
+ mergedInvalidated.push({ kind: "trackedChange", entityId: id, storyId: logical.byId.get(id).storyId });
637622
+ }
637623
+ }
636806
637624
  const createdRefs = receipt3.createdRefs ?? [];
637625
+ const trackedChangeLogicalIds = collectHistoryTrackedChangeLogicalIds(receipt3, logical);
637626
+ recordCommittedTxIdForHistory(this.context, receipt3.txId, {
637627
+ ...trackedChangeLogicalIds.size > 0 ? { trackedChangeLogicalIds } : {},
637628
+ ...touchedGroups.size > 0 ? { trackedChangeGroupEffects: {
637629
+ created: [],
637630
+ updated: survivingGroups,
637631
+ removed: [...touchedGroups].filter((id) => !survivingGroups.includes(id))
637632
+ } } : {}
637633
+ });
636807
637634
  return {
636808
637635
  success: true,
636809
637636
  inserted: createdRefs.length > 0 ? projectInsertedEntitiesWithLogicalIds(createdRefs, getPostLogical()) : [],
636810
637637
  removed: projectRemovedEntitiesWithLogicalIds(mergedInvalidated, logical),
637638
+ ...survivingGroups.length ? { updated: survivingGroups.map((entityId) => ({ kind: "entity", entityType: "trackedChange", entityId })) } : {},
636811
637639
  invalidatedRefs: projectAffectedRefsWithLogicalIds(mergedInvalidated, logical),
636812
637640
  remappedRefs: projectRemappedRefsWithLogicalIds(receipt3.remappedRefs ?? [], logical),
636813
637641
  affectedStories: projectAffectedStories(receipt3.storiesChanged ?? [], this.context.session, receipt3.partsChanged),
@@ -636822,7 +637650,7 @@ class V2TrackedChangesAdapter {
636822
637650
  if (!entry) {
636823
637651
  return failure17("TARGET_NOT_FOUND", `No tracked change with id "${target.range.anchor}".`);
636824
637652
  }
636825
- if (entry.reviewGroup) {
637653
+ if (entry.reviewGroup && !(entry.reviewGroup.kind === "text-rewrite" && entry.reviewGroup.role === "child")) {
636826
637654
  return failure17("INVALID_INPUT", `trackChanges.decide range: tracked change "${entry.id}" is part of a grouped Word revision; ` + "decide it atomically by id.");
636827
637655
  }
636828
637656
  if (entry.type === "structural" || entry.type === "move") {
@@ -636989,7 +637817,7 @@ class V2TrackedChangesAdapter {
636989
637817
  if (!overlap.logical) {
636990
637818
  return failure17("INTERNAL_ERROR", `trackChanges.decide range: overlapped fragment "${overlap.fragment.rsid}" was not mapped to a logical tracked change.`);
636991
637819
  }
636992
- if (overlap.logical.reviewGroup) {
637820
+ if (overlap.logical.reviewGroup && overlap.logical.reviewGroup.kind !== "text-rewrite") {
636993
637821
  return failure17("INVALID_INPUT", `trackChanges.decide range: tracked change "${overlap.logical.id}" is part of a grouped multi-paragraph ` + "insertion; decide it atomically by id.");
636994
637822
  }
636995
637823
  }
@@ -637154,6 +637982,10 @@ function isTextCoordinateSpace(value2) {
637154
637982
  return value2 === undefined || value2 === "visible" || value2 === "tracked";
637155
637983
  }
637156
637984
  function selectFragmentForLogicalRange(entry, side) {
637985
+ if (entry.reviewGroup?.kind === "text-rewrite" && entry.reviewGroup.role === "parent") {
637986
+ const kind = side === "delete" || side === "deleted" || side === "source" ? "del" : "ins";
637987
+ return entry.fragments.find((fragment3) => fragment3.kind === kind) ?? entry.fragments[0] ?? null;
637988
+ }
637157
637989
  if (entry.type === "replacement") {
637158
637990
  if (side === "delete" || side === "deleted" || side === "source") {
637159
637991
  const deletedRsid = entry.sides?.deleted?.rsid;
@@ -637487,11 +638319,11 @@ function logicalEntryMatchesStoryFilter(entry, filter) {
637487
638319
  return !filter.noteId || entry.noteId === filter.noteId;
637488
638320
  }
637489
638321
  function isVisibleLogicalChange(entry) {
637490
- if (entry.reviewGroup?.role === "child")
637491
- return false;
637492
- return entry.subsumption?.role !== "child";
638322
+ return isVisibleLogicalTrackedChange(entry);
637493
638323
  }
637494
638324
  function resolveSubsumedLogicalChange(logical, entry) {
638325
+ if (entry.reviewGroup?.kind === "text-rewrite")
638326
+ return entry;
637495
638327
  if (entry.reviewGroup?.role === "child" && entry.reviewGroup.parentId) {
637496
638328
  return logical.byId.get(entry.reviewGroup.parentId) ?? entry;
637497
638329
  }
@@ -637534,6 +638366,7 @@ function buildDiscoveryItem2(entry, context, logical, linkedCommentIds, resolveS
637534
638366
  ...navigationTarget ? { navigationTarget } : {},
637535
638367
  ...structuralDescriptor ? { structuralDescriptor } : {},
637536
638368
  revisionGroupId: entry.revisionGroupId,
638369
+ ...entry.reviewGroup?.kind === "text-rewrite" && logical ? { reviewGroup: projectTextRewriteReviewGroup(entry, logical) } : {},
637537
638370
  splitFromId: entry.splitFromId,
637538
638371
  sourceIds: projectSourceIds(entry),
637539
638372
  wordRevisionIds: projectWordRevisionIdsAlias(entry),
@@ -637670,6 +638503,7 @@ function buildInfo(entry, context, logical, linkedCommentIds, resolveSession) {
637670
638503
  sourceIds: projectSourceIds(entry),
637671
638504
  wordRevisionIds: projectWordRevisionIdsAlias(entry),
637672
638505
  revisionGroupId: entry.revisionGroupId,
638506
+ ...entry.reviewGroup?.kind === "text-rewrite" && logical ? { reviewGroup: projectTextRewriteReviewGroup(entry, logical) } : {},
637673
638507
  splitFromId: entry.splitFromId,
637674
638508
  ...structuralDescriptor ? { structuralDescriptor } : {},
637675
638509
  ...replacement ? { replacement } : {},
@@ -637777,7 +638611,7 @@ function isGoogleDocsLikePackage(session) {
637777
638611
  return getSDDocumentSessionInternalPartBytes(session, "/docProps/app.xml") == null && getSDDocumentSessionInternalPartBytes(session, "/docProps/core.xml") == null && getSDDocumentSessionInternalPartBytes(session, "/docProps/custom.xml") == null && getSDDocumentSessionInternalPartBytes(session, "/word/settings.xml") != null;
637778
638612
  }
637779
638613
  function projectGrouping(entry) {
637780
- if (entry.reviewGroup)
638614
+ if (entry.reviewGroup && !(entry.reviewGroup.kind === "text-rewrite" && entry.reviewGroup.role === "child"))
637781
638615
  return "unknown";
637782
638616
  return entry.type === "replacement" || entry.sides ? "replacement-pair" : "standalone";
637783
638617
  }
@@ -638779,6 +639613,8 @@ function createSuccessorRsidAllocator(raw) {
638779
639613
  }
638780
639614
  var resolvedTrackedChangeIdsBySession, TEXT_DECODER6, TEXT_ENCODER, EMUS_PER_CSS_PIXEL = 9525, BROWSER_RENDERABLE_IMAGE_CONTENT_TYPES, DocumentApiAdapterError, STRUCTURAL_DESCRIPTOR_OPERATIONS;
638781
639615
  var init_adapter21 = __esm(() => {
639616
+ init_review_read_model();
639617
+ init_review_read_model();
638782
639618
  init_src3();
638783
639619
  init_sd_document_session_internal();
638784
639620
  init_story_surface();
@@ -648772,17 +649608,17 @@ class V2GetTextAdapter {
648772
649608
  if (!bytes)
648773
649609
  return "";
648774
649610
  const scopedBytes = resolved.descriptor.storyByteRange ? bytes.subarray(resolved.descriptor.storyByteRange[0], resolved.descriptor.storyByteRange[1]) : bytes;
648775
- return extractVisibleTextFromXml3(TD100.decode(scopedBytes));
649611
+ return extractVisibleTextFromXml4(TD100.decode(scopedBytes));
648776
649612
  }
648777
649613
  }
648778
- var TD100, extractVisibleTextFromXml3;
649614
+ var TD100, extractVisibleTextFromXml4;
648779
649615
  var init_adapter26 = __esm(() => {
648780
649616
  init_sd_document_session_internal();
648781
649617
  init_story_identity();
648782
649618
  init_story_surface();
648783
649619
  init_visible_text();
648784
649620
  TD100 = new TextDecoder;
648785
- extractVisibleTextFromXml3 = extractVisibleTextFromXml2;
649621
+ extractVisibleTextFromXml4 = extractVisibleTextFromXml2;
648786
649622
  });
648787
649623
 
648788
649624
  // ../../../v2/document-api-v2-adapter/dist/search/node-discovery.js
@@ -648880,7 +649716,7 @@ function collectRunNodes(context, resolved, story) {
648880
649716
  const paragraphXml = stripPendingDeletions(TD101.decode(bytes.subarray(entry.byteStart, entry.byteEnd)));
648881
649717
  let offset = 0;
648882
649718
  for (const runXml of scanRunSpans(paragraphXml)) {
648883
- const text4 = extractVisibleTextFromXml3(runXml);
649719
+ const text4 = extractVisibleTextFromXml4(runXml);
648884
649720
  if (text4.length === 0)
648885
649721
  continue;
648886
649722
  const start = offset;
@@ -649051,7 +649887,7 @@ function readCellText(context, storyId, bodyStart, bodyEnd) {
649051
649887
  return "";
649052
649888
  if (bodyEnd > bytes.length || bodyStart < 0 || bodyEnd <= bodyStart)
649053
649889
  return "";
649054
- return extractVisibleTextFromXml3(TD101.decode(bytes.subarray(bodyStart, bodyEnd)));
649890
+ return extractVisibleTextFromXml4(TD101.decode(bytes.subarray(bodyStart, bodyEnd)));
649055
649891
  }
649056
649892
  function addressStory(locator, resolved) {
649057
649893
  if (resolved.storyKind === "main")
@@ -650487,7 +651323,7 @@ async function compileOrderedAtomicTextPlan(context, input, evaluatedRevision) {
650487
651323
  };
650488
651324
  }
650489
651325
  try {
650490
- const compiled = await compileOrderedTextProgram(context, textSteps, input.in, evaluatedRevision);
651326
+ const compiled = await compileOrderedTextProgram(context, textSteps, input.in, evaluatedRevision, input.changeMode === "tracked");
650491
651327
  steps.push(...compiled.steps);
650492
651328
  return { evaluatedRevision, steps, failures, atomicTextProgram: { edits: compiled.edits } };
650493
651329
  } catch (error48) {
@@ -650503,7 +651339,7 @@ async function compileOrderedAtomicTextPlan(context, input, evaluatedRevision) {
650503
651339
  return { evaluatedRevision, steps, failures };
650504
651340
  }
650505
651341
  }
650506
- async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedRevision) {
651342
+ async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedRevision, preserveReviewOrigins) {
650507
651343
  const cache = {
650508
651344
  offsetMaps: new WeakMap,
650509
651345
  paragraphBytes: new Map,
@@ -650581,7 +651417,10 @@ async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedR
650581
651417
  for (const match of matches.slice().reverse()) {
650582
651418
  const replacement = sourceStep.op === "text.delete" ? "" : replacementTextForMatch(sourceStep, match.text, match.groups);
650583
651419
  if (replacement !== match.text) {
650584
- replaceStagedText(paragraph4, match.from, match.to, replacement, sourceStep.id, sourceStepOrder);
651420
+ const spans = paragraph4.coordinateSpace !== "tracked" ? planTextReplacement(match.text, replacement) : [{ start: 0, end: match.text.length, text: replacement }];
651421
+ for (const span of spans.slice().reverse()) {
651422
+ replaceStagedText(paragraph4, match.from + span.start, match.from + span.end, span.text, sourceStep.id, sourceStepOrder, preserveReviewOrigins);
651423
+ }
650585
651424
  }
650586
651425
  }
650587
651426
  }
@@ -650600,12 +651439,13 @@ async function compileOrderedTextProgram(context, sourceSteps, story, evaluatedR
650600
651439
  }
650601
651440
  const edits = [];
650602
651441
  for (const paragraph4 of staged.values()) {
650603
- for (const edit of materializeStagedEdits(paragraph4)) {
651442
+ for (const edit of materializeStagedEdits(paragraph4, preserveReviewOrigins)) {
650604
651443
  const on = resolveOriginalParagraphRange(context, paragraph4, edit.from, edit.to);
650605
651444
  edits.push({
650606
651445
  on,
650607
651446
  newText: edit.text,
650608
651447
  ownerStepId: edit.ownerStepId,
651448
+ rewriteIntent: compiledSteps.find((step3) => step3.stepId === edit.ownerStepId)?.op === "text.rewrite",
650609
651449
  resolution: {
650610
651450
  target: {
650611
651451
  kind: "text",
@@ -650710,13 +651550,19 @@ function isStringWordBoundary(text4, at, length) {
650710
651550
  const after = at + length < text4.length ? text4.charCodeAt(at + length) : -1;
650711
651551
  return !isWord(before) && !isWord(after);
650712
651552
  }
650713
- function replaceStagedText(paragraph4, from, to, replacement, ownerStepId, ownerOrder) {
651553
+ function overlappingTrackedStep(stepId) {
651554
+ return new DocumentApiValidationError2("CAPABILITY_UNSUPPORTED", `step "${stepId}" overlaps an earlier tracked step; this atomic plan cannot preserve separate review origins.`);
651555
+ }
651556
+ function replaceStagedText(paragraph4, from, to, replacement, ownerStepId, ownerOrder, preserveReviewOrigins) {
650714
651557
  const { pieces } = paragraph4;
650715
651558
  const startIndex = splitStagedPiecesAt(pieces, from);
650716
651559
  const endIndex = splitStagedPiecesAt(pieces, to);
650717
651560
  const removed = pieces.slice(startIndex, endIndex);
650718
651561
  const anchor = removed.length > 0 ? Math.min(...removed.map((piece) => piece.sourceStart)) : stagedBoundarySourceOffset(pieces, startIndex);
650719
651562
  const sourceEnd = removed.reduce((maximum, piece) => Math.max(maximum, piece.sourceEnd), anchor);
651563
+ if (preserveReviewOrigins && (removed.some((piece) => piece.ownerStepId && piece.ownerStepId !== ownerStepId) || paragraph4.rangeOwners.some((owner) => owner.stepId !== ownerStepId && owner.from < sourceEnd && owner.to > anchor))) {
651564
+ throw overlappingTrackedStep(ownerStepId);
651565
+ }
650720
651566
  if (sourceEnd > anchor) {
650721
651567
  paragraph4.rangeOwners = paragraph4.rangeOwners.filter((owner) => owner.to <= anchor || owner.from >= sourceEnd);
650722
651568
  paragraph4.rangeOwners.push({ from: anchor, to: sourceEnd, stepId: ownerStepId, order: ownerOrder });
@@ -650774,7 +651620,7 @@ function stagedBoundarySourceOffset(pieces, index2) {
650774
651620
  }
650775
651621
  return 0;
650776
651622
  }
650777
- function materializeStagedEdits(paragraph4) {
651623
+ function materializeStagedEdits(paragraph4, preserveReviewOrigins) {
650778
651624
  const edits = [];
650779
651625
  let sourceCursor = 0;
650780
651626
  let replacements = [];
@@ -650790,13 +651636,17 @@ function materializeStagedEdits(paragraph4) {
650790
651636
  const intervalInserted = inserted.filter((piece) => piece.sourceStart >= start && (piece.sourceStart < end || index2 === points.length - 2 && piece.sourceStart === end));
650791
651637
  const text4 = intervalInserted.map((piece) => piece.text).join("");
650792
651638
  if (paragraph4.originalText.slice(start, end) !== text4) {
650793
- const owner = [
651639
+ const owners = [
650794
651640
  ...paragraph4.rangeOwners.filter((owner2) => owner2.from < end && owner2.to > start).map((owner2) => ({ stepId: owner2.stepId, order: owner2.order })),
650795
651641
  ...intervalInserted.flatMap((piece) => piece.ownerStepId && piece.ownerOrder != null ? [{ stepId: piece.ownerStepId, order: piece.ownerOrder }] : [])
650796
- ].sort((left, right) => right.order - left.order)[0];
651642
+ ].sort((left, right) => right.order - left.order);
651643
+ const owner = owners[0];
650797
651644
  if (!owner) {
650798
651645
  throw new DocumentApiValidationError2("INTERNAL_ERROR", "projected text edit has no owning mutation step.");
650799
651646
  }
651647
+ if (preserveReviewOrigins && owners.some((candidate) => candidate.stepId !== owner.stepId)) {
651648
+ throw overlappingTrackedStep(owner.stepId);
651649
+ }
650800
651650
  edits.push({ from: start, to: end, text: text4, ownerStepId: owner.stepId });
650801
651651
  }
650802
651652
  }
@@ -651425,7 +652275,8 @@ function commitStep(selectionMutation, paragraphs, compiled, changeMode) {
651425
652275
  const edits = changedIndexes.map((index2) => ({
651426
652276
  on: compiled.kernelRanges[index2],
651427
652277
  newText: requests[index2].text,
651428
- resolution: resolutions[index2]
652278
+ resolution: resolutions[index2],
652279
+ rewriteIntent: compiled.op === "text.rewrite"
651429
652280
  }));
651430
652281
  return selectionMutation.executeResolvedTextRewrites(edits, { changeMode });
651431
652282
  }
@@ -651433,7 +652284,7 @@ function commitStep(selectionMutation, paragraphs, compiled, changeMode) {
651433
652284
  let hasSuccessfulRequest = false;
651434
652285
  const trackedChangeRefs = [];
651435
652286
  for (const request of requests) {
651436
- const receipt3 = commitRequest(selectionMutation, paragraphs, request, changeMode);
652287
+ const receipt3 = commitRequest(selectionMutation, paragraphs, request, changeMode, compiled.op === "text.rewrite");
651437
652288
  if (receipt3.success) {
651438
652289
  hasSuccessfulRequest = true;
651439
652290
  appendUniqueTrackedChangeRefs(trackedChangeRefs, readTrackedChangeRefs3(receipt3));
@@ -651452,7 +652303,7 @@ function commitStep(selectionMutation, paragraphs, compiled, changeMode) {
651452
652303
  ...trackedChangeRefs.length > 0 ? { trackedChangeRefs } : {}
651453
652304
  };
651454
652305
  }
651455
- function commitRequest(selectionMutation, paragraphs, request, changeMode) {
652306
+ function commitRequest(selectionMutation, paragraphs, request, changeMode, rewriteIntent = false) {
651456
652307
  if (request.kind === "format") {
651457
652308
  const trackedChangeRefs = [];
651458
652309
  if (request.inline) {
@@ -651511,14 +652362,14 @@ function commitRequest(selectionMutation, paragraphs, request, changeMode) {
651511
652362
  target: request.target,
651512
652363
  text: request.text,
651513
652364
  ...request.in ? { in: request.in } : {}
651514
- }, { changeMode });
652365
+ }, { changeMode }, rewriteIntent);
651515
652366
  }
651516
652367
  return selectionMutation.execute({
651517
652368
  kind: "replace",
651518
652369
  ref: request.ref,
651519
652370
  text: request.text,
651520
652371
  ...request.in ? { in: request.in } : {}
651521
- }, { changeMode });
652372
+ }, { changeMode }, rewriteIntent);
651522
652373
  }
651523
652374
  function buildStepOutcome(compiled, effect, trackedChanges = [], trackedChangeCount = trackedChanges.length) {
651524
652375
  const resolutions = compiled.resolutions ?? (compiled.resolution ? [compiled.resolution] : []);
@@ -651559,8 +652410,7 @@ function readTrackedChangeRefs3(receipt3) {
651559
652410
  if (!receipt3 || typeof receipt3 !== "object")
651560
652411
  return [];
651561
652412
  const record3 = receipt3;
651562
- const candidates = [
651563
- ...Array.isArray(record3.trackedChangeRefs) ? record3.trackedChangeRefs : [],
652413
+ const candidates = Array.isArray(record3.trackedChangeRefs) ? record3.trackedChangeRefs : [
651564
652414
  ...Array.isArray(record3.inserted) ? record3.inserted : [],
651565
652415
  ...Array.isArray(record3.updated) ? record3.updated : []
651566
652416
  ];
@@ -690920,7 +691770,7 @@ function parseParagraphXml(xml, inheritedNamespaceBindings = {}, trackedWrapperI
690920
691770
  } else if (tagLocalName === "hyperlink") {
690921
691771
  const inner = stripOuterTag(next.xml);
690922
691772
  const closingTag = extractClosingTag(next.xml);
690923
- const innerSegments = parseInnerInline(inner, namespaceBindingsForElement(next.openTagInner, paragraphNamespaceBindings));
691773
+ const innerSegments = parseInnerInline(inner, namespaceBindingsForElement(next.openTagInner, paragraphNamespaceBindings), trackedWrapperIdentityState);
690924
691774
  segments.push({
690925
691775
  kind: "atom",
690926
691776
  atomKind: INLINE_ATOM_KIND.preserved,
@@ -707880,7 +708730,7 @@ function runStorySurfaceMirror(prepared, options, admission, paragraphOnlyReview
707880
708730
  };
707881
708731
  }
707882
708732
  }
707883
- const familyResult = runFamilyMirror(prepared, extension2, options, admission.directStoryText, paragraphOnlyReviewStoryIds);
708733
+ const familyResult = runFamilyMirror(prepared, extension2, options, admission.directStoryText, admission.trackedDecision, paragraphOnlyReviewStoryIds);
707884
708734
  if (!familyResult.mirrored) {
707885
708735
  return {
707886
708736
  txId: prepared.txId,
@@ -707938,7 +708788,7 @@ function hasStrictMirrorPrerequisites(prepared, options) {
707938
708788
  }
707939
708789
  }
707940
708790
  }
707941
- function runFamilyMirror(prepared, extension2, options, directStoryText, paragraphOnlyReviewStoryIds) {
708791
+ function runFamilyMirror(prepared, extension2, options, directStoryText, trackedDecision, paragraphOnlyReviewStoryIds) {
707942
708792
  if (!options.resolveStoryShard) {
707943
708793
  return {
707944
708794
  mirrored: false,
@@ -708007,7 +708857,17 @@ function runFamilyMirror(prepared, extension2, options, directStoryText, paragra
708007
708857
  });
708008
708858
  return { ...sessionSync, mirrorPath: "session-sync" };
708009
708859
  }
708010
- return mirrorPreparedTrackedDecide(prepared, extension2, options);
708860
+ if (!trackedDecision) {
708861
+ return {
708862
+ mirrored: false,
708863
+ mirrorPath: "story-tracked-decide",
708864
+ failure: {
708865
+ storyId: prepared.resolvedTargets.stories[0] ?? "",
708866
+ message: "storyTrackedDecide requires an admitted cross-story preflight"
708867
+ }
708868
+ };
708869
+ }
708870
+ return mirrorPreparedTrackedDecide(prepared, trackedDecision);
708011
708871
  }
708012
708872
  if (extension2.family === "compareApply") {
708013
708873
  return {
@@ -708222,30 +709082,11 @@ function mirrorPreparedCommentInsert(prepared, extension2, options) {
708222
709082
  });
708223
709083
  return { mirrored: true, mirrorPath: "session-sync" };
708224
709084
  }
708225
- function mirrorPreparedTrackedDecide(prepared, extension2, options) {
708226
- const validation = validatePreparedTrackedDecide(prepared, extension2, options);
708227
- if (!validation.ok) {
708228
- return {
708229
- mirrored: false,
708230
- mirrorPath: "story-tracked-decide",
708231
- failure: {
708232
- storyId: prepared.resolvedTargets.stories[0] ?? "",
708233
- message: validation.failureReason
708234
- }
708235
- };
708236
- }
708237
- const source = validation.source;
708238
- const storyDocs = validation.storyDocs;
708239
- for (const { storyId, doc: doc2 } of storyDocs) {
708240
- const targets = validation.targets.filter((target) => target.storyId === storyId);
708241
- if (targets.length === 0)
708242
- continue;
708243
- const result = applyTrackedTextDecisionsToStory({
708244
- doc: doc2,
708245
- targets,
708246
- decision: source.decision,
708247
- txId: prepared.txId,
708248
- removedCommentIds: collectInvalidatedCommentIds(prepared)
709085
+ function mirrorPreparedTrackedDecide(prepared, preflight2) {
709086
+ for (const { storyId, plan } of preflight2.stories) {
709087
+ const result = applyPreflightedTrackedTextDecisionsToStory({
709088
+ plan,
709089
+ txId: prepared.txId
708249
709090
  });
708250
709091
  if (!result.ok) {
708251
709092
  return {
@@ -708319,6 +709160,26 @@ function validatePreparedTrackedDecide(prepared, extension2, options) {
708319
709160
  }
708320
709161
  return { ok: true, source, storyDocs, targets: trackedTextDecide.targets };
708321
709162
  }
709163
+ function preflightPreparedTrackedDecide(input) {
709164
+ const stories = [];
709165
+ const removedCommentIds = collectInvalidatedCommentIds(input.prepared);
709166
+ for (const { storyId, doc: doc2 } of input.storyDocs) {
709167
+ const targets = input.targets.filter((target) => target.storyId === storyId);
709168
+ if (targets.length === 0)
709169
+ continue;
709170
+ const result = preflightTrackedTextDecisionsToStory({
709171
+ doc: doc2,
709172
+ targets,
709173
+ decision: input.source.decision,
709174
+ removedCommentIds
709175
+ });
709176
+ if (!result.ok) {
709177
+ return { ok: false, failureReason: `${storyId}: ${result.failureReason}` };
709178
+ }
709179
+ stories.push({ storyId, plan: result.plan });
709180
+ }
709181
+ return { ok: true, preflight: { stories } };
709182
+ }
708322
709183
  function isSupportedPreparedTrackedTextKind(kind) {
708323
709184
  return kind === "ins" || kind === "del";
708324
709185
  }
@@ -708355,47 +709216,133 @@ function isSupportedPreparedTrackedCarrier(target) {
708355
709216
  return true;
708356
709217
  return target.carrierKind === "field-insertion" && target.trackedKind === "ins";
708357
709218
  }
708358
- function applyTrackedTextDecisionsToStory(input) {
709219
+ function preflightTrackedTextDecisionsToStory(input) {
708359
709220
  const resolved = [];
708360
- for (const target of input.targets) {
708361
- const spans = findPreparedLiveTrackedTextSpans(input.doc, target);
708362
- const alreadyDecided = spans.length === 0 && hasTrackedDecisionLedgerEntry(input.doc, target.rsid);
708363
- if (spans.length === 0 && !alreadyDecided) {
709221
+ const usedSpanIds = new Set;
709222
+ const candidatesByTarget = input.targets.map((target) => ({
709223
+ target,
709224
+ spans: findPreparedLiveTrackedTextSpans(input.doc, target)
709225
+ }));
709226
+ for (const { target, spans } of candidatesByTarget) {
709227
+ const span = spans.find((candidate) => !usedSpanIds.has(liveTrackedTextSpanId(candidate)));
709228
+ const alreadyDecided = !span && spans.length === 0 && hasTrackedDecisionLedgerEntry(input.doc, target.rsid);
709229
+ if (!span && !alreadyDecided) {
708364
709230
  return { ok: false, failureReason: `tracked decision target ${target.rsid} is not a live tracked text change` };
708365
709231
  }
708366
- resolved.push({ target, spans });
709232
+ if (span)
709233
+ usedSpanIds.add(liveTrackedTextSpanId(span));
709234
+ resolved.push({ target, spans: span ? [span] : [] });
709235
+ }
709236
+ for (const { target, spans } of candidatesByTarget) {
709237
+ if (spans.some((span) => !usedSpanIds.has(liveTrackedTextSpanId(span)))) {
709238
+ return {
709239
+ ok: false,
709240
+ failureReason: `tracked decision target ${target.rsid} metadata does not cover every matching live carrier`
709241
+ };
709242
+ }
708367
709243
  }
708368
709244
  const live = resolved.filter((entry) => entry.spans.length > 0);
708369
- if (live.length === 0)
709245
+ try {
709246
+ const removedCommentCarrierIds = collectCommentCarrierIds(input.removedCommentIds);
709247
+ const work = live.flatMap((entry) => entry.spans.map((span) => {
709248
+ const block = findBlockMap(input.doc, span.blockId)?.block;
709249
+ if (!block)
709250
+ throw new Error(`target block ${span.blockId} is not present in the story shard`);
709251
+ return {
709252
+ target: entry.target,
709253
+ span,
709254
+ block,
709255
+ leftBoundaryAtoms: [],
709256
+ leftBoundaryAnchors: []
709257
+ };
709258
+ }));
709259
+ for (const item of work) {
709260
+ const { target, span, block, leftBoundaryAtoms, leftBoundaryAnchors } = item;
709261
+ const blockLength = getBlockText(block).length;
709262
+ if (span.startOffset < 0 || span.startOffset > blockLength) {
709263
+ throw new Error(`tracked text span ${target.rsid} starts outside block ${span.blockId}`);
709264
+ }
709265
+ if (span.trackedKind === "ins" && input.decision === "reject") {
709266
+ if (span.endOffset < span.startOffset || span.endOffset > blockLength) {
709267
+ throw new Error(`tracked insert span ${target.rsid} is outside block ${span.blockId}`);
709268
+ }
709269
+ }
709270
+ if (span.trackedKind === "del" && input.decision === "reject") {
709271
+ let reachedStart = false;
709272
+ const removedTrackedCarrierIds = trackedTextCarrierIds(span, false);
709273
+ getBlockAtoms(block).forEach((atom) => {
709274
+ if (reachedStart)
709275
+ return;
709276
+ const atomId = String(atom.get(ATOM_KEY.id) ?? "");
709277
+ if (atomId === span.startAtomId) {
709278
+ reachedStart = true;
709279
+ return;
709280
+ }
709281
+ if (atomId && Number(atom.get(ATOM_KEY.visibleOffset) ?? -1) === span.startOffset && Number(atom.get(ATOM_KEY.length) ?? 0) === 0) {
709282
+ if (removedCommentCarrierIds.has(atomId))
709283
+ return;
709284
+ if (removedTrackedCarrierIds.has(atomId)) {
709285
+ throw new Error(`left-boundary atom ${atomId} aliases a removed tracked carrier`);
709286
+ }
709287
+ leftBoundaryAtoms.push(atom);
709288
+ const anchorIdentity2 = rangeAnchorIdentityForAtom(atom);
709289
+ if (anchorIdentity2) {
709290
+ const matchingAnchors = getBlockAnchors(block).toArray().filter((anchor) => anchor.get(ANCHOR_KEY.id) === atom.get(ATOM_KEY.id) && anchor.get(ANCHOR_KEY.kind) === anchorIdentity2.kind && anchor.get(ANCHOR_KEY.boundary) === anchorIdentity2.boundary && Number(anchor.get(ANCHOR_KEY.visibleOffset) ?? -1) === span.startOffset);
709291
+ if (matchingAnchors.length !== 1) {
709292
+ throw new Error(`left-boundary atom ${atomId} does not resolve one exact anchor carrier`);
709293
+ }
709294
+ leftBoundaryAnchors.push(matchingAnchors[0]);
709295
+ }
709296
+ }
709297
+ });
709298
+ if (!reachedStart) {
709299
+ throw new Error(`tracked deletion start ${span.startAtomId} is not present in block ${span.blockId}`);
709300
+ }
709301
+ }
709302
+ }
709303
+ return {
709304
+ ok: true,
709305
+ plan: {
709306
+ doc: input.doc,
709307
+ decision: input.decision,
709308
+ removedCommentCarrierIds,
709309
+ resolved,
709310
+ work
709311
+ }
709312
+ };
709313
+ } catch (error50) {
709314
+ return { ok: false, failureReason: error50 instanceof Error ? error50.message : String(error50) };
709315
+ }
709316
+ }
709317
+ function liveTrackedTextSpanId(span) {
709318
+ return `${span.blockId}\x00${span.startAtomId}\x00${span.endAtomId}`;
709319
+ }
709320
+ function applyPreflightedTrackedTextDecisionsToStory(input) {
709321
+ if (input.plan.work.length === 0)
708370
709322
  return { ok: true, applied: false, alreadyDecided: true };
708371
709323
  try {
708372
- resolveStoryShardScope(input.doc).doc.transact(() => {
708373
- const work = live.flatMap((entry) => entry.spans.map((span) => ({ target: entry.target, span })));
708374
- for (const { target, span } of work) {
708375
- const found = findBlockMap(input.doc, span.blockId)?.block;
708376
- if (!found)
708377
- throw new Error(`target block ${span.blockId} is not present in the story shard`);
708378
- removeTrackedTextCarriers(found, span, input.decision === "reject" && target.carrierKind === "field-insertion");
708379
- removeCommentCarriersByIds(found, input.removedCommentIds);
708380
- }
708381
- const sorted = work.sort((left, right) => {
709324
+ resolveStoryShardScope(input.plan.doc).doc.transact(() => {
709325
+ const { decision, doc: doc2, removedCommentCarrierIds, resolved, work } = input.plan;
709326
+ for (const { target, span, block } of work) {
709327
+ removeTrackedTextCarriers(block, span, decision === "reject" && target.carrierKind === "field-insertion");
709328
+ removeCommentCarriersByIds(block, removedCommentCarrierIds);
709329
+ }
709330
+ const sorted = [...work].sort((left, right) => {
708382
709331
  if (left.span.blockId !== right.span.blockId)
708383
709332
  return left.span.blockId < right.span.blockId ? -1 : 1;
708384
709333
  if (left.span.startOffset !== right.span.startOffset)
708385
709334
  return right.span.startOffset - left.span.startOffset;
708386
- if (left.span.trackedKind === right.span.trackedKind)
708387
- return 0;
709335
+ if (left.span.trackedKind === right.span.trackedKind) {
709336
+ return right.span.startAtomIndex - left.span.startAtomIndex;
709337
+ }
708388
709338
  return left.span.trackedKind === "ins" ? -1 : 1;
708389
709339
  });
708390
- for (const { target, span } of sorted) {
708391
- if (span.trackedKind === "ins" && input.decision === "reject") {
709340
+ for (const { span, leftBoundaryAtoms, leftBoundaryAnchors } of sorted) {
709341
+ if (span.trackedKind === "ins" && decision === "reject") {
708392
709342
  const length3 = span.endOffset - span.startOffset;
708393
- if (length3 < 0) {
708394
- throw new Error(`tracked insert span ${target.rsid} is outside block ${span.blockId}`);
708395
- }
708396
709343
  if (length3 > 0) {
708397
709344
  deleteText2({
708398
- doc: input.doc,
709345
+ doc: doc2,
708399
709346
  blockId: span.blockId,
708400
709347
  offset: span.startOffset,
708401
709348
  length: length3,
@@ -708403,8 +709350,8 @@ function applyTrackedTextDecisionsToStory(input) {
708403
709350
  });
708404
709351
  }
708405
709352
  }
708406
- if (span.trackedKind === "del" && input.decision === "reject") {
708407
- const found = findBlockMap(input.doc, span.blockId)?.block;
709353
+ if (span.trackedKind === "del" && decision === "reject") {
709354
+ const found = findBlockMap(doc2, span.blockId)?.block;
708408
709355
  if (!found)
708409
709356
  throw new Error(`target block ${span.blockId} is not present in the story shard`);
708410
709357
  let offset = span.startOffset;
@@ -708416,7 +709363,7 @@ function applyTrackedTextDecisionsToStory(input) {
708416
709363
  continue;
708417
709364
  }
708418
709365
  insertText2({
708419
- doc: input.doc,
709366
+ doc: doc2,
708420
709367
  blockId: span.blockId,
708421
709368
  offset,
708422
709369
  text: segment.text,
@@ -708443,10 +709390,12 @@ function applyTrackedTextDecisionsToStory(input) {
708443
709390
  if (restoredBreakXml) {
708444
709391
  throw new Error(`attributed break restoration in ${span.blockId} is incomplete`);
708445
709392
  }
709393
+ leftBoundaryAtoms.forEach((atom) => atom.set(ATOM_KEY.visibleOffset, span.startOffset));
709394
+ leftBoundaryAnchors.forEach((anchor) => anchor.set(ANCHOR_KEY.visibleOffset, span.startOffset));
708446
709395
  }
708447
709396
  }
708448
709397
  for (const { target } of resolved) {
708449
- recordTrackedDecision(input.doc, target.rsid, input.decision, input.txId);
709398
+ recordTrackedDecision(doc2, target.rsid, decision, input.txId);
708450
709399
  }
708451
709400
  }, STORY_SURFACE_BACKEND_ORIGIN);
708452
709401
  } catch (error50) {
@@ -708525,6 +709474,7 @@ function collectLiveTrackedTextSpansInBlock(block, rsid, trackedKind) {
708525
709474
  blockId,
708526
709475
  startOffset: start.offset,
708527
709476
  endOffset: trackedKind === "del" ? start.offset + deletedTextLength2 : end.offset,
709477
+ startAtomIndex: start.index,
708528
709478
  startAtomId: start.id,
708529
709479
  endAtomId: end.id,
708530
709480
  preservedAtomIds: preservedForSpan.map((atom) => atom.id),
@@ -708536,24 +709486,38 @@ function collectLiveTrackedTextSpansInBlock(block, rsid, trackedKind) {
708536
709486
  return spans;
708537
709487
  }
708538
709488
  function removeTrackedTextCarriers(block, span, removeContainedAtoms) {
708539
- const ids = new Set([
709489
+ const ids = trackedTextCarrierIds(span, removeContainedAtoms);
709490
+ deleteYMapArrayEntriesByIds(getBlockAtoms(block), ATOM_KEY.id, ids);
709491
+ deleteYMapArrayEntriesByIds(getBlockAnchors(block), ANCHOR_KEY.id, ids);
709492
+ }
709493
+ function trackedTextCarrierIds(span, includeContainedAtoms) {
709494
+ return new Set([
708540
709495
  span.startAtomId,
708541
709496
  span.endAtomId,
708542
709497
  ...span.preservedAtomIds,
708543
- ...removeContainedAtoms ? span.containedAtomIds : []
709498
+ ...includeContainedAtoms ? span.containedAtomIds : []
708544
709499
  ]);
708545
- deleteYMapArrayEntriesByIds(getBlockAtoms(block), ATOM_KEY.id, ids);
708546
- deleteYMapArrayEntriesByIds(getBlockAnchors(block), ANCHOR_KEY.id, ids);
708547
709500
  }
708548
- function removeCommentCarriersByIds(block, commentIds) {
708549
- if (commentIds.size === 0)
708550
- return;
709501
+ function rangeAnchorIdentityForAtom(atom) {
709502
+ const atomKind = atom.get(ATOM_KEY.kind);
709503
+ if (atomKind !== INLINE_ATOM_KIND.commentMarker && atomKind !== INLINE_ATOM_KIND.bookmark)
709504
+ return null;
709505
+ const marker = String(asRecord6(atom.get(ATOM_KEY.meta)).marker ?? "");
709506
+ const boundary = marker.endsWith("End") ? "end" : marker.endsWith("Start") ? "start" : "point";
709507
+ return { kind: atomKind === INLINE_ATOM_KIND.commentMarker ? "comment" : "bookmark", boundary };
709508
+ }
709509
+ function collectCommentCarrierIds(commentIds) {
708551
709510
  const ids = new Set;
708552
709511
  for (const commentId of commentIds) {
708553
709512
  ids.add(`comment:${commentId}:start`);
708554
709513
  ids.add(`comment:${commentId}:end`);
708555
709514
  ids.add(`comment:${commentId}:ref`);
708556
709515
  }
709516
+ return ids;
709517
+ }
709518
+ function removeCommentCarriersByIds(block, ids) {
709519
+ if (ids.size === 0)
709520
+ return;
708557
709521
  deleteYMapArrayEntriesByIds(getBlockAtoms(block), ATOM_KEY.id, ids);
708558
709522
  deleteYMapArrayEntriesByIds(getBlockAnchors(block), ANCHOR_KEY.id, ids);
708559
709523
  }
@@ -708663,7 +709627,10 @@ function admitPreparedStorySurfaceMutation(prepared, options) {
708663
709627
  return options.session ? { ok: true } : { ok: false, message: "tracked-change decision session sync requires an authoritative session" };
708664
709628
  }
708665
709629
  const trackedDecision = validatePreparedTrackedDecide(prepared, extension2, options);
708666
- return trackedDecision.ok ? { ok: true } : { ok: false, message: trackedDecision.failureReason };
709630
+ if (!trackedDecision.ok)
709631
+ return { ok: false, message: trackedDecision.failureReason };
709632
+ const preflight2 = preflightPreparedTrackedDecide({ prepared, ...trackedDecision });
709633
+ return preflight2.ok ? { ok: true, trackedDecision: preflight2.preflight } : { ok: false, message: preflight2.failureReason };
708667
709634
  }
708668
709635
  if (extension2.family === "storyTable") {
708669
709636
  if (extension2.historyReplay) {
@@ -712543,7 +713510,7 @@ function createHeadlessCollabRoomCoordinator(options) {
712543
713510
  if (isCommentsFamilyPartUri(String(partUri)))
712544
713511
  out.add(String(partUri));
712545
713512
  }
712546
- out.add(COMMENTS_PART_URI4);
713513
+ out.add(COMMENTS_PART_URI5);
712547
713514
  return Array.from(out).sort();
712548
713515
  }
712549
713516
  function syncRelationshipsPart(partUri, bytes) {
@@ -713063,7 +714030,7 @@ function createHeadlessCollabRoomCoordinator(options) {
713063
714030
  return [packageShardId(options.rootId, SHARD_KIND.settings, SETTINGS_PART_URI5)];
713064
714031
  }
713065
714032
  if (isCommentsFamilyPartKind(descriptor.partKind)) {
713066
- return [packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4)];
714033
+ return [packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5)];
713067
714034
  }
713068
714035
  if (descriptor.partKind === "image" || descriptor.partKind === "media") {
713069
714036
  return [
@@ -714319,7 +715286,7 @@ function createHeadlessCollabRoomCoordinator(options) {
714319
715286
  seedCommentsShardIfNeeded(collabUnitTargetOrDoc(options.graph.commentsHandle), pairedPartKeys);
714320
715287
  return options.graph.commentsHandle;
714321
715288
  }
714322
- const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4);
715289
+ const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
714323
715290
  const { unit } = materializeSubtreePackageHandle(shardId, SHARD_KIND.comments);
714324
715291
  const handle = {
714325
715292
  shardId,
@@ -714345,12 +715312,12 @@ function createHeadlessCollabRoomCoordinator(options) {
714345
715312
  function allocateCommentIdFromSharedShard(input) {
714346
715313
  if (disposed)
714347
715314
  return null;
714348
- const handle = options.graph.commentsHandle ?? ensureCommentsShard([encodeLogicalOwnerKey(COMMENTS_PART_URI4)]);
715315
+ const handle = options.graph.commentsHandle ?? ensureCommentsShard([encodeLogicalOwnerKey(COMMENTS_PART_URI5)]);
714349
715316
  if (!handle)
714350
715317
  return null;
714351
715318
  let allocated = null;
714352
715319
  handle.doc.transact(() => {
714353
- seedCommentsShardIfNeeded(collabUnitTargetOrDoc(handle), [encodeLogicalOwnerKey(COMMENTS_PART_URI4)]);
715320
+ seedCommentsShardIfNeeded(collabUnitTargetOrDoc(handle), [encodeLogicalOwnerKey(COMMENTS_PART_URI5)]);
714354
715321
  const commentsMap = getPartRecordsMap(collabUnitTargetOrDoc(handle)).get("comments");
714355
715322
  const inUse = new Set;
714356
715323
  if (commentsMap instanceof YMap) {
@@ -714373,14 +715340,14 @@ function createHeadlessCollabRoomCoordinator(options) {
714373
715340
  return allocated;
714374
715341
  }
714375
715342
  function seedCommentsShardIfNeeded(doc2, pairedPartKeys) {
714376
- const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4);
715343
+ const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
714377
715344
  try {
714378
715345
  seedCommentsShard({
714379
715346
  doc: doc2,
714380
715347
  shardId,
714381
- ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI4),
714382
- ownerPartUri: COMMENTS_PART_URI4,
714383
- pairedPartKeys: pairedPartKeys.length > 0 ? Array.from(new Set(pairedPartKeys)).sort() : [encodeLogicalOwnerKey(COMMENTS_PART_URI4)],
715348
+ ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI5),
715349
+ ownerPartUri: COMMENTS_PART_URI5,
715350
+ pairedPartKeys: pairedPartKeys.length > 0 ? Array.from(new Set(pairedPartKeys)).sort() : [encodeLogicalOwnerKey(COMMENTS_PART_URI5)],
714384
715351
  comments: [],
714385
715352
  people: []
714386
715353
  });
@@ -714406,7 +715373,7 @@ function createHeadlessCollabRoomCoordinator(options) {
714406
715373
  meta4.set(PACKAGE_PART_META_KEY.pairedPartKeys, Array.from(merged).sort());
714407
715374
  }
714408
715375
  function connectCommentsHandleIfNeeded(pairedPartKeys) {
714409
- const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI4);
715376
+ const shardId = packageShardId(options.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
714410
715377
  if (disposed)
714411
715378
  return;
714412
715379
  if (options.graph.commentsHandle) {
@@ -714542,13 +715509,13 @@ function createHeadlessCollabRoomCoordinator(options) {
714542
715509
  const descriptorKind = part.partKind === "rels" ? SHARD_KIND.relationships : part.partKind === "contentTypes" ? SHARD_KIND.contentTypes : part.partKind === "styles" ? SHARD_KIND.styles : part.partKind === "numbering" ? SHARD_KIND.numbering : part.partKind === "settings" || part.partKind === "webSettings" ? SHARD_KIND.settings : isCommentsFamilyPartKind(part.partKind) ? SHARD_KIND.comments : part.partKind === "image" || part.partKind === "media" ? SHARD_KIND.mediaManifest : isOpaqueManifestPartKind(part.partKind) ? SHARD_KIND.opaquePart : null;
714543
715510
  if (!descriptorKind)
714544
715511
  return;
714545
- if (descriptorKind === SHARD_KIND.comments && part.partUri !== COMMENTS_PART_URI4)
715512
+ if (descriptorKind === SHARD_KIND.comments && part.partUri !== COMMENTS_PART_URI5)
714546
715513
  return;
714547
715514
  upsertShardDescriptor(options.rootDoc, makeShardDescriptor({
714548
715515
  rootId: options.rootId,
714549
715516
  shardKind: descriptorKind,
714550
- logicalOwner: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI4 : part.partKey,
714551
- logicalOwnerDisplay: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI4 : part.partUri,
715517
+ logicalOwner: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI5 : part.partKey,
715518
+ logicalOwnerDisplay: descriptorKind === SHARD_KIND.comments ? COMMENTS_PART_URI5 : part.partUri,
714552
715519
  loadPolicy: descriptorKind === SHARD_KIND.relationships || descriptorKind === SHARD_KIND.contentTypes || descriptorKind === SHARD_KIND.styles || descriptorKind === SHARD_KIND.numbering || descriptorKind === SHARD_KIND.settings || descriptorKind === SHARD_KIND.comments ? SHARD_LOAD_POLICY.eager : SHARD_LOAD_POLICY.lazy,
714553
715520
  requirement: descriptorKind === SHARD_KIND.relationships || descriptorKind === SHARD_KIND.contentTypes || descriptorKind === SHARD_KIND.styles || descriptorKind === SHARD_KIND.numbering || descriptorKind === SHARD_KIND.settings || descriptorKind === SHARD_KIND.comments ? SHARD_REQUIREMENT.required : SHARD_REQUIREMENT.optional,
714554
715521
  bootstrapStatus: SHARD_BOOTSTRAP_STATUS.seeded,
@@ -714712,7 +715679,7 @@ function createHeadlessCollabRoomCoordinator(options) {
714712
715679
  options.onRegistryChanged();
714713
715680
  }
714714
715681
  function retireCommentsFamilyPart(partUri) {
714715
- if (partUri === COMMENTS_PART_URI4 && options.graph.commentsHandle) {
715682
+ if (partUri === COMMENTS_PART_URI5 && options.graph.commentsHandle) {
714716
715683
  resetPackagePartPayload(collabUnitTargetOrDoc(options.graph.commentsHandle));
714717
715684
  options.graph.commentsHandle = null;
714718
715685
  }
@@ -714806,7 +715773,7 @@ function isMediaPartUri(partUri) {
714806
715773
  return /\/word\/media\/image\d+\.(?:png|jpe?g|jfif)$/i.test(partUri);
714807
715774
  }
714808
715775
  function isCommentsFamilyPartUri(partUri) {
714809
- return partUri === COMMENTS_PART_URI4 || partUri === COMMENTS_EXTENDED_PART_URI4 || partUri === COMMENTS_IDS_PART_URI4 || partUri === PEOPLE_PART_URI;
715776
+ return partUri === COMMENTS_PART_URI5 || partUri === COMMENTS_EXTENDED_PART_URI5 || partUri === COMMENTS_IDS_PART_URI5 || partUri === PEOPLE_PART_URI;
714810
715777
  }
714811
715778
  function isCommentsFamilyPartKind(partKind) {
714812
715779
  return partKind === "comments" || partKind === "comments-extended" || partKind === "comments-ids" || partKind === "people";
@@ -714831,11 +715798,11 @@ function partKindForPackagePartUri(partUri) {
714831
715798
  return "settings";
714832
715799
  if (partUri === WEB_SETTINGS_PART_URI)
714833
715800
  return "webSettings";
714834
- if (partUri === COMMENTS_PART_URI4)
715801
+ if (partUri === COMMENTS_PART_URI5)
714835
715802
  return "comments";
714836
- if (partUri === COMMENTS_EXTENDED_PART_URI4)
715803
+ if (partUri === COMMENTS_EXTENDED_PART_URI5)
714837
715804
  return "comments-extended";
714838
- if (partUri === COMMENTS_IDS_PART_URI4)
715805
+ if (partUri === COMMENTS_IDS_PART_URI5)
714839
715806
  return "comments-ids";
714840
715807
  if (partUri === PEOPLE_PART_URI)
714841
715808
  return "people";
@@ -714923,11 +715890,11 @@ function relTargetForPart(ownerPartUri2, targetPartUri) {
714923
715890
  function contentTypeForPackagePart(partUri) {
714924
715891
  if (partUri.endsWith(".rels"))
714925
715892
  return REL_CONTENT_TYPE;
714926
- if (partUri === COMMENTS_PART_URI4)
715893
+ if (partUri === COMMENTS_PART_URI5)
714927
715894
  return COMMENTS_CONTENT_TYPE;
714928
- if (partUri === COMMENTS_EXTENDED_PART_URI4)
715895
+ if (partUri === COMMENTS_EXTENDED_PART_URI5)
714929
715896
  return COMMENTS_EXTENDED_CONTENT_TYPE;
714930
- if (partUri === COMMENTS_IDS_PART_URI4)
715897
+ if (partUri === COMMENTS_IDS_PART_URI5)
714931
715898
  return COMMENTS_IDS_CONTENT_TYPE;
714932
715899
  if (partUri === PEOPLE_PART_URI)
714933
715900
  return PEOPLE_CONTENT_TYPE;
@@ -715559,7 +716526,7 @@ function listManifestPartUris(rootDoc, partKinds) {
715559
716526
  }
715560
716527
  return out;
715561
716528
  }
715562
- var TEXT_DECODER11, CONTENT_TYPES_PART_URI16 = "/[Content_Types].xml", NUMBERING_PART_URI6 = "/word/numbering.xml", SETTINGS_PART_URI5 = "/word/settings.xml", WEB_SETTINGS_PART_URI = "/word/webSettings.xml", MAIN_DOCUMENT_PART_URI2 = "/word/document.xml", MAIN_DOCUMENT_RELS_PART_URI = "/word/_rels/document.xml.rels", ROOT_RELS_PART_URI = "/_rels/.rels", COMMENTS_PART_URI4 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI4 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI4 = "/word/commentsIds.xml", PEOPLE_PART_URI = "/word/people.xml", MEDIA_OWNER_URI = "/word/media", REL_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml", COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", COMMENTS_EXTENDED_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", COMMENTS_IDS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml", PEOPLE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml", NUMBERING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", IMAGE_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", HYPERLINK_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", NUMBERING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", FIRST_LIST_LEVEL_OPAQUE_XML = '<w:lvlJc w:val="left"/><w:pPr><w:ind w:left="720" w:hanging="360"/></w:pPr>';
716529
+ var TEXT_DECODER11, CONTENT_TYPES_PART_URI16 = "/[Content_Types].xml", NUMBERING_PART_URI6 = "/word/numbering.xml", SETTINGS_PART_URI5 = "/word/settings.xml", WEB_SETTINGS_PART_URI = "/word/webSettings.xml", MAIN_DOCUMENT_PART_URI2 = "/word/document.xml", MAIN_DOCUMENT_RELS_PART_URI = "/word/_rels/document.xml.rels", ROOT_RELS_PART_URI = "/_rels/.rels", COMMENTS_PART_URI5 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI5 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI5 = "/word/commentsIds.xml", PEOPLE_PART_URI = "/word/people.xml", MEDIA_OWNER_URI = "/word/media", REL_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml", COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", COMMENTS_EXTENDED_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", COMMENTS_IDS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml", PEOPLE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.people+xml", NUMBERING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", IMAGE_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", HYPERLINK_REL_TYPE4 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", NUMBERING_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", FIRST_LIST_LEVEL_OPAQUE_XML = '<w:lvlJc w:val="left"/><w:pPr><w:ind w:left="720" w:hanging="360"/></w:pPr>';
715563
716530
  var init_collaboration_v2_room_coordinator = __esm(() => {
715564
716531
  init_yjs();
715565
716532
  init_dist9();
@@ -716452,7 +717419,7 @@ async function buildCanonicalShardGraph(input) {
716452
717419
  input.trace?.mark("canonical:settings");
716453
717420
  const commentsFamily = buildCommentsFamily(roomInventory);
716454
717421
  let commentsHandle = null;
716455
- const commentsShardId = packageShardId2(input.runtime.rootId, SHARD_KIND.comments, COMMENTS_PART_URI5);
717422
+ const commentsShardId = packageShardId2(input.runtime.rootId, SHARD_KIND.comments, COMMENTS_PART_URI6);
716456
717423
  {
716457
717424
  const unit = createCollabUnitHandle({ rootDoc, shardId: commentsShardId, shardKind: SHARD_KIND.comments });
716458
717425
  if (commentsFamily != null) {
@@ -716569,7 +717536,7 @@ function buildSettingsFamily(inventory) {
716569
717536
  return { settings, webSettings };
716570
717537
  }
716571
717538
  function buildCommentsFamily(inventory) {
716572
- const family = [COMMENTS_PART_URI5, COMMENTS_EXTENDED_PART_URI5, COMMENTS_IDS_PART_URI5, PEOPLE_PART_URI2].map((partUri) => inventory.get(partUri)).filter(Boolean);
717539
+ const family = [COMMENTS_PART_URI6, COMMENTS_EXTENDED_PART_URI6, COMMENTS_IDS_PART_URI6, PEOPLE_PART_URI2].map((partUri) => inventory.get(partUri)).filter(Boolean);
716573
717540
  if (family.length === 0)
716574
717541
  return null;
716575
717542
  return {
@@ -716932,8 +717899,8 @@ function trySeedCommentsShard(doc2, shardId, catalog, pairedPartKeys, sourcePart
716932
717899
  seedCommentsShard({
716933
717900
  doc: doc2,
716934
717901
  shardId,
716935
- ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI5),
716936
- ownerPartUri: COMMENTS_PART_URI5,
717902
+ ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI6),
717903
+ ownerPartUri: COMMENTS_PART_URI6,
716937
717904
  pairedPartKeys,
716938
717905
  comments,
716939
717906
  people: [],
@@ -716949,8 +717916,8 @@ function trySeedEmptyCommentsShard(doc2, shardId) {
716949
717916
  seedCommentsShard({
716950
717917
  doc: doc2,
716951
717918
  shardId,
716952
- ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI5),
716953
- ownerPartUri: COMMENTS_PART_URI5,
717919
+ ownerPartKey: encodeLogicalOwnerKey(COMMENTS_PART_URI6),
717920
+ ownerPartUri: COMMENTS_PART_URI6,
716954
717921
  pairedPartKeys: [],
716955
717922
  comments: [],
716956
717923
  people: []
@@ -717193,7 +718160,7 @@ function formatLateJoinValidationFailure(validation) {
717193
718160
  const diagnostics = validation.diagnostics.length > 0 ? validation.diagnostics.map((diagnostic2) => `${diagnostic2.code}: ${diagnostic2.message}`).join("; ") : "no diagnostics reported";
717194
718161
  return `v2 collaboration late-join validation failed (${validation.classification.classification}, ${readiness}): ${diagnostics}`;
717195
718162
  }
717196
- var TEXT_DECODER12, DEFAULT_CLAIMER_ID = "headless-open", REPLACEMENT_REQUEST_KEY_PREFIX = "replaceFile:", REPLACEMENT_HEARTBEAT_INTERVAL_MS = 5000, REPLACEMENT_LEASE_TIMEOUT_MS = 30000, SETTINGS_PART_URI6 = "/word/settings.xml", WEB_SETTINGS_PART_URI2 = "/word/webSettings.xml", COMMENTS_PART_URI5 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI5 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI5 = "/word/commentsIds.xml", PEOPLE_PART_URI2 = "/word/people.xml", MEDIA_OWNER_URI2 = "/word/media", INLINE_BINARY_FAMILIES, OPAQUE_PART_FAMILIES, DEFAULT_OPEN_INTENT, POST_SYNC_SETTLE_MAX_MS = 1000, POST_SYNC_QUIET_WINDOW_MS = 20, replacementSequence = 0, replacementHeartbeatObservations;
718163
+ var TEXT_DECODER12, DEFAULT_CLAIMER_ID = "headless-open", REPLACEMENT_REQUEST_KEY_PREFIX = "replaceFile:", REPLACEMENT_HEARTBEAT_INTERVAL_MS = 5000, REPLACEMENT_LEASE_TIMEOUT_MS = 30000, SETTINGS_PART_URI6 = "/word/settings.xml", WEB_SETTINGS_PART_URI2 = "/word/webSettings.xml", COMMENTS_PART_URI6 = "/word/comments.xml", COMMENTS_EXTENDED_PART_URI6 = "/word/commentsExtended.xml", COMMENTS_IDS_PART_URI6 = "/word/commentsIds.xml", PEOPLE_PART_URI2 = "/word/people.xml", MEDIA_OWNER_URI2 = "/word/media", INLINE_BINARY_FAMILIES, OPAQUE_PART_FAMILIES, DEFAULT_OPEN_INTENT, POST_SYNC_SETTLE_MAX_MS = 1000, POST_SYNC_QUIET_WINDOW_MS = 20, replacementSequence = 0, replacementHeartbeatObservations;
717197
718164
  var init_collaboration_v2_open = __esm(() => {
717198
718165
  init_dist9();
717199
718166
  init_setup();