@superdoc/mcp 1.3.0-next.11 → 1.3.0-next.13

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 +264 -50
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31318,7 +31318,7 @@ var init_host = __esm(() => {
31318
31318
  });
31319
31319
 
31320
31320
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31321
- var SDK_VERSION = "2.16.0-next.11";
31321
+ var SDK_VERSION = "2.16.0-next.13";
31322
31322
 
31323
31323
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31324
31324
  import { chmodSync, existsSync } from "node:fs";
@@ -134922,6 +134922,58 @@ function parseDirectRunSequence(xml, allowRevisions) {
134922
134922
  return null;
134923
134923
  return { currentText, originalText, revisions };
134924
134924
  }
134925
+ function splitLeadingNoteMarkerRun(xml, family) {
134926
+ const firstRun = /^\s*<((?:[A-Za-z_][\w.-]*:)?r)\b(?:"[^"]*"|'[^']*'|[^>"'])*>[\s\S]*?<\/\1>/.exec(xml);
134927
+ if (!firstRun)
134928
+ return null;
134929
+ const markerRunXml = firstRun[0];
134930
+ const localName2 = family === "footnotes" ? "footnoteRef" : "endnoteRef";
134931
+ const markerTag = new RegExp(`<((?:[A-Za-z_][\\w.-]*:)?)${localName2}\\s*\\/>`, "g");
134932
+ const markers = [...markerRunXml.matchAll(markerTag)];
134933
+ if (markers.length !== 1)
134934
+ return null;
134935
+ let valid = true;
134936
+ let depth = 0;
134937
+ let markerCount = 0;
134938
+ const parser = new import_saxes3.SaxesParser({
134939
+ xmlns: true,
134940
+ additionalNamespaces: replayAdditionalNamespaces(markerRunXml)
134941
+ });
134942
+ parser.on("error", () => {
134943
+ valid = false;
134944
+ });
134945
+ parser.on("opentag", (tag) => {
134946
+ depth += 1;
134947
+ if (depth === 1 && tag.local === "replay")
134948
+ return;
134949
+ if (depth === 2 && tag.uri === W_NS && tag.local === "r")
134950
+ return;
134951
+ if (depth === 3 && tag.uri === W_NS && tag.local === "rPr")
134952
+ return;
134953
+ if (depth === 3 && tag.uri === W_NS && tag.local === localName2 && tag.isSelfClosing && Object.keys(tag.attributes).length === 0) {
134954
+ markerCount += 1;
134955
+ return;
134956
+ }
134957
+ if (depth === 3 || (tag.local === "footnoteRef" || tag.local === "endnoteRef"))
134958
+ valid = false;
134959
+ });
134960
+ parser.on("closetag", () => {
134961
+ depth -= 1;
134962
+ });
134963
+ try {
134964
+ parser.write(`<replay>${markerRunXml}</replay>`).close();
134965
+ } catch {
134966
+ valid = false;
134967
+ }
134968
+ const withoutMarker = markerRunXml.replace(markerTag, "<w:t/>");
134969
+ if (!valid || depth !== 0 || markerCount !== 1 || parseDirectRunSequence(withoutMarker, false)?.currentText !== "")
134970
+ return null;
134971
+ return { markerRunXml, remainingRunXml: xml.slice(markerRunXml.length) };
134972
+ }
134973
+ function sameNoteMarkerRunXml(base2, target) {
134974
+ const withoutRedundantWordNamespace = (xml) => xml.split(` xmlns:w="${W_NS}"`).join("").split(` xmlns:w='${W_NS}'`).join("");
134975
+ return withoutRedundantWordNamespace(base2) === withoutRedundantWordNamespace(target);
134976
+ }
134925
134977
  function inspectDirectParagraphRevisionRuns(xml) {
134926
134978
  return parseDirectRunSequence(xml, true);
134927
134979
  }
@@ -135265,9 +135317,21 @@ function parseXmlStartTag(rawTag) {
135265
135317
  return null;
135266
135318
  }
135267
135319
  function validateRunContents(xml, options) {
135268
- if (xml === "")
135320
+ const baseHasNoteMarker = options.baseRunXml !== undefined && /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/.test(options.baseRunXml);
135321
+ const targetHasNoteMarker = /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/.test(xml);
135322
+ let runs = xml;
135323
+ if (baseHasNoteMarker || targetHasNoteMarker) {
135324
+ const family = options.noteMarkerFamily;
135325
+ const target = family && splitLeadingNoteMarkerRun(xml, family);
135326
+ const base2 = family && options.baseRunXml !== undefined ? splitLeadingNoteMarkerRun(options.baseRunXml, family) : undefined;
135327
+ if (!target || options.baseRunXml !== undefined && (!base2 || !sameNoteMarkerRunXml(base2.markerRunXml, target.markerRunXml))) {
135328
+ return { ok: false, reason: "target runs change or misplace the note marker" };
135329
+ }
135330
+ runs = target.remainingRunXml;
135331
+ }
135332
+ if (runs === "")
135269
135333
  return { ok: true };
135270
- const replayXml = stripAllowedNoteReferences(xml, options);
135334
+ const replayXml = stripAllowedNoteReferences(runs, options);
135271
135335
  const withoutCarriers = replayXml !== null && options.baseRunXml ? stripRetainedCarrier(replayXml, options.baseRunXml, options.allowNamespaceDeclarationDifference === true) : replayXml;
135272
135336
  const withoutBookmarks = withoutCarriers !== null && /<(?:[\w.-]+:)?bookmark(?:Start|End)\b/.test(withoutCarriers) ? preservedBookmarkRunTokens(withoutCarriers)?.strippedXml ?? null : withoutCarriers;
135273
135337
  if (withoutBookmarks === null || UNSUPPORTED_XML.test(withoutBookmarks) || RELATIONSHIP_REFERENCE.test(withoutBookmarks)) {
@@ -136990,7 +137054,8 @@ function validateCompareApplyPlan(value, baseBody = []) {
136990
137054
  if (!isRecord9(group) || !Array.isArray(group.operations))
136991
137055
  return;
136992
137056
  group.operations.forEach((operation, operationIndex) => {
136993
- validateBodyOperation(operation, `storyOperations[${index}].operations[${operationIndex}]`, problems);
137057
+ const noteMarkerFamily = (group.family === "footnotes" || group.family === "endnotes") && isRecord9(operation) && (operation.kind === "edit" || operation.kind === "formatEdit") ? group.family : undefined;
137058
+ validateBodyOperation(operation, `storyOperations[${index}].operations[${operationIndex}]`, problems, { noteMarkerFamily });
136994
137059
  });
136995
137060
  });
136996
137061
  }
@@ -139106,7 +139171,7 @@ function attachExactTargetRevisionReplayToStories(groups, base2, target, matchRe
139106
139171
  });
139107
139172
  return { groups: replayGroups, coveredBaseAnnotations, coveredTargetAnnotations, changedTrackedXmlReplayed };
139108
139173
  }
139109
- function firstUnsafeReplayReason(operations, noteLifecycle = [], targetStories = [], baseBody = []) {
139174
+ function firstUnsafeReplayReason(operations, noteLifecycle = [], targetStories = [], baseBody = [], noteMarkerFamily) {
139110
139175
  const createdNoteReferences = noteLifecycle.filter((operation) => operation.kind === "create-note-definition" || operation.kind === "create-note-story").map((operation) => ({ family: operation.family, noteId: operation.noteId }));
139111
139176
  const retainedNoteReferences = targetStories.flatMap((story) => (story.family === "footnotes" || story.family === "endnotes") && story.noteId ? [{ family: story.family, noteId: story.noteId }] : []);
139112
139177
  const allowedNoteReferences = [...createdNoteReferences, ...retainedNoteReferences];
@@ -139116,7 +139181,7 @@ function firstUnsafeReplayReason(operations, noteLifecycle = [], targetStories =
139116
139181
  continue;
139117
139182
  const result = validateCompareReplayPayload(operation, {
139118
139183
  allowedNoteReferences,
139119
- ...operation.kind === "edit" || operation.kind === "formatEdit" ? { baseRunXml: baseRunByBlockId.get(operation.blockId) } : {}
139184
+ ...operation.kind === "edit" || operation.kind === "formatEdit" ? { baseRunXml: baseRunByBlockId.get(operation.blockId), noteMarkerFamily } : {}
139120
139185
  });
139121
139186
  if (!result.ok)
139122
139187
  return result.reason;
@@ -139310,7 +139375,9 @@ function planCompare(base2, target) {
139310
139375
  for (const group of storyOperations) {
139311
139376
  if (!replayableStoryFamilies.has(group.family))
139312
139377
  continue;
139313
- const unsafeStoryReason = firstUnsafeReplayReason(group.operations);
139378
+ const noteMarkerFamily = group.family === "footnotes" || group.family === "endnotes" ? group.family : undefined;
139379
+ const baseStory = noteMarkerFamily ? base2.stories?.find((story) => story.storyId === group.storyId && story.family === group.family && story.noteId === group.noteId) : undefined;
139380
+ const unsafeStoryReason = firstUnsafeReplayReason(group.operations, [], [], baseStory?.entries ?? [], noteMarkerFamily);
139314
139381
  if (!unsafeStoryReason || unsafeStoryFamilies.has(group.family))
139315
139382
  continue;
139316
139383
  unsafeStoryFamilies.add(group.family);
@@ -221816,7 +221883,7 @@ function runCompareApplyCommit(input) {
221816
221883
  if (input.options.expectedPackageRevision && input.options.expectedPackageRevision !== state.packageRevision) {
221817
221884
  return rejected14(txId, "base-revision-drift");
221818
221885
  }
221819
- if (input.readCurrentPackageBinding() !== op.planBinding) {
221886
+ if (input.readCurrentComparePlanBinding() !== op.planBinding) {
221820
221887
  return rejected14(txId, "base-revision-drift");
221821
221888
  }
221822
221889
  const changeMode = op.changeMode;
@@ -222582,7 +222649,10 @@ function normalizeCompareBodyStep(step2, sectionSteps, referenceSteps, allowedNo
222582
222649
  return step2.targetRevisionReplay === undefined || step2.targetRevisionReplay.structuralAction === "delete" ? step2 : null;
222583
222650
  }
222584
222651
  const baseRunXml = step2.kind === "edit" || step2.kind === "formatEdit" ? liveCompareBodyRunXml(state, storyId, step2.blockId) : undefined;
222585
- if (!validateCompareBodyReplayPayload(step2, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml))
222652
+ const noteMarkerFamily = step2.kind === "edit" || step2.kind === "formatEdit" ? storyId.startsWith("footnotes:") ? "footnotes" : storyId.startsWith("endnotes:") ? "endnotes" : undefined : undefined;
222653
+ if (noteMarkerFamily && baseRunXml && /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/.test(baseRunXml) && step2.targetRunXml === undefined)
222654
+ return null;
222655
+ if (!validateCompareBodyReplayPayload(step2, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml, noteMarkerFamily))
222586
222656
  return null;
222587
222657
  const targetParagraphPropertiesXml = step2.targetParagraphPropertiesXml === undefined ? undefined : canonicalizeCompareBodyParagraphPropertiesXml(step2.targetParagraphPropertiesXml, sectionSteps);
222588
222658
  const targetRunXml = step2.targetRunXml === undefined ? undefined : (step2.targetRunXml.includes("<w:drawing") || step2.targetRunXml.includes("<w:fldSimple")) && baseRunXml && referenceSteps.length === 0 ? step2.targetRunXml : canonicalizeCompareBodyRunXml(step2.targetRunXml, referenceSteps);
@@ -222598,7 +222668,7 @@ function normalizeCompareBodyStep(step2, sectionSteps, referenceSteps, allowedNo
222598
222668
  targetRunXml,
222599
222669
  replayDependencies: "replayDependencies" in step2 ? step2.replayDependencies : undefined,
222600
222670
  targetRevisionReplay: "targetRevisionReplay" in step2 ? step2.targetRevisionReplay : undefined
222601
- }, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml) ? normalized : null;
222671
+ }, sectionSteps, referenceSteps, allowedNoteReferences, step2.text, baseRunXml, noteMarkerFamily) ? normalized : null;
222602
222672
  }
222603
222673
  function liveCompareBodyRunXml(state, storyId, blockId) {
222604
222674
  const entry = getStoryParagraphIndexFromState(state, storyId)?.byParaId(blockId);
@@ -222731,7 +222801,7 @@ function sourceProofBindsReference(proof, family) {
222731
222801
  const childXml = wrappedSource.slice(child.start, child.end);
222732
222802
  return isValidNoteReferenceReplayRunXml(childXml, family, proof.noteId, child.namespaceBindings) && replayCarrierXmlEquals(childXml, proof.referenceRunXml);
222733
222803
  }
222734
- function validateCompareBodyReplayPayload(payload, sectionSteps, referenceSteps, allowedNoteReferences, expectedCurrentText, baseRunXml) {
222804
+ function validateCompareBodyReplayPayload(payload, sectionSteps, referenceSteps, allowedNoteReferences, expectedCurrentText, baseRunXml, noteMarkerFamily) {
222735
222805
  if (payload.targetRunXml !== undefined && expectedCurrentText !== undefined && projectCompareReplayCurrentText(payload.targetRunXml) !== expectedCurrentText.replace(/\uFFFC/g, "")) {
222736
222806
  return false;
222737
222807
  }
@@ -222739,7 +222809,12 @@ function validateCompareBodyReplayPayload(payload, sectionSteps, referenceSteps,
222739
222809
  if (targetParagraphPropertiesXml === null)
222740
222810
  return false;
222741
222811
  const targetRunXml = payload.targetRunXml === undefined ? undefined : stripProtectedReferenceTokens(payload.targetRunXml, referenceSteps);
222742
- return targetRunXml !== null && validateCompareReplayPayload({ ...payload, targetParagraphPropertiesXml, targetRunXml }, { allowedNoteReferences, baseRunXml, allowNamespaceDeclarationDifference: baseRunXml !== undefined }).ok;
222812
+ return targetRunXml !== null && validateCompareReplayPayload({ ...payload, targetParagraphPropertiesXml, targetRunXml }, {
222813
+ allowedNoteReferences,
222814
+ baseRunXml,
222815
+ noteMarkerFamily,
222816
+ allowNamespaceDeclarationDifference: baseRunXml !== undefined
222817
+ }).ok;
222743
222818
  }
222744
222819
  function stripProtectedSectionTokens(xml, sectionSteps) {
222745
222820
  const tokens = collectProtectedSectionTokens(xml, sectionSteps);
@@ -223717,6 +223792,24 @@ function unchangedBookmarkReferenceSteps(oldRuns, targetRuns) {
223717
223792
  afterNamespaceBindings: bookmarkBindings
223718
223793
  }];
223719
223794
  }
223795
+ function retainedNoteMarkerRuns(oldRuns, targetRuns, storyId) {
223796
+ const markerPattern = /<(?:[A-Za-z_][\w.-]*:)?(?:footnoteRef|endnoteRef)\b/;
223797
+ if (!markerPattern.test(oldRuns) && !markerPattern.test(targetRuns)) {
223798
+ return { markerRunXml: "", oldRuns, targetRuns };
223799
+ }
223800
+ const family = storyId.startsWith("footnotes:") ? "footnotes" : storyId.startsWith("endnotes:") ? "endnotes" : null;
223801
+ if (!family)
223802
+ return null;
223803
+ const oldMarker = splitLeadingNoteMarkerRun(oldRuns, family);
223804
+ const targetMarker = splitLeadingNoteMarkerRun(targetRuns, family);
223805
+ if (!oldMarker || !targetMarker || !sameNoteMarkerRunXml(oldMarker.markerRunXml, targetMarker.markerRunXml))
223806
+ return null;
223807
+ return {
223808
+ markerRunXml: oldMarker.markerRunXml,
223809
+ oldRuns: oldMarker.remainingRunXml,
223810
+ targetRuns: targetMarker.remainingRunXml
223811
+ };
223812
+ }
223720
223813
  function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pushHistory, referenceSteps) {
223721
223814
  const { state, txId } = input;
223722
223815
  const partUri = storyPartUriFromStoryId2(storyId);
@@ -223738,6 +223831,9 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
223738
223831
  const closeStart = paraXml.lastIndexOf("</");
223739
223832
  const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
223740
223833
  const oldRunsRaw = stripElements(innerXml, "pPr");
223834
+ const retainedMarker = retainedNoteMarkerRuns(oldRunsRaw, newRuns, storyId);
223835
+ if (!retainedMarker)
223836
+ return rejected14(txId, "unsupported-context");
223741
223837
  const stableBookmarkSteps = unchangedBookmarkReferenceSteps(oldRunsRaw, newRuns);
223742
223838
  if (stableBookmarkSteps === null && referenceSteps.length === 0)
223743
223839
  return rejected14(txId, "unsupported-context");
@@ -223756,10 +223852,10 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
223756
223852
  storyId
223757
223853
  });
223758
223854
  }
223759
- const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
223855
+ const oldRunsDel = retainedMarker.oldRuns.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
223760
223856
  const hunkStamps = makeCompareHunkStampSource(stamps, input);
223761
- const retainedCarrier = newRuns.includes("<w:drawing") || newRuns.includes("<w:fldSimple") && protectedReferenceSteps.length === 0;
223762
- const protectedRuns = retainedCarrier ? protectedReferenceSteps.length === 0 ? renderTrackedRunsWithRetainedCarrier(oldRunsRaw, newRuns, hunkStamps.next, paragraphWrapper.wordprocessingPrefix, bytes, entry.byteStart, entry.byteEnd) : null : renderTrackedRunsWithProtectedReferences(oldRunsRaw, newRuns, protectedReferenceSteps, hunkStamps.next, paragraphWrapper.wordprocessingPrefix);
223857
+ const retainedCarrier = retainedMarker.targetRuns.includes("<w:drawing") || retainedMarker.targetRuns.includes("<w:fldSimple") && protectedReferenceSteps.length === 0;
223858
+ const protectedRuns = retainedCarrier ? protectedReferenceSteps.length === 0 ? renderTrackedRunsWithRetainedCarrier(retainedMarker.oldRuns, retainedMarker.targetRuns, hunkStamps.next, paragraphWrapper.wordprocessingPrefix, bytes, entry.byteStart, entry.byteEnd) : null : renderTrackedRunsWithProtectedReferences(retainedMarker.oldRuns, retainedMarker.targetRuns, protectedReferenceSteps, hunkStamps.next, paragraphWrapper.wordprocessingPrefix);
223763
223859
  if (retainedCarrier && !protectedRuns)
223764
223860
  return rejected14(txId, "unsupported-context");
223765
223861
  if (!protectedRuns && stableBookmarkSteps?.length)
@@ -223772,10 +223868,10 @@ function runCompareBodyEditCommit(input, storyId, step2, changeMode, options, pu
223772
223868
  } else {
223773
223869
  const fallbackPair = hunkStamps.next();
223774
223870
  delXml = oldRunsDel ? wrapTracked("del", oldRunsDel, fallbackPair.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "";
223775
- insXml = newRuns ? wrapTracked("ins", newRuns, fallbackPair.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
223871
+ insXml = retainedMarker.targetRuns ? wrapTracked("ins", retainedMarker.targetRuns, fallbackPair.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
223776
223872
  }
223777
223873
  const trackedPPrXml = buildTrackedParagraphProperties(targetParagraphPropertiesXml, pPrXml, stamps.paragraphProperties ?? stamps.ins, paragraphWrapper.wordprocessingPrefix);
223778
- const assembledParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
223874
+ const assembledParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}` + `${retainedMarker.markerRunXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
223779
223875
  if (hunkStamps.usedPairs.length === 0) {
223780
223876
  newParaXml = assembledParaXml;
223781
223877
  } else {
@@ -224068,6 +224164,9 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
224068
224164
  const closeStart = paraXml.lastIndexOf("</");
224069
224165
  const innerXml = closeStart > openEnd ? paraXml.slice(openEnd, closeStart) : "";
224070
224166
  const oldRunsRaw = stripElements(innerXml, "pPr");
224167
+ const retainedMarker = retainedNoteMarkerRuns(oldRunsRaw, targetRunXml, storyId);
224168
+ if (!retainedMarker)
224169
+ return rejected14(txId, "unsupported-context");
224071
224170
  const paragraphPropertiesChanged = !equivalentParagraphProperties(targetPPrXml, pPrXml);
224072
224171
  const stableBookmarkSteps = unchangedBookmarkReferenceSteps(oldRunsRaw, targetRunXml);
224073
224172
  if (stableBookmarkSteps === null && referenceSteps.length === 0)
@@ -224135,12 +224234,12 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
224135
224234
  const stamps = compareTrackedStampPair(input, paragraphPropertiesChanged);
224136
224235
  if (!stamps)
224137
224236
  return rejected14(txId, "no-author-configured");
224138
- const oldRunsDel = oldRunsRaw.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
224139
- const protectedRuns = renderTrackedRunsWithProtectedReferences(oldRunsRaw, targetRunXml, protectedReferenceSteps, () => stamps, paragraphWrapper.wordprocessingPrefix);
224237
+ const oldRunsDel = retainedMarker.oldRuns.replace(/<((?:[\w.-]+:)?)t(\b[^>]*)>/g, "<$1delText$2>").replace(/<\/((?:[\w.-]+:)?)t>/g, "</$1delText>");
224238
+ const protectedRuns = renderTrackedRunsWithProtectedReferences(retainedMarker.oldRuns, retainedMarker.targetRuns, protectedReferenceSteps, () => stamps, paragraphWrapper.wordprocessingPrefix);
224140
224239
  if (!protectedRuns && stableBookmarkSteps?.length)
224141
224240
  return rejected14(txId, "unsupported-context");
224142
224241
  const delXml = protectedRuns?.xml ?? (oldRunsDel ? wrapTracked("del", oldRunsDel, stamps.del, "rsidDel", paragraphWrapper.wordprocessingPrefix) : "");
224143
- const insXml = protectedRuns ? "" : targetRunXml ? wrapTracked("ins", targetRunXml, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
224242
+ const insXml = protectedRuns ? "" : retainedMarker.targetRuns ? wrapTracked("ins", retainedMarker.targetRuns, stamps.ins, "rsidR", paragraphWrapper.wordprocessingPrefix) : "";
224144
224243
  if (delXml || insXml) {
224145
224244
  createdRefs.push({ kind: "trackedChange", entityId: stamps.ins.rsid, storyId });
224146
224245
  }
@@ -224152,7 +224251,7 @@ function runCompareBodyFormatEditCommit(input, storyId, step2, changeMode, optio
224152
224251
  });
224153
224252
  }
224154
224253
  const trackedPPrXml = buildTrackedParagraphProperties(targetParagraphPropertiesXml, pPrXml, stamps.paragraphProperties ?? stamps.ins, paragraphWrapper.wordprocessingPrefix);
224155
- newParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
224254
+ newParaXml = `${paragraphWrapper.openTag}${trackedPPrXml}` + `${retainedMarker.markerRunXml}${delXml}${insXml}${paragraphWrapper.closeTag}`;
224156
224255
  }
224157
224256
  } else {
224158
224257
  newParaXml = `${paragraphWrapper.openTag}${targetPPrXml}${targetRunXml}${paragraphWrapper.closeTag}`;
@@ -228689,13 +228788,14 @@ function changeIlvl(input, delta) {
228689
228788
  const trackedFormatting = buildTrackedListFormattingMetadata(input, op.target.storyId);
228690
228789
  if (trackedFormatting && "reason" in trackedFormatting)
228691
228790
  return rejected15(input.txId, trackedFormatting.reason);
228692
- const { target, bytes, paraXml, plan } = prepared;
228791
+ const { target, bytes, paraXml, plan, paragraphStyleId } = prepared;
228693
228792
  return commitParagraphNumPrRewrite({
228694
228793
  input,
228695
228794
  target,
228696
228795
  bytes,
228697
228796
  paraXml,
228698
228797
  numPr: { numId: plan.numId, ilvl: plan.ilvl },
228798
+ paragraphStyleId,
228699
228799
  trackedFormatting
228700
228800
  });
228701
228801
  }
@@ -228716,10 +228816,30 @@ function prepareListLevelChange(state, op, delta, author) {
228716
228816
  });
228717
228817
  if (!structural.ok)
228718
228818
  return structural;
228719
- const plan = decideListLevelChange(resolveEffectiveListReferenceForState(state, paraXml), delta);
228819
+ const effective = resolveEffectiveListReferenceForState(state, paraXml);
228820
+ const plan = decideListLevelChange(effective, delta);
228720
228821
  if (plan.kind === "reject")
228721
228822
  return { ok: false, reason: plan.reason };
228722
- return { ok: true, target, bytes, paraXml, plan };
228823
+ const targetStyle = resolveTargetLevelParagraphStyle(state, effective, plan.ilvl);
228824
+ if (!targetStyle.ok)
228825
+ return targetStyle;
228826
+ return { ok: true, target, bytes, paraXml, plan, paragraphStyleId: targetStyle.paragraphStyleId };
228827
+ }
228828
+ function resolveTargetLevelParagraphStyle(state, effective, ilvl) {
228829
+ if (effective.definition.status !== "resolved")
228830
+ return { ok: false, reason: effectiveListRejectionReason(effective) };
228831
+ const level = resolveNumberingLevel(effective.definition, ilvl);
228832
+ if (!level)
228833
+ return { ok: false, reason: "list-numbering-level-missing" };
228834
+ const paragraphStyleId = level.level.paragraphStyleId;
228835
+ if (paragraphStyleId === null)
228836
+ return { ok: true, paragraphStyleId: null };
228837
+ const styles = getEffectiveListResolverContextForState(state);
228838
+ const record3 = styles.styleIndex.get(paragraphStyleId);
228839
+ if (styles.stylesStatus !== "available" || !record3 || !isParagraphStyleRecord(record3) || record3.listCarrierStatus === "malformed") {
228840
+ return { ok: false, reason: "list-numbering-link-invalid" };
228841
+ }
228842
+ return { ok: true, paragraphStyleId };
228723
228843
  }
228724
228844
  function validateListLevelChange(state, op, author) {
228725
228845
  const prepared = prepareListLevelChange(state, op, op.kind === "listIndent" ? 1 : -1, author);
@@ -228839,8 +228959,11 @@ function changeIlvlRange(input, delta) {
228839
228959
  });
228840
228960
  continue;
228841
228961
  }
228962
+ const targetStyle = resolveTargetLevelParagraphStyle(input.state, ref3, nextIlvl);
228963
+ if (!targetStyle.ok)
228964
+ return rejected15(input.txId, targetStyle.reason);
228842
228965
  const trackedFormatting = trackedAllocator && !("reason" in trackedAllocator) ? trackedAllocator.mint() : undefined;
228843
- const rewrite = trackedFormatting ? rewriteParagraphNumPrTracked(paraXml, { numId: ref3.authoredNumId, ilvl: nextIlvl }, trackedFormatting) : rewriteParagraphNumPr(paraXml, { numId: ref3.authoredNumId, ilvl: nextIlvl });
228966
+ const rewrite = trackedFormatting ? rewriteParagraphNumPrTracked(paraXml, { numId: ref3.authoredNumId, ilvl: nextIlvl }, trackedFormatting, targetStyle.paragraphStyleId) : rewriteParagraphNumPr(paraXml, { numId: ref3.authoredNumId, ilvl: nextIlvl }, targetStyle.paragraphStyleId);
228844
228967
  if (!rewrite.ok)
228845
228968
  return rejected15(input.txId, rewrite.reason);
228846
228969
  items.push({
@@ -229097,13 +229220,13 @@ function decodeByteRange2(bytes, startByte, endByte) {
229097
229220
  return "";
229098
229221
  return TD60.decode(bytes.subarray(startByte, endByte));
229099
229222
  }
229100
- function rewriteParagraphNumPr(paraXml, numPr) {
229223
+ function rewriteParagraphNumPr(paraXml, numPr, paragraphStyleId) {
229101
229224
  const selfClosingParaMatch = paraXml.match(/^<((?:[\w.-]+:)?p)\b([^>]*)\/>$/);
229102
229225
  if (selfClosingParaMatch) {
229103
229226
  const paragraphQName = selfClosingParaMatch[1];
229104
229227
  const attrs = selfClosingParaMatch[2] ?? "";
229105
229228
  const names2 = wordNamesForQName(paragraphQName);
229106
- const listParagraphStyleXml = renderParagraphStyle(names2, "ListParagraph");
229229
+ const listParagraphStyleXml = renderParagraphStyle(names2, paragraphStyleId ?? "ListParagraph");
229107
229230
  const numPrXml2 = renderParagraphNumPr(names2, numPr);
229108
229231
  return {
229109
229232
  ok: true,
@@ -229121,7 +229244,7 @@ function rewriteParagraphNumPr(paraXml, numPr) {
229121
229244
  const pPrName = names2.element("pPr");
229122
229245
  return {
229123
229246
  ok: true,
229124
- xml: `${openTag}<${pPrName}>${renderParagraphStyle(names2, "ListParagraph")}` + `${renderParagraphNumPr(names2, numPr)}</${pPrName}>${inner}`
229247
+ xml: `${openTag}<${pPrName}>${renderParagraphStyle(names2, paragraphStyleId ?? "ListParagraph")}` + `${renderParagraphNumPr(names2, numPr)}</${pPrName}>${inner}`
229125
229248
  };
229126
229249
  }
229127
229250
  const pPrQName = /^<((?:[\w.-]+:)?pPr)\b/.exec(split.pPr)?.[1];
@@ -229131,7 +229254,7 @@ function rewriteParagraphNumPr(paraXml, numPr) {
229131
229254
  const children = readLivePPrChildren(split.pPr);
229132
229255
  if (!children)
229133
229256
  return { ok: false, reason: "list-target-not-found" };
229134
- const withStyle = children.some((child) => child.localName === "pStyle") ? split.pPr : rewriteLivePPrChild(split.pPr, "pStyle", renderParagraphStyle(names, "ListParagraph"), { ordered: true });
229257
+ const withStyle = paragraphStyleId === null || paragraphStyleId === undefined ? children.some((child) => child.localName === "pStyle") ? split.pPr : rewriteLivePPrChild(split.pPr, "pStyle", renderParagraphStyle(names, "ListParagraph"), { ordered: true }) : rewriteLivePPrChild(split.pPr, "pStyle", renderParagraphStyle(names, paragraphStyleId), { ordered: true });
229135
229258
  if (withStyle === null)
229136
229259
  return { ok: false, reason: "list-target-not-found" };
229137
229260
  const numPrXml = renderParagraphNumPr(names, numPr);
@@ -229229,7 +229352,7 @@ function readLivePPrChildren(pPrXml) {
229229
229352
  return children;
229230
229353
  }
229231
229354
  function commitParagraphNumPrRewrite(args) {
229232
- const rewrite = args.trackedFormatting ? rewriteParagraphNumPrTracked(args.paraXml, args.numPr, args.trackedFormatting) : rewriteParagraphNumPr(args.paraXml, args.numPr);
229355
+ const rewrite = args.trackedFormatting ? rewriteParagraphNumPrTracked(args.paraXml, args.numPr, args.trackedFormatting, args.paragraphStyleId) : rewriteParagraphNumPr(args.paraXml, args.numPr, args.paragraphStyleId);
229233
229356
  if (!rewrite.ok)
229234
229357
  return rejected15(args.input.txId, rewrite.reason);
229235
229358
  return commitParagraphRewrite({
@@ -229330,8 +229453,8 @@ function buildTrackedListFormattingAllocator(input, storyId) {
229330
229453
  }
229331
229454
  };
229332
229455
  }
229333
- function rewriteParagraphNumPrTracked(paraXml, numPr, tracked) {
229334
- const direct = rewriteParagraphNumPr(paraXml, numPr);
229456
+ function rewriteParagraphNumPrTracked(paraXml, numPr, tracked, paragraphStyleId) {
229457
+ const direct = rewriteParagraphNumPr(paraXml, numPr, paragraphStyleId);
229335
229458
  if (!direct.ok)
229336
229459
  return direct;
229337
229460
  return wrapParagraphTrackedChange(direct.xml, paraXml, tracked);
@@ -239497,13 +239620,13 @@ function allocateTransactionId() {
239497
239620
  return `tx-${time3}-${nextTx.toString(36)}-${random}`;
239498
239621
  }
239499
239622
  function createSDTransactionContext(input) {
239500
- return new TxContext(input.state, input.author, input.readCurrentPackageBinding, input.options, input.onCommitted);
239623
+ return new TxContext(input.state, input.author, input.readCurrentComparePlanBinding, input.options, input.onCommitted);
239501
239624
  }
239502
239625
 
239503
239626
  class TxContext {
239504
- constructor(state, author, readCurrentPackageBinding, options = {}, onCommitted) {
239627
+ constructor(state, author, readCurrentComparePlanBinding, options = {}, onCommitted) {
239505
239628
  this.state = state;
239506
- this.readCurrentPackageBinding = readCurrentPackageBinding;
239629
+ this.readCurrentComparePlanBinding = readCurrentComparePlanBinding;
239507
239630
  this.options = options;
239508
239631
  this.onCommitted = onCommitted;
239509
239632
  this.txId = allocateTransactionId();
@@ -240102,7 +240225,7 @@ class TxContext {
240102
240225
  author: this.author,
240103
240226
  authorOverride: this.authorOverride,
240104
240227
  txTimestamp: this.txTimestamp,
240105
- readCurrentPackageBinding: this.readCurrentPackageBinding,
240228
+ readCurrentComparePlanBinding: this.readCurrentComparePlanBinding,
240106
240229
  options: this.options,
240107
240230
  op,
240108
240231
  pushHistory: (entry) => this.pushHistoryEntry(entry),
@@ -247981,7 +248104,12 @@ var init_comment_export_normalization = __esm(() => {
247981
248104
 
247982
248105
  // ../../../v2/editor-core/dist/document/transactions/note-export-hygiene.js
247983
248106
  function planNoteExportHygiene(state) {
247984
- const noteFree = isNoteFreePackage(state);
248107
+ return buildNoteExportHygienePlan(state, isNoteFreePackage(state));
248108
+ }
248109
+ function planNoteExportHygieneForFingerprint(state) {
248110
+ return buildNoteExportHygienePlan(state, isNoteFreePackageForFingerprint(state));
248111
+ }
248112
+ function buildNoteExportHygienePlan(state, noteFree) {
247985
248113
  const removals = new Set;
247986
248114
  if (noteFree) {
247987
248115
  for (const partUri of [FOOTNOTES_PART_URI2, ENDNOTES_PART_URI2]) {
@@ -248011,6 +248139,12 @@ function transformXmlBytes(bytes, transform2) {
248011
248139
  return next === xml ? bytes : TE41.encode(next);
248012
248140
  }
248013
248141
  function isNoteFreePackage(state) {
248142
+ return isNoteFreePackageCore(state, { pruneUnconfiguredOrphanSidecar: state.renderCommitSequence !== 0 });
248143
+ }
248144
+ function isNoteFreePackageForFingerprint(state) {
248145
+ return isNoteFreePackageCore(state, { pruneUnconfiguredOrphanSidecar: true });
248146
+ }
248147
+ function isNoteFreePackageCore(state, options) {
248014
248148
  for (const partUri of listStoryPartUris2(state)) {
248015
248149
  const bytes = state.packageBytes.get(partUri);
248016
248150
  if (!bytes)
@@ -248032,7 +248166,7 @@ function isNoteFreePackage(state) {
248032
248166
  if (hasConfiguredNoteSettings(settingsXml))
248033
248167
  return false;
248034
248168
  const hasNoteSidecar = state.packageBytes.has(FOOTNOTES_PART_URI2) || state.packageBytes.has(ENDNOTES_PART_URI2);
248035
- if (state.renderCommitSequence === 0 && hasNoteSidecar && !/<w:(?:footnotePr|endnotePr)\b/.test(settingsXml))
248169
+ if (!options.pruneUnconfiguredOrphanSidecar && hasNoteSidecar && !/<w:(?:footnotePr|endnotePr)\b/.test(settingsXml))
248036
248170
  return false;
248037
248171
  return true;
248038
248172
  }
@@ -249150,6 +249284,45 @@ function computeSDDocumentSessionInternalPackageBinding(session) {
249150
249284
  const payload = PACKAGE_BINDING_TEXT_ENCODER.encode(JSON.stringify({ version: "sd-package-binding/v1", parts }));
249151
249285
  return `sha256:${sha256HexSync(payload)}`;
249152
249286
  }
249287
+ function computeSDDocumentSessionInternalSemanticPackageBinding(session) {
249288
+ const internal = INTERNALS.get(session);
249289
+ if (!internal)
249290
+ throw new Error("internal: unknown SDDocumentSession instance");
249291
+ const noteHygienePlan = planNoteExportHygieneForFingerprint(internal.state);
249292
+ const partUris = new Set([
249293
+ ...internal.state.parts.keys(),
249294
+ ...internal.state.packageBytes.keys()
249295
+ ]);
249296
+ const parts = [...partUris].filter((partUri) => !noteHygienePlan.removals.has(partUri)).map((partUri) => {
249297
+ const descriptor = internal.state.parts.get(partUri)?.descriptor ?? null;
249298
+ const sourcePartSize = internal.openResult.packageOpen.pkg.parts.get(partUri)?.uncompressedSize;
249299
+ const unchangedFromSource = descriptor?.revision === internal.state.sourcePartRevisions.get(partUri);
249300
+ const oversizedUnchangedSource = unchangedFromSource && sourcePartSize !== undefined && sourcePartSize > 64 * 1024 * 1024;
249301
+ const rawBytes = oversizedUnchangedSource ? null : descriptor ? getSDDocumentSessionInternalCapturePartBytes(session, partUri, unchangedFromSource ? 64 * 1024 * 1024 : Number.MAX_SAFE_INTEGER) : internal.state.packageBytes.get(partUri) ?? null;
249302
+ const bytes = rawBytes ? canonicalizePartBytesForSemanticBinding(partUri, rawBytes, noteHygienePlan) : null;
249303
+ return {
249304
+ partUri,
249305
+ contentType: descriptor?.contentType ?? null,
249306
+ kind: descriptor?.kind ?? null,
249307
+ byteLength: bytes?.length ?? null,
249308
+ bytesSha256: bytes ? sha256HexSync(bytes) : null
249309
+ };
249310
+ }).sort((a, b) => a.partUri.localeCompare(b.partUri));
249311
+ const payload = PACKAGE_BINDING_TEXT_ENCODER.encode(JSON.stringify({ version: "sd-package-binding-semantic/v1", parts }));
249312
+ return `sha256-semantic:${sha256HexSync(payload)}`;
249313
+ }
249314
+ function canonicalizePartBytesForSemanticBinding(partUri, bytes, noteHygienePlan) {
249315
+ const noteProjected = noteHygienePlan.transformPartBytes(partUri, bytes);
249316
+ const wordXmlNormalized = normalizeWordXmlForSave(partUri, noteProjected);
249317
+ if (!WORD_XML_PART_RE.test(partUri))
249318
+ return wordXmlNormalized;
249319
+ const xml = SAVE_XML_DECODER.decode(wordXmlNormalized);
249320
+ const stripped = stripSessionIssuedTrackedChangeIdsForFingerprint(xml);
249321
+ return stripped === xml ? wordXmlNormalized : SAVE_XML_ENCODER.encode(stripped);
249322
+ }
249323
+ function stripSessionIssuedTrackedChangeIdsForFingerprint(xml) {
249324
+ return xml.replace(RSID_ATTR_FOR_FINGERPRINT_RE, "").replace(SIMPLE_TRACKED_CHANGE_WRAPPER_OPEN_RE, (tag) => tag.replace(WRAPPER_ID_ATTR_FOR_FINGERPRINT_RE, ""));
249325
+ }
249153
249326
  function markSDDocumentSessionInternalExactPackageSave(session, binding) {
249154
249327
  var _a3;
249155
249328
  const internal = INTERNALS.get(session);
@@ -250169,7 +250342,7 @@ function beginSDDocumentSessionInternalTransaction(session, options) {
250169
250342
  return createSDTransactionContext({
250170
250343
  state: internal.state,
250171
250344
  author: internal.author,
250172
- readCurrentPackageBinding: () => computeSDDocumentSessionInternalPackageBinding(session),
250345
+ readCurrentComparePlanBinding: () => computeSDDocumentSessionInternalSemanticPackageBinding(session),
250173
250346
  options: mergedOptions,
250174
250347
  onCommitted: internal.onMutationCommitted
250175
250348
  });
@@ -252948,7 +253121,7 @@ async function waitForQueuedPreScan(controller, cancel) {
252948
253121
  }
252949
253122
  return outcome.value;
252950
253123
  }
252951
- var SAVE_XML_DECODER, SAVE_XML_ENCODER, PACKAGE_BINDING_TEXT_ENCODER, WORD_XML_PART_RE, REVIEW_SOURCE_COPY_CHUNK_BYTES, INTERNALS, LIVE_MAIN_STORY_SCAN_MEMO, RELS_DECODER, DEFAULT_SAVE_COMPRESSION_LEVEL = 6, SAVE_ZIP_ENTRY_MTIME, EMPTY_PART_URI_SET, ALREADY_COMPRESSED_PART_RE, RAW_FONT_PART_RE, SDSourceBackedSaveUnsupportedError, REMOTE_PROJECTION_GENERATIONS, COLLABORATION_ATTACHMENTS, FIELD_STABLE_ID_ALLOCATORS;
253124
+ var SAVE_XML_DECODER, SAVE_XML_ENCODER, PACKAGE_BINDING_TEXT_ENCODER, WORD_XML_PART_RE, REVIEW_SOURCE_COPY_CHUNK_BYTES, INTERNALS, LIVE_MAIN_STORY_SCAN_MEMO, RELS_DECODER, DEFAULT_SAVE_COMPRESSION_LEVEL = 6, SAVE_ZIP_ENTRY_MTIME, EMPTY_PART_URI_SET, ALREADY_COMPRESSED_PART_RE, RAW_FONT_PART_RE, RSID_ATTR_FOR_FINGERPRINT_RE, SIMPLE_TRACKED_CHANGE_WRAPPER_OPEN_RE, WRAPPER_ID_ATTR_FOR_FINGERPRINT_RE, SDSourceBackedSaveUnsupportedError, REMOTE_PROJECTION_GENERATIONS, COLLABORATION_ATTACHMENTS, FIELD_STABLE_ID_ALLOCATORS;
252952
253125
  var init_sd_document_session = __esm(() => {
252953
253126
  init_textbox_atom_replacement();
252954
253127
  init_paragraph_signal_index();
@@ -253025,6 +253198,9 @@ var init_sd_document_session = __esm(() => {
253025
253198
  EMPTY_PART_URI_SET = new Set;
253026
253199
  ALREADY_COMPRESSED_PART_RE = /\.(png|jpe?g|gif|webp|bmp|ico|tiff?|emf|wmf|mp3|mp4|m4a|mov|avi|wmv|ogg|zip|gz|woff2?|eot)$/i;
253027
253200
  RAW_FONT_PART_RE = /\.(ttf|otf|odttf)$/i;
253201
+ RSID_ATTR_FOR_FINGERPRINT_RE = /\s+w:rsid\w*="[^"]*"/g;
253202
+ SIMPLE_TRACKED_CHANGE_WRAPPER_OPEN_RE = /<w:(?:ins|del|rPrChange|pPrChange)\b[^>]*>/g;
253203
+ WRAPPER_ID_ATTR_FOR_FINGERPRINT_RE = /\s+w:id="[^"]*"/g;
253028
253204
  SDSourceBackedSaveUnsupportedError = class SDSourceBackedSaveUnsupportedError extends Error {
253029
253205
  constructor(code, partUri, message) {
253030
253206
  super(message);
@@ -357887,6 +358063,16 @@ function collectCellScopes(tableCatalog) {
357887
358063
  function computeComparePackageFingerprint(context) {
357888
358064
  return computeSDDocumentSessionInternalPackageBinding(context.session);
357889
358065
  }
358066
+ function computeCompareSemanticPackageFingerprint(context) {
358067
+ return computeSDDocumentSessionInternalSemanticPackageBinding(context.session);
358068
+ }
358069
+ function resolveComparePlanBindingMatch(context, expectedBinding) {
358070
+ const liveSemanticBinding = computeCompareSemanticPackageFingerprint(context);
358071
+ if (liveSemanticBinding === expectedBinding)
358072
+ return { matched: true, liveSemanticBinding };
358073
+ const liveLegacyBinding = computeComparePackageFingerprint(context);
358074
+ return { matched: liveLegacyBinding === expectedBinding, liveSemanticBinding };
358075
+ }
357890
358076
  var init_fingerprint = __esm(() => {
357891
358077
  init_sd_document_session_internal();
357892
358078
  });
@@ -359771,7 +359957,7 @@ function projectCompareSnapshot(context, posture, options) {
359771
359957
  return {
359772
359958
  version: "sd-compare-snapshot/v1",
359773
359959
  identity: {
359774
- fingerprint: computeComparePackageFingerprint(context),
359960
+ fingerprint: computeCompareSemanticPackageFingerprint(context),
359775
359961
  ...options.label !== undefined ? { label: options.label } : {}
359776
359962
  },
359777
359963
  sourcePosture: posture,
@@ -359837,10 +360023,11 @@ function compareOperationId(storyId, ordinal) {
359837
360023
  function applyComparePlan(context, plan, options = {}) {
359838
360024
  const reviewMarkup = options.reviewMarkup !== false;
359839
360025
  const changeMode = reviewMarkup ? "tracked" : "direct";
359840
- const liveBinding = computeComparePackageFingerprint(context);
359841
- if (liveBinding !== plan.planBinding) {
359842
- throw new SDCompareError("PRECONDITION_FAILED", `compare plan is stale: live document binding ${liveBinding} does not match plan binding ${plan.planBinding}.`);
360026
+ const bindingResolution = resolveComparePlanBindingMatch(context, plan.planBinding);
360027
+ if (!bindingResolution.matched) {
360028
+ throw new SDCompareError("PRECONDITION_FAILED", `compare plan is stale: live document binding ${bindingResolution.liveSemanticBinding} ` + `does not match plan binding ${plan.planBinding}.`);
359843
360029
  }
360030
+ const effectivePlanBinding = bindingResolution.liveSemanticBinding;
359844
360031
  let operationOrdinal = plan.bodyOperations.length;
359845
360032
  const storyGroups = (plan.storyOperations ?? []).filter((group) => group.operations.length > 0).map((group) => ({
359846
360033
  storyId: group.storyId,
@@ -359914,7 +360101,7 @@ function applyComparePlan(context, plan, options = {}) {
359914
360101
  tx.compareApply({
359915
360102
  operationId: "v2-compare-apply",
359916
360103
  storyId: mainStoryId,
359917
- planBinding: plan.planBinding,
360104
+ planBinding: effectivePlanBinding,
359918
360105
  changeMode,
359919
360106
  bodySteps,
359920
360107
  ...storyGroups.length > 0 ? {
@@ -363282,7 +363469,8 @@ function buildHeaderFooterLifecyclePlan(base3, target) {
363282
363469
  const after = targetParts.get(partUri);
363283
363470
  const kind = after?.kind ?? before.kind;
363284
363471
  const relationshipsChanged = !headerFooterPartRelationshipsEqual(before?.relationshipsBytes ?? null, after?.relationshipsBytes ?? null);
363285
- const changed = !before || !after || !numbersEqual(before.bytes, after.bytes) || relationshipsChanged;
363472
+ const contentChanged = Boolean(before && after && (before.bytes.length !== after.bytes.length || before.bytes.some((value2, index2) => value2 !== after.bytes[index2])));
363473
+ const changed = !before || !after || contentChanged || relationshipsChanged;
363286
363474
  if (!changed)
363287
363475
  continue;
363288
363476
  if (hasUnsafeRelationshipDependencyChange(before, after, relationshipsChanged)) {
@@ -363299,7 +363487,7 @@ function buildHeaderFooterLifecyclePlan(base3, target) {
363299
363487
  });
363300
363488
  } else if (before && !after) {
363301
363489
  rewrites.push({ family: "header-footer-parts", partUri, kind: "remove" });
363302
- } else if (before && after && !numbersEqual(before.bytes, after.bytes)) {
363490
+ } else if (before && after && contentChanged) {
363303
363491
  contentRewrites.push({
363304
363492
  family: "header-footer-parts",
363305
363493
  partUri,
@@ -364965,6 +365153,17 @@ function isCommentRelationshipSemanticKey(semanticKey) {
364965
365153
  const relType = semanticKey.slice(sep + 1);
364966
365154
  return /\/relationships\/(?:comments|commentsExtended|commentsIds|commentsExtensible|threadedComments|people)$/i.test(relType);
364967
365155
  }
365156
+ function isResolutionSidecarAddition(key2, targetEntry) {
365157
+ if (!targetEntry)
365158
+ return false;
365159
+ if (key2 === "ct:override:/word/commentsExtended.xml") {
365160
+ return targetEntry.semanticKey === key2 && targetEntry.contentSignature === sha256HexSync(TE62.encode("override:/word/commentsExtended.xml=" + "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml"));
365161
+ }
365162
+ if (!key2.startsWith("rel:/word/document.xml|"))
365163
+ return false;
365164
+ const type = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
365165
+ return targetEntry.semanticKey === `/word/document.xml|${type}` && targetEntry.contentSignature === sha256HexSync(TE62.encode(`type:${type}#mode:Internal#target:/word/commentsExtended.xml`));
365166
+ }
364968
365167
  function isCommentScopedPackageKey(context, key2, presentInBase, hasCommentCreate, targetEntry) {
364969
365168
  if (key2.startsWith("ct:")) {
364970
365169
  const uri = key2.slice(key2.indexOf(":", 3) + 1);
@@ -365000,10 +365199,15 @@ function packageGraphKeysNotCoveredByComments(context, base3, target, steps) {
365000
365199
  changedKeys.add(key2);
365001
365200
  const hasCommentCreate = steps.some((s) => s.kind === "create");
365002
365201
  const hasCommentDelete = steps.some((s) => s.kind === "delete");
365202
+ const hasRootResolution = steps.some((s) => s.kind === "set-resolved" && s.resolved && !s.targetIsReply && s.targetParentParaId === null);
365203
+ const addedResolutionSidecarKeys = [...changedKeys].filter((key2) => !baseSigs.has(key2) && targetSigs.has(key2) && isResolutionSidecarAddition(key2, targetEntries.get(key2)));
365204
+ const coversResolutionSidecar = hasRootResolution && addedResolutionSidecarKeys.length === 2 && addedResolutionSidecarKeys.includes("ct:override:/word/commentsExtended.xml");
365003
365205
  const notCovered = [];
365004
365206
  for (const key2 of changedKeys) {
365005
365207
  const presentInBase = baseSigs.has(key2);
365006
365208
  const presentInTarget = targetSigs.has(key2);
365209
+ if (coversResolutionSidecar && addedResolutionSidecarKeys.includes(key2))
365210
+ continue;
365007
365211
  let lifecycleCoversEntry = false;
365008
365212
  if (presentInBase !== presentInTarget) {
365009
365213
  lifecycleCoversEntry = presentInBase ? hasCommentDelete : hasCommentCreate;
@@ -368176,7 +368380,12 @@ class V2DiffAdapter {
368176
368380
  }
368177
368381
  const liveFingerprint = liveSnapshot.identity.fingerprint;
368178
368382
  const expectedBinding = payload.applyPlan.planBinding;
368179
- if (liveFingerprint !== payload.base.identity.fingerprint || liveFingerprint !== expectedBinding) {
368383
+ let bindingsMatch = liveFingerprint === payload.base.identity.fingerprint && liveFingerprint === expectedBinding;
368384
+ if (!bindingsMatch) {
368385
+ const liveLegacyFingerprint = computeComparePackageFingerprint(this.context);
368386
+ bindingsMatch = liveLegacyFingerprint === payload.base.identity.fingerprint && liveLegacyFingerprint === expectedBinding;
368387
+ }
368388
+ if (!bindingsMatch) {
368180
368389
  throw diffValidationError("PRECONDITION_FAILED", `diff.apply: package binding mismatch — current=${liveFingerprint} ` + `expectedBase=${payload.base.identity.fingerprint} planBinding=${expectedBinding}.`, { current: liveFingerprint, expectedBase: payload.base.identity.fingerprint, planBinding: expectedBinding });
368181
368390
  }
368182
368391
  const physicalSourceProblems = [
@@ -370140,6 +370349,7 @@ var init_adapter24 = __esm(() => {
370140
370349
  init_compare();
370141
370350
  init_sd_document_session_internal();
370142
370351
  init_part_fingerprint();
370352
+ init_fingerprint();
370143
370353
  init_section_xml();
370144
370354
  init_adapter23();
370145
370355
  init_header_footer_lifecycle();
@@ -432314,16 +432524,20 @@ function mirrorStoryBlocksFromSession(input) {
432314
432524
  if (!tailBlockId) {
432315
432525
  throw new Error("storyBlocks mirror could not resolve tail paragraph id for paragraphSplit");
432316
432526
  }
432527
+ const context = loadStorySyncContext(input.session, input.storyId);
432528
+ const headPayload = readSessionBlockPayload(context, source.target.paraId);
432529
+ const tailPayload = readSessionBlockPayload(context, tailBlockId);
432317
432530
  if (!findBlockMap(input.doc, tailBlockId)) {
432531
+ const offset = source.coordinateSpace === "tracked" ? parseParagraphXml(headPayload.xml, headPayload.namespaceBindings, trackedWrapperIdentityStateForPayload(headPayload)).visibleText.length : source.offset;
432318
432532
  splitBlock({
432319
432533
  doc: input.doc,
432320
432534
  blockId: source.target.paraId,
432321
- offset: source.offset,
432535
+ offset,
432322
432536
  tailBlockId,
432323
432537
  origin: STORY_SURFACE_BACKEND_ORIGIN
432324
432538
  });
432325
432539
  }
432326
- syncBlocksFromSession(input.session, input.storyId, input.doc, [source.target.paraId, tailBlockId]);
432540
+ syncBlockPayloads(input.doc, [headPayload, tailPayload]);
432327
432541
  writeParagraphMembershipTableOverlaysFromSession(input.session, input.prepared, input.storyId, input.doc, [source.target.paraId, tailBlockId], "paragraph.split");
432328
432542
  return;
432329
432543
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc/mcp",
3
- "version": "1.3.0-next.11",
3
+ "version": "1.3.0-next.13",
4
4
  "description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -24,13 +24,13 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "@modelcontextprotocol/sdk": "^1.26.0",
27
- "@superdoc/sdk": "2.16.0-next.11",
27
+ "@superdoc/sdk": "2.16.0-next.13",
28
28
  "debug": "^4.4.3",
29
29
  "zod": "^4.3.6"
30
30
  },
31
31
  "devDependencies": {
32
- "superdoc": "2.19.0-next.10",
33
- "@superdoc/docx-engine": "0.18.0-next.10",
32
+ "superdoc": "2.19.0-next.12",
33
+ "@superdoc/docx-engine": "0.18.0-next.12",
34
34
  "@superdoc/document-api": "0.1.0-alpha.0",
35
35
  "@types/bun": "^1.3.8",
36
36
  "@types/node": "22.19.2",