@adeu/core 1.27.0 → 1.29.0
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.
- package/dist/index.cjs +696 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -2
- package/dist/index.d.ts +63 -2
- package/dist/index.js +696 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/diff.test.ts +8 -1
- package/src/diff.ts +242 -3
- package/src/engine.atomic.test.ts +5 -1
- package/src/engine.batch.test.ts +16 -6
- package/src/engine.bugs.test.ts +49 -0
- package/src/engine.tables.test.ts +31 -0
- package/src/engine.ts +443 -66
- package/src/ingest.test.ts +3 -1
- package/src/ingest.ts +35 -5
- package/src/mapper.ts +94 -11
- package/src/repro_agy_bug.test.ts +108 -0
- package/src/repro_qa_mcp_issues_2026_07_20.test.ts +224 -0
- package/src/repro_qa_report_v9.test.ts +392 -0
- package/src/sanitize/core.ts +12 -1
- package/src/sanitize/report.ts +9 -7
- package/src/sanitize/sanitize.test.ts +1 -0
- package/src/sanitize/transforms.ts +39 -0
- package/src/utils/docx.ts +87 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/docx/bridge.ts","../src/docx/dom.ts","../src/docx/primitives.ts","../src/comments.ts","../src/utils/safe-regex.ts","../src/utils/docx.ts","../src/mapper.ts","../src/diff.ts","../src/pagination.ts","../src/markup.ts","../src/utils/text.ts","../src/engine.ts","../src/sanitize/transforms.ts","../src/domain.ts","../src/ingest.ts","../src/outline.ts","../src/sanitize/core.ts","../src/sanitize/report.ts","../src/index.ts"],"sourcesContent":["// FILE: node/packages/core/src/docx/bridge.ts\nimport { unzipSync, zipSync, strFromU8, strToU8 } from \"fflate\";\nimport {\n parseXml,\n findChild,\n findAllDescendants,\n serializeXml,\n} from \"./dom.js\";\n\nexport class Relationship {\n constructor(\n public id: string,\n public type: string,\n public target: string,\n public isExternal: boolean,\n ) {}\n}\n\nexport class Part {\n public rels: Map<string, Relationship> = new Map();\n public _element: Element;\n public package?: DocxPackage;\n constructor(\n public partname: string,\n public blob: string,\n element: Element,\n public contentType: string,\n ) {\n this._element = element;\n }\n\n public addRelationship(\n id: string,\n type: string,\n target: string,\n isExternal: boolean = false,\n ) {\n this.rels.set(id, new Relationship(id, type, target, isExternal));\n\n // Directly append the relationship element to the document structure\n if (this.partname.endsWith(\".rels\")) {\n const doc = this._element.ownerDocument;\n if (doc) {\n // Use strict namespace to ensure it parses successfully on reload\n const relEl = doc.createElementNS(\n \"http://schemas.openxmlformats.org/package/2006/relationships\",\n \"Relationship\",\n );\n relEl.setAttribute(\"Id\", id);\n relEl.setAttribute(\"Type\", type);\n relEl.setAttribute(\"Target\", target);\n if (isExternal) relEl.setAttribute(\"TargetMode\", \"External\");\n this._element.appendChild(relEl);\n }\n }\n }\n}\n\nexport class DocxPackage {\n public parts: Part[] = [];\n public mainDocumentPart!: Part;\n\n constructor(public unzipped: Record<string, Uint8Array>) {}\n\n public getPartByPath(path: string): Part | undefined {\n // Strip leading slash for zip compat\n const searchPath = path.startsWith(\"/\") ? path.substring(1) : path;\n return this.parts.find(\n (p) => p.partname === searchPath || p.partname === \"/\" + searchPath,\n );\n }\n\n public nextPartname(pattern: string): string {\n let i = 1;\n while (true) {\n const candidate = pattern.replace(\"%d\", i === 1 ? \"\" : i.toString());\n if (!this.getPartByPath(candidate)) return candidate;\n i++;\n }\n }\n\n public addPart(\n partname: string,\n contentType: string,\n xmlString: string,\n ): Part {\n const doc = parseXml(xmlString);\n const part = new Part(\n partname,\n xmlString,\n doc.documentElement,\n contentType,\n );\n part.package = this;\n this.parts.push(part);\n\n // Update [Content_Types].xml\n const ctPart = this.getPartByPath(\"[Content_Types].xml\");\n if (ctPart) {\n const docCT = ctPart._element.ownerDocument;\n if (docCT) {\n const override = docCT.createElement(\"Override\");\n override.setAttribute(\"PartName\", partname);\n override.setAttribute(\"ContentType\", contentType);\n ctPart._element.appendChild(override);\n }\n }\n return part;\n }\n\n public getOrCreateRelsPart(sourcePartname: string): Part {\n // e.g., /word/document.xml -> /word/_rels/document.xml.rels\n const parts = sourcePartname.split(\"/\");\n const file = parts.pop();\n const relsPath = parts.join(\"/\") + \"/_rels/\" + file + \".rels\";\n\n let relsPart = this.getPartByPath(relsPath);\n if (!relsPart) {\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"></Relationships>`;\n relsPart = this.addPart(\n relsPath,\n \"application/vnd.openxmlformats-package.relationships+xml\",\n xml,\n );\n }\n return relsPart;\n }\n}\n\nexport class DocumentObject {\n public part: Part;\n public settings: { oddAndEvenPagesHeaderFooter: boolean } = {\n oddAndEvenPagesHeaderFooter: false,\n };\n // Simplification for the TS port: sections hold header/footer refs\n public sections: any[] = [];\n\n constructor(\n public pkg: DocxPackage,\n part: Part,\n ) {\n this.part = part;\n }\n\n public get element(): Element {\n return findChild(this.part._element, \"w:body\") || this.part._element;\n }\n\n /**\n * Main entrypoint for loading a DOCX buffer into the DOM wrapper.\n */\n public static async load(\n buffer: Buffer | ArrayBuffer,\n ): Promise<DocumentObject> {\n const u8 = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n const unzipped = unzipSync(u8);\n const pkg = new DocxPackage(unzipped);\n\n // 1. Load Content Types\n const ctFile = unzipped[\"[Content_Types].xml\"];\n let contentTypes: Record<string, string> = {};\n if (ctFile) {\n const ctXml = parseXml(strFromU8(ctFile));\n const overrides = findAllDescendants(ctXml.documentElement, \"Override\");\n for (const override of overrides) {\n contentTypes[override.getAttribute(\"PartName\") || \"\"] =\n override.getAttribute(\"ContentType\") || \"\";\n }\n }\n\n // 2. Pre-load all XML parts to allow synchronous traversal later\n for (const [path, fileData] of Object.entries(unzipped)) {\n if (path.endsWith(\".xml\") || path.endsWith(\".rels\")) {\n const text = strFromU8(fileData);\n const doc = parseXml(text);\n const cType = contentTypes[\"/\" + path] || \"application/xml\";\n const part = new Part(\"/\" + path, text, doc.documentElement, cType);\n part.package = pkg;\n pkg.parts.push(part);\n }\n }\n\n // 3. Resolve Relationships for the main document\n const mainPart = pkg.getPartByPath(\"word/document.xml\");\n if (!mainPart) throw new Error(\"Invalid DOCX: Missing word/document.xml\");\n pkg.mainDocumentPart = mainPart;\n\n const relsPart = pkg.getPartByPath(\"word/_rels/document.xml.rels\");\n if (relsPart) {\n const relElements = findAllDescendants(relsPart._element, \"Relationship\");\n for (const rel of relElements) {\n const rId = rel.getAttribute(\"Id\");\n const target = rel.getAttribute(\"Target\");\n const type = rel.getAttribute(\"Type\");\n const targetMode = rel.getAttribute(\"TargetMode\");\n\n if (rId && target && type) {\n mainPart.rels.set(\n rId,\n new Relationship(rId, type, target, targetMode === \"External\"),\n );\n }\n }\n }\n\n return new DocumentObject(pkg, mainPart);\n }\n\n public relateTo(part: Part, relType: string) {\n let rId = 1;\n while (this.part.rels.has(`rId${rId}`)) rId++;\n const id = `rId${rId}`;\n\n // In DOCX, targets in .rels are relative to the source part's directory.\n // /word/document.xml relating to /word/comments.xml -> target is \"comments.xml\"\n const target = part.partname.split(\"/\").pop()!;\n\n this.part.rels.set(id, new Relationship(id, relType, target, false));\n const relsPart = this.pkg.getOrCreateRelsPart(this.part.partname);\n relsPart.addRelationship(id, relType, target, false);\n }\n\n public relateToExternal(target: string, relType: string): string {\n let rId = 1;\n while (this.part.rels.has(`rId${rId}`)) rId++;\n const id = `rId${rId}`;\n\n this.part.rels.set(id, new Relationship(id, relType, target, true));\n const relsPart = this.pkg.getOrCreateRelsPart(this.part.partname);\n relsPart.addRelationship(id, relType, target, true);\n return id;\n }\n\n public async save(): Promise<Buffer> {\n for (const part of this.pkg.parts) {\n let xmlStr = serializeXml(part._element.ownerDocument || part._element);\n // Lazily declare the w16du namespace on any part that picked up a\n // tracked change (w16du:dateUtc) without a root declaration — a\n // tracked edit in a header/footer/footnotes part would otherwise\n // serialize an undeclared prefix no parser (including ours) accepts.\n // Unmodified parts never contain \"w16du:\" and stay untouched.\n // Mirrors the Python engine's _inject_w16du_if_needed at save time.\n if (xmlStr.includes(\"w16du:\") && !xmlStr.includes(\"xmlns:w16du=\")) {\n part._element.setAttribute(\n \"xmlns:w16du\",\n \"http://schemas.microsoft.com/office/word/2023/wordml/word16du\",\n );\n xmlStr = serializeXml(part._element.ownerDocument || part._element);\n }\n if (!xmlStr.startsWith(\"<?xml\")) {\n xmlStr =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n' + xmlStr;\n }\n this.pkg.unzipped[part.partname.substring(1)] = strToU8(xmlStr); // Strip leading slash\n }\n return Buffer.from(zipSync(this.pkg.unzipped));\n }\n}\n","import { DOMParser, XMLSerializer } from \"@xmldom/xmldom\";\n\n/**\n * Simulates docx.oxml.ns.qn. In xmldom, namespaces are preserved in tagName.\n */\nexport const qn = (name: string) => name;\n\n/**\n * Simulates lxml element.find(\"w:tag\") - strictly searches DIRECT children only.\n */\nexport function findChild(element: Element, tagName: string): Element | null {\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n if (\n child.nodeType === 1 /* ELEMENT_NODE */ &&\n (child as Element).tagName === tagName\n ) {\n return child as Element;\n }\n }\n return null;\n}\n\n/**\n * Simulates lxml element.findall(\"w:tag\") - strictly searches DIRECT children only.\n */\nexport function findChildren(element: Element, tagName: string): Element[] {\n const result: Element[] = [];\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n if (child.nodeType === 1 && (child as Element).tagName === tagName) {\n result.push(child as Element);\n }\n }\n return result;\n}\n\n/**\n * Simulates lxml element.findall(\".//w:tag\") - searches ALL descendants.\n */\nexport function findAllDescendants(\n element: Element,\n tagName: string,\n): Element[] {\n return Array.from(element.getElementsByTagName(tagName));\n}\n\n/**\n * Parses raw XML strings into xmldom Documents.\n */\nexport function parseXml(xmlString: string): Document {\n // Strip UTF-8 BOM if present\n if (xmlString.startsWith(\"\\uFEFF\")) {\n xmlString = xmlString.slice(1);\n }\n return new DOMParser().parseFromString(xmlString, \"text/xml\") as unknown as Document;\n}\n\n/**\n * Serializes an xmldom Document or Element back to a string,\n * enforcing deterministic attribute ordering on the root element.\n */\nexport function serializeXml(node: Node): string {\n let xml = new XMLSerializer().serializeToString(node as any);\n\n // BUG-11: Deterministic namespace ordering on root elements.\n const rootTagRegex = /<([a-zA-Z0-9_:]+)(\\s+[^>]+?)(>|\\/>)/;\n const match = rootTagRegex.exec(xml);\n\n if (match && !match[1].startsWith(\"?\")) {\n const index = match.index;\n const textBefore = xml.substring(0, index);\n\n // Ensure this is the absolute root tag (only <?xml...?> allowed before it)\n const isRoot =\n !textBefore.includes(\"<\") ||\n (textBefore.trim().startsWith(\"<?xml\") &&\n (textBefore.match(/</g) || []).length === 1);\n\n if (isRoot) {\n const fullTag = match[0];\n const elemStart = `<${match[1]}`;\n const attrsStr = match[2];\n const tagEnd = match[3];\n\n // Robust extraction matching any quote style and internal spacing\n const attrRegex = /([a-zA-Z0-9_:]+)\\s*=\\s*([\"'])(.*?)\\2/g;\n const attrs: string[] = [];\n let m;\n while ((m = attrRegex.exec(attrsStr)) !== null) {\n attrs.push(m[0].trim());\n }\n\n // Sort attributes: xmlns definitions first, then standard attributes\n attrs.sort((a, b) => {\n const aName = a.split(\"=\")[0].trim();\n const bName = b.split(\"=\")[0].trim();\n const aIsXmlns = aName.startsWith(\"xmlns\");\n const bIsXmlns = bName.startsWith(\"xmlns\");\n if (aIsXmlns && !bIsXmlns) return -1;\n if (!aIsXmlns && bIsXmlns) return 1;\n return aName < bName ? -1 : aName > bName ? 1 : 0;\n });\n\n const newTag =\n attrs.length > 0\n ? `${elemStart} ${attrs.join(\" \")}${tagEnd}`\n : `${elemStart}${tagEnd}`;\n xml =\n xml.substring(0, index) +\n newTag +\n xml.substring(index + fullTag.length);\n }\n }\n\n return xml;\n}\n","import { findChild } from './dom.js';\n\nexport class Paragraph {\n constructor(public _element: Element, public _parent: any) {}\n \n get text(): string {\n let t = '';\n const texts = this._element.getElementsByTagName('w:t');\n for (let i = 0; i < texts.length; i++) {\n t += texts[i].textContent || '';\n }\n return t;\n }\n}\n\nexport class Run {\n constructor(public _element: Element, public _parent: any) {}\n}\n\nexport class Cell {\n constructor(public _element: Element, public _parent: any) {}\n}\n\nexport class Row {\n public cells: Cell[] = [];\n constructor(public _element: Element, public _parent: any) {\n const tcs = this._element.getElementsByTagName('w:tc');\n for (let i = 0; i < tcs.length; i++) {\n this.cells.push(new Cell(tcs[i], this));\n }\n }\n}\n\nexport class Table {\n public rows: Row[] = [];\n constructor(public _element: Element, public _parent: any) {\n const trs = this._element.getElementsByTagName('w:tr');\n for (let i = 0; i < trs.length; i++) {\n this.rows.push(new Row(trs[i], this));\n }\n }\n}\n\nexport class NotesPart {\n public _element: Element;\n constructor(public part: any, public note_type: 'fn' | 'en') {\n this._element = part._element;\n }\n}\n\nexport class FootnoteItem {\n public id: string;\n public part: any;\n constructor(public _element: Element, public _parent: any, public note_type: 'fn' | 'en') {\n this.id = _element.getAttribute('w:id') || '';\n this.part = _parent.part;\n }\n}\n\nexport interface DocxEvent {\n type: string;\n id: string;\n author?: string;\n date?: string;\n}","import { DocxPackage, Part, DocumentObject } from './docx/bridge.js';\nimport { findAllDescendants, findChild, parseXml } from './docx/dom.js';\n\nconst NS = {\n w: 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',\n w14: 'http://schemas.microsoft.com/office/word/2010/wordml',\n w15: 'http://schemas.microsoft.com/office/word/2012/wordml',\n w16cid: 'http://schemas.microsoft.com/office/word/2016/wordml/cid',\n w16cex: 'http://schemas.microsoft.com/office/word/2018/wordml/cex',\n mc: 'http://schemas.openxmlformats.org/markup-compatibility/2006'\n};\n\nconst CT = {\n COMMENTS: 'application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml',\n EXTENDED: 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml',\n IDS: 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml',\n EXTENSIBLE: 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtensible+xml'\n};\n\nconst RT = {\n COMMENTS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments',\n EXTENDED: 'http://schemas.microsoft.com/office/2011/relationships/commentsExtended',\n IDS: 'http://schemas.microsoft.com/office/2016/09/relationships/commentsIds',\n EXTENSIBLE: 'http://schemas.microsoft.com/office/2018/08/relationships/commentsExtensible'\n};\n\nexport class CommentsManager {\n private _commentsPart: Part | null = null;\n private _extendedPart: Part | null = null;\n private _idsPart: Part | null = null;\n private _extensiblePart: Part | null = null;\n private _nextId: number | null = null;\n\n constructor(public doc: DocumentObject) {}\n\n public get commentsPart(): Part {\n if (!this._commentsPart) {\n this._commentsPart = this._getOrCreateCommentsPart();\n this._ensureNamespaces();\n }\n return this._commentsPart!;\n }\n\n public get extendedPart(): Part {\n if (!this._extendedPart) this._extendedPart = this._getOrCreateExtendedPart();\n return this._extendedPart!;\n }\n\n public get idsPart(): Part {\n if (!this._idsPart) this._idsPart = this._getOrCreateIdsPart();\n return this._idsPart!;\n }\n\n public get extensiblePart(): Part {\n if (!this._extensiblePart) this._extensiblePart = this._getOrCreateExtensiblePart();\n return this._extensiblePart!;\n }\n\n public get nextId(): number {\n if (this._nextId === null) this._nextId = this._getNextCommentId();\n return this._nextId;\n }\n\n public set nextId(value: number) {\n this._nextId = value;\n }\n\n private _getExistingPartByType(contentType: string): Part | null {\n return this.doc.pkg.parts.find(p => p.contentType === contentType) || null;\n }\n\n private _linkPart(part: Part, relType: string): Part {\n for (const rel of this.doc.part.rels.values()) {\n if (!rel.isExternal && rel.target === part.partname.split('/').pop()) {\n return part;\n }\n }\n this.doc.relateTo(part, relType);\n return part;\n }\n\n private _getOrCreateCommentsPart(): Part {\n let part = this._getExistingPartByType(CT.COMMENTS);\n if (part) return this._linkPart(part, RT.COMMENTS);\n\n const partname = this.doc.pkg.nextPartname('/word/comments%d.xml');\n const xml = `<w:comments xmlns:w=\"${NS.w}\" xmlns:w14=\"${NS.w14}\" xmlns:w15=\"${NS.w15}\" xmlns:w16cid=\"${NS.w16cid}\" xmlns:w16cex=\"${NS.w16cex}\" xmlns:mc=\"${NS.mc}\" mc:Ignorable=\"w14 w15 w16cid w16cex\"></w:comments>`;\n part = this.doc.pkg.addPart(partname, CT.COMMENTS, xml);\n this.doc.relateTo(part, RT.COMMENTS);\n return part;\n }\n\n private _getOrCreateExtendedPart(): Part {\n let part = this._getExistingPartByType(CT.EXTENDED);\n if (part) return this._linkPart(part, RT.EXTENDED);\n\n const partname = this.doc.pkg.nextPartname('/word/commentsExtended%d.xml');\n const xml = `<w15:commentsEx xmlns:w15=\"${NS.w15}\"></w15:commentsEx>`;\n part = this.doc.pkg.addPart(partname, CT.EXTENDED, xml);\n this.doc.relateTo(part, RT.EXTENDED);\n return part;\n }\n\n private _getOrCreateIdsPart(): Part {\n let part = this._getExistingPartByType(CT.IDS);\n if (part) return this._linkPart(part, RT.IDS);\n\n const partname = this.doc.pkg.nextPartname('/word/commentsIds%d.xml');\n const xml = `<w16cid:commentsIds xmlns:w16cid=\"${NS.w16cid}\"></w16cid:commentsIds>`;\n part = this.doc.pkg.addPart(partname, CT.IDS, xml);\n this.doc.relateTo(part, RT.IDS);\n return part;\n }\n\n private _getOrCreateExtensiblePart(): Part {\n let part = this._getExistingPartByType(CT.EXTENSIBLE);\n if (part) return this._linkPart(part, RT.EXTENSIBLE);\n\n const partname = this.doc.pkg.nextPartname('/word/commentsExtensible%d.xml');\n const xml = `<w16cex:commentsExtensible xmlns:w16cex=\"${NS.w16cex}\"></w16cex:commentsExtensible>`;\n part = this.doc.pkg.addPart(partname, CT.EXTENSIBLE, xml);\n this.doc.relateTo(part, RT.EXTENSIBLE);\n return part;\n }\n\n private _ensureNamespaces() {\n // When the comments part already existed (e.g. a legacy or pandoc-produced\n // document) its root <w:comments> may omit the namespaces we rely on —\n // most importantly w14, which qualifies the w14:paraId / w14:textId\n // attributes we write on each comment paragraph. Without the declaration\n // the serialised XML is invalid (\"Namespace prefix w14 ... is not defined\").\n // Declare any missing namespace prefixes on the existing root element.\n const root = this._commentsPart?._element;\n if (!root) return;\n\n const required: [string, string][] = [\n ['xmlns:w', NS.w],\n ['xmlns:w14', NS.w14],\n ['xmlns:w15', NS.w15],\n ['xmlns:w16cid', NS.w16cid],\n ['xmlns:w16cex', NS.w16cex],\n ['xmlns:mc', NS.mc],\n ];\n for (const [attr, uri] of required) {\n if (!root.getAttribute(attr)) {\n root.setAttribute(attr, uri);\n }\n }\n }\n\n private _getNextCommentId(): number {\n const ids = [0];\n const part = this._getExistingPartByType(CT.COMMENTS);\n if (part) {\n const comments = findAllDescendants(part._element, 'w:comment');\n for (const c of comments) {\n const idStr = c.getAttribute('w:id');\n if (idStr) ids.push(parseInt(idStr, 10) || 0);\n }\n }\n return Math.max(...ids) + 1;\n }\n\n private _generateHexId(): string {\n return Math.floor(Math.random() * 0xFFFFFFFF).toString(16).toUpperCase().padStart(8, '0');\n }\n\n private _getInitials(author: string): string {\n if (!author) return '';\n return author.split(' ').filter(Boolean).map(p => p[0]).join('').toUpperCase();\n }\n\n private _findParaIdForComment(commentId: string): string | null {\n if (!this._commentsPart) return null;\n for (const c of findAllDescendants(this._commentsPart._element, 'w:comment')) {\n if (c.getAttribute('w:id') === commentId) {\n for (const p of findAllDescendants(c, 'w:p')) {\n const pid = p.getAttribute('w14:paraId');\n if (pid) return pid;\n }\n }\n }\n return null;\n }\n\n private _findThreadRootParaId(commentId: string): string | null {\n const directParaId = this._findParaIdForComment(commentId);\n const extPart = this._getExistingPartByType(CT.EXTENDED);\n if (!directParaId || !extPart) return directParaId;\n\n for (let i = 0; i < extPart._element.childNodes.length; i++) {\n const child = extPart._element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n if (child.getAttribute('w15:paraId') === directParaId) {\n const parent = child.getAttribute('w15:paraIdParent');\n if (parent) return parent;\n }\n }\n return directParaId;\n }\n\n public addComment(author: string, text: string, parentId: string | null = null): string {\n const commentId = this.nextId.toString();\n this.nextId++;\n const now = new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n\n const doc = this.commentsPart._element.ownerDocument!;\n const comment = doc.createElement('w:comment');\n comment.setAttribute('w:id', commentId);\n comment.setAttribute('w:author', author);\n comment.setAttribute('w:date', now);\n \n const initials = this._getInitials(author);\n if (initials) comment.setAttribute('w:initials', initials);\n\n const extPart = this._getExistingPartByType(CT.EXTENDED);\n if (parentId && !extPart) {\n comment.setAttribute('w15:p', parentId);\n }\n\n const paraId = this._generateHexId();\n const rsid = this._generateHexId();\n\n const p = doc.createElement('w:p');\n p.setAttribute('w14:paraId', paraId);\n p.setAttribute('w14:textId', '77777777');\n p.setAttribute('w:rsidR', rsid);\n p.setAttribute('w:rsidRDefault', rsid);\n p.setAttribute('w:rsidP', rsid);\n\n const pPr = doc.createElement('w:pPr');\n const pStyle = doc.createElement('w:pStyle');\n pStyle.setAttribute('w:val', 'CommentText');\n pPr.appendChild(pStyle);\n p.appendChild(pPr);\n\n const rRef = doc.createElement('w:r');\n const rPrRef = doc.createElement('w:rPr');\n const rStyleRef = doc.createElement('w:rStyle');\n rStyleRef.setAttribute('w:val', 'CommentReference');\n rPrRef.appendChild(rStyleRef);\n rRef.appendChild(rPrRef);\n rRef.appendChild(doc.createElement('w:annotationRef'));\n p.appendChild(rRef);\n\n const r = doc.createElement('w:r');\n const t = doc.createElement('w:t');\n t.textContent = text;\n r.appendChild(t);\n p.appendChild(r);\n comment.appendChild(p);\n\n this.commentsPart._element.appendChild(comment);\n\n if (this.extendedPart) {\n const parentParaId = parentId ? this._findThreadRootParaId(parentId) : null;\n const exDoc = this.extendedPart._element.ownerDocument!;\n const commentEx = exDoc.createElement('w15:commentEx');\n commentEx.setAttribute('w15:paraId', paraId);\n if (parentParaId) commentEx.setAttribute('w15:paraIdParent', parentParaId);\n commentEx.setAttribute('w15:done', '0');\n this.extendedPart._element.appendChild(commentEx);\n }\n\n if (this.idsPart) {\n const idsDoc = this.idsPart._element.ownerDocument!;\n const commentIdEl = idsDoc.createElement('w16cid:commentId');\n commentIdEl.setAttribute('w16cid:paraId', paraId);\n commentIdEl.setAttribute('w16cid:durableId', this._generateHexId());\n this.idsPart._element.appendChild(commentIdEl);\n }\n\n if (this.extensiblePart) {\n let durableId: string | null = null;\n for (let i = 0; i < this.idsPart._element.childNodes.length; i++) {\n const child = this.idsPart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w16cid:paraId') === paraId) {\n durableId = child.getAttribute('w16cid:durableId');\n break;\n }\n }\n if (durableId) {\n const cexDoc = this.extensiblePart._element.ownerDocument!;\n const extEl = cexDoc.createElement('w16cex:commentExtensible');\n extEl.setAttribute('w16cex:durableId', durableId);\n extEl.setAttribute('w16cex:dateUtc', now);\n this.extensiblePart._element.appendChild(extEl);\n }\n }\n\n return commentId;\n }\n\n public deleteComment(commentId: string) {\n if (!this.commentsPart) return;\n\n let commentEl: Element | null = null;\n for (const c of findAllDescendants(this.commentsPart._element, 'w:comment')) {\n if (c.getAttribute('w:id') === commentId) {\n commentEl = c;\n break;\n }\n }\n\n if (!commentEl) return;\n\n let paraId: string | null = null;\n for (const p of findAllDescendants(commentEl, 'w:p')) {\n const pid = p.getAttribute('w14:paraId');\n if (pid) {\n paraId = pid;\n break;\n }\n }\n\n if (paraId) {\n const repliesToDelete: string[] = [];\n if (this.extendedPart) {\n for (let i = 0; i < this.extendedPart._element.childNodes.length; i++) {\n const child = this.extendedPart._element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n \n if (child.getAttribute('w15:paraIdParent') === paraId) {\n const childParaId = child.getAttribute('w15:paraId');\n if (childParaId) {\n for (const c of findAllDescendants(this.commentsPart._element, 'w:comment')) {\n for (const p of findAllDescendants(c, 'w:p')) {\n if (p.getAttribute('w14:paraId') === childParaId) {\n const cid = c.getAttribute('w:id');\n if (cid) repliesToDelete.push(cid);\n break;\n }\n }\n }\n }\n }\n }\n }\n\n for (const repId of repliesToDelete) {\n this.deleteComment(repId);\n }\n\n let durableId: string | null = null;\n\n if (this.idsPart) {\n const toRemove: Element[] = [];\n for (let i = 0; i < this.idsPart._element.childNodes.length; i++) {\n const child = this.idsPart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w16cid:paraId') === paraId) {\n durableId = child.getAttribute('w16cid:durableId');\n toRemove.push(child);\n }\n }\n toRemove.forEach(c => this.idsPart!._element.removeChild(c));\n }\n\n if (this.extendedPart) {\n const toRemove: Element[] = [];\n for (let i = 0; i < this.extendedPart._element.childNodes.length; i++) {\n const child = this.extendedPart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w15:paraId') === paraId) {\n toRemove.push(child);\n }\n }\n toRemove.forEach(c => this.extendedPart!._element.removeChild(c));\n }\n\n if (durableId && this.extensiblePart) {\n const toRemove: Element[] = [];\n for (let i = 0; i < this.extensiblePart._element.childNodes.length; i++) {\n const child = this.extensiblePart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w16cex:durableId') === durableId) {\n toRemove.push(child);\n }\n }\n toRemove.forEach(c => this.extensiblePart!._element.removeChild(c));\n }\n }\n\n if (commentEl.parentNode) {\n commentEl.parentNode.removeChild(commentEl);\n }\n }\n}\n\n// Keep the global extraction function matching Python behavior\nexport function extract_comments_data(pkg: DocxPackage): Record<string, any> {\n // Temporary bridge to use the new class\n const docObj = {\n pkg,\n part: pkg.mainDocumentPart,\n relateTo: () => {} // Mock since extraction is read-only\n } as unknown as DocumentObject;\n \n const mgr = new CommentsManager(docObj);\n const data: Record<string, any> = {};\n \n const part = pkg.parts.find(p => p.contentType === CT.COMMENTS);\n if (!part) return data;\n\n const para_id_to_cid: Record<string, string> = {};\n const comments = findAllDescendants(part._element, 'w:comment');\n\n for (const c of comments) {\n const c_id = c.getAttribute('w:id');\n if (!c_id) continue;\n\n const c_author = c.getAttribute('w:author') || 'Unknown';\n const c_date = c.getAttribute('w:date') || '';\n \n let is_resolved = false;\n const val = c.getAttribute('w15:done');\n if (val === '1' || val === 'true' || val === 'on') is_resolved = true;\n\n let parent_id = c.getAttribute('w15:p') || null;\n\n const p_elems = findAllDescendants(c, 'w:p');\n for (const p of p_elems) {\n const pid = p.getAttribute('w14:paraId');\n if (pid) para_id_to_cid[pid] = c_id;\n }\n\n const text_parts: string[] = [];\n for (const p of p_elems) {\n const t_elems = findAllDescendants(p, 'w:t');\n for (const t of t_elems) {\n if (t.textContent) text_parts.push(t.textContent);\n }\n text_parts.push('\\n');\n }\n const full_text = text_parts.join('').trim();\n\n data[c_id] = {\n author: c_author,\n text: full_text,\n date: c_date,\n resolved: is_resolved,\n parent_id: parent_id,\n };\n }\n\n const extPart = pkg.parts.find(p => p.contentType === CT.EXTENDED);\n if (extPart) {\n const children = extPart._element.childNodes;\n for (let i = 0; i < children.length; i++) {\n const child = children[i] as Element;\n if (child.nodeType !== 1) continue;\n\n const para_id = child.getAttribute('w15:paraId');\n const parent_para_id = child.getAttribute('w15:paraIdParent');\n const done_val = child.getAttribute('w15:done');\n\n if (para_id) {\n const c_id = para_id_to_cid[para_id];\n if (c_id && data[c_id]) {\n if (parent_para_id) {\n const p_id = para_id_to_cid[parent_para_id];\n if (p_id) data[c_id].parent_id = p_id;\n }\n if (done_val === '1' || done_val === 'true' || done_val === 'on') {\n data[c_id].resolved = true;\n }\n }\n }\n }\n }\n\n return data;\n}","// FILE: src/utils/safe-regex.ts\n/**\n * Time-budgeted execution of USER/LLM-supplied regular expressions.\n *\n * `regex: true` on a ModifyText edit and `search_regex` on read_docx hand an\n * LLM-controlled pattern to V8's backtracking engine. A pathological pattern\n * like `(a|a)*$` against a run of repeated characters hangs the event loop\n * indefinitely (QA 2026-07-17 F5 — ReDoS; mirrors the Python fix).\n *\n * JS regexes cannot be interrupted in-thread, but V8 CAN interrupt regex\n * execution running inside a `vm` context with a `timeout` — that is the\n * mechanism used here. `node:vm` is a builtin, preserving the zero-dependency\n * bundle constraint.\n *\n * Only USER-SUPPLIED patterns belong here. The engine's own generated\n * patterns (fuzzy matchers etc.) are built to be linear-time.\n */\n\nimport * as vm from \"node:vm\";\n\nexport const USER_PATTERN_TIMEOUT_MS = 2000;\n\nexport class RegexTimeoutError extends Error {\n public pattern: string;\n constructor(pattern: string) {\n super(\n `Regular expression exceeded the ${USER_PATTERN_TIMEOUT_MS / 1000}s matching time budget ` +\n `(catastrophic backtracking). Simplify the pattern — nested quantifiers like (a+)+ ` +\n `are the usual cause — or use a literal target instead.`,\n );\n this.name = \"RegexTimeoutError\";\n this.pattern = pattern;\n }\n}\n\nfunction runBudgeted<T>(pattern: string, script: string, sandbox: object): T {\n try {\n return vm.runInNewContext(script, sandbox, {\n timeout: USER_PATTERN_TIMEOUT_MS,\n }) as T;\n } catch (e: any) {\n if (e && e.code === \"ERR_SCRIPT_EXECUTION_TIMEOUT\") {\n throw new RegexTimeoutError(pattern);\n }\n throw e;\n }\n}\n\n/**\n * All non-overlapping matches of a user pattern, under the wall-clock budget.\n * Invalid patterns throw SyntaxError exactly like `new RegExp(...)` would.\n * The budget covers the ENTIRE scan, not just the first match.\n */\nexport function userFindAllMatches(\n pattern: string,\n text: string,\n flags: string = \"\",\n): Array<{ start: number; end: number }> {\n const normalized = flags.includes(\"g\") ? flags : flags + \"g\";\n const re = new RegExp(pattern, normalized); // throws SyntaxError on bad pattern\n const raw = runBudgeted<Array<{ start: number; end: number }>>(\n pattern,\n `{\n const out = [];\n let m;\n while ((m = re.exec(text)) !== null) {\n out.push({ start: m.index, end: m.index + m[0].length });\n if (m.index === re.lastIndex) re.lastIndex++;\n }\n out;\n }`,\n { re, text },\n );\n // Re-materialize in this realm (vm objects come from another context).\n return raw.map((r) => ({ start: r.start, end: r.end }));\n}\n\n/** First match of a user pattern under the wall-clock budget, or null. */\nexport function userSearch(pattern: string, text: string, flags: string = \"\"): { start: number; end: number } | null {\n const re = new RegExp(pattern, flags.replace(\"g\", \"\"));\n const raw = runBudgeted<{ start: number; end: number } | null>(\n pattern,\n `{\n const m = re.exec(text);\n m ? { start: m.index, end: m.index + m[0].length } : null;\n }`,\n { re, text },\n );\n return raw ? { start: raw.start, end: raw.end } : null;\n}\n","import { qn, findChild, findAllDescendants } from \"../docx/dom.js\";\nimport {\n Paragraph,\n Table,\n Run,\n NotesPart,\n FootnoteItem,\n DocxEvent,\n} from \"../docx/primitives.js\";\n\nexport const QN_W_P = \"w:p\";\nexport const QN_W_R = \"w:r\";\nexport const QN_W_T = \"w:t\";\nexport const QN_W_DELTEXT = \"w:delText\";\nexport const QN_W_TAB = \"w:tab\";\nexport const QN_W_BR = \"w:br\";\nexport const QN_W_CR = \"w:cr\";\nexport const QN_W_RPR = \"w:rPr\";\nexport const QN_W_RPRCHANGE = \"w:rPrChange\";\nexport const QN_W_COMMENTREFERENCE = \"w:commentReference\";\nexport const QN_W_FOOTNOTEREFERENCE = \"w:footnoteReference\";\nexport const QN_W_ENDNOTEREFERENCE = \"w:endnoteReference\";\nexport const QN_W_FLDCHAR = \"w:fldChar\";\nexport const QN_W_FLDCHARTYPE = \"w:fldCharType\";\nexport const QN_W_INSTRTEXT = \"w:instrText\";\nexport const QN_W_INS = \"w:ins\";\nexport const QN_W_DEL = \"w:del\";\nexport const QN_W_ID = \"w:id\";\nexport const QN_W_AUTHOR = \"w:author\";\nexport const QN_W_DATE = \"w:date\";\nexport const QN_W_COMMENTRANGESTART = \"w:commentRangeStart\";\nexport const QN_W_COMMENTRANGEEND = \"w:commentRangeEnd\";\nexport const QN_W_HYPERLINK = \"w:hyperlink\";\nexport const QN_R_ID = \"r:id\";\nexport const QN_W_FLDSIMPLE = \"w:fldSimple\";\nexport const QN_W_INSTR = \"w:instr\";\nexport const QN_W_BOOKMARKSTART = \"w:bookmarkStart\";\nexport const QN_W_NAME = \"w:name\";\nexport const QN_W_SDT = \"w:sdt\";\nexport const QN_W_SMARTTAG = \"w:smartTag\";\nexport const QN_W_SDTCONTENT = \"w:sdtContent\";\nexport const QN_W_B = \"w:b\";\nexport const QN_W_I = \"w:i\";\nexport const QN_W_VAL = \"w:val\";\nexport const QN_W_PPR = \"w:pPr\";\nexport const QN_W_PSTYLE = \"w:pStyle\";\nexport const QN_W_OUTLINELVL = \"w:outlineLvl\";\nexport const QN_W_NUMPR = \"w:numPr\";\nexport const QN_W_NUMID = \"w:numId\";\nexport const QN_W_ILVL = \"w:ilvl\";\nexport const QN_W_DRAWING = \"w:drawing\";\nexport const QN_W_OBJECT = \"w:object\";\nexport const QN_W_PICT = \"w:pict\";\nexport const QN_WP_DOCPR = \"wp:docPr\";\nexport const QN_V_IMAGEDATA = \"v:imagedata\";\nexport const QN_O_TITLE = \"o:title\";\n\nconst _CUSTOM_HEADING_NAME_RE = /Heading[ ]?([1-6])(?![0-9])/;\n\n/**\n * Resolves the DocxPackage owning `obj`, whatever wrapper it is (Part,\n * DocumentObject, Cell/Row/Table/NotesPart chains). Returns null when no\n * package is reachable.\n */\nfunction _resolve_package(obj: any): any {\n let cur = obj;\n const seen = new Set<any>();\n while (cur && !seen.has(cur)) {\n seen.add(cur);\n if (cur.package) return cur.package;\n if (cur.pkg) return cur.pkg;\n if (cur.part && (cur.part.package || cur.part.pkg)) {\n return cur.part.package || cur.part.pkg;\n }\n cur = cur._parent || cur.part || null;\n }\n return null;\n}\n\nexport function _get_style_cache(\n part: any,\n): [Record<string, any>, string | null] {\n const pkg = part.package || part.pkg || (part.part ? part.part.pkg : null);\n if (pkg && pkg._adeu_style_cache) {\n return pkg._adeu_style_cache;\n }\n\n const cache: Record<string, any> = {};\n let default_pstyle: string | null = null;\n const raw_styles: Record<string, any> = {};\n\n const stylesPart = pkg?.getPartByPath(\"word/styles.xml\");\n if (!stylesPart) {\n const result: [Record<string, any>, string | null] = [cache, null];\n if (pkg) pkg._adeu_style_cache = result;\n return result;\n }\n\n const styles = findAllDescendants(stylesPart._element, \"w:style\");\n for (const s of styles) {\n const s_id = s.getAttribute(\"w:styleId\");\n if (!s_id) continue;\n\n const s_type = s.getAttribute(\"w:type\");\n const is_default =\n s.getAttribute(\"w:default\") === \"1\" ||\n s.getAttribute(\"w:default\") === \"true\";\n\n if (s_type === \"paragraph\" && is_default) default_pstyle = s_id;\n\n const name_el = findChild(s, \"w:name\");\n let name = name_el ? name_el.getAttribute(\"w:val\") : s_id;\n\n if (name && typeof name === \"string\") {\n if (name.toLowerCase().startsWith(\"heading\")) {\n name = name.replace(/^heading/i, \"Heading\");\n } else if (name.toLowerCase() === \"title\") {\n name = \"Title\";\n }\n }\n\n const based_on_el = findChild(s, \"w:basedOn\");\n const based_on = based_on_el ? based_on_el.getAttribute(\"w:val\") : null;\n\n let outline_lvl: number | null = null;\n let num_id: string | null = null;\n let num_ilvl: number | null = null;\n const pPr = findChild(s, \"w:pPr\");\n if (pPr) {\n const oLvl = findChild(pPr, \"w:outlineLvl\");\n if (oLvl) {\n const val = oLvl.getAttribute(\"w:val\");\n if (val && /^\\d+$/.test(val)) outline_lvl = parseInt(val, 10);\n }\n // Style-level list binding: Word's built-in \"List Bullet\" /\n // \"List Number\" styles carry <w:numPr> in styles.xml, not on the\n // paragraph. Without this, style-based lists project as plain\n // paragraphs and the agent loses ordered-vs-unordered semantics\n // (QA 2026-07-18 M4).\n const numPr = findChild(pPr, \"w:numPr\");\n if (numPr) {\n const numId_el = findChild(numPr, \"w:numId\");\n if (numId_el) {\n const n_val = numId_el.getAttribute(\"w:val\");\n if (n_val && n_val !== \"0\") num_id = n_val;\n }\n const ilvl_el = findChild(numPr, \"w:ilvl\");\n if (ilvl_el) {\n const i_val = ilvl_el.getAttribute(\"w:val\");\n if (i_val && /^\\d+$/.test(i_val)) num_ilvl = parseInt(i_val, 10);\n }\n }\n }\n\n let bold: boolean | null = null;\n const rPr = findChild(s, \"w:rPr\");\n if (rPr) {\n const b = findChild(rPr, \"w:b\");\n if (b) {\n const val = b.getAttribute(\"w:val\");\n bold = val !== \"0\" && val !== \"false\" && val !== \"off\";\n }\n }\n\n raw_styles[s_id] = {\n name,\n based_on,\n outline_level: outline_lvl,\n bold,\n num_id,\n num_ilvl,\n };\n }\n\n const resolve_style = (s_id: string, visited: Set<string>): any => {\n if (cache[s_id]) return cache[s_id];\n if (visited.has(s_id) || !raw_styles[s_id])\n return {\n name: s_id,\n outline_level: null,\n bold: false,\n num_id: null,\n num_ilvl: null,\n };\n\n visited.add(s_id);\n const raw = raw_styles[s_id];\n const based_on_id = raw.based_on;\n\n let o_lvl = raw.outline_level;\n let bold_val = raw.bold !== null ? raw.bold : false;\n let n_id = raw.num_id;\n let n_ilvl = raw.num_ilvl;\n\n if (based_on_id) {\n const parent = resolve_style(based_on_id, visited);\n if (o_lvl === null) o_lvl = parent.outline_level;\n if (raw.bold === null) bold_val = parent.bold;\n if (n_id === null) n_id = parent.num_id ?? null;\n if (n_ilvl === null) n_ilvl = parent.num_ilvl ?? null;\n }\n\n const resolved = {\n name: raw.name,\n outline_level: o_lvl,\n bold: bold_val,\n num_id: n_id,\n num_ilvl: n_ilvl,\n };\n cache[s_id] = resolved;\n return resolved;\n };\n\n for (const s_id in raw_styles) resolve_style(s_id, new Set());\n\n const result: [Record<string, any>, string | null] = [cache, default_pstyle];\n if (pkg) pkg._adeu_style_cache = result;\n return result;\n}\n\n/**\n * Parses word/numbering.xml once per package into\n * {numId: {ilvl: numFmt}} (e.g. {\"5\": {0: \"decimal\", 1: \"lowerLetter\"}}).\n *\n * Used to distinguish bullet lists from ordered lists in the projection\n * (QA 2026-07-18 M4). Missing part / malformed XML yields an empty cache,\n * which projects every list with the bullet marker (the historical default).\n */\nexport function _get_numbering_cache(\n part: any,\n): Record<string, Record<number, string>> {\n const pkg = _resolve_package(part);\n if (!pkg) return {};\n if (pkg._adeu_numbering_cache) return pkg._adeu_numbering_cache;\n\n const cache: Record<string, Record<number, string>> = {};\n let numbering_root: Element | null = null;\n try {\n const numberingPart = (pkg.parts || []).find((p: any) =>\n String(p.partname).endsWith(\"/numbering.xml\"),\n );\n if (numberingPart) numbering_root = numberingPart._element;\n } catch {\n numbering_root = null;\n }\n\n if (numbering_root) {\n const abstract_fmts: Record<string, Record<number, string>> = {};\n for (const abstract of findAllDescendants(numbering_root, \"w:abstractNum\")) {\n const a_id = abstract.getAttribute(\"w:abstractNumId\");\n if (a_id === null) continue;\n const lvl_map: Record<number, string> = {};\n for (const lvl of findAllDescendants(abstract, \"w:lvl\")) {\n const ilvl_val = lvl.getAttribute(\"w:ilvl\");\n const fmt_el = findChild(lvl, \"w:numFmt\");\n if (ilvl_val !== null && /^-?\\d+$/.test(ilvl_val) && fmt_el) {\n const fmt = fmt_el.getAttribute(\"w:val\");\n if (fmt) lvl_map[parseInt(ilvl_val, 10)] = fmt;\n }\n }\n abstract_fmts[a_id] = lvl_map;\n }\n\n for (const num of findAllDescendants(numbering_root, \"w:num\")) {\n const n_id = num.getAttribute(\"w:numId\");\n const a_ref = findChild(num, \"w:abstractNumId\");\n if (n_id === null || !a_ref) continue;\n const a_id = a_ref.getAttribute(\"w:val\");\n if (a_id !== null && abstract_fmts[a_id] !== undefined) {\n cache[n_id] = abstract_fmts[a_id];\n }\n }\n }\n\n pkg._adeu_numbering_cache = cache;\n return cache;\n}\n\n/**\n * Markdown marker for a list paragraph: '* ' for bullets, '1. ' for every\n * numbered format (Markdown renderers renumber sequentially). Unknown\n * numbering (no numbering.xml entry) keeps the historical '* '.\n */\nexport function get_list_marker(\n paragraph_part: any,\n num_id: string | null,\n ilvl: number,\n): string {\n let fmt: string | null = null;\n if (num_id !== null && num_id !== undefined) {\n const lvl_map = _get_numbering_cache(paragraph_part)[num_id];\n if (lvl_map && Object.keys(lvl_map).length > 0) {\n fmt = lvl_map[ilvl] !== undefined ? lvl_map[ilvl] : null;\n if (fmt === null) {\n // Fall back to the nearest defined level at or below ilvl.\n for (let lookup = ilvl; lookup >= 0; lookup--) {\n if (lvl_map[lookup] !== undefined) {\n fmt = lvl_map[lookup];\n break;\n }\n }\n }\n }\n }\n if (fmt !== null && fmt !== \"bullet\") return \"1. \";\n return \"* \";\n}\n\nfunction _detect_heading_level_from_name(name: string): number | null {\n if (!name) return null;\n const match = name.match(_CUSTOM_HEADING_NAME_RE);\n return match ? parseInt(match[1], 10) : null;\n}\n\nexport function is_native_heading(\n paragraph: Paragraph,\n style_cache?: Record<string, any>,\n default_pstyle?: string | null,\n): boolean {\n if (!style_cache) {\n [style_cache, default_pstyle] = _get_style_cache(\n paragraph._parent.part || paragraph._parent,\n );\n }\n const pPr = findChild(paragraph._element, QN_W_PPR);\n\n if (pPr) {\n const oLvl = findChild(pPr, QN_W_OUTLINELVL);\n if (oLvl) {\n const val = oLvl.getAttribute(QN_W_VAL);\n if (val && /^\\d+$/.test(val)) {\n const lvl = parseInt(val, 10);\n if (lvl >= 0 && lvl <= 8) return true;\n }\n }\n }\n\n let style_id = default_pstyle;\n if (pPr) {\n const pStyle = findChild(pPr, QN_W_PSTYLE);\n if (pStyle) style_id = pStyle.getAttribute(QN_W_VAL) || default_pstyle;\n }\n\n const style_info = style_id && style_cache ? style_cache[style_id] : null;\n if (\n style_info &&\n style_info.outline_level !== null &&\n style_info.outline_level >= 0 &&\n style_info.outline_level <= 8\n ) {\n return true;\n }\n\n let style_name = style_info ? style_info.name : style_id; // FALLBACK TO ID\n if (style_name && typeof style_name === \"string\" && style_name.toLowerCase().startsWith(\"heading\")) {\n style_name = style_name.replace(/^heading/i, \"Heading\");\n }\n if (style_name?.startsWith(\"Heading\")) return true;\n if (style_name === \"Title\") return true;\n if (style_name && style_name !== \"Normal\") {\n if (_detect_heading_level_from_name(style_name) !== null) return true;\n }\n\n return false;\n}\nexport function get_paragraph_prefix(\n paragraph: Paragraph,\n style_cache?: Record<string, any>,\n default_pstyle?: string | null,\n): string {\n if (!style_cache) {\n [style_cache, default_pstyle] = _get_style_cache(\n paragraph._parent.part || paragraph._parent,\n );\n }\n const pPr = findChild(paragraph._element, QN_W_PPR);\n\n if (pPr) {\n const oLvl = findChild(pPr, QN_W_OUTLINELVL);\n if (oLvl) {\n const val = oLvl.getAttribute(QN_W_VAL);\n if (val && /^\\d+$/.test(val)) {\n const lvl = parseInt(val, 10);\n if (lvl >= 0 && lvl <= 8) return \"#\".repeat(lvl + 1) + \" \";\n }\n }\n }\n\n let style_id = default_pstyle;\n if (pPr) {\n const pStyle = findChild(pPr, QN_W_PSTYLE);\n if (pStyle) style_id = pStyle.getAttribute(QN_W_VAL) || default_pstyle;\n }\n\n const style_info = style_id && style_cache ? style_cache[style_id] : null;\n if (\n style_info &&\n style_info.outline_level !== null &&\n style_info.outline_level >= 0 &&\n style_info.outline_level <= 8\n ) {\n return \"#\".repeat(style_info.outline_level + 1) + \" \";\n }\n\n let style_name = style_info ? style_info.name : style_id; // FALLBACK TO ID\n if (style_name && typeof style_name === \"string\" && style_name.toLowerCase().startsWith(\"heading\")) {\n style_name = style_name.replace(/^heading/i, \"Heading\");\n }\n if (style_name?.startsWith(\"Heading\")) {\n const match = style_name.replace(\"Heading\", \"\").trim();\n if (/^\\d+$/.test(match)) return \"#\".repeat(parseInt(match, 10)) + \" \";\n }\n\n if (style_name === \"Title\") return \"# \";\n\n // Check for List Formatting (direct paragraph numPr first, then the\n // style chain — Word's built-in List Bullet/List Number styles keep their\n // numPr in styles.xml, QA 2026-07-18 M4).\n let list_num_id: string | null = null;\n let list_ilvl: number | null = null;\n let numbering_disabled = false;\n if (pPr) {\n const numPr = findChild(pPr, QN_W_NUMPR);\n if (numPr) {\n const numId = findChild(numPr, QN_W_NUMID);\n if (numId) {\n const val = numId.getAttribute(QN_W_VAL);\n if (val === \"0\") {\n // ECMA-376 §17.9.15: a direct numId of 0 REMOVES the numbering a\n // style would otherwise apply.\n numbering_disabled = true;\n } else if (val) {\n list_num_id = val;\n const ilvl = findChild(numPr, QN_W_ILVL);\n if (ilvl) {\n const valAttr = ilvl.getAttribute(QN_W_VAL);\n if (valAttr !== null && /^\\d+$/.test(valAttr)) {\n list_ilvl = parseInt(valAttr, 10);\n }\n }\n }\n }\n }\n }\n if (list_num_id === null && !numbering_disabled && style_info) {\n const style_num_id = style_info.num_id;\n if (style_num_id) {\n list_num_id = style_num_id;\n if (list_ilvl === null) {\n list_ilvl =\n style_info.num_ilvl !== undefined ? style_info.num_ilvl : null;\n }\n }\n }\n if (list_num_id !== null) {\n const level = list_ilvl !== null ? list_ilvl : 0;\n const marker = get_list_marker(\n paragraph._parent ? paragraph._parent.part || paragraph._parent : null,\n list_num_id,\n level,\n );\n return \" \".repeat(level) + marker;\n }\n\n if (style_name && style_name !== \"Normal\") {\n const custom_level = _detect_heading_level_from_name(style_name);\n if (custom_level !== null) return \"#\".repeat(custom_level) + \" \";\n }\n\n if (!style_name || style_name === \"Normal\") {\n const text = paragraph.text.trim();\n if (text && text.length < 100 && text === text.toUpperCase()) {\n let is_bold = false;\n if (style_info?.bold) {\n is_bold = true;\n } else {\n const runs = findAllDescendants(paragraph._element, QN_W_R);\n for (const r of runs) {\n const tList = findAllDescendants(r, QN_W_T);\n const tText = tList.map((t) => t.textContent || \"\").join(\"\");\n if (tText.trim()) {\n const rPr_run = findChild(r, QN_W_RPR);\n if (rPr_run) {\n const b = findChild(rPr_run, QN_W_B);\n if (\n b &&\n b.getAttribute(QN_W_VAL) !== \"0\" &&\n b.getAttribute(QN_W_VAL) !== \"false\"\n ) {\n is_bold = true;\n }\n }\n break;\n }\n }\n }\n if (is_bold) return \"## \";\n }\n }\n\n return \"\";\n}\n\nexport function is_heading_paragraph(\n paragraph: Paragraph,\n style_cache?: Record<string, any>,\n default_pstyle?: string | null,\n): boolean {\n const prefix = get_paragraph_prefix(paragraph, style_cache, default_pstyle);\n if (!prefix) return false;\n const stripped = prefix.trimEnd();\n return stripped.length > 0 && stripped === \"#\".repeat(stripped.length);\n}\n\nexport function get_run_style_markers(\n run: Run,\n is_heading: boolean | null = null,\n): [string, string] {\n let prefix = \"\";\n let suffix = \"\";\n\n const rPr = findChild(run._element, QN_W_RPR);\n let is_bold = false;\n let is_italic = false;\n\n if (rPr) {\n const b = findChild(rPr, QN_W_B);\n if (\n b &&\n b.getAttribute(QN_W_VAL) !== \"0\" &&\n b.getAttribute(QN_W_VAL) !== \"false\"\n )\n is_bold = true;\n\n const i = findChild(rPr, QN_W_I);\n if (\n i &&\n i.getAttribute(QN_W_VAL) !== \"0\" &&\n i.getAttribute(QN_W_VAL) !== \"false\"\n )\n is_italic = true;\n }\n\n if (is_heading === null) {\n const parent = run._parent;\n is_heading =\n parent instanceof Paragraph ? is_native_heading(parent) : false;\n }\n\n if (is_bold && !is_heading) {\n prefix += \"**\";\n suffix = \"**\" + suffix;\n }\n\n if (is_italic) {\n prefix += \"_\";\n suffix = \"_\" + suffix;\n }\n\n return [prefix, suffix];\n}\n\n/**\n * Splits `text` into [leading_ws, core, trailing_ws]. Emphasis markers must\n * wrap only the core: `**The Supplier **` (a bold run with a trailing space)\n * is malformed Markdown — CommonMark requires the closing delimiter to hug\n * non-whitespace — and it poisons every downstream CriticMarkup consumer\n * (QA 2026-07-19 F-03/F-10). Fully-whitespace text yields [\"\", \"\", text] so\n * callers skip the markers entirely.\n */\nexport function split_boundary_whitespace(\n text: string,\n): [string, string, string] {\n const core = text.trim();\n if (!core) return [\"\", \"\", text];\n const lead_len = text.length - text.trimStart().length;\n return [\n text.substring(0, lead_len),\n text.substring(lead_len, lead_len + core.length),\n text.substring(lead_len + core.length),\n ];\n}\n\nexport function apply_formatting_to_segments(\n text: string,\n prefix: string,\n suffix: string,\n): string {\n if (!prefix && !suffix) return text;\n if (!text) return \"\";\n\n const wrap = (segment: string): string => {\n const [lead, core, trail] = split_boundary_whitespace(segment);\n if (!core) return segment;\n return `${lead}${prefix}${core}${suffix}${trail}`;\n };\n\n if (!text.includes(\"\\n\")) return wrap(text);\n\n const parts = text.split(\"\\n\");\n return parts.map((p) => (p ? wrap(p) : \"\")).join(\"\\n\");\n}\n\nexport function get_run_text(run: Run): string {\n let text = \"\";\n for (let i = 0; i < run._element.childNodes.length; i++) {\n const child = run._element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n if (child.tagName === QN_W_T || child.tagName === QN_W_DELTEXT) {\n const raw = child.textContent || \"\";\n text += raw.replace(/\\t/g, \" \");\n } else if (child.tagName === QN_W_TAB) {\n text += \" \";\n } else if (child.tagName === QN_W_BR || child.tagName === QN_W_CR) {\n text += \"\\n\";\n }\n }\n return text;\n}\n\nexport function* iter_block_items(\n parent: any,\n): Generator<Paragraph | Table | FootnoteItem> {\n const parent_elm = parent._element || parent.element || parent;\n\n if (parent.constructor.name === \"NotesPart\") {\n const tag = parent.note_type === \"fn\" ? \"w:footnote\" : \"w:endnote\";\n const notes = findAllDescendants(parent_elm, tag);\n for (const child of notes) {\n if (\n child.getAttribute(\"w:type\") === \"separator\" ||\n child.getAttribute(\"w:type\") === \"continuationSeparator\"\n )\n continue;\n // Word reserves non-positive note ids (-1 separator, 0 continuation\n // separator). Some generators omit the w:type attribute on them, so\n // filter by id as well — they must never surface as user footnotes\n // like \"[^fn--1]:\" (QA 2026-07-18 M6).\n const note_id = child.getAttribute(\"w:id\");\n if (\n note_id !== null &&\n /^\\s*[-+]?\\d+\\s*$/.test(note_id) &&\n parseInt(note_id, 10) <= 0\n )\n continue;\n yield new FootnoteItem(child, parent, parent.note_type);\n }\n return;\n }\n\n for (let i = 0; i < parent_elm.childNodes.length; i++) {\n const child = parent_elm.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n if (child.tagName === QN_W_P) {\n yield new Paragraph(child, parent);\n } else if (child.tagName === \"w:tbl\") {\n yield new Table(child, parent);\n }\n }\n}\n\nexport function* iter_document_parts(doc: any): Generator<any> {\n for (const [container] of iter_document_parts_with_kind(doc)) {\n yield container;\n }\n}\n\n/**\n * Like iter_document_parts, but yields [container, kind] where kind is one\n * of \"header\" / \"body\" / \"footer\" / \"footnotes\" / \"endnotes\".\n *\n * The kind sequence defines the document's structural part layout. The\n * projection flattens all parts into one string, so diff/apply need these\n * kinds to refuse (or correctly re-anchor) edits that would otherwise cross\n * an OPC part boundary — the QA 2026-07-18 C1 failure wrote a final body\n * paragraph into word/footer1.xml.\n */\nexport function* iter_document_parts_with_kind(\n doc: any,\n): Generator<[any, string]> {\n // 1. Headers\n const headers = doc.pkg.parts.filter(\n (p: any) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml\",\n );\n for (const h of headers) yield [h, \"header\"];\n\n // 2. Main Document Body\n yield [doc, \"body\"];\n\n // 3. Footers\n const footers = doc.pkg.parts.filter(\n (p: any) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\",\n );\n for (const f of footers) yield [f, \"footer\"];\n\n // 4. Notes\n const fnPart = doc.pkg.getPartByPath(\"word/footnotes.xml\");\n const enPart = doc.pkg.getPartByPath(\"word/endnotes.xml\");\n\n if (fnPart) yield [new NotesPart(fnPart, \"fn\"), \"footnotes\"];\n if (enPart) yield [new NotesPart(enPart, \"en\"), \"endnotes\"];\n}\n\nfunction _is_page_instr(instr: string): boolean {\n if (!instr) return false;\n const parts = instr.toUpperCase().trim().split(/\\s+/);\n return parts.length > 0 && (parts[0] === \"PAGE\" || parts[0] === \"NUMPAGES\");\n}\n\nexport function _get_part(parent: any): any {\n if (!parent) return null;\n if (parent.part) return parent.part;\n if (parent.pkg && parent.pkg.mainDocumentPart)\n return parent.pkg.mainDocumentPart;\n if (parent._parent) return _get_part(parent._parent);\n return null;\n}\n\nexport function* iter_paragraph_content(\n paragraph: Paragraph,\n): Generator<Run | DocxEvent> {\n let in_complex_field = false;\n let current_instr = \"\";\n let hide_result = false;\n\n function* process_run_element(\n r_element: Element,\n ): Generator<Run | DocxEvent> {\n let c_id: string | null = null;\n const rPr = findChild(r_element, QN_W_RPR);\n if (rPr) {\n const rPrChange = findChild(rPr, QN_W_RPRCHANGE);\n if (rPrChange) {\n c_id = rPrChange.getAttribute(QN_W_ID);\n yield {\n type: \"fmt_start\",\n id: c_id!,\n author: rPrChange.getAttribute(QN_W_AUTHOR) || undefined,\n date: rPrChange.getAttribute(QN_W_DATE) || undefined,\n };\n }\n }\n\n for (let i = 0; i < r_element.childNodes.length; i++) {\n const child = r_element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n const tag = child.tagName;\n if (tag === QN_W_DRAWING || tag === QN_W_OBJECT) {\n // Inline image/object: project a read-only marker so the agent can\n // see that a material element exists here (QA 2026-07-18 M5).\n // id/date carry (docPr id, alt text) — the marker renders as\n // .\n const doc_pr = findAllDescendants(child, QN_WP_DOCPR)[0] || null;\n let alt = \"\";\n let img_id = \"0\";\n if (doc_pr) {\n alt = doc_pr.getAttribute(\"descr\") || doc_pr.getAttribute(\"title\") || \"\";\n img_id = doc_pr.getAttribute(\"id\") || \"0\";\n }\n yield { type: \"image\", id: img_id, date: alt };\n } else if (tag === QN_W_PICT) {\n // Legacy VML picture. Only actual images (v:imagedata) get a\n // marker; textpath-only shapes (watermarks) are reported by\n // sanitize's watermark audit instead of polluting the text.\n const imagedata = findAllDescendants(child, QN_V_IMAGEDATA)[0] || null;\n if (imagedata) {\n const alt = imagedata.getAttribute(QN_O_TITLE) || \"\";\n yield { type: \"image\", id: \"vml\", date: alt };\n }\n } else if (tag === QN_W_COMMENTREFERENCE) {\n const ref_id = child.getAttribute(QN_W_ID);\n if (ref_id) yield { type: \"ref\", id: ref_id };\n } else if (tag === QN_W_FOOTNOTEREFERENCE) {\n const f_id = child.getAttribute(QN_W_ID);\n if (f_id) yield { type: \"footnote\", id: f_id };\n } else if (tag === QN_W_ENDNOTEREFERENCE) {\n const e_id = child.getAttribute(QN_W_ID);\n if (e_id) yield { type: \"endnote\", id: e_id };\n } else if (tag === QN_W_FLDCHAR) {\n const fld_type = child.getAttribute(QN_W_FLDCHARTYPE);\n if (fld_type === \"begin\") {\n in_complex_field = true;\n current_instr = \"\";\n } else if (fld_type === \"separate\") {\n if (_is_page_instr(current_instr)) hide_result = true;\n else {\n const parts = current_instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\")\n yield { type: \"xref_start\", id: parts[1] };\n }\n } else if (fld_type === \"end\") {\n if (!hide_result) {\n const parts = current_instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\")\n yield { type: \"xref_end\", id: parts[1] };\n }\n in_complex_field = false;\n current_instr = \"\";\n hide_result = false;\n }\n } else if (tag === QN_W_INSTRTEXT && in_complex_field && !hide_result) {\n current_instr += child.textContent || \"\";\n }\n }\n\n if (!hide_result) yield new Run(r_element, paragraph);\n if (c_id !== null) yield { type: \"fmt_end\", id: c_id };\n }\n\n function* traverse_node(node: Element): Generator<Run | DocxEvent> {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n const tag = child.tagName;\n if (tag === QN_W_R) yield* process_run_element(child);\n else if (tag === QN_W_INS) {\n const i_id = child.getAttribute(QN_W_ID)!;\n yield {\n type: \"ins_start\",\n id: i_id,\n author: child.getAttribute(QN_W_AUTHOR) || undefined,\n date: child.getAttribute(QN_W_DATE) || undefined,\n };\n yield* traverse_node(child);\n yield { type: \"ins_end\", id: i_id };\n } else if (tag === QN_W_DEL) {\n const d_id = child.getAttribute(QN_W_ID)!;\n yield {\n type: \"del_start\",\n id: d_id,\n author: child.getAttribute(QN_W_AUTHOR) || undefined,\n date: child.getAttribute(QN_W_DATE) || undefined,\n };\n yield* traverse_node(child);\n yield { type: \"del_end\", id: d_id };\n } else if (tag === QN_W_COMMENTRANGESTART)\n yield { type: \"start\", id: child.getAttribute(QN_W_ID)! };\n else if (tag === QN_W_COMMENTRANGEEND)\n yield { type: \"end\", id: child.getAttribute(QN_W_ID)! };\n else if (tag === QN_W_HYPERLINK) {\n const rId = child.getAttribute(QN_R_ID) || child.getAttribute(\"id\");\n let url = \"\";\n const part = _get_part(paragraph._parent);\n if (rId && part) {\n const rel = part.rels.get(rId);\n if (rel && rel.isExternal) url = rel.target;\n }\n if (url) yield { type: \"hyperlink_start\", id: rId!, date: url };\n yield* traverse_node(child);\n if (url) yield { type: \"hyperlink_end\", id: rId!, date: url };\n } else if (tag === QN_W_FLDSIMPLE) {\n const instr = child.getAttribute(QN_W_INSTR) || \"\";\n const parts = instr.trim().split(/\\s+/);\n const target = parts.length > 1 && parts[0] === \"REF\" ? parts[1] : \"\";\n if (target) yield { type: \"xref_start\", id: target };\n yield* traverse_node(child);\n if (target) yield { type: \"xref_end\", id: target };\n } else if (tag === QN_W_BOOKMARKSTART) {\n const b_name = child.getAttribute(QN_W_NAME);\n if (b_name && (!b_name.startsWith(\"_\") || b_name.startsWith(\"_Ref\")))\n yield { type: \"bookmark\", id: b_name };\n } else if (\n tag === QN_W_SDT ||\n tag === QN_W_SMARTTAG ||\n tag === QN_W_SDTCONTENT\n ) {\n yield* traverse_node(child);\n }\n }\n }\n\n yield* traverse_node(paragraph._element);\n}\n","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, Run, DocxEvent } from \"./docx/primitives.js\";\nimport { findAllDescendants, findChild } from \"./docx/dom.js\";\nimport { extract_comments_data } from \"./comments.js\";\nimport { RegexTimeoutError, userFindAllMatches, userSearch } from \"./utils/safe-regex.js\";\nimport {\n _get_style_cache,\n get_paragraph_prefix,\n get_run_style_markers,\n get_run_text,\n is_heading_paragraph,\n split_boundary_whitespace,\n is_native_heading,\n iter_block_items,\n iter_document_parts_with_kind,\n iter_paragraph_content,\n} from \"./utils/docx.js\";\n\nexport interface TextSpan {\n start: number;\n end: number;\n text: string;\n run: Run | null;\n paragraph: Paragraph | null;\n ins_id?: string | null;\n del_id?: string | null;\n hyperlink_id?: string | null;\n comment_ids?: string[];\n // Which OPC part (index into DocumentMapper.part_ranges) this span was\n // projected from. Text edits may never resolve across two different\n // parts — the QA 2026-07-18 C1 corruption wrote body text into a footer.\n part_index: number;\n // True for the read-only image marker projection .\n is_image_marker?: boolean;\n // Character offset of this span's text within its run's projected text.\n // One run may back several spans: hoisting boundary whitespace outside\n // style markers (QA 2026-07-19 F-03) projects a bold \"The Supplier \" run\n // as core + trailing-space spans, and only the first starts at run\n // offset 0. All span->run local-offset arithmetic must add this.\n run_offset?: number;\n}\n\nexport function renumber_snapshot_ids(\n doc: DocumentObject,\n): [Record<string, string>, Record<string, string>] {\n const chg_remap: Record<string, string> = {};\n let next_chg = 1;\n const body_root = doc.element;\n\n const chg_elements: Element[] = [];\n const all_elements = findAllDescendants(body_root, \"*\");\n for (const el of all_elements) {\n if (el.tagName === \"w:ins\" || el.tagName === \"w:del\") {\n chg_elements.push(el);\n }\n }\n\n for (const elem of chg_elements) {\n const old_id = elem.getAttribute(\"w:id\");\n if (!old_id) continue;\n if (chg_remap[old_id]) {\n elem.setAttribute(\"w:id\", chg_remap[old_id]);\n continue;\n }\n const new_id = next_chg.toString();\n chg_remap[old_id] = new_id;\n elem.setAttribute(\"w:id\", new_id);\n next_chg++;\n }\n\n const com_remap: Record<string, string> = {};\n let next_com = 1;\n const comments_part = doc.pkg.parts.find(\n (p) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\",\n );\n\n if (comments_part) {\n const comments_root = comments_part._element;\n for (const c of findAllDescendants(comments_root, \"w:comment\")) {\n const old_id = c.getAttribute(\"w:id\");\n if (!old_id) continue;\n if (com_remap[old_id]) {\n c.setAttribute(\"w:id\", com_remap[old_id]);\n continue;\n }\n const new_id = next_com.toString();\n com_remap[old_id] = new_id;\n c.setAttribute(\"w:id\", new_id);\n next_com++;\n }\n }\n\n for (const elem of all_elements) {\n if (\n [\n \"w:commentReference\",\n \"w:commentRangeStart\",\n \"w:commentRangeEnd\",\n ].includes(elem.tagName)\n ) {\n const old_id = elem.getAttribute(\"w:id\");\n if (old_id && com_remap[old_id]) {\n elem.setAttribute(\"w:id\", com_remap[old_id]);\n }\n }\n }\n\n if (comments_part) {\n for (const c of findAllDescendants(comments_part._element, \"w:comment\")) {\n const parent_id = c.getAttribute(\"w15:p\");\n if (parent_id && com_remap[parent_id]) {\n c.setAttribute(\"w15:p\", com_remap[parent_id]);\n }\n }\n }\n\n return [chg_remap, com_remap];\n}\n\n// Markdown style delimiters the projection emits as VIRTUAL spans around\n// formatted runs (see get_run_style_markers). Literal asterisks/underscores\n// typed in the document live inside real (run-backed) spans and are never\n// confused with these.\nconst STYLE_MARKER_TEXTS = new Set([\"**\", \"__\", \"*\", \"_\"]);\n\nexport class DocumentMapper {\n public doc: DocumentObject;\n public clean_view: boolean;\n public original_view: boolean;\n public comments_map: Record<string, any>;\n public full_text: string = \"\";\n public spans: TextSpan[] = [];\n public appendix_start_index: number = -1;\n // [start, end, kind] per projected part, in projection order. Spans carry\n // the matching index in .part_index. Together these let the engine refuse\n // or re-anchor edits at OPC part boundaries (QA 2026-07-18 C1).\n public part_ranges: [number, number, string][] = [];\n private _current_part_index = 0;\n private _text_chunks: string[] = [];\n private _plain_projection: [string, number[]] | null = null;\n\n constructor(\n doc: DocumentObject,\n clean_view: boolean = false,\n original_view: boolean = false,\n ) {\n this.doc = doc;\n this.clean_view = clean_view;\n this.original_view = original_view;\n this.comments_map = extract_comments_data(doc.pkg);\n this._build_map();\n }\n\n private _build_map() {\n let current_offset = 0;\n this.spans = [];\n this._text_chunks = [];\n this.full_text = \"\";\n this._plain_projection = null;\n this.part_ranges = [];\n this._current_part_index = 0;\n\n let part_idx = 0;\n for (const [part, part_kind] of iter_document_parts_with_kind(this.doc)) {\n this._current_part_index = part_idx;\n const part_start = current_offset;\n current_offset = this._map_blocks(part, current_offset);\n this.part_ranges.push([part_start, current_offset, part_kind]);\n\n if (\n this.spans.length > 0 &&\n this.spans[this.spans.length - 1].text !== \"\\n\\n\"\n ) {\n this._add_virtual_text(\"\\n\\n\", current_offset, null);\n current_offset += 2;\n }\n part_idx++;\n }\n\n while (\n this.spans.length > 0 &&\n this.spans[this.spans.length - 1].text === \"\\n\\n\"\n ) {\n this.spans.pop();\n this._text_chunks.pop();\n }\n\n this.full_text = this._text_chunks.join(\"\");\n this.appendix_start_index = -1;\n }\n\n /** [part_index, start, end, kind] for parts that projected any text. */\n private _nonempty_part_ranges(): [number, number, number, string][] {\n const out: [number, number, number, string][] = [];\n for (let i = 0; i < this.part_ranges.length; i++) {\n const [s, e, k] = this.part_ranges[i];\n if (e > s) out.push([i, s, e, k]);\n }\n return out;\n }\n\n public part_kind_of(part_index: number): string | null {\n if (part_index >= 0 && part_index < this.part_ranges.length) {\n return this.part_ranges[part_index][2];\n }\n return null;\n }\n\n /** Kind of the part whose projected range contains `index`, or null. */\n public part_kind_at(index: number): string | null {\n for (const [, start, end, kind] of this._nonempty_part_ranges()) {\n if (start <= index && index <= end) return kind;\n }\n return null;\n }\n\n /**\n * When `index` falls strictly AFTER one part's text and at-or-before the\n * start of the next part's text (i.e. inside the \"\\n\\n\" separator or\n * exactly at the next part's first character), returns\n * [previous_part_index, next_part_index]. Returns null everywhere else —\n * including index == previous part's end, which is an ordinary\n * end-of-part text position, not a boundary gap.\n */\n public part_boundary_at(index: number): [number, number] | null {\n const ranges = this._nonempty_part_ranges();\n for (let j = 1; j < ranges.length; j++) {\n const [prev_i, , prev_end] = ranges[j - 1];\n const [next_i, next_start] = ranges[j];\n if (prev_end < index && index <= next_start) {\n return [prev_i, next_i];\n }\n }\n return null;\n }\n\n private _map_blocks(container: any, offset: number): number {\n let current = offset;\n const c_type = container.constructor.name;\n const part = container.part || container;\n const [style_cache, default_pstyle] = _get_style_cache(part);\n\n if (c_type === \"NotesPart\") {\n const header =\n container.note_type === \"fn\" ? \"## Footnotes\" : \"## Endnotes\";\n const sep = `---\\n${header}`;\n this._add_virtual_text(sep, current, null);\n current += sep.length;\n this._add_virtual_text(\"\\n\\n\", current, null);\n current += 2;\n }\n\n let is_first_para = true;\n let previous_item: any = null;\n\n for (const item of iter_block_items(container)) {\n const i_type = item.constructor.name;\n\n if (i_type === \"FootnoteItem\") {\n current = this._map_blocks(item, current);\n } else if (item instanceof Paragraph) {\n if (!is_first_para) {\n const prev_para =\n previous_item instanceof Paragraph ? previous_item : null;\n this._add_virtual_text(\"\\n\\n\", current, prev_para);\n current += 2;\n }\n\n let prefix = get_paragraph_prefix(item, style_cache, default_pstyle);\n if (is_first_para && c_type === \"FootnoteItem\") {\n prefix = `[^${container.note_type}-${container.id}]: ` + prefix;\n }\n if (prefix) {\n this._add_virtual_text(prefix, current, item);\n current += prefix.length;\n }\n\n current = this._map_paragraph_content(\n item,\n current,\n style_cache,\n default_pstyle,\n );\n is_first_para = false;\n previous_item = item;\n } else if (item instanceof Table) {\n if (!is_first_para) {\n const prev_para =\n previous_item instanceof Paragraph ? previous_item : null;\n this._add_virtual_text(\"\\n\\n\", current, prev_para);\n current += 2;\n }\n current = this._map_table(item, current);\n is_first_para = false;\n previous_item = item;\n }\n }\n\n return current;\n }\n\n private _map_table(table: Table, offset: number): number {\n let current = offset;\n let rows_processed = 0;\n\n for (const row of table.rows) {\n const tr = row._element;\n const trPr = findChild(tr, \"w:trPr\");\n const ins = trPr ? findChild(trPr, \"w:ins\") : null;\n const del_node = trPr ? findChild(trPr, \"w:del\") : null;\n\n if (this.clean_view && del_node) continue;\n if (this.original_view && ins) continue;\n\n if (rows_processed > 0) {\n this._add_virtual_text(\"\\n\", current, null);\n current += 1;\n }\n\n if (ins && !this.clean_view && !this.original_view) {\n this._add_virtual_text(\"{++ \", current, null);\n current += 4;\n } else if (del_node && !this.clean_view && !this.original_view) {\n this._add_virtual_text(\"{-- \", current, null);\n current += 4;\n }\n\n const seen_cells = new Set();\n let cells_processed = 0;\n\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n if (cells_processed > 0) {\n this._add_virtual_text(\" | \", current, null);\n current += 3;\n }\n\n const cell_start = current;\n current = this._map_blocks(cell, current);\n\n // Parity with ingest.extract_table: emit a {#cell:<paraId>} anchor and\n // bind a zero-width span to the cell's first paragraph so the engine\n // can resolve \"write into this cell\" even when the cell is empty\n // (pPr-only paragraph with no run).\n if (!this.clean_view && !this.original_view) {\n const firstP = cell._element.getElementsByTagName(\"w:p\")[0] as\n | Element\n | undefined;\n const paraId = firstP ? firstP.getAttribute(\"w14:paraId\") : null;\n if (paraId && firstP) {\n // Zero-width span bound to the empty cell paragraph: gives\n // get_insertion_anchor a paragraph to land on. Placed at the anchor\n // token offset so resolution targets THIS cell, not a neighbour.\n const cellPara = new Paragraph(firstP, cell);\n this._add_virtual_text(\"\", current, cellPara);\n const anchor = `{#cell:${paraId}}`;\n this._add_virtual_text(anchor, current, cellPara);\n current += anchor.length;\n }\n }\n cells_processed += 1;\n }\n\n if (ins && !this.clean_view && !this.original_view) {\n const suffix = ` |Chg:${ins.getAttribute(\"w:id\")}++}`;\n this._add_virtual_text(suffix, current, null);\n current += suffix.length;\n } else if (del_node && !this.clean_view && !this.original_view) {\n const suffix = ` |Chg:${del_node.getAttribute(\"w:id\")}--}`;\n this._add_virtual_text(suffix, current, null);\n current += suffix.length;\n }\n\n rows_processed += 1;\n }\n\n return current;\n }\n\n private _strip_markdown_formatting(text: string): string {\n let result = text;\n result = result.replace(/^#+\\s*/gm, \"\");\n result = result.replace(/\\*\\*(\\w[\\w\\s]*\\w|\\w{2,})\\*\\*/g, \"$1\");\n result = result.replace(/__(\\w[\\w\\s]*\\w|\\w{2,})__/g, \"$1\");\n result = result.replace(/(?<!\\w)_(\\w[\\w\\s]*\\w|\\w{2,})_(?!\\w)/g, \"$1\");\n result = result.replace(/(?<!\\w)\\*(\\w[\\w\\s]*\\w|\\w{2,})\\*(?!\\w)/g, \"$1\");\n return result;\n }\n\n private _map_paragraph_content(\n paragraph: Paragraph,\n start_offset: number,\n style_cache?: any,\n default_pstyle?: string | null,\n ): number {\n let current = start_offset;\n\n const span: TextSpan = {\n start: current,\n end: current,\n text: \"\",\n run: null,\n paragraph,\n part_index: this._current_part_index,\n };\n this.spans.push(span);\n\n const active_ids = new Set<string>();\n const active_ins: Record<string, DocxEvent> = {};\n const active_del: Record<string, DocxEvent> = {};\n const active_fmt: Record<string, DocxEvent> = {};\n\n let deferred_meta_states: any[] = [];\n let current_wrappers: [string, string] = [\"\", \"\"];\n let current_style: [string, string] = [\"\", \"\"];\n let active_hyperlink_id: string | null = null;\n // [kind, text, run, run_offset, ins_id, del_id, comment_ids]\n let pending_runs: [\n string,\n string,\n Run | null,\n number,\n string | null,\n string | null,\n string[],\n ][] = [];\n\n const flush_pending_runs = () => {\n if (pending_runs.length === 0) return;\n const [s_tok, e_tok] = current_wrappers;\n if (s_tok) {\n this._add_virtual_text(s_tok, current, paragraph);\n current += s_tok.length;\n }\n for (const [kind, txt, r_obj, r_off, i_id, d_id, c_ids] of pending_runs) {\n if (kind === \"virtual\") {\n this._add_virtual_text(txt, current, paragraph, active_hyperlink_id);\n } else {\n const s: TextSpan = {\n start: current,\n end: current + txt.length,\n text: txt,\n run: r_obj,\n paragraph,\n ins_id: i_id || undefined,\n del_id: d_id || undefined,\n hyperlink_id: active_hyperlink_id || undefined,\n comment_ids: c_ids.length > 0 ? c_ids : undefined,\n part_index: this._current_part_index,\n run_offset: r_off,\n };\n this.spans.push(s);\n this._text_chunks.push(txt);\n }\n current += txt.length;\n }\n if (e_tok) {\n this._add_virtual_text(e_tok, current, paragraph);\n current += e_tok.length;\n }\n pending_runs = [];\n };\n\n const items = Array.from(iter_paragraph_content(paragraph));\n const is_heading = is_heading_paragraph(\n paragraph,\n style_cache,\n default_pstyle,\n );\n const native_heading = is_native_heading(\n paragraph,\n style_cache,\n default_pstyle,\n );\n let leading_strip_active = is_heading;\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n\n if (item instanceof Run) {\n const [prefix, suffix] = get_run_style_markers(item, native_heading);\n // [kind, text, run, run_offset]\n const run_parts: [string, string, Run | null, number][] = [];\n const text = get_run_text(item);\n\n if (leading_strip_active) {\n if (text === \"\" || /^\\s*$/.test(text)) continue;\n leading_strip_active = false;\n }\n\n // run_local tracks each real part's offset within the run's projected\n // text, so spans resolve back to exact run positions even when one\n // run backs several spans.\n let run_local = 0;\n const append_wrapped = (segment: string): void => {\n // Boundary whitespace stays OUTSIDE the style markers —\n // `**The Supplier **` is malformed Markdown (QA 2026-07-19 F-03).\n // Must mirror apply_formatting_to_segments exactly (the Virtual\n // Text contract).\n const [lead, core, trail] = split_boundary_whitespace(segment);\n if (!core) {\n run_parts.push([\"real\", segment, item, run_local]);\n run_local += segment.length;\n return;\n }\n if (lead) {\n run_parts.push([\"real\", lead, item, run_local]);\n run_local += lead.length;\n }\n if (prefix) run_parts.push([\"virtual\", prefix, null, 0]);\n run_parts.push([\"real\", core, item, run_local]);\n run_local += core.length;\n if (suffix) run_parts.push([\"virtual\", suffix, null, 0]);\n if (trail) {\n run_parts.push([\"real\", trail, item, run_local]);\n run_local += trail.length;\n }\n };\n\n if (text.includes(\"\\n\") && (prefix || suffix)) {\n const parts = text.split(\"\\n\");\n for (let idx = 0; idx < parts.length; idx++) {\n if (idx > 0) {\n run_parts.push([\"real\", \"\\n\", item, run_local]);\n run_local += 1;\n }\n if (parts[idx]) append_wrapped(parts[idx]);\n }\n } else if ((prefix || suffix) && text) {\n append_wrapped(text);\n } else {\n if (prefix) run_parts.push([\"virtual\", prefix, null, 0]);\n if (text) run_parts.push([\"real\", text, item, 0]);\n if (suffix) run_parts.push([\"virtual\", suffix, null, 0]);\n }\n\n if (this.clean_view && Object.keys(active_del).length > 0) {\n // pass\n }\n if (this.original_view && Object.keys(active_ins).length > 0) {\n // pass\n }\n\n const full_seg_text = run_parts.map((x) => x[1]).join(\"\");\n const curr_ins_id = Object.keys(active_ins).pop() || null;\n const curr_del_id = Object.keys(active_del).pop() || null;\n\n if (\n full_seg_text &&\n !(this.clean_view && curr_del_id) &&\n !(this.original_view && curr_ins_id)\n ) {\n const new_wrappers =\n this.clean_view || this.original_view\n ? ([\"\", \"\"] as [string, string])\n : this._get_wrappers(\n curr_ins_id,\n curr_del_id,\n active_ids,\n active_fmt,\n );\n const new_style: [string, string] = [prefix, suffix];\n\n if (\n pending_runs.length > 0 &&\n new_wrappers[0] === current_wrappers[0] &&\n new_wrappers[1] === current_wrappers[1]\n ) {\n let skip_leading_prefix = false;\n if (\n new_style[0] === current_style[0] &&\n new_style[1] === current_style[1] &&\n current_style[0] !== \"\" &&\n pending_runs[pending_runs.length - 1][0] === \"virtual\" &&\n pending_runs[pending_runs.length - 1][1] === current_style[1]\n ) {\n pending_runs.pop();\n skip_leading_prefix = true;\n }\n\n const curr_comment_ids = Array.from(active_ids);\n for (const [kind, txt, r_obj, r_off] of run_parts) {\n if (\n skip_leading_prefix &&\n kind === \"virtual\" &&\n txt === new_style[0]\n ) {\n skip_leading_prefix = false;\n continue;\n }\n pending_runs.push([\n kind,\n txt,\n r_obj,\n r_off,\n curr_ins_id,\n curr_del_id,\n curr_comment_ids,\n ]);\n }\n current_style = new_style;\n } else {\n flush_pending_runs();\n current_wrappers = new_wrappers;\n current_style = new_style;\n const curr_comment_ids = Array.from(active_ids);\n for (const [kind, txt, r_obj, r_off] of run_parts) {\n pending_runs.push([\n kind,\n txt,\n r_obj,\n r_off,\n curr_ins_id,\n curr_del_id,\n curr_comment_ids,\n ]);\n }\n }\n }\n\n if (!this.clean_view && !this.original_view) {\n const has_meta =\n Object.keys(active_ins).length > 0 ||\n Object.keys(active_del).length > 0 ||\n active_ids.size > 0 ||\n Object.keys(active_fmt).length > 0;\n if (has_meta) {\n deferred_meta_states.push([\n { ...active_ins },\n { ...active_del },\n new Set(active_ids),\n { ...active_fmt },\n ]);\n }\n\n let should_defer = false;\n const has_any_meta =\n curr_ins_id !== null ||\n curr_del_id !== null ||\n Object.keys(active_fmt).length > 0 ||\n active_ids.size > 0;\n\n if (has_any_meta) {\n let j = i + 1;\n let next_has_meta = false;\n let temp_ins_count = Object.keys(active_ins).length;\n let temp_del_count = Object.keys(active_del).length;\n let temp_fmt_count = Object.keys(active_fmt).length;\n const temp_comment_ids = new Set(active_ids);\n\n while (j < items.length) {\n const next_item = items[j];\n if (next_item instanceof Run) {\n if (!get_run_text(next_item)) {\n j++;\n continue;\n }\n if (\n temp_ins_count > 0 ||\n temp_del_count > 0 ||\n temp_fmt_count > 0 ||\n temp_comment_ids.size > 0\n ) {\n next_has_meta = true;\n }\n break;\n } else {\n const ev = next_item as DocxEvent;\n if (ev.type === \"ins_start\") temp_ins_count++;\n else if (ev.type === \"ins_end\")\n temp_ins_count = Math.max(0, temp_ins_count - 1);\n else if (ev.type === \"del_start\") temp_del_count++;\n else if (ev.type === \"del_end\")\n temp_del_count = Math.max(0, temp_del_count - 1);\n else if (ev.type === \"fmt_start\") temp_fmt_count++;\n else if (ev.type === \"fmt_end\")\n temp_fmt_count = Math.max(0, temp_fmt_count - 1);\n else if (ev.type === \"start\") temp_comment_ids.add(ev.id);\n else if (ev.type === \"end\") temp_comment_ids.delete(ev.id);\n }\n j++;\n }\n\n if (next_has_meta) should_defer = true;\n }\n\n if (!should_defer && deferred_meta_states.length > 0) {\n const meta_block =\n this._build_merged_meta_block(deferred_meta_states);\n if (meta_block) {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const full_meta = `{>>${meta_block}<<}`;\n this._add_virtual_text(full_meta, current, paragraph);\n current += full_meta.length;\n }\n deferred_meta_states = [];\n }\n }\n } else {\n const ev = item as DocxEvent;\n leading_strip_active = false;\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n\n if (ev.type === \"start\") active_ids.add(ev.id);\n else if (ev.type === \"end\") active_ids.delete(ev.id);\n else if (ev.type === \"ins_start\") active_ins[ev.id] = ev;\n else if (ev.type === \"ins_end\") delete active_ins[ev.id];\n else if (ev.type === \"del_start\") active_del[ev.id] = ev;\n else if (ev.type === \"del_end\") delete active_del[ev.id];\n else if (ev.type === \"fmt_start\") active_fmt[ev.id] = ev;\n else if (ev.type === \"fmt_end\") delete active_fmt[ev.id];\n else if (ev.type === \"image\") {\n // Read-only image marker (QA 2026-07-18 M5). Hidden when the run is\n // filtered by the active view, exactly like its neighbouring text.\n const hidden =\n (this.clean_view && Object.keys(active_del).length > 0) ||\n (this.original_view && Object.keys(active_ins).length > 0);\n if (!hidden) {\n const alt = (ev.date || \"image\")\n .replace(/\\]/g, \")\")\n .replace(/\\n/g, \" \");\n const txt = ``;\n this._add_virtual_text(txt, current, paragraph, null, true);\n current += txt.length;\n }\n } else if (ev.type === \"footnote\" || ev.type === \"endnote\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const prefix_str = ev.type === \"footnote\" ? \"fn\" : \"en\";\n const txt = `[^${prefix_str}-${ev.id}]`;\n this._add_virtual_text(txt, current, paragraph);\n current += txt.length;\n } else if (ev.type === \"hyperlink_start\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n this._add_virtual_text(\"[\", current, paragraph, ev.id);\n current += 1;\n active_hyperlink_id = ev.id;\n } else if (ev.type === \"hyperlink_end\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const txt = `](${ev.date})`;\n this._add_virtual_text(txt, current, paragraph, ev.id);\n current += txt.length;\n active_hyperlink_id = null;\n } else if (ev.type === \"xref_start\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n this._add_virtual_text(\"[~\", current, paragraph);\n current += 2;\n } else if (ev.type === \"xref_end\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const txt = `~](#${ev.id})`;\n this._add_virtual_text(txt, current, paragraph);\n current += txt.length;\n } else if (ev.type === \"bookmark\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const txt = `{#${ev.id}}`;\n this._add_virtual_text(txt, current, paragraph);\n current += txt.length;\n }\n }\n }\n\n flush_pending_runs();\n\n if (deferred_meta_states.length > 0) {\n const meta_block = this._build_merged_meta_block(deferred_meta_states);\n if (meta_block) {\n const full_meta = `{>>${meta_block}<<}`;\n this._add_virtual_text(full_meta, current, paragraph);\n current += full_meta.length;\n }\n }\n\n return current;\n }\n\n private _get_wrappers(\n ins_id: string | null,\n del_id: string | null,\n active_ids: Set<string>,\n active_fmt: Record<string, DocxEvent>,\n ): [string, string] {\n if (del_id) return [\"{--\", \"--}\"];\n if (ins_id) return [\"{++\", \"++}\"];\n if (active_ids.size > 0 || Object.keys(active_fmt).length > 0)\n return [\"{==\", \"==}\"];\n return [\"\", \"\"];\n }\n\n private _build_merged_meta_block(states_list: any[]): string {\n const change_lines: string[] = [];\n const comment_lines: string[] = [];\n const seen_sigs = new Set<string>();\n\n for (const [ins_map, del_map, comments_set, fmt_map] of states_list) {\n for (const [uid, meta] of Object.entries(\n ins_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n const auth = meta.author || \"Unknown\";\n change_lines.push(`[${sig} insert] ${auth}`);\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n del_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n const auth = meta.author || \"Unknown\";\n change_lines.push(`[${sig} delete] ${auth}`);\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n fmt_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n const auth = meta.author || \"Unknown\";\n change_lines.push(`[${sig} format] ${auth}`);\n seen_sigs.add(sig);\n }\n }\n\n const sorted_ids = Array.from(comments_set as Set<string>).sort();\n for (const c_id of sorted_ids) {\n if (!this.comments_map[c_id]) continue;\n const sig = `Com:${c_id}`;\n if (!seen_sigs.has(sig)) {\n const data = this.comments_map[c_id];\n let header = `[${sig}] ${data.author}`;\n if (data.date) header += ` @ ${data.date}`;\n if (data.resolved) header += `(RESOLVED)`;\n comment_lines.push(`${header}: ${data.text}`);\n seen_sigs.add(sig);\n }\n }\n }\n\n return [...change_lines, ...comment_lines].join(\"\\n\");\n }\n\n private _add_virtual_text(\n text: string,\n offset: number,\n context_paragraph: Paragraph | null,\n hyperlink_id: string | null = null,\n is_image_marker = false,\n ) {\n const span: TextSpan = {\n start: offset,\n end: offset + text.length,\n text,\n run: null,\n paragraph: context_paragraph,\n hyperlink_id: hyperlink_id || undefined,\n part_index: this._current_part_index,\n is_image_marker: is_image_marker || undefined,\n };\n this.spans.push(span);\n this._text_chunks.push(text);\n }\n\n private _replace_smart_quotes(text: string): string {\n return text\n .replace(/“/g, '\"')\n .replace(/”/g, '\"')\n .replace(/‘/g, \"'\")\n .replace(/’/g, \"'\");\n }\n\n private _make_fuzzy_regex(target_text: string): string {\n target_text = this._strip_markdown_formatting(target_text);\n target_text = this._replace_smart_quotes(target_text);\n\n const parts: string[] = [];\n const token_pattern = /(\\[_+\\])|(\\s+)|(['\"])|([.,;:\\/\\-\\[\\](){}+=$?*!|#^<>\\\\%&@~`_])/g;\n\n let last_idx = 0;\n let match;\n const escapeRegExp = (str: string) =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n while ((match = token_pattern.exec(target_text)) !== null) {\n const literal = target_text.substring(last_idx, match.index);\n if (literal) parts.push(escapeRegExp(literal));\n\n const g_placeholder = match[1];\n const g_space = match[2];\n const g_quote = match[3];\n const g_punct = match[4];\n\n if (g_placeholder) {\n parts.push(\"\\\\[_+\\\\]\");\n } else if (g_space) {\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n parts.push(\"\\\\s+\");\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n } else if (g_quote) {\n if (g_quote === \"'\") parts.push(\"[\\u2018\\u2019']\");\n else parts.push('[\"\\u201c\\u201d]');\n } else if (g_punct) {\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n parts.push(escapeRegExp(g_punct));\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n }\n\n last_idx = token_pattern.lastIndex;\n }\n\n const remaining = target_text.substring(last_idx);\n if (remaining) parts.push(escapeRegExp(remaining));\n\n return parts.join(\"\");\n }\n\n /**\n * Returns [plain_text, offset_map] where plain_text is full_text with the\n * VIRTUAL markdown style delimiters (bold/italic markers emitted around\n * formatted runs) removed, and offset_map[i] is the full_text index of\n * plain_text[i].\n *\n * Formatting run boundaries can fall mid-word (e.g. a paragraph projected\n * as \"**Al**pha\"), where neither exact matching nor the whitespace-anchored\n * fuzzy regex can find the plain target \"Alpha\". Matching against this\n * projection and mapping the span back to full_text closes that gap (QA H2).\n *\n * Built lazily and invalidated by _build_map(): most batches never need it.\n */\n private _get_plain_projection(): [string, number[]] {\n if (this._plain_projection === null) {\n const chunks: string[] = [];\n const offsets: number[] = [];\n for (const s of this.spans) {\n if (\n s.run === null &&\n s.paragraph !== null &&\n STYLE_MARKER_TEXTS.has(s.text)\n ) {\n continue;\n }\n chunks.push(s.text);\n for (let k = s.start; k < s.end; k++) offsets.push(k);\n }\n this._plain_projection = [chunks.join(\"\"), offsets];\n }\n return this._plain_projection;\n }\n\n /**\n * Matches a markdown-stripped target against the plain projection and maps\n * each hit back to a [start, length] span in full_text. Interior style\n * markers end up inside the returned span (so \"Alpha\" over \"**Al**pha\"\n * resolves to the \"Al**pha\" range); markers just outside the matched\n * characters are excluded.\n */\n private _find_plain_projection_matches(\n target_text: string,\n ): [number, number][] {\n const [plain_text, offsets] = this._get_plain_projection();\n if (plain_text.length === this.full_text.length) {\n return []; // No virtual style markers anywhere; nothing new to find.\n }\n const norm_target = this._replace_smart_quotes(\n this._strip_markdown_formatting(target_text),\n );\n if (!norm_target) return [];\n const norm_plain = this._replace_smart_quotes(plain_text);\n const results: [number, number][] = [];\n let from = 0;\n while (true) {\n const p_start = norm_plain.indexOf(norm_target, from);\n if (p_start === -1) break;\n const p_end = p_start + norm_target.length;\n const raw_start = offsets[p_start];\n const raw_end = offsets[p_end - 1] + 1;\n results.push([raw_start, raw_end - raw_start]);\n from = p_end;\n }\n return results;\n }\n\n public find_match_index(\n target_text: string,\n is_regex: boolean = false,\n ): [number, number] {\n if (is_regex) {\n // User/LLM-supplied pattern: run it under a wall-clock budget so a\n // catastrophic pattern cannot hang the event loop (QA 2026-07-17 F5).\n // RegexTimeoutError propagates for a clean per-edit error; only\n // invalid-pattern errors mean \"no match\" here.\n try {\n const match = userSearch(target_text, this.full_text);\n if (match) return [match.start, match.end - match.start];\n } catch (e) {\n if (e instanceof RegexTimeoutError) throw e;\n }\n return [-1, 0];\n }\n\n let start_idx = this.full_text.indexOf(target_text);\n if (start_idx !== -1) return [start_idx, target_text.length];\n\n const norm_full = this._replace_smart_quotes(this.full_text);\n const norm_target = this._replace_smart_quotes(target_text);\n start_idx = norm_full.indexOf(norm_target);\n if (start_idx !== -1) return [start_idx, target_text.length];\n\n const stripped_target = this._strip_markdown_formatting(target_text);\n if (this.full_text.includes(stripped_target)) {\n start_idx = this.full_text.indexOf(stripped_target);\n return [start_idx, stripped_target.length];\n }\n\n // 3.5 Plain-projection match: the target crosses a formatting run\n // boundary (possibly mid-word), so the projection carries style markers\n // the plain target doesn't have (QA H2).\n const plain_first = this._find_plain_projection_matches(target_text);\n if (plain_first.length > 0) return plain_first[0];\n\n try {\n const pattern = new RegExp(this._make_fuzzy_regex(target_text));\n const match = pattern.exec(this.full_text);\n if (match) return [match.index, match[0].length];\n } catch (e) {}\n\n return [-1, 0];\n }\n\n public find_all_match_indices(\n target_text: string,\n is_regex: boolean = false,\n ): [number, number][] {\n if (!target_text) return [];\n\n if (is_regex) {\n // Budgeted like find_match_index above (QA 2026-07-17 F5).\n try {\n const matches = userFindAllMatches(target_text, this.full_text);\n if (matches.length > 0) return matches.map((m) => [m.start, m.end - m.start]);\n } catch (e) {\n if (e instanceof RegexTimeoutError) throw e;\n }\n return [];\n }\n // Exact tiers use plain indexOf scans, NOT RegExp: building a RegExp from\n // an arbitrarily long escaped target throws \"regular expression too\n // large\" for oversized inputs, crashing validation instead of returning\n // a clean not-found (QA C2 hardening).\n const findAllLiteral = (\n haystack: string,\n needle: string,\n ): [number, number][] => {\n const out: [number, number][] = [];\n if (!needle) return out;\n let from = 0;\n while (true) {\n const idx = haystack.indexOf(needle, from);\n if (idx === -1) break;\n out.push([idx, needle.length]);\n from = idx + needle.length;\n }\n return out;\n };\n\n let matches = findAllLiteral(this.full_text, target_text);\n if (matches.length > 0) return matches;\n\n const norm_full = this._replace_smart_quotes(this.full_text);\n const norm_target = this._replace_smart_quotes(target_text);\n matches = findAllLiteral(norm_full, norm_target);\n if (matches.length > 0) return matches;\n\n const stripped_target = this._strip_markdown_formatting(target_text);\n matches = findAllLiteral(this.full_text, stripped_target);\n if (matches.length > 0) return matches;\n\n // 3.5 Plain-projection match (target spans a bold/italic run boundary,\n // possibly mid-word). See _find_plain_projection_matches (QA H2).\n const plain_matches = this._find_plain_projection_matches(target_text);\n if (plain_matches.length > 0) return plain_matches;\n\n try {\n const pattern = new RegExp(this._make_fuzzy_regex(target_text), \"g\");\n const fuzzy = [...this.full_text.matchAll(pattern)];\n if (fuzzy.length > 0) return fuzzy.map((m) => [m.index!, m[0].length]);\n } catch (e) {}\n\n return [];\n }\n\n public find_target_runs(target_text: string): Run[] {\n const [start_idx, length] = this.find_match_index(target_text);\n if (start_idx === -1) return [];\n return this._resolve_runs_at_range(start_idx, start_idx + length);\n }\n\n public find_target_runs_by_index(\n start_index: number,\n length: number,\n rebuild_map = true,\n ): Run[] {\n return this._resolve_runs_at_range(\n start_index,\n start_index + length,\n rebuild_map,\n );\n }\n\n public get_virtual_spans_in_range(\n start_index: number,\n length: number,\n ): TextSpan[] {\n const end_index = start_index + length;\n return this.spans.filter(\n (s) =>\n s.run === null &&\n s.text === \"\\n\\n\" &&\n s.start >= start_index &&\n s.end <= end_index,\n );\n }\n\n private _resolve_runs_at_range(\n start_idx: number,\n end_idx: number,\n rebuild_map = true,\n ): Run[] {\n const affected_spans = this.spans.filter(\n (s) => s.end > start_idx && s.start < end_idx,\n );\n if (affected_spans.length === 0) return [];\n\n const real_spans = affected_spans.filter((s) => s.run !== null);\n if (real_spans.length === 0) return [];\n\n // One run may back several spans (boundary whitespace hoisted outside\n // style markers projects a run as lead/core/trail spans, QA 2026-07-19\n // F-03): deduplicate by identity or the run would be split and wrapped\n // once per span.\n const working_runs: Run[] = [];\n for (const s of real_spans) {\n if (!working_runs.some((r) => r === s.run)) {\n working_runs.push(s.run!);\n }\n }\n\n let dom_modified = false;\n\n // 1. Start Split — all local offsets are run-relative: span-relative\n // position plus the span's own offset within the run.\n const first_real_span = real_spans[0];\n let start_split_adjustment = 0;\n\n // A range may START on a virtual span (word-diff hunks absorb a style\n // marker adjacent to real changes, e.g. the `**` closing a bold run).\n // Virtual characters have no physical width: clamp to the first real\n // span's start or the subtraction goes negative and the split point\n // lands INSIDE the preceding run's kept text — the \"**The Suppli**\"\n // partial-word artifact (QA 2026-07-19 v8 F-04).\n const local_start =\n Math.max(start_idx, first_real_span.start) -\n first_real_span.start +\n (first_real_span.run_offset || 0);\n if (local_start > 0) {\n const split_source = working_runs[0];\n const [, right_run] = this._split_run_at_index(\n split_source,\n local_start,\n );\n for (let w = 0; w < working_runs.length; w++) {\n if (working_runs[w] === split_source) working_runs[w] = right_run;\n }\n dom_modified = true;\n start_split_adjustment = local_start;\n }\n\n // 2. End Split\n const last_real_span = real_spans[real_spans.length - 1];\n const is_same_run = first_real_span.run === last_real_span.run;\n const run_to_split = working_runs[working_runs.length - 1];\n const overlap_end = Math.min(last_real_span.end, end_idx);\n let local_end =\n overlap_end - last_real_span.start + (last_real_span.run_offset || 0);\n\n if (is_same_run && start_split_adjustment > 0) {\n local_end -= start_split_adjustment;\n }\n\n const run_text = get_run_text(run_to_split);\n if (local_end > 0 && local_end < run_text.length) {\n const [left_run] = this._split_run_at_index(run_to_split, local_end);\n working_runs[working_runs.length - 1] = left_run;\n dom_modified = true;\n }\n\n if (dom_modified && rebuild_map) {\n this._build_map();\n }\n\n return working_runs;\n }\n\n public get_insertion_anchor(\n index: number,\n rebuild_map = true,\n ): [Run | null, Paragraph | null] {\n const preceding = this.spans.filter((s) => s.end === index);\n if (preceding.length > 0) {\n for (let i = preceding.length - 1; i >= 0; i--) {\n if (preceding[i].run) return [preceding[i].run, preceding[i].paragraph];\n }\n for (let i = preceding.length - 1; i >= 0; i--) {\n const para = preceding[i].paragraph;\n if (para) {\n // Every span ending exactly here is virtual (CriticMarkup\n // wrappers, {>>...<<} meta blocks, prefixes). If real text\n // precedes this index in the SAME paragraph, anchor after its\n // last run: falling back to the bare paragraph would drop the\n // insertion at paragraph start, ahead of the very redlines and\n // comment ranges that fence off the true position (mirrors the\n // Python mapper).\n for (let j = this.spans.length - 1; j >= 0; j--) {\n const prev = this.spans[j];\n if (\n prev.end <= index &&\n prev.run !== null &&\n prev.paragraph === para\n ) {\n return [prev.run, prev.paragraph];\n }\n }\n return [null, para];\n }\n }\n }\n\n const containing = this.spans.filter(\n (s) => s.start < index && index < s.end,\n );\n if (containing.length > 0) {\n const span = containing[0];\n if (span.run === null) {\n if (span.paragraph === null) {\n return this.get_insertion_anchor(span.end, rebuild_map);\n }\n return [null, span.paragraph];\n } else {\n const offset = index - span.start + (span.run_offset || 0);\n const [left] = this._split_run_at_index(span.run, offset);\n if (rebuild_map) this._build_map();\n return [left, span.paragraph];\n }\n }\n\n if (index === 0 && this.spans.length > 0) {\n for (const s of this.spans) if (s.run) return [s.run, s.paragraph];\n for (const s of this.spans) if (s.paragraph) return [null, s.paragraph];\n return [null, null];\n }\n\n const preceding_gap = this.spans.filter((s) => s.end < index);\n if (preceding_gap.length > 0) {\n for (let i = preceding_gap.length - 1; i >= 0; i--) {\n if (preceding_gap[i].run)\n return [preceding_gap[i].run, preceding_gap[i].paragraph];\n }\n for (let i = preceding_gap.length - 1; i >= 0; i--) {\n if (preceding_gap[i].paragraph)\n return [null, preceding_gap[i].paragraph];\n }\n }\n\n return [null, null];\n }\n\n private _split_run_at_index(run: Run, split_index: number): [Run, Run] {\n const text = get_run_text(run);\n const left_text = text.substring(0, split_index);\n const right_text = text.substring(split_index);\n\n this._set_run_text_elements(run._element, left_text);\n\n const new_r_element = run._element.cloneNode(true) as Element;\n this._set_run_text_elements(new_r_element, right_text);\n\n if (run._element.parentNode) {\n run._element.parentNode.insertBefore(\n new_r_element,\n run._element.nextSibling,\n );\n }\n\n const new_run = new Run(new_r_element, run._parent);\n return [run, new_run];\n }\n\n private _set_run_text_elements(r_element: Element, new_text: string) {\n const to_remove: Element[] = [];\n for (let i = 0; i < r_element.childNodes.length; i++) {\n const child = r_element.childNodes[i] as Element;\n if (\n child.nodeType === 1 &&\n [\"w:t\", \"w:delText\", \"w:br\", \"w:cr\", \"w:tab\"].includes(child.tagName)\n ) {\n to_remove.push(child);\n }\n }\n for (const child of to_remove) {\n r_element.removeChild(child);\n }\n\n const doc = r_element.ownerDocument;\n if (doc) {\n const new_t = doc.createElement(\"w:t\");\n new_t.textContent = new_text;\n if (new_text.trim() !== new_text) {\n new_t.setAttribute(\"xml:space\", \"preserve\");\n }\n r_element.appendChild(new_t);\n }\n }\n\n public get_context_at_range(\n start_idx: number,\n end_idx: number,\n ): TextSpan | null {\n const real_spans = this.spans.filter(\n (s) => s.run && s.end > start_idx && s.start < end_idx,\n );\n if (real_spans.length > 0) return real_spans[0];\n return null;\n }\n}\n","import { unzipSync } from \"fflate\";\nimport diff_match_patch from \"diff-match-patch\";\nimport { DeleteTableRow, InsertTableRow, ModifyText } from \"./models.js\";\nimport type {\n ExtractStructure,\n RowGeometry,\n TableGeometry,\n} from \"./ingest.js\";\n\nexport type DiffEdit = ModifyText | InsertTableRow | DeleteTableRow;\n\nfunction _count_standalone_underscores(s: string): number {\n let count = 0;\n let i = 0;\n const n = s.length;\n const isAlnum = (char: string) => /[a-zA-Z0-9]/.test(char);\n while (i < n) {\n if (s[i] === \"_\") {\n // Is it part of \"__\"?\n let is_double = false;\n if ((i > 0 && s[i - 1] === \"_\") || (i < n - 1 && s[i + 1] === \"_\")) {\n is_double = true;\n }\n\n // Is it intra-word?\n let is_intra = false;\n if (i > 0 && isAlnum(s[i - 1]) && i < n - 1 && isAlnum(s[i + 1])) {\n is_intra = true;\n }\n\n if (!is_double && !is_intra) {\n count++;\n }\n }\n i++;\n }\n return count;\n}\n\nexport function trim_common_context(\n target: string,\n new_val: string,\n): [number, number] {\n if (!target || !new_val) return [0, 0];\n\n const isSpace = (char: string) => /\\s/.test(char);\n\n // 1. Prefix with Word Boundary Check\n let prefix_len = 0;\n let limit = Math.min(target.length, new_val.length);\n while (prefix_len < limit && target[prefix_len] === new_val[prefix_len]) {\n prefix_len++;\n }\n\n // Backtrack to nearest whitespace if we split a word\n if (prefix_len < target.length && prefix_len < new_val.length) {\n while (prefix_len > 0) {\n const target_split =\n !isSpace(target[prefix_len - 1]) && !isSpace(target[prefix_len]);\n const new_split =\n !isSpace(new_val[prefix_len - 1]) && !isSpace(new_val[prefix_len]);\n if (target_split || new_split) {\n prefix_len--;\n } else {\n break;\n }\n }\n }\n\n // Backtrack prefix to avoid splitting markdown markers\n while (prefix_len > 0) {\n if (prefix_len < target.length) {\n const charSeq = target.substring(prefix_len - 1, prefix_len + 1);\n if (charSeq === \"**\" || charSeq === \"__\") {\n prefix_len--;\n continue;\n }\n }\n\n const left = target.substring(0, prefix_len);\n const b_count = (left.match(/\\*\\*/g) || []).length;\n const u2_count = (left.match(/__/g) || []).length;\n const u1_count = _count_standalone_underscores(left);\n\n if (b_count % 2 !== 0) {\n prefix_len = left.lastIndexOf(\"**\");\n continue;\n }\n if (u2_count % 2 !== 0) {\n prefix_len = left.lastIndexOf(\"__\");\n continue;\n }\n if (u1_count % 2 !== 0) {\n let idx = left.length - 1;\n const isAlnum = (char: string) => /[a-zA-Z0-9]/.test(char);\n while (idx >= 0) {\n if (\n left[idx] === \"_\" &&\n (idx === 0 || left[idx - 1] !== \"_\") &&\n (idx === left.length - 1 || left[idx + 1] !== \"_\")\n ) {\n const is_intra = idx > 0 && isAlnum(left[idx - 1]) && idx < left.length - 1 && isAlnum(left[idx + 1]);\n if (!is_intra) {\n prefix_len = idx;\n break;\n }\n }\n idx--;\n }\n continue;\n }\n\n // Safety: Backtrack if we consumed a Markdown Header marker (#)\n let temp_len = prefix_len;\n let hit_header = false;\n while (temp_len > 0) {\n const char = target[temp_len - 1];\n if (char === \"#\") {\n prefix_len = temp_len - 1;\n while (prefix_len > 0 && target[prefix_len - 1] !== \"\\n\") {\n prefix_len--;\n }\n hit_header = true;\n break;\n }\n if (char === \"\\n\") break;\n temp_len--;\n }\n if (hit_header) continue;\n\n break;\n }\n\n // 2. Suffix with Word Boundary Check\n let suffix_len = 0;\n const target_rem_len = target.length - prefix_len;\n const new_rem_len = new_val.length - prefix_len;\n const limit_suffix = Math.min(target_rem_len, new_rem_len);\n\n while (\n suffix_len < limit_suffix &&\n target[target.length - 1 - suffix_len] ===\n new_val[new_val.length - 1 - suffix_len]\n ) {\n suffix_len++;\n }\n\n if (suffix_len > 0) {\n while (suffix_len > 0) {\n let target_split = false;\n if (suffix_len < target.length) {\n target_split =\n !isSpace(target[target.length - 1 - suffix_len]) &&\n !isSpace(target[target.length - suffix_len]);\n }\n let new_split = false;\n if (suffix_len < new_val.length) {\n new_split =\n !isSpace(new_val[new_val.length - 1 - suffix_len]) &&\n !isSpace(new_val[new_val.length - suffix_len]);\n }\n if (target_split || new_split) {\n suffix_len--;\n } else {\n break;\n }\n }\n }\n\n while (suffix_len > 0) {\n const idx = target.length - suffix_len;\n if (idx > 0) {\n const charSeq = target.substring(idx - 1, idx + 1);\n if (charSeq === \"**\" || charSeq === \"__\") {\n suffix_len--;\n continue;\n }\n }\n\n const right = target.substring(target.length - suffix_len);\n const b_count = (right.match(/\\*\\*/g) || []).length;\n const u2_count = (right.match(/__/g) || []).length;\n const u1_count = _count_standalone_underscores(right);\n\n if (b_count % 2 !== 0) {\n suffix_len -= right.indexOf(\"**\") + 2;\n continue;\n }\n if (u2_count % 2 !== 0) {\n suffix_len -= right.indexOf(\"__\") + 2;\n continue;\n }\n if (u1_count % 2 !== 0) {\n let idx_in_right = 0;\n const isAlnum = (char: string) => /[a-zA-Z0-9]/.test(char);\n while (idx_in_right < right.length) {\n if (\n right[idx_in_right] === \"_\" &&\n (idx_in_right === 0 || right[idx_in_right - 1] !== \"_\") &&\n (idx_in_right === right.length - 1 || right[idx_in_right + 1] !== \"_\")\n ) {\n const is_intra = idx_in_right > 0 && isAlnum(right[idx_in_right - 1]) && idx_in_right < right.length - 1 && isAlnum(right[idx_in_right + 1]);\n if (!is_intra) {\n suffix_len -= idx_in_right + 1;\n break;\n }\n }\n idx_in_right++;\n }\n continue;\n }\n break;\n }\n\n if (\n suffix_len > 0 &&\n /^\\s+$/.test(target.substring(target.length - suffix_len))\n ) {\n suffix_len = 0;\n }\n\n // Absorb balanced wrappers\n for (const marker of [\"**\", \"__\", \"_\"]) {\n const mlen = marker.length;\n const tgt_rem = target.substring(prefix_len, target.length - suffix_len);\n const new_rem = new_val.substring(prefix_len, new_val.length - suffix_len);\n\n if (\n tgt_rem.startsWith(marker) &&\n new_rem.startsWith(marker) &&\n tgt_rem.endsWith(marker) &&\n new_rem.endsWith(marker) &&\n tgt_rem.length >= 2 * mlen &&\n new_rem.length >= 2 * mlen\n ) {\n prefix_len += mlen;\n suffix_len += mlen;\n }\n }\n\n return [prefix_len, suffix_len];\n}\n\nfunction _words_to_chars(\n text1: string,\n text2: string,\n): [string, string, string[]] {\n const token_array: string[] = [];\n const token_hash: Record<string, number> = {};\n\n // RegExp equivalent to Python's r\"(\\s+|\\w+|[^\\w\\s])\" with unicode support\n const split_pattern = /(\\s+|[\\p{L}\\p{N}_]+|[^\\p{L}\\p{N}_\\s])/gu;\n\n const encode_text = (text: string) => {\n // Keep delimiters via capture group in split\n const tokens = text.split(split_pattern).filter(Boolean);\n let encoded_chars = \"\";\n for (const token of tokens) {\n if (token in token_hash) {\n encoded_chars += String.fromCharCode(token_hash[token]);\n } else {\n const code = token_array.length;\n token_hash[token] = code;\n token_array.push(token);\n encoded_chars += String.fromCharCode(code);\n }\n }\n return encoded_chars;\n };\n\n return [encode_text(text1), encode_text(text2), token_array];\n}\n\nexport function generate_edits_from_text(\n original_text: string,\n modified_text: string,\n): ModifyText[] {\n const dmp = new diff_match_patch.diff_match_patch();\n dmp.Diff_Timeout = 2.0; // Enforce strict 2-second timeout to prevent deep recursion hangs\n\n const [chars1, chars2, token_array] = _words_to_chars(\n original_text,\n modified_text,\n );\n const diffs = dmp.diff_main(chars1, chars2, false);\n dmp.diff_cleanupSemantic(diffs);\n\n // Manually map characters back to words to bypass prototype volatility (diff_charsToLines_)\n for (let i = 0; i < diffs.length; i++) {\n const chars = diffs[i][1];\n let text = \"\";\n for (let j = 0; j < chars.length; j++)\n text += token_array[chars.charCodeAt(j)];\n diffs[i][1] = text;\n }\n\n const edits: ModifyText[] = [];\n let current_original_index = 0;\n let pending_delete: [number, string] | null = null;\n\n for (const [op, text] of diffs) {\n if (op === 0) {\n // Equal\n if (pending_delete) {\n const [idx, del_txt] = pending_delete;\n edits.push({\n type: \"modify\",\n target_text: del_txt,\n new_text: \"\",\n comment: \"Diff: Text deleted\",\n _match_start_index: idx,\n });\n pending_delete = null;\n }\n current_original_index += text.length;\n } else if (op === -1) {\n // Delete\n pending_delete = [current_original_index, text];\n current_original_index += text.length;\n } else if (op === 1) {\n // Insert\n if (pending_delete) {\n const [idx, del_txt] = pending_delete;\n edits.push({\n type: \"modify\",\n target_text: del_txt,\n new_text: text,\n comment: \"Diff: Replacement\",\n _match_start_index: idx,\n });\n pending_delete = null;\n } else {\n edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: text,\n comment: \"Diff: Text inserted\",\n _match_start_index: current_original_index,\n });\n }\n }\n }\n\n if (pending_delete) {\n const [idx, del_txt] = pending_delete;\n edits.push({\n type: \"modify\",\n target_text: del_txt,\n new_text: \"\",\n comment: \"Diff: Text deleted\",\n _match_start_index: idx,\n });\n }\n\n return edits;\n}\n// ---------------------------------------------------------------------------\n// Structured (part- and table-aware) diff — QA 2026-07-18 C1/C2.\n// ---------------------------------------------------------------------------\n\ntype Opcode = [\n tag: \"equal\" | \"replace\" | \"delete\" | \"insert\",\n i1: number,\n i2: number,\n j1: number,\n j2: number,\n];\n\n/**\n * difflib.SequenceMatcher.get_opcodes() equivalent over string arrays,\n * LCS-based. The row-key arrays this runs on are tiny (table row counts), so\n * the O(n*m) table is negligible. Adjacent non-equal steps coalesce into one\n * \"replace\"/\"delete\"/\"insert\" block exactly like difflib's opcodes.\n */\nfunction _sequence_opcodes(a: string[], b: string[]): Opcode[] {\n const n = a.length;\n const m = b.length;\n // dp[i][j] = LCS length of a[i:] vs b[j:]\n const dp: Int32Array[] = [];\n for (let i = 0; i <= n; i++) dp.push(new Int32Array(m + 1));\n for (let i = n - 1; i >= 0; i--) {\n for (let j = m - 1; j >= 0; j--) {\n dp[i][j] =\n a[i] === b[j]\n ? dp[i + 1][j + 1] + 1\n : Math.max(dp[i + 1][j], dp[i][j + 1]);\n }\n }\n\n const ops: Opcode[] = [];\n let i = 0;\n let j = 0;\n let pend_i1 = 0;\n let pend_j1 = 0;\n let pend_del = 0;\n let pend_ins = 0;\n\n const flushPending = () => {\n if (pend_del === 0 && pend_ins === 0) return;\n const tag =\n pend_del > 0 && pend_ins > 0\n ? \"replace\"\n : pend_del > 0\n ? \"delete\"\n : \"insert\";\n ops.push([tag, pend_i1, pend_i1 + pend_del, pend_j1, pend_j1 + pend_ins]);\n pend_del = 0;\n pend_ins = 0;\n };\n\n while (i < n || j < m) {\n if (i < n && j < m && a[i] === b[j]) {\n flushPending();\n const i1 = i;\n const j1 = j;\n while (i < n && j < m && a[i] === b[j]) {\n i++;\n j++;\n }\n ops.push([\"equal\", i1, i, j1, j]);\n } else {\n if (pend_del === 0 && pend_ins === 0) {\n pend_i1 = i;\n pend_j1 = j;\n }\n if (j < m && (i === n || dp[i][j + 1] >= dp[i + 1][j])) {\n pend_ins++;\n j++;\n } else {\n pend_del++;\n i++;\n }\n }\n }\n flushPending();\n return ops;\n}\n\nconst _IMAGE_MARKER_RE = /!\\[[^\\]]*\\]\\(docx-image:[^)]*\\)/g;\n\n/**\n * Removes generated edits whose image-marker multisets differ between\n * target and new text. The engine (validate_edit_strings) rightly refuses\n * such edits — markers are read-only projections — so emitting them would\n * make the diff pipeline reject its own output. An added/removed image is\n * reported as a warning instead of an unappliable edit.\n */\nfunction _drop_image_marker_hunks(\n edits: ModifyText[],\n warnings: string[],\n): ModifyText[] {\n const _normalized = (s: string): string =>\n s.replace(_IMAGE_MARKER_RE, \"\").replace(/\\s+/g, \" \").trim();\n\n const kept: ModifyText[] = [];\n for (const e of edits) {\n const t_imgs = ((e.target_text || \"\").match(_IMAGE_MARKER_RE) || []).sort();\n const n_imgs = ((e.new_text || \"\").match(_IMAGE_MARKER_RE) || []).sort();\n if (JSON.stringify(t_imgs) === JSON.stringify(n_imgs)) {\n kept.push(e);\n continue;\n }\n if (_normalized(e.target_text || \"\") === _normalized(e.new_text || \"\")) {\n warnings.push(\n \"An inline image was added or removed between the documents. Images cannot be \" +\n \"transferred by text edits — the image-only difference was skipped; apply it \" +\n \"manually in Word.\",\n );\n } else {\n warnings.push(\n \"A text change overlapping an added/removed inline image was skipped — images \" +\n \"cannot be transferred by text edits. Apply that section manually in Word.\",\n );\n }\n }\n return kept;\n}\n\n/**\n * Removes generated hunks whose pinned range cuts INTO a read-only image\n * marker without covering it whole — the shape an alt-text-only difference\n * produces (`RED` -> `BLUE` inside ``). The engine\n * categorically rejects such edits, so emitting them makes diff output\n * unappliable by apply (QA 2026-07-19 F-04/F-14). Hunks that contain\n * complete markers are judged by _drop_image_marker_hunks instead.\n */\nfunction _drop_marker_interior_hunks(\n edits: ModifyText[],\n text_orig: string,\n warnings: string[],\n): ModifyText[] {\n const marker_spans: [number, number][] = [];\n for (const m of text_orig.matchAll(_IMAGE_MARKER_RE)) {\n marker_spans.push([m.index!, m.index! + m[0].length]);\n }\n if (marker_spans.length === 0) return edits;\n\n const kept: ModifyText[] = [];\n let warned = false;\n for (const e of edits) {\n const idx = e._match_start_index;\n if (idx === undefined || idx === null) {\n kept.push(e);\n continue;\n }\n const end = idx + (e.target_text || \"\").length;\n const cuts_into_marker = marker_spans.some(\n ([m_start, m_end]) =>\n m_start < end && idx < m_end && !(idx <= m_start && m_end <= end),\n );\n if (!cuts_into_marker) {\n kept.push(e);\n continue;\n }\n if (!warned) {\n warnings.push(\n \"An image's alternative text differs between the documents. Image markers \" +\n \"() are read-only projections, so this difference cannot be \" +\n \"expressed as a text edit — it was skipped; update the image or its alt text \" +\n \"manually in Word.\",\n );\n warned = true;\n }\n }\n return kept;\n}\n\n/**\n * True when every projected row reads exactly as its cells joined by \" | \".\n * Rows wrapped in tracked-row CriticMarkup ({++ … ++} / {-- … --}) do not,\n * and such tables are diffed as plain text rather than as row structures.\n */\nfunction _rows_are_plain(text: string, table: TableGeometry): boolean {\n for (const row of table.rows) {\n if (text.substring(row.start, row.end) !== row.cells.join(\" | \")) {\n return false;\n }\n }\n return true;\n}\n\nconst _ROW_KEY_SEP = \"\\x1f\";\n\n/**\n * Row-level alignment opcodes between two tables, or null when the row sets\n * differ only cell-internally (no rows added/removed) — the caller then\n * keeps fine-grained word-level text edits instead of row operations.\n */\nfunction _table_row_opcodes(\n rows_o: RowGeometry[],\n rows_m: RowGeometry[],\n): Opcode[] | null {\n const keys_o = rows_o.map((r) => r.cells.join(_ROW_KEY_SEP));\n const keys_m = rows_m.map((r) => r.cells.join(_ROW_KEY_SEP));\n const opcodes = _sequence_opcodes(keys_o, keys_m);\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (\n tag === \"insert\" ||\n tag === \"delete\" ||\n (tag === \"replace\" && i2 - i1 !== j2 - j1)\n ) {\n return opcodes;\n }\n }\n return null;\n}\n\n/**\n * Emits structured operations (delete_row / insert_row / per-row modify)\n * that transform table_o's row set into table_m's, following the alignment\n * `opcodes` from _table_row_opcodes (QA 2026-07-18 C2: a generic text edit\n * cannot add or remove rows — it writes fake pipe text into one cell or is\n * rejected by the cell-count validator).\n */\nfunction _row_ops_for_table(\n table_o: TableGeometry,\n table_m: TableGeometry,\n opcodes: Opcode[],\n warnings: string[],\n): DiffEdit[] {\n const rows_o = table_o.rows;\n const rows_m = table_m.rows;\n const keys_o = rows_o.map((r) => r.cells.join(_ROW_KEY_SEP));\n\n const row_text = (r: RowGeometry): string => r.cells.join(\" | \");\n\n // Duplicate row texts make text-anchored row operations ambiguous. The\n // engine fails closed with a strict-mode ambiguity error at apply time;\n // tell the user up front so the rejection is not a surprise.\n if (new Set(keys_o).size !== keys_o.length) {\n warnings.push(\n \"A table contains rows with identical text; the generated row operations anchor by \" +\n \"row text and may be rejected as ambiguous at apply time. If that happens, apply the \" +\n \"row changes with explicit insert_row/delete_row edits.\",\n );\n }\n\n // Rows removed by the transformation (deletes + surplus rows of shrinking\n // replaces) can never anchor an insert.\n const removed = new Set<number>();\n const replaced_new_text: Record<number, string> = {};\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (tag === \"delete\") {\n for (let k = i1; k < i2; k++) removed.add(k);\n } else if (tag === \"replace\") {\n const pairs = Math.min(i2 - i1, j2 - j1);\n for (let k = i1 + pairs; k < i2; k++) removed.add(k);\n for (let k = 0; k < pairs; k++) {\n replaced_new_text[i1 + k] = row_text(rows_m[j1 + k]);\n }\n }\n }\n\n const surviving: number[] = [];\n for (let k = 0; k < rows_o.length; k++) {\n if (!removed.has(k)) surviving.push(k);\n }\n\n const anchor_text = (orig_idx: number): string => {\n // Anchor on the row's FINAL text: modified rows are matched via the\n // engine's clean-view fallback after their own edit applies.\n return replaced_new_text[orig_idx] !== undefined\n ? replaced_new_text[orig_idx]\n : row_text(rows_o[orig_idx]);\n };\n\n const insert_ops = (\n new_rows: RowGeometry[],\n at_orig_index: number,\n ): DiffEdit[] => {\n const ops: DiffEdit[] = [];\n const before = surviving.filter((k) => k < at_orig_index);\n const after = surviving.filter((k) => k >= at_orig_index);\n if (before.length > 0) {\n // Insert below the preceding surviving row. Emitting in reverse keeps\n // the final order: below-A(B), then below-A(C) yields A,C,B — so emit\n // C first.\n const anchor_idx = before[before.length - 1];\n const anchor = anchor_text(anchor_idx);\n for (const r of [...new_rows].reverse()) {\n ops.push({\n type: \"insert_row\",\n target_text: anchor,\n position: \"below\",\n cells: [...r.cells],\n // Pin to the anchor row's offset: text anchors alone are\n // ambiguous when tables share identical rows. Pins do not\n // survive JSON round-trips (the strict text match applies then,\n // failing closed with the duplicate-row warning above).\n _match_start_index: rows_o[anchor_idx].start,\n });\n }\n } else if (after.length > 0) {\n const anchor_idx = after[0];\n const anchor = anchor_text(anchor_idx);\n for (const r of new_rows) {\n ops.push({\n type: \"insert_row\",\n target_text: anchor,\n position: \"above\",\n cells: [...r.cells],\n _match_start_index: rows_o[anchor_idx].start,\n });\n }\n } else {\n warnings.push(\n \"A table gained rows but no original row survives to anchor them; \" +\n \"these row insertions were skipped — add them with explicit insert_row operations.\",\n );\n }\n return ops;\n };\n\n const ops: DiffEdit[] = [];\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (tag === \"equal\") continue;\n if (tag === \"replace\") {\n const pairs = Math.min(i2 - i1, j2 - j1);\n for (let k = 0; k < pairs; k++) {\n const o_txt = row_text(rows_o[i1 + k]);\n const m_txt = row_text(rows_m[j1 + k]);\n if (o_txt !== m_txt) {\n ops.push({\n type: \"modify\",\n target_text: o_txt,\n new_text: m_txt,\n comment: \"Diff: Table row modified\",\n _is_table_edit: true,\n });\n }\n }\n for (let k = i1 + pairs; k < i2; k++) {\n ops.push({\n type: \"delete_row\",\n target_text: row_text(rows_o[k]),\n _match_start_index: rows_o[k].start,\n });\n }\n const surplus_new = rows_m.slice(j1 + pairs, j2);\n if (surplus_new.length > 0) {\n ops.push(...insert_ops(surplus_new, i2));\n }\n } else if (tag === \"delete\") {\n for (let k = i1; k < i2; k++) {\n ops.push({\n type: \"delete_row\",\n target_text: row_text(rows_o[k]),\n _match_start_index: rows_o[k].start,\n });\n }\n } else if (tag === \"insert\") {\n ops.push(...insert_ops(rows_m.slice(j1, j2), i1));\n }\n }\n return ops;\n}\n\n/**\n * DOCX-to-DOCX diff over projections extracted with return_structure=true.\n *\n * Improvements over a flat generate_edits_from_text pass:\n * - each OPC part (header/body/footer/notes) diffs against its\n * counterpart, so no edit can span a part boundary and content that\n * moved between parts is reported instead of hidden (QA 2026-07-18 C1);\n * - table row insertions/deletions become structured insert_row /\n * delete_row operations instead of pipe-text edits (QA C2).\n *\n * Every ModifyText keeps its _match_start_index pinned into text_orig, which\n * the engine consumes positionally (the Node engine has no\n * make_edits_self_contained JSON round trip like the Python CLI).\n *\n * Returns { edits, warnings }. Warnings describe fallbacks the caller should\n * surface (differing part layouts, unanchorable rows, …).\n */\nexport function generate_structured_edits(\n text_orig: string,\n struct_orig: ExtractStructure,\n text_mod: string,\n struct_mod: ExtractStructure,\n): { edits: DiffEdit[]; warnings: string[] } {\n const warnings: string[] = [];\n const edits: DiffEdit[] = [];\n\n const kinds_o = struct_orig.part_ranges\n .filter(([s, e]) => e > s)\n .map(([, , k]) => k);\n const kinds_m = struct_mod.part_ranges\n .filter(([s, e]) => e > s)\n .map(([, , k]) => k);\n\n if (JSON.stringify(kinds_o) !== JSON.stringify(kinds_m)) {\n warnings.push(\n `The documents have different part layouts (${kinds_o.join(\" + \") || \"none\"} vs ` +\n `${kinds_m.join(\" + \") || \"none\"}); comparing flattened text instead. Header/footer ` +\n \"additions or removals cannot be expressed as text edits.\",\n );\n const flat = _drop_marker_interior_hunks(\n _drop_image_marker_hunks(\n generate_edits_from_text(text_orig, text_mod),\n warnings,\n ),\n text_orig,\n warnings,\n );\n return { edits: [...flat], warnings };\n }\n\n const ranges_o = struct_orig.part_ranges\n .filter(([s, e]) => e > s)\n .map(([s, e]) => [s, e] as [number, number]);\n const ranges_m = struct_mod.part_ranges\n .filter(([s, e]) => e > s)\n .map(([s, e]) => [s, e] as [number, number]);\n\n for (let p = 0; p < ranges_o.length; p++) {\n const [po_start, po_end] = ranges_o[p];\n const [pm_start, pm_end] = ranges_m[p];\n\n const tables_o = struct_orig.tables.filter(\n (t) => po_start <= t.start && t.end <= po_end,\n );\n const tables_m = struct_mod.tables.filter(\n (t) => pm_start <= t.start && t.end <= pm_end,\n );\n\n const tables_alignable =\n tables_o.length === tables_m.length &&\n tables_o.every((t) => _rows_are_plain(text_orig, t)) &&\n tables_m.every((t) => _rows_are_plain(text_mod, t));\n if (tables_o.length !== tables_m.length) {\n warnings.push(\n `A ${kinds_o[p]} part has ${tables_o.length} table(s) in the ` +\n `original but ${tables_m.length} in the modified document; its tables were compared as plain ` +\n \"text. Adding or removing whole tables is not supported via diff/apply.\",\n );\n }\n\n if (!tables_alignable) {\n const part_edits = generate_edits_from_text(\n text_orig.substring(po_start, po_end),\n text_mod.substring(pm_start, pm_end),\n );\n for (const e of part_edits) {\n e._match_start_index = (e._match_start_index || 0) + po_start;\n }\n edits.push(...part_edits);\n continue;\n }\n\n // Walk interleaved segments: text-before-table, table, text-after…\n const boundaries_o: [number, number][] = [\n [po_start, po_start],\n ...tables_o.map((t) => [t.start, t.end] as [number, number]),\n [po_end, po_end],\n ];\n const boundaries_m: [number, number][] = [\n [pm_start, pm_start],\n ...tables_m.map((t) => [t.start, t.end] as [number, number]),\n [pm_end, pm_end],\n ];\n\n for (let seg_idx = 0; seg_idx < boundaries_o.length - 1; seg_idx++) {\n const seg_o_start = boundaries_o[seg_idx][1];\n const seg_o_end = boundaries_o[seg_idx + 1][0];\n const seg_m_start = boundaries_m[seg_idx][1];\n const seg_m_end = boundaries_m[seg_idx + 1][0];\n const seg_edits = generate_edits_from_text(\n text_orig.substring(seg_o_start, seg_o_end),\n text_mod.substring(seg_m_start, seg_m_end),\n );\n for (const e of seg_edits) {\n e._match_start_index = (e._match_start_index || 0) + seg_o_start;\n }\n edits.push(...seg_edits);\n\n if (seg_idx < tables_o.length) {\n const t_o = tables_o[seg_idx];\n const t_m = tables_m[seg_idx];\n const row_opcodes = _table_row_opcodes(t_o.rows, t_m.rows);\n if (row_opcodes !== null) {\n edits.push(..._row_ops_for_table(t_o, t_m, row_opcodes, warnings));\n } else {\n // Cell-internal changes only (row sets align 1:1). Emit one\n // ROW-LEVEL edit per differing row — the engine splits it into\n // per-cell sub-edits along the \" | \" boundaries. A word-level diff\n // over the whole table span produces hunks that start or end\n // inside a cell separator, which apply into the wrong cell or\n // write literal pipe text. Unpinned like every other table edit:\n // pinned application bypasses the cell splitter, and the full row\n // text is the anchor contract.\n for (let k = 0; k < t_o.rows.length; k++) {\n const o_txt = t_o.rows[k].cells.join(\" | \");\n const m_txt = t_m.rows[k].cells.join(\" | \");\n if (o_txt === m_txt) continue;\n edits.push({\n type: \"modify\",\n target_text: o_txt,\n new_text: m_txt,\n comment: \"Diff: Table row modified\",\n _is_table_edit: true,\n });\n }\n }\n }\n }\n }\n\n // Row operations anchor by row text (pins do not survive JSON): if the\n // anchor text also appears elsewhere in the document — e.g. two tables\n // sharing a header row — the strict text match at apply time is\n // ambiguous. In-process consumers ride the pinned offsets; JSON consumers\n // fail closed, so tell the user why up front.\n const countOccurrences = (haystack: string, needle: string): number => {\n let count = 0;\n let from = 0;\n while (true) {\n const idx = haystack.indexOf(needle, from);\n if (idx === -1) break;\n count++;\n from = idx + needle.length;\n }\n return count;\n };\n let ambiguous_anchor_warned = false;\n for (const e of edits) {\n if (\n (e.type === \"insert_row\" ||\n e.type === \"delete_row\" ||\n (e as any)._is_table_edit) &&\n !ambiguous_anchor_warned\n ) {\n if (e.target_text && countOccurrences(text_orig, e.target_text) > 1) {\n warnings.push(\n `The row anchor \"${e.target_text.substring(0, 60)}\" appears more than once in the document. ` +\n \"Applying this diff from its JSON output may be rejected as ambiguous — \" +\n \"make the anchor rows unique, or apply the row changes with explicit \" +\n \"insert_row/delete_row edits.\",\n );\n ambiguous_anchor_warned = true;\n }\n }\n }\n\n // Our own output must never trip the engine's read-only image-marker\n // validation: an added/removed image becomes a warning, not an edit —\n // and so does an alt-text change, whose hunk lands INSIDE a marker.\n const modify_edits = edits.filter(\n (e): e is ModifyText => e.type === \"modify\",\n );\n const kept_modifies = new Set(\n _drop_marker_interior_hunks(\n _drop_image_marker_hunks(modify_edits, warnings),\n text_orig,\n warnings,\n ),\n );\n const final_edits = edits.filter(\n (e) => e.type !== \"modify\" || kept_modifies.has(e as ModifyText),\n );\n\n return { edits: final_edits, warnings };\n}\n\n/**\n * Compares embedded media bytes (word/media/*) between two DOCX packages.\n * Adeu's diff is a text comparison: two documents whose images differ but\n * whose projections agree produce an empty diff, which reads as \"visually\n * identical\" unless the caller says otherwise (QA 2026-07-19 F-04). Returns\n * warning strings describing changed/added/removed media members; empty when\n * the media sets are byte-identical (or either package is unreadable — the\n * caller has already surfaced package-level errors).\n */\nexport function collect_media_difference_warnings(\n original_docx: Uint8Array,\n modified_docx: Uint8Array,\n): string[] {\n const media_hashes = (data: Uint8Array): Map<string, string> => {\n const hashes = new Map<string, string>();\n try {\n const unzipped = unzipSync(data);\n for (const [name, bytes] of Object.entries(unzipped)) {\n if (!name.startsWith(\"word/media/\")) continue;\n // FNV-1a over the bytes: cheap, dependency-free content fingerprint.\n let h1 = 0x811c9dc5;\n let h2 = 0xcbf29ce4;\n for (let i = 0; i < bytes.length; i++) {\n h1 = Math.imul(h1 ^ bytes[i], 0x01000193) >>> 0;\n h2 = Math.imul(h2 ^ bytes[bytes.length - 1 - i], 0x01000193) >>> 0;\n }\n hashes.set(name, `${bytes.length}:${h1.toString(16)}:${h2.toString(16)}`);\n }\n } catch {\n return new Map();\n }\n return hashes;\n };\n\n const hashes_orig = media_hashes(original_docx);\n const hashes_mod = media_hashes(modified_docx);\n\n const changed: string[] = [];\n const added: string[] = [];\n const removed: string[] = [];\n for (const [name, hash] of hashes_orig) {\n if (!hashes_mod.has(name)) removed.push(name);\n else if (hashes_mod.get(name) !== hash) changed.push(name);\n }\n for (const name of hashes_mod.keys()) {\n if (!hashes_orig.has(name)) added.push(name);\n }\n changed.sort();\n added.sort();\n removed.sort();\n if (changed.length + added.length + removed.length === 0) return [];\n\n const parts: string[] = [];\n if (changed.length) parts.push(`${changed.length} changed`);\n if (added.length) parts.push(`${added.length} added`);\n if (removed.length) parts.push(`${removed.length} removed`);\n const names = [...changed, ...added, ...removed].slice(0, 5).join(\", \");\n return [\n `The documents' embedded media differ (${parts.join(\", \")}: ${names}). This diff compares ` +\n \"TEXT only — an empty edit list does not mean the documents are visually identical. \" +\n \"Image changes must be applied manually in Word.\",\n ];\n}\n\nexport function create_unified_diff(\n original_text: string,\n modified_text: string,\n context_lines: number = 3,\n): string {\n const dmp = new diff_match_patch.diff_match_patch();\n dmp.Diff_Timeout = 2.0;\n\n const a = dmp.diff_linesToChars_(original_text, modified_text);\n const diffs = dmp.diff_main(a.chars1, a.chars2, false);\n dmp.diff_charsToLines_(diffs, a.lineArray);\n\n const output: string[] = [];\n output.push(\"--- Original\");\n output.push(\"+++ Modified\");\n\n let i = 0;\n while (i < diffs.length) {\n while (i < diffs.length && diffs[i][0] === 0) i++;\n if (i >= diffs.length) break;\n\n let start = i;\n let preContext: string[] = [];\n if (start > 0 && diffs[start - 1][0] === 0) {\n const lines = diffs[start - 1][1].replace(/\\n$/, \"\").split(\"\\n\");\n preContext = lines.slice(-context_lines);\n }\n\n const chunk: string[] = [];\n chunk.push(...preContext.map((l) => ` ${l}`));\n\n while (i < diffs.length) {\n const [op, text] = diffs[i];\n const lines = text.replace(/\\n$/, \"\").split(\"\\n\");\n\n if (op === 0) {\n if (lines.length > context_lines * 2) break;\n chunk.push(...lines.map((l) => ` ${l}`));\n } else {\n const prefix = op === -1 ? \"-\" : \"+\";\n chunk.push(...lines.map((l) => `${prefix}${l}`));\n }\n i++;\n }\n\n let postContext: string[] = [];\n if (i < diffs.length && diffs[i][0] === 0) {\n const lines = diffs[i][1].replace(/\\n$/, \"\").split(\"\\n\");\n postContext = lines.slice(0, context_lines);\n }\n chunk.push(...postContext.map((l) => ` ${l}`));\n\n output.push(\"@@ ... @@\");\n output.push(...chunk);\n }\n\n if (output.length === 2) return \"\"; // No changes\n return output.join(\"\\n\");\n}\n\nexport function create_word_patch_diff(\n original_text: string,\n modified_text: string,\n original_path: string = \"Original\",\n modified_path: string = \"Modified\"\n): string {\n const edits = generate_edits_from_text(original_text, modified_text);\n const output: string[] = [\n `--- ${original_path}`,\n `+++ ${modified_path}`,\n \"\"\n ];\n \n const CONTEXT_SIZE = 40;\n\n for (const edit of edits) {\n const raw_start = edit._match_start_index || 0;\n const raw_target = edit.target_text || \"\";\n const raw_new = edit.new_text || \"\";\n\n const [prefix_len, suffix_len] = trim_common_context(raw_target, raw_new);\n\n const target_end_in_target = raw_target.length - suffix_len;\n const new_end_in_new = raw_new.length - suffix_len;\n\n const display_target = raw_target.substring(prefix_len, target_end_in_target);\n const display_new = raw_new.substring(prefix_len, new_end_in_new);\n\n const change_start = raw_start + prefix_len;\n const change_end = change_start + display_target.length;\n\n let pre_start = Math.max(0, change_start - CONTEXT_SIZE);\n let pre_context = original_text.substring(pre_start, change_start);\n if (pre_start > 0) pre_context = \"...\" + pre_context;\n\n let post_end = Math.min(original_text.length, change_end + CONTEXT_SIZE);\n let post_context = original_text.substring(change_end, post_end);\n if (post_end < original_text.length) post_context = post_context + \"...\";\n\n pre_context = pre_context.replace(/\\n/g, \" \").replace(/\\r/g, \"\");\n post_context = post_context.replace(/\\n/g, \" \").replace(/\\r/g, \"\");\n\n output.push(\"@@ Word Patch @@\");\n output.push(` ${pre_context}`);\n if (display_target) output.push(`- ${display_target}`);\n if (display_new) output.push(`+ ${display_new}`);\n output.push(` ${post_context}`);\n output.push(\"\");\n }\n\n return output.join(\"\\n\");\n}\n","/**\n * Stateless paginator for projected DOCX Markdown.\n */\n\nconst PAGE_TARGET_CHARS = 19_000;\nconst APPENDIX_MARKER = '<!-- READONLY_BOUNDARY_START -->';\n\nconst _CRITIC_TOKENS: Record<string, string> = {\n '{++': '++}',\n '{--': '--}',\n '{==': '==}',\n '{>>': '<<}',\n};\n\nconst _CHG_ID_PATTERN = /\\bChg:(\\d+)\\b/g;\n\nexport interface PageInfo {\n page: number;\n total_pages: number;\n has_next: boolean;\n has_prev: boolean;\n tracked_change_count: number;\n page_content: string;\n}\n\nexport interface PaginationResult {\n pages: PageInfo[];\n total_pages: number;\n body_pages: string[];\n body_page_offsets: number[];\n}\n\nexport function split_structural_appendix(markdown: string): [string, string] {\n if (!markdown) return ['', ''];\n\n const idx = markdown.indexOf(APPENDIX_MARKER);\n if (idx === -1) return [markdown, ''];\n\n const line_start = markdown.lastIndexOf('\\n', idx) + 1;\n const body = markdown.substring(0, line_start).trimEnd();\n const appendix = markdown.substring(line_start);\n\n return [body, appendix];\n}\n\nexport function paginate(markdown_body: string, structural_appendix: string = ''): PaginationResult {\n if (!markdown_body) {\n const appendix_clean = structural_appendix ? structural_appendix.trim() : '';\n const content = appendix_clean;\n return {\n pages: [{\n page: 1,\n total_pages: 1,\n has_next: false,\n has_prev: false,\n tracked_change_count: _count_tracked_changes(content),\n page_content: content,\n }],\n total_pages: 1,\n body_pages: [''],\n body_page_offsets: [0],\n };\n }\n\n const block_records = _tokenize_into_atomic_blocks(markdown_body);\n const [body_pages, body_page_offsets] = _assemble_pages(block_records);\n\n let final_pages: string[];\n if (structural_appendix && structural_appendix.trim()) {\n const appendix = structural_appendix.trim();\n final_pages = body_pages.map(bp => bp ? `${bp}\\n\\n${appendix}` : appendix);\n } else {\n final_pages = [...body_pages];\n }\n\n const total = final_pages.length;\n const page_infos: PageInfo[] = final_pages.map((content, i) => ({\n page: i + 1,\n total_pages: total,\n has_next: (i + 1 < total),\n has_prev: (i + 1 > 1),\n tracked_change_count: _count_tracked_changes(content),\n page_content: content,\n }));\n\n return {\n pages: page_infos,\n total_pages: total,\n body_pages,\n body_page_offsets,\n };\n}\n\nfunction _tokenize_into_atomic_blocks(markdown_body: string): [string, number][] {\n const raw_blocks = _split_on_safe_paragraph_breaks(markdown_body);\n return _merge_footnote_sections(raw_blocks);\n}\n\nfunction _split_on_safe_paragraph_breaks(text: string): [string, number][] {\n const counters: Record<string, number> = { '++}': 0, '--}': 0, '==}': 0, '<<}': 0 };\n const blocks: [string, number][] = [];\n let block_start = 0;\n let i = 0;\n const n = text.length;\n\n while (i < n) {\n let matched_open = false;\n for (const [open_tok, close_tok] of Object.entries(_CRITIC_TOKENS)) {\n if (text.startsWith(open_tok, i)) {\n counters[close_tok]++;\n i += open_tok.length;\n matched_open = true;\n break;\n }\n }\n if (matched_open) continue;\n\n let matched_close = false;\n for (const close_tok of Object.values(_CRITIC_TOKENS)) {\n if (text.startsWith(close_tok, i)) {\n if (counters[close_tok] > 0) counters[close_tok]--;\n i += close_tok.length;\n matched_close = true;\n break;\n }\n }\n if (matched_close) continue;\n\n if (text[i] === '\\n' && i + 1 < n && text[i + 1] === '\\n') {\n if (Object.values(counters).every(c => c === 0)) {\n const block_text = text.substring(block_start, i);\n if (block_text) blocks.push([block_text, block_start]);\n\n let j = i;\n while (j < n && text[j] === '\\n') j++;\n i = j;\n block_start = i;\n continue;\n }\n }\n\n i++;\n }\n\n if (block_start < n) {\n const block_text = text.substring(block_start, n);\n if (block_text) blocks.push([block_text, block_start]);\n }\n\n return blocks;\n}\n\nfunction _merge_footnote_sections(blocks: [string, number][]): [string, number][] {\n if (!blocks.length) return blocks;\n\n const merged: [string, number][] = [];\n let i = 0;\n\n while (i < blocks.length) {\n const [block_text, block_offset] = blocks[i];\n const stripped = block_text.trimStart();\n const is_section_header = stripped.startsWith('## Footnotes') || stripped.startsWith('## Endnotes');\n\n if (!is_section_header) {\n merged.push([block_text, block_offset]);\n i++;\n continue;\n }\n\n let accumulated_text = block_text;\n let j = i + 1;\n while (j < blocks.length) {\n const [next_text] = blocks[j];\n const next_stripped = next_text.trimStart();\n if (next_stripped.startsWith('[^fn-') || next_stripped.startsWith('[^en-')) {\n accumulated_text = `${accumulated_text}\\n\\n${next_text}`;\n j++;\n } else {\n break;\n }\n }\n\n merged.push([accumulated_text, block_offset]);\n i = j;\n }\n\n return merged;\n}\n\nfunction _assemble_pages(block_records: [string, number][]): [string[], number[]] {\n if (!block_records.length) return [[''], [0]];\n\n const pages: string[] = [];\n const page_starts: number[] = [];\n\n let current_blocks: string[] = [];\n let current_size = 0;\n let current_start = -1;\n\n const flush_current = () => {\n if (current_blocks.length > 0) {\n pages.push(current_blocks.join('\\n\\n'));\n page_starts.push(current_start);\n }\n current_blocks = [];\n current_size = 0;\n current_start = -1;\n };\n\n for (const [block_text, block_offset] of block_records) {\n const block_size = block_text.length;\n const added_size = block_size + (current_blocks.length > 0 ? 2 : 0);\n\n if (current_blocks.length > 0 && current_size + added_size > PAGE_TARGET_CHARS) {\n flush_current();\n }\n\n if (current_blocks.length === 0 && block_size > PAGE_TARGET_CHARS) {\n pages.push(block_text);\n page_starts.push(block_offset);\n continue;\n }\n\n if (current_blocks.length === 0) current_start = block_offset;\n current_blocks.push(block_text);\n current_size += current_size > 0 ? added_size : block_size;\n }\n\n flush_current();\n\n if (!pages.length) return [[''], [0]];\n return [pages, page_starts];\n}\n\nfunction _count_tracked_changes(page_content: string): number {\n const matches = [...page_content.matchAll(_CHG_ID_PATTERN)];\n const distinct = new Set(matches.map(m => m[1]));\n return distinct.size;\n}","import { trim_common_context } from \"./diff.js\";\nimport { ModifyText } from \"./models.js\";\nimport { RegexTimeoutError, userFindAllMatches } from \"./utils/safe-regex.js\";\n\n/** One entry per input edit in apply_edits_to_markdown's edit_reports. */\nexport interface MarkupEditReport {\n index: number;\n status: \"applied\" | \"failed\";\n error: string | null;\n occurrences: number;\n}\nexport const AMBIGUITY_EXAMPLES_CAP = 5;\nexport const AMBIGUITY_CONTEXT_CHARS = 50;\nfunction _should_strip_markers(text: string, marker: string): boolean {\n if (!text.startsWith(marker) || !text.endsWith(marker)) return false;\n if (text.length < marker.length * 2) return false;\n\n const inner = text.substring(marker.length, text.length - marker.length);\n if (!inner) return false;\n\n if (inner.includes(marker)) return false;\n if (!/[a-zA-Z]/.test(inner)) return false;\n\n if (marker === \"__\" && /^\\w+$/.test(inner)) return false;\n if (marker === \"_\") {\n if (inner.includes(\"_\")) return false;\n if (/^[0-9_]+$/.test(inner)) return false;\n }\n\n return true;\n}\n\nfunction _strip_balanced_markers(text: string): [string, string, string] {\n let prefix_markup = \"\";\n let suffix_markup = \"\";\n let clean_text = text;\n\n const markers = [\"**\", \"__\", \"_\", \"*\"];\n\n for (const marker of markers) {\n if (_should_strip_markers(clean_text, marker)) {\n prefix_markup += marker;\n suffix_markup = marker + suffix_markup;\n clean_text = clean_text.substring(\n marker.length,\n clean_text.length - marker.length,\n );\n break;\n }\n }\n\n return [prefix_markup, clean_text, suffix_markup];\n}\n\nexport function _replace_smart_quotes(text: string): string {\n return text\n .replace(/“/g, '\"')\n .replace(/”/g, '\"')\n .replace(/‘/g, \"'\")\n .replace(/’/g, \"'\");\n}\n\n/**\n * Strips markdown formatting markers and builds a position map.\n * Returns [stripped_text, position_map] where position_map[i] = original\n * index. Mirrors Python markup._strip_markdown_for_matching.\n */\nfunction _strip_markdown_for_matching(text: string): [string, number[]] {\n const result: string[] = [];\n const position_map: number[] = [];\n let i = 0;\n\n while (i < text.length) {\n // Skip ** or __\n const pair = text.substring(i, i + 2);\n if (i < text.length - 1 && (pair === \"**\" || pair === \"__\")) {\n i += 2;\n continue;\n }\n // Skip single * or _ that look like markdown (at word boundaries)\n if (text[i] === \"*\" || text[i] === \"_\") {\n const prev_char = i > 0 ? text[i - 1] : \" \";\n const next_char = i < text.length - 1 ? text[i + 1] : \" \";\n // If at boundary (space or start/end), likely markdown\n if (\n [\" \", \"\\n\", \"\\t\"].includes(prev_char) ||\n [\" \", \"\\n\", \"\\t\"].includes(next_char)\n ) {\n i += 1;\n continue;\n }\n }\n\n position_map.push(i);\n result.push(text[i]);\n i += 1;\n }\n\n return [result.join(\"\"), position_map];\n}\n\nfunction _find_safe_boundaries(\n text: string,\n start: number,\n end: number,\n): [number, number] {\n let new_start = start;\n let new_end = end;\n\n const expand_if_unbalanced = (marker: string) => {\n const current_match = text.substring(new_start, new_end);\n const count = (\n current_match.match(new RegExp(marker.replace(/\\*/g, \"\\\\*\"), \"g\")) || []\n ).length;\n\n if (count % 2 !== 0) {\n const suffix = text.substring(new_end);\n if (suffix.startsWith(marker)) {\n new_end += marker.length;\n return;\n }\n const prefix = text.substring(0, new_start);\n if (prefix.endsWith(marker)) {\n new_start -= marker.length;\n return;\n }\n }\n };\n\n for (let i = 0; i < 2; i++) {\n expand_if_unbalanced(\"**\");\n expand_if_unbalanced(\"__\");\n expand_if_unbalanced(\"_\");\n expand_if_unbalanced(\"*\");\n }\n\n return [new_start, new_end];\n}\n\nfunction _refine_match_boundaries(\n text: string,\n start: number,\n end: number,\n): [number, number] {\n const markers = [\"**\", \"__\", \"*\", \"_\"];\n let current_text = text.substring(start, end);\n let best_start = start;\n let best_end = end;\n\n const countMarker = (str: string, mk: string) =>\n (str.match(new RegExp(mk.replace(/\\*/g, \"\\\\*\"), \"g\")) || []).length;\n\n for (const marker of markers) {\n if (current_text.startsWith(marker)) {\n const current_score = countMarker(current_text, marker) % 2;\n const trimmed_text = current_text.substring(marker.length);\n const trimmed_score = countMarker(trimmed_text, marker) % 2;\n\n if (current_score === 1 && trimmed_score === 0) {\n best_start += marker.length;\n current_text = trimmed_text;\n }\n }\n }\n\n for (const marker of markers) {\n if (current_text.endsWith(marker)) {\n const current_score = countMarker(current_text, marker) % 2;\n const trimmed_text = current_text.substring(\n 0,\n current_text.length - marker.length,\n );\n const trimmed_score = countMarker(trimmed_text, marker) % 2;\n\n if (current_score === 1 && trimmed_score === 0) {\n best_end -= marker.length;\n current_text = trimmed_text;\n }\n }\n }\n\n return [best_start, best_end];\n}\n\nexport function _make_fuzzy_regex(target_text: string): string {\n target_text = _replace_smart_quotes(target_text);\n\n const parts: string[] = [];\n const token_pattern = /(_+)|(\\s+)|(['\"])|([.,;:\\/\\-\\[\\](){}+=$?*!|#^<>\\\\%&@~`])/g;\n\n // Note: JS does not support atomic groups (?>...).\n // However, because we only match markdown characters * and _,\n // we can use a character class `[*_]*` which is mathematically equivalent\n // to `(?:\\*\\*|__|\\*|_)*` but fundamentally immune to catastrophic backtracking!\n const md_noise = \"[*_]*\";\n const structural_noise = \"(?:\\\\s*(?:[*+\\\\->]|\\\\d+\\\\.)\\\\s+|\\\\s*\\\\n\\\\s*)\";\n\n const start_list_marker = \"(?:[ \\\\t]*(?:[*+\\\\->]|\\\\d+\\\\.)\\\\s+)?\";\n parts.push(start_list_marker);\n parts.push(md_noise);\n\n let last_idx = 0;\n let match;\n\n const escapeRegExp = (str: string) =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n while ((match = token_pattern.exec(target_text)) !== null) {\n const literal = target_text.substring(last_idx, match.index);\n if (literal) {\n parts.push(escapeRegExp(literal));\n parts.push(md_noise);\n }\n\n const g_underscore = match[1];\n const g_space = match[2];\n const g_quote = match[3];\n const g_punct = match[4];\n\n if (g_underscore) {\n parts.push(\"_+\");\n } else if (g_space) {\n if (g_space.includes(\"\\n\")) {\n parts.push(`(?:${structural_noise}|\\\\s+)+`);\n } else {\n parts.push(\"\\\\s+\");\n }\n } else if (g_quote) {\n if (g_quote === \"'\") parts.push(\"[\\u2018\\u2019']\");\n else parts.push('[\"\\u201c\\u201d]');\n } else if (g_punct) {\n parts.push(escapeRegExp(g_punct));\n }\n\n parts.push(md_noise);\n last_idx = token_pattern.lastIndex;\n }\n\n const remaining = target_text.substring(last_idx);\n if (remaining) parts.push(escapeRegExp(remaining));\n\n return parts.join(\"\");\n}\n\nexport function _find_match_in_text(\n text: string,\n target: string,\n): [number, number] {\n const matches = _find_all_matches_in_text(text, target);\n if (matches.length > 0) return matches[0];\n return [-1, -1];\n}\n\n/**\n * Every non-overlapping match of `target` in `text` as [start, end] pairs,\n * using the SAME strategy ladder as the apply engine's\n * DocumentMapper.find_all_match_indices: regex (when requested) or\n * exact → smart-quote-normalized → fuzzy. Markup previews must resolve\n * matching identically to apply, or the preview lies (QA 2026-07-18 M1).\n */\nexport function _find_all_matches_in_text(\n text: string,\n target: string,\n is_regex = false,\n): [number, number][] {\n if (!target) return [];\n\n if (is_regex) {\n // Same semantics as the mapper: budgeted user regex; an invalid pattern\n // simply produces no matches (surfaced as \"not found\").\n // RegexTimeoutError propagates for a clean per-edit error.\n try {\n return userFindAllMatches(target, text).map((m) => [m.start, m.end]);\n } catch (e) {\n if (e instanceof RegexTimeoutError) throw e;\n return [];\n }\n }\n\n // Literal indexOf scans (no RegExp over an arbitrarily long escaped\n // target, mirroring the mapper's exact tiers).\n const findAllLiteral = (\n haystack: string,\n needle: string,\n ): [number, number][] => {\n const out: [number, number][] = [];\n let from = 0;\n while (true) {\n const idx = haystack.indexOf(needle, from);\n if (idx === -1) break;\n out.push([idx, idx + needle.length]);\n from = idx + needle.length;\n }\n return out;\n };\n\n // 1. Exact matches\n let spans = findAllLiteral(text, target);\n if (spans.length > 0) {\n return spans.map(([s, e]) => _find_safe_boundaries(text, s, e));\n }\n\n // 2. Smart quote normalization\n const norm_text = _replace_smart_quotes(text);\n const norm_target = _replace_smart_quotes(target);\n spans = findAllLiteral(norm_text, norm_target);\n if (spans.length > 0) {\n return spans.map(([s, e]) => _find_safe_boundaries(text, s, e));\n }\n\n // 3. Markdown-stripped match, mirroring the mapper's strip-markdown and\n // plain-projection rungs: a plain target must find text whose projection\n // carries **bold**/_italic_ markers (even mid-word), and a marked target\n // must find plain text.\n const [stripped_text, pos_map] = _strip_markdown_for_matching(norm_text);\n const [stripped_target] = _strip_markdown_for_matching(norm_target);\n if (\n stripped_target &&\n (stripped_text !== norm_text || stripped_target !== norm_target)\n ) {\n const results: [number, number][] = [];\n for (const [p_start, p_end] of findAllLiteral(stripped_text, stripped_target)) {\n const raw_start = pos_map[p_start];\n const raw_end = pos_map[p_end - 1] + 1;\n results.push(_find_safe_boundaries(text, raw_start, raw_end));\n }\n if (results.length > 0) return results;\n }\n\n // 4. Fuzzy regex matches (handles markdown noise, list markers, etc.).\n // The [*_]* character classes in _make_fuzzy_regex prevent catastrophic\n // backtracking.\n try {\n const pattern = new RegExp(_make_fuzzy_regex(target), \"g\");\n const results: [number, number][] = [];\n for (const match of text.matchAll(pattern)) {\n const [refined_start, refined_end] = _refine_match_boundaries(\n text,\n match.index!,\n match.index! + match[0].length,\n );\n results.push(_find_safe_boundaries(text, refined_start, refined_end));\n }\n if (results.length > 0) return results;\n } catch (e) {\n // Ignore regex compilation errors from edge cases\n }\n\n return [];\n}\n\nexport function _build_critic_markup(\n target_text: string,\n new_text: string,\n comment: string | null | undefined,\n edit_index: number,\n include_index: boolean,\n highlight_only: boolean,\n): string {\n const parts: string[] = [];\n\n let [prefix_markup, clean_target, suffix_markup] =\n _strip_balanced_markers(target_text);\n\n let clean_new = new_text;\n if (prefix_markup && new_text) {\n if (\n new_text.startsWith(prefix_markup) &&\n new_text.endsWith(suffix_markup)\n ) {\n const inner_len = prefix_markup.length;\n clean_new =\n new_text.length > inner_len * 2\n ? new_text.substring(inner_len, new_text.length - inner_len)\n : new_text;\n }\n }\n\n parts.push(prefix_markup);\n\n if (highlight_only) {\n parts.push(`{==${clean_target}==}`);\n } else {\n const has_target = Boolean(clean_target);\n const has_new = Boolean(clean_new);\n\n if (has_target && !has_new) parts.push(`{--${clean_target}--}`);\n else if (!has_target && has_new) parts.push(`{++${clean_new}++}`);\n else if (has_target && has_new)\n parts.push(`{--${clean_target}--}{++${clean_new}++}`);\n }\n\n parts.push(suffix_markup);\n\n const meta_parts: string[] = [];\n if (comment) meta_parts.push(comment);\n if (include_index) meta_parts.push(`[Edit:${edit_index}]`);\n\n if (meta_parts.length > 0) {\n parts.push(`{>>${meta_parts.join(\" \")}<<}`);\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Applies edits to Markdown text and returns CriticMarkup-annotated output.\n *\n * Edit resolution follows the SAME semantics as `apply` (QA 2026-07-18 M1):\n * - `regex: true` targets match as regular expressions\n * - `match_mode` is honored: \"strict\" (default) refuses ambiguous targets,\n * \"first\" marks the first occurrence, \"all\" marks every occurrence\n * - a missing target is a per-edit failure, never a silent skip\n *\n * When `edit_reports` is provided, one entry per input edit is appended:\n * { index: 0-based input position, status: \"applied\"|\"failed\",\n * error: string|null, occurrences: number }.\n */\nexport function apply_edits_to_markdown(\n markdown_text: string,\n edits: ModifyText[],\n include_index = false,\n highlight_only = false,\n edit_reports?: MarkupEditReport[],\n): string {\n if (!edits || edits.length === 0) return markdown_text;\n\n const _report = (\n idx: number,\n status: \"applied\" | \"failed\",\n error: string | null = null,\n occurrences = 0,\n ) => {\n if (edit_reports) edit_reports.push({ index: idx, status, error, occurrences });\n };\n\n // Step 1: Find match positions for each edit\n const matched_edits: [number, number, string, ModifyText, number][] = [];\n\n for (let idx = 0; idx < edits.length; idx++) {\n const edit = edits[idx];\n const target = edit.target_text || \"\";\n const match_mode = (edit as any).match_mode || \"strict\";\n const is_regex = Boolean((edit as any).regex);\n\n if (!target) {\n _report(\n idx,\n \"failed\",\n `- Edit ${idx + 1} Failed: target_text is empty. Pure insertions are expressed as a ` +\n \"replacement: put the text immediately around the insertion point in target_text and \" +\n \"repeat it (plus the new text) in new_text.\",\n );\n continue;\n }\n\n let spans: [number, number][];\n try {\n spans = _find_all_matches_in_text(markdown_text, target, is_regex);\n } catch (e) {\n if (!(e instanceof RegexTimeoutError)) throw e;\n _report(idx, \"failed\", `- Edit ${idx + 1} Failed: ${e.message}`);\n continue;\n }\n\n if (spans.length === 0) {\n _report(\n idx,\n \"failed\",\n `- Edit ${idx + 1} Failed: Target text not found in document:\\n \"${target.substring(0, 80)}\"`,\n );\n continue;\n }\n\n if (spans.length > 1 && match_mode === \"strict\") {\n _report(\n idx,\n \"failed\",\n format_ambiguity_error(idx + 1, target, markdown_text, spans),\n );\n continue;\n }\n\n const selected =\n match_mode === \"strict\" || match_mode === \"first\" ? spans.slice(0, 1) : spans;\n for (const [start, end] of selected) {\n matched_edits.push([start, end, markdown_text.substring(start, end), edit, idx]);\n }\n _report(idx, \"applied\", null, selected.length);\n }\n\n // Step 2: Check for overlapping edits\n const matched_edits_filtered: [number, number, string, ModifyText, number][] =\n [];\n const occupied_ranges: [number, number][] = [];\n\n matched_edits.sort((a, b) => a[4] - b[4]);\n\n for (const [start, end, actual_text, edit, orig_idx] of matched_edits) {\n let overlaps = false;\n for (const [occ_start, occ_end] of occupied_ranges) {\n if (start < occ_end && end > occ_start) {\n overlaps = true;\n if (edit_reports) {\n const msg = `- Edit ${orig_idx + 1} Failed: overlaps with a previously matched edit.`;\n for (const r of edit_reports) {\n if (r.index === orig_idx) {\n r.status = \"failed\";\n r.error = msg;\n r.occurrences = 0;\n }\n }\n }\n break;\n }\n }\n\n if (!overlaps) {\n matched_edits_filtered.push([start, end, actual_text, edit, orig_idx]);\n occupied_ranges.push([start, end]);\n }\n }\n\n matched_edits_filtered.sort((a, b) => b[0] - a[0]);\n\n let result = markdown_text;\n\n for (const [\n start,\n end,\n actual_text,\n edit,\n orig_idx,\n ] of matched_edits_filtered) {\n const new_txt = edit.new_text || \"\";\n const [prefix_len, suffix_len] = trim_common_context(actual_text, new_txt);\n\n const unmodified_prefix =\n prefix_len > 0 ? actual_text.substring(0, prefix_len) : \"\";\n const unmodified_suffix =\n suffix_len > 0\n ? actual_text.substring(actual_text.length - suffix_len)\n : \"\";\n\n const t_end = actual_text.length - suffix_len;\n const n_end = new_txt.length - suffix_len;\n\n const isolated_target = actual_text.substring(prefix_len, t_end);\n const isolated_new = new_txt.substring(prefix_len, n_end);\n\n const markup = _build_critic_markup(\n isolated_target,\n isolated_new,\n edit.comment,\n // 1-based, matching apply's \"Edit N\" reports and batch validation\n // errors (QA 2026-07-17 F10; mirrors Python).\n orig_idx + 1,\n include_index,\n highlight_only,\n );\n\n const full_replacement = unmodified_prefix + markup + unmodified_suffix;\n result =\n result.substring(0, start) + full_replacement + result.substring(end);\n }\n\n return result;\n}\nexport function format_ambiguity_error(\n edit_index: number,\n target_text: string,\n haystack: string,\n match_positions: [number, number][],\n): string {\n const total = match_positions.length;\n if (total < 2) {\n throw new Error(\n `format_ambiguity_error requires at least 2 matches, got ${total}`,\n );\n }\n\n const shown = match_positions.slice(0, AMBIGUITY_EXAMPLES_CAP);\n const remaining = total - shown.length;\n\n const lines: string[] = [\n `- Edit ${edit_index} Failed: Ambiguous match. Target text appears ${total} times. First ${shown.length} occurrences:`,\n ];\n\n for (let i = 0; i < shown.length; i++) {\n const [start, end] = shown[i];\n const pre_start = Math.max(0, start - AMBIGUITY_CONTEXT_CHARS);\n const post_end = Math.min(haystack.length, end + AMBIGUITY_CONTEXT_CHARS);\n\n const pre_context = haystack\n .substring(pre_start, start)\n .replace(/\\n/g, \" \");\n const post_context = haystack.substring(end, post_end).replace(/\\n/g, \" \");\n let match_text = haystack.substring(start, end).replace(/\\n/g, \" \");\n\n if (match_text.length > 50) {\n match_text =\n match_text.substring(0, 25) +\n \"...\" +\n match_text.substring(match_text.length - 20);\n }\n\n const prefix_marker = pre_start > 0 ? \"...\" : \"\";\n const suffix_marker = post_end < haystack.length ? \"...\" : \"\";\n\n lines.push(\n ` ${i + 1}. \"${prefix_marker}${pre_context}[${match_text}]${post_context}${suffix_marker}\"`,\n );\n }\n\n if (remaining > 0) {\n lines.push(` ... and ${remaining} more occurrence(s) not shown.`);\n }\n\n // Tell the agent EXACTLY how to re-call. Without this, agents loop forever\n // refining target_text/regex because they never learn that match_mode is the\n // built-in escape hatch for genuine ambiguity. The safe strategy (more\n // context) comes first: blindly switching to \"first\"/\"all\" has silently\n // modified unrelated occurrences — dates, section numbers — in real use\n // (QA C1), so those options carry an explicit verification warning.\n // Wording mirrors the Python engine's format_ambiguity_error.\n lines.push(\" To resolve, re-send this edit using ONE of these strategies:\");\n lines.push(\n \" 1. RECOMMENDED: Provide more surrounding context in your target_text to uniquely \" +\n 'identify a single location (keep the default \"match_mode\": \"strict\").',\n );\n lines.push(\n ` 2. Set \"match_mode\": \"all\" to modify ALL ${total} occurrences — only after verifying ` +\n \"from the occurrence list above that EVERY occurrence should change.\",\n );\n lines.push(\n ' 3. Set \"match_mode\": \"first\" to modify only the FIRST occurrence — only after verifying ' +\n \"the first occurrence above is the one you intend to change.\",\n );\n\n return lines.join(\"\\n\");\n}\n","// FILE: src/utils/text.ts\n// Small text helpers shared by engine output paths. Mirrors the Python\n// engine's adeu/utils/text.py so both engines bound their report output\n// identically (QA C2).\n\n// Default cap for echoing caller-supplied strings (target_text/new_text) back\n// in batch reports and error messages. Reports feed straight into LLM context\n// windows via MCP, so an oversized edit value must never be reflected in full\n// (QA C2: a 2MB new_text was echoed twice, unbounded, in the apply report).\nexport const REPORT_ECHO_CAP = 500;\n\n// Tighter cap for the inline redline preview snippets ({--...--}{++...++}),\n// which additionally carry surrounding document context.\nexport const PREVIEW_TEXT_CAP = 200;\n\n/**\n * Bounds `text` to roughly `cap` visible characters, keeping the head and\n * tail and stating how much was omitted. Returns short strings unchanged.\n */\nexport function truncate_middle(text: string, cap: number): string {\n if (text === null || text === undefined || text.length <= cap) return text;\n const head = Math.max(1, Math.floor((cap * 2) / 3));\n const tail = Math.max(1, cap - head);\n const omitted = text.length - head - tail;\n return `${text.slice(0, head)}… [${omitted.toLocaleString(\"en-US\")} chars omitted] …${text.slice(-tail)}`;\n}\n","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, Run, DocxEvent } from \"./docx/primitives.js\";\nimport { DocumentMapper, TextSpan } from \"./mapper.js\";\nimport { CommentsManager } from \"./comments.js\";\nimport {\n ModifyText,\n InsertTableRow,\n DeleteTableRow,\n AcceptChange,\n RejectChange,\n ReplyComment,\n DocumentChange,\n} from \"./models.js\";\nimport { trim_common_context, generate_edits_from_text } from \"./diff.js\";\nimport { findChild, findAllDescendants, serializeXml } from \"./docx/dom.js\";\nimport { split_structural_appendix, paginate } from \"./pagination.js\";\nimport {\n is_heading_paragraph,\n is_native_heading,\n get_run_style_markers,\n get_run_text,\n apply_formatting_to_segments,\n} from \"./utils/docx.js\";\nimport { format_ambiguity_error } from \"./markup.js\";\nimport {\n PREVIEW_TEXT_CAP,\n REPORT_ECHO_CAP,\n truncate_middle,\n} from \"./utils/text.js\";\nimport { RegexTimeoutError } from \"./utils/safe-regex.js\";\n\n// Width of the surrounding-document window shown in redline previews.\nconst PREVIEW_CONTEXT_CHARS = 30;\n\n// --- DOM Mutation Helpers for xmldom ---\nfunction getNextElement(el: Element): Element | null {\n let next = el.nextSibling;\n while (next) {\n if (next.nodeType === 1) return next as Element;\n next = next.nextSibling;\n }\n return null;\n}\n\nfunction getPreviousElement(el: Element): Element | null {\n let prev = el.previousSibling;\n while (prev) {\n if (prev.nodeType === 1) return prev as Element;\n prev = prev.previousSibling;\n }\n return null;\n}\n\nfunction insertAfter(newNode: Node, refNode: Element) {\n if (refNode.parentNode) {\n refNode.parentNode.insertBefore(newNode, refNode.nextSibling);\n }\n}\n\nfunction insertBefore(newNode: Node, refNode: Element) {\n if (refNode.parentNode) {\n refNode.parentNode.insertBefore(newNode, refNode);\n }\n}\n\nfunction insertAtIndex(parent: Element, index: number, child: Node) {\n const children = Array.from(parent.childNodes).filter(\n (n) => n.nodeType === 1,\n );\n if (index >= children.length) {\n parent.appendChild(child);\n } else {\n parent.insertBefore(child, children[index]);\n }\n}\n\nfunction safeCloneEdit(val: any, seen: WeakMap<any, any> = new WeakMap()): any {\n if (val === null || typeof val !== \"object\") {\n return val;\n }\n if (seen.has(val)) {\n return seen.get(val);\n }\n if (val.nodeType !== undefined || typeof val.cloneNode === \"function\") {\n return val;\n }\n if (Array.isArray(val)) {\n const copy: any[] = [];\n seen.set(val, copy);\n for (let i = 0; i < val.length; i++) {\n copy.push(safeCloneEdit(val[i], seen));\n }\n return copy;\n }\n const copy: any = {};\n seen.set(val, copy);\n for (const key of Object.keys(val)) {\n copy[key] = safeCloneEdit(val[key], seen);\n }\n return copy;\n}\n\nfunction takeSnapshot(doc: any): any {\n const parts = [...doc.pkg.parts];\n const unzipped = { ...doc.pkg.unzipped };\n const rels = new Map<any, Map<string, any>>();\n const elements = new Map<any, Element>();\n for (const part of parts) {\n rels.set(part, new Map(part.rels));\n if (part._element) {\n elements.set(part, part._element.cloneNode(true) as Element);\n }\n }\n return { parts, unzipped, rels, elements };\n}\n\nfunction restoreSnapshot(doc: any, snapshot: any): void {\n doc.pkg.parts = [...snapshot.parts];\n for (const key of Object.keys(doc.pkg.unzipped)) {\n delete doc.pkg.unzipped[key];\n }\n for (const [key, val] of Object.entries(snapshot.unzipped)) {\n doc.pkg.unzipped[key] = val;\n }\n for (const part of snapshot.parts) {\n part.rels = new Map(snapshot.rels.get(part)!);\n const originalEl = snapshot.elements.get(part);\n if (originalEl && part._element) {\n const xmlDoc = part._element.ownerDocument;\n if (xmlDoc && xmlDoc.documentElement) {\n xmlDoc.replaceChild(originalEl, xmlDoc.documentElement);\n }\n part._element = originalEl;\n }\n }\n}\n\nfunction stripMatchingHeadingHashes(\n target: string,\n newText: string,\n): [string, string] {\n if (!target || !newText) return [target, newText];\n const targetMatch = target.match(/^(#+)\\s+/);\n const newMatch = newText.match(/^(#+)\\s+/);\n if (targetMatch && newMatch && targetMatch[1] === newMatch[1]) {\n const hashes = targetMatch[1];\n const targetClean = target.substring(hashes.length).trimStart();\n const newClean = newText.substring(hashes.length).trimStart();\n return [targetClean, newClean];\n }\n return [target, newText];\n}\n\n// --- Validation ---\nexport class BatchValidationError extends Error {\n public errors: string[];\n constructor(errors: string[]) {\n super(\"Batch validation failed:\\n\" + errors.join(\"\\n\"));\n this.name = \"BatchValidationError\";\n this.errors = errors;\n }\n}\n\n// Appended to a validation error when earlier edits in the same batch have\n// already applied: the failing target may simply be stale under the\n// sequential batch contract. Wording mirrors the Python engine exactly.\nfunction sequential_context_hint(applied_so_far: number): string {\n return (\n `\\n Note: ${applied_so_far} earlier edit(s) in this batch were already ` +\n \"applied. Batches apply sequentially — each edit must target the document \" +\n \"text as it reads AFTER the preceding edits (e.g. target the replacement \" +\n \"text an earlier edit introduced, not the original wording).\"\n );\n}\n\n// Report placeholder for edits blocked only by OTHER edits' validation\n// failures under the transactional batch contract. Mirrors Python.\nconst TRANSACTIONAL_NOT_APPLIED_ERROR =\n \"Not applied: the batch is transactional and other edits failed \" +\n \"validation (see their errors). Fix or remove those edits and re-run.\";\n\n// Characters XML 1.0 cannot represent: C0 controls except tab/newline/CR.\n// Word refuses to open a package carrying them, and @xmldom serializes them\n// silently, so they must be rejected before they reach the DOM\n// (QA 2026-07-17 F11; mirrors Python's clean per-edit error).\nconst XML_ILLEGAL_CHARS_RE = /[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g;\n\nexport function describe_illegal_control_chars(text: string): string | null {\n if (!text) return null;\n const found = text.match(XML_ILLEGAL_CHARS_RE);\n if (!found) return null;\n const codes = Array.from(new Set(found.map((c) => `0x${c.charCodeAt(0).toString(16).padStart(2, \"0\")}`))).sort();\n return codes.join(\", \");\n}\n\nexport function validate_edit_strings(\n edits: any[],\n index_offset: number = 0,\n): string[] {\n const errors: string[] = [];\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const t_text = edit.target_text || \"\";\n const n_text = edit.new_text || \"\";\n\n // VAL-CRIT-8: XML-illegal control characters (QA 2026-07-17 F11).\n const checked_fields: Array<[string, string]> = [\n [\"target_text\", t_text],\n [\"new_text\", n_text],\n ];\n if (edit.comment) checked_fields.push([\"comment\", edit.comment]);\n (edit.cells || []).forEach((cell: string, cell_idx: number) => {\n checked_fields.push([`cells[${cell_idx}]`, cell || \"\"]);\n });\n for (const [field_name, field_value] of checked_fields) {\n const described = describe_illegal_control_chars(field_value);\n if (described) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: \\`${field_name}\\` contains control character(s) ` +\n `(${described}) that cannot be stored in a DOCX. Remove them and re-submit.`,\n );\n }\n }\n\n if (\n n_text.includes(\"{++\") ||\n n_text.includes(\"{--\") ||\n n_text.includes(\"{>>\") ||\n n_text.includes(\"{==\")\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Do not manually write CriticMarkup tags ({++, {--, {>>, {==) in \\`new_text\\`. The engine handles redlining automatically. To add a comment, use the \\`comment\\` parameter.`,\n );\n }\n\n if (t_text.includes(\"[^\") || n_text.includes(\"[^\")) {\n const t_fns = (t_text.match(/\\[\\^(?:fn|en)-[^\\]]+\\]/g) || []).sort();\n const n_fns = (n_text.match(/\\[\\^(?:fn|en)-[^\\]]+\\]/g) || []).sort();\n if (JSON.stringify(t_fns) !== JSON.stringify(n_fns)) {\n if (\n n_fns.length > t_fns.length ||\n n_fns.some(\n (f: string) =>\n n_fns.filter((x: string) => x === f).length >\n t_fns.filter((x: string) => x === f).length,\n )\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot insert footnote/endnote markers via text replace. Markers like \\`[^fn-N]\\` are read-only projections. Use Word's References menu.`,\n );\n } else {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot delete footnote/endnote references via text replace. The marker corresponds to a structural XML element.`,\n );\n }\n }\n }\n\n if (t_text.includes(\"](\") || n_text.includes(\"](\")) {\n const t_links = (t_text.match(/\\[(?!~)[^\\]]+\\]\\([^)]+\\)/g) || []).sort();\n const n_links = (n_text.match(/\\[(?!~)[^\\]]+\\]\\([^)]+\\)/g) || []).sort();\n if (t_links.length !== n_links.length) {\n if (n_links.length > t_links.length) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot insert hyperlinks via text replace. Use a dedicated structural operation.`,\n );\n } else {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot delete hyperlinks via text replace. The marker corresponds to a structural XML element.`,\n );\n }\n } else if (\n t_links.length > 1 &&\n JSON.stringify(t_links) !== JSON.stringify(n_links)\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Can only edit or retarget one hyperlink per text replacement. Please split into multiple edits.`,\n );\n }\n }\n\n if (t_text.includes(\"[~\") || n_text.includes(\"[~\")) {\n const t_xrefs = t_text.match(/\\[~[^~]+~\\]\\(#[^\\)]+\\)/g) || [];\n const n_xrefs = n_text.match(/\\[~[^~]+~\\]\\(#[^\\)]+\\)/g) || [];\n if (t_xrefs.length !== n_xrefs.length) {\n if (n_xrefs.length > t_xrefs.length) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot insert cross-references via text replace. Markers are read-only projections.`,\n );\n } else {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot delete cross-references via text replace. The marker corresponds to a structural XML element.`,\n );\n }\n } else {\n // Advanced XREF validation simplified for port scope\n if (JSON.stringify(t_xrefs) !== JSON.stringify(n_xrefs)) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Modifying or retargeting cross-reference markers is disallowed to prevent dependency corruption.`,\n );\n }\n }\n }\n\n // QA 2026-07-18 M5: image markers are read-only projections of\n // w:drawing elements. They cannot be fabricated, duplicated or removed\n // through text replacement.\n if (t_text.includes(\"docx-image:\") || n_text.includes(\"docx-image:\")) {\n const t_imgs = (t_text.match(/!\\[[^\\]]*\\]\\(docx-image:[^)]*\\)/g) || []).sort();\n const n_imgs = (n_text.match(/!\\[[^\\]]*\\]\\(docx-image:[^)]*\\)/g) || []).sort();\n if (JSON.stringify(t_imgs) !== JSON.stringify(n_imgs)) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: image markers () are read-only ` +\n \"projections of embedded images. They cannot be inserted, altered, or removed \" +\n \"via text replacement — edit the text around the image instead.\",\n );\n }\n }\n\n if (t_text.includes(\"{#\") || n_text.includes(\"{#\")) {\n const t_anchors = t_text.match(/\\{#[^\\}]+\\}/g) || [];\n const n_anchors = n_text.match(/\\{#[^\\}]+\\}/g) || [];\n for (const a of n_anchors) {\n if (\n n_anchors.filter((x: string) => x === a).length >\n t_anchors.filter((x: string) => x === a).length\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot modify or insert internal anchor markers (\\`{#...}\\`). These represent structural XML bookmarks.`,\n );\n break;\n }\n }\n }\n\n if (edit.type === \"modify\" && n_text) {\n const lines = n_text.split(/[\\r\\n]+/);\n for (const line of lines) {\n const stripped = line.trimStart();\n if (stripped.startsWith(\"#######\")) {\n const level = stripped.length - stripped.replace(/^#+/, \"\").length;\n if (\n stripped.substring(level).startsWith(\" \") ||\n stripped.substring(level) === \"\"\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Heading level ${level} is not supported (maximum is 6).`,\n );\n break;\n }\n }\n }\n }\n\n if (\n t_text.includes(\"READONLY_BOUNDARY_START\") ||\n n_text.includes(\"READONLY_BOUNDARY_START\") ||\n t_text.includes(\"# Document Structure (Read-Only)\") ||\n n_text.includes(\"# Document Structure (Read-Only)\") ||\n t_text.includes(\"Document Structure (Read-Only)\") ||\n n_text.includes(\"Document Structure (Read-Only)\")\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Modification targets the read-only boundary (Structural Appendix). This section cannot be edited.`,\n );\n }\n }\n\n return errors;\n}\n\n// --- Engine ---\nexport class RedlineEngine {\n public doc: DocumentObject;\n public author: string;\n public timestamp: string;\n public current_id: number;\n public mapper: DocumentMapper;\n public comments_manager: CommentsManager;\n public clean_mapper: DocumentMapper | null = null;\n public original_mapper: DocumentMapper | null = null;\n public skipped_details: string[] = [];\n\n constructor(doc: DocumentObject, author: string = \"Adeu AI (TS)\") {\n this.doc = doc;\n this.author = author;\n this.timestamp = new Date().toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n\n const w16du_ns =\n \"http://schemas.microsoft.com/office/word/2023/wordml/word16du\";\n for (const part of this.doc.pkg.parts) {\n if (part === this.doc.part) {\n if (!part._element.hasAttribute(\"xmlns:w16du\")) {\n part._element.setAttribute(\"xmlns:w16du\", w16du_ns);\n }\n }\n }\n\n this.current_id = this._scan_existing_ids();\n this.mapper = new DocumentMapper(this.doc);\n this.comments_manager = new CommentsManager(this.doc);\n }\n\n /**\n * Return a hint when a short, single-token anchor contains punctuation that\n * can split awkwardly, else null.\n *\n * Surface this ONLY for edits that actually failed to match/apply. On a\n * successful edit the batch report already carries the redline preview, so\n * emitting this would be a false positive: the punctuation (dates,\n * `[_name_]` placeholders, `____` blanks) is frequently the literal target\n * and the edit succeeds despite it. Mirrors the Python engine.\n */\n private _check_punctuation_warning(target_text: string): string | null {\n if (!target_text) return null;\n if (target_text.length > 20 || target_text.includes(\" \")) return null;\n if (target_text.includes(\"_\") || target_text.includes(\"-\")) {\n return `Warning: target_text '${target_text}' contains tokenization-splitting punctuation ('_' or '-'). This can trigger mid-word splits in the diff engine. Consider using a longer plain-prose anchor.`;\n }\n return null;\n }\n\n private _word_diff_sub_edits(\n target_str: string,\n new_str: string,\n base_offset: number,\n parent_comment: string | null = null,\n is_table: boolean = false,\n active_mapper: any = null,\n ): any[] {\n let raw_sub_edits: any[] = [];\n try {\n raw_sub_edits = generate_edits_from_text(target_str, new_str);\n } catch (e) {\n console.error(\"generate_edits_from_text failed, falling back to wholesale edit\", e);\n raw_sub_edits = [];\n }\n\n // Hunks made purely of style markers are projection artifacts, never\n // user intent: they arise when a PLAIN target fuzzy-matched styled\n // document text (\"Net 90 Days\" against \"**Net 90 Days**\"), and the\n // resulting `**`-deletion sub-edits target virtual spans that can never\n // apply — phantom skips while the formatting silently stays (QA\n // 2026-07-19 F-02 sibling). Edits that DO declare markers never reach\n // this word-diff path (they resolve as whole-span markdown proxies).\n const _marker_only = (text: string): boolean => {\n const stripped = text.trim();\n return stripped.length > 0 && /^[*_]+$/.test(stripped);\n };\n raw_sub_edits = raw_sub_edits.filter(\n (e: any) =>\n !(\n (!e.target_text || _marker_only(e.target_text)) &&\n (!e.new_text || _marker_only(e.new_text)) &&\n (e.target_text || e.new_text)\n ),\n );\n\n if (!raw_sub_edits || raw_sub_edits.length === 0) {\n const fallback_edit: any = {\n type: \"modify\",\n target_text: target_str,\n new_text: new_str,\n comment: parent_comment,\n };\n fallback_edit._resolved_start_idx = base_offset;\n fallback_edit._match_start_index = base_offset;\n fallback_edit._active_mapper_ref = active_mapper;\n if (is_table) {\n fallback_edit._is_table_edit = true;\n }\n if (target_str === new_str) {\n fallback_edit._internal_op = \"COMMENT_ONLY\";\n } else if (!target_str && new_str) {\n fallback_edit._internal_op = \"INSERTION\";\n } else if (target_str && !new_str) {\n fallback_edit._internal_op = \"DELETION\";\n } else if (target_str && new_str) {\n fallback_edit._internal_op = \"MODIFICATION\";\n } else {\n fallback_edit._internal_op = \"COMMENT_ONLY\";\n }\n return [fallback_edit];\n }\n\n const sub_edits: any[] = [];\n let comment_assigned = false;\n for (const raw_edit of raw_sub_edits) {\n const sub_start = base_offset + (raw_edit._match_start_index || 0);\n const should_attach_comment = (parent_comment !== null) && !comment_assigned;\n if (should_attach_comment) {\n comment_assigned = true;\n }\n\n const sub_edit: any = {\n type: \"modify\",\n target_text: raw_edit.target_text,\n new_text: raw_edit.new_text,\n comment: should_attach_comment ? parent_comment : null,\n };\n sub_edit._resolved_start_idx = sub_start;\n sub_edit._match_start_index = sub_start;\n sub_edit._active_mapper_ref = active_mapper;\n if (is_table) {\n sub_edit._is_table_edit = true;\n }\n\n const t_val = raw_edit.target_text;\n const n_val = raw_edit.new_text;\n if (!t_val && n_val) {\n sub_edit._internal_op = \"INSERTION\";\n } else if (t_val && !n_val) {\n sub_edit._internal_op = \"DELETION\";\n } else if (t_val && n_val) {\n sub_edit._internal_op = \"MODIFICATION\";\n } else {\n sub_edit._internal_op = \"COMMENT_ONLY\";\n }\n\n sub_edits.push(sub_edit);\n }\n\n return sub_edits;\n }\n /**\n * Best-effort \"did you mean\" hint for a failed target. The common loop trap\n * (observed in the field) is an anchored regex like `^\\( x \\)$` against a\n * mid-document string: ^/$ bind to the whole full_text, so it never matches\n * even though the literal `( x )` is present. We strip regex anchoring/escapes\n * and probe full_text for a literal occurrence; if found, we tell the model\n * the exact literal that WOULD match so it drops the anchors instead of\n * escalating the regex further.\n */\n private _nearest_match_hint(\n target_text: string | undefined,\n is_regex: boolean,\n ): string {\n if (!target_text) return \"\";\n let probe = target_text;\n if (is_regex) {\n // Strip leading/trailing anchors and surrounding \\s* the model tends to add.\n probe = probe.replace(/^\\^/, \"\").replace(/\\$$/, \"\");\n probe = probe.replace(/^\\\\s\\*/, \"\").replace(/\\\\s\\*$/, \"\");\n // Unescape the common literal escapes so \"\\( x \\)\" -> \"( x )\".\n probe = probe.replace(/\\\\([.^$*+?()[\\]{}|\\\\/])/g, \"$1\");\n }\n probe = probe.trim();\n if (!probe || probe === target_text) {\n // No anchors to strip, or nothing changed: nothing useful to suggest.\n if (!is_regex) return \"\";\n }\n const idx = this.mapper.full_text.indexOf(probe);\n if (idx !== -1) {\n const ctx_start = Math.max(0, idx - 15);\n const ctx_end = Math.min(\n this.mapper.full_text.length,\n idx + probe.length + 15,\n );\n const ctx = this.mapper.full_text\n .substring(ctx_start, ctx_end)\n .replace(/\\n/g, \" \");\n return (\n `\\n Did you mean the literal \"${probe}\"? It appears in the document` +\n ` (…${ctx}…). If you used a regex, drop the ^/$ anchors — they match` +\n ` the start/end of the entire document, not a line.`\n );\n }\n return \"\";\n }\n // CriticMarkup wrapper pairs used when tidying preview context windows.\n private static readonly _PREVIEW_WRAPPER_PAIRS: [string, string][] = [\n [\"{--\", \"--}\"],\n [\"{++\", \"++}\"],\n [\"{==\", \"==}\"],\n [\"{>>\", \"<<}\"],\n ];\n\n /**\n * Makes a fixed-width slice of the raw-view projection presentable: drops\n * complete {>>...<<} meta blocks (annotations of pre-existing changes, not\n * part of this edit) and any wrapper fragments the window boundary chopped\n * in half. Without this, previews leak internal scaffolding like\n * \"[Chg:5 delete]\" (QA H1). Mirrors the Python engine.\n */\n private static _tidy_preview_context(\n snippet: string,\n side: \"before\" | \"after\",\n ): string {\n snippet = snippet.replace(/\\{>>[\\s\\S]*?<<\\}/g, \"\");\n\n for (const [open_tok, close_tok] of RedlineEngine._PREVIEW_WRAPPER_PAIRS) {\n if (side === \"before\") {\n // Cut through the last closer whose opener lies left of the window.\n let depth = 0;\n let cut = 0;\n let i = 0;\n while (i < snippet.length) {\n if (snippet.startsWith(open_tok, i)) {\n depth += 1;\n i += open_tok.length;\n } else if (snippet.startsWith(close_tok, i)) {\n if (depth === 0) cut = i + close_tok.length;\n else depth -= 1;\n i += close_tok.length;\n } else {\n i += 1;\n }\n }\n snippet = snippet.substring(cut);\n } else {\n // Cut from the first opener whose closer lies right of the window.\n const opens: number[] = [];\n let i = 0;\n while (i < snippet.length) {\n if (snippet.startsWith(open_tok, i)) {\n opens.push(i);\n i += open_tok.length;\n } else if (snippet.startsWith(close_tok, i)) {\n if (opens.length > 0) opens.pop();\n i += close_tok.length;\n } else {\n i += 1;\n }\n }\n if (opens.length > 0) snippet = snippet.substring(0, opens[0]);\n }\n }\n\n // 1-2 char remnants of a 3-char wrapper token chopped by the window edge.\n if (side === \"before\") {\n snippet = snippet.replace(/^[-+=<>]{0,2}\\}/, \"\");\n } else {\n snippet = snippet.replace(/\\{[-+=<>]{0,2}$/, \"\");\n }\n return snippet;\n }\n\n /**\n * Snapshots the document text around a resolved edit BEFORE anything is\n * applied. Previews rendered after the batch mutates the DOM cannot slice\n * full_text at the stored offsets: applied edits shift offsets and inject\n * tracked-change markup, garbling previews with unrelated edits and\n * internal scaffolding (QA H1).\n */\n private _capture_preview_context(edit: any): void {\n if (edit.type !== \"modify\") return;\n const start_idx = edit._resolved_start_idx;\n if (start_idx === undefined || start_idx === null) return;\n const active_mapper = edit._active_mapper_ref || this.mapper;\n const full_text = active_mapper.full_text;\n if (!full_text) return;\n const length = (edit.target_text || \"\").length;\n const before = full_text.substring(\n Math.max(0, start_idx - PREVIEW_CONTEXT_CHARS),\n start_idx,\n );\n const after = full_text.substring(\n start_idx + length,\n start_idx + length + PREVIEW_CONTEXT_CHARS,\n );\n edit._preview_context = [\n RedlineEngine._tidy_preview_context(before, \"before\"),\n RedlineEngine._tidy_preview_context(after, \"after\"),\n ];\n }\n\n /**\n * Like _capture_preview_context, but snapshots the context around the\n * ORIGINAL edit's full matched span (stashed by _pre_resolve_heuristic_edit),\n * so the report preview can present the complete logical change of a\n * compound modification instead of its first sub-edit.\n */\n private _capture_parent_preview_context(parent: any): void {\n if (!parent || parent.type !== \"modify\") return;\n if (parent._preview_context || !parent._preview_span) return;\n const [start_idx, match_len] = parent._preview_span;\n const active_mapper = parent._preview_mapper_ref || this.mapper;\n const full_text = active_mapper.full_text;\n if (!full_text) return;\n const before = full_text.substring(\n Math.max(0, start_idx - PREVIEW_CONTEXT_CHARS),\n start_idx,\n );\n const after = full_text.substring(\n start_idx + match_len,\n start_idx + match_len + PREVIEW_CONTEXT_CHARS,\n );\n parent._preview_context = [\n RedlineEngine._tidy_preview_context(before, \"before\"),\n RedlineEngine._tidy_preview_context(after, \"after\"),\n ];\n }\n\n /**\n * Renders the preview from the edit's full matched span. The common\n * prefix/suffix between matched and replacement text is moved into the\n * surrounding context so the {--...--}{++...++} block shows the minimal\n * complete change.\n */\n private _build_full_match_preview(edit: any): [string | null, string | null] {\n let [context_before, context_after] = edit._preview_context as [\n string,\n string,\n ];\n let matched: string = edit._preview_matched_text || \"\";\n let new_text: string =\n edit._preview_new_text !== undefined && edit._preview_new_text !== null\n ? edit._preview_new_text\n : edit.new_text || \"\";\n\n // Heading markdown prefixes are projection artifacts, not literal\n // document text — keep them out of the {--...--}/{++...++} body.\n const [matched_clean, matched_style] = this._parse_markdown_style(matched);\n const [new_clean, new_style] = this._parse_markdown_style(new_text);\n if (matched_style && matched_style.startsWith(\"Heading\")) {\n context_before = context_before + matched.substring(0, matched.length - matched_clean.length);\n matched = matched_clean;\n }\n if (new_style && new_style.startsWith(\"Heading\")) {\n new_text = new_clean;\n }\n\n const [prefix_len, suffix_len] = trim_common_context(matched, new_text);\n let display_target = matched.substring(\n prefix_len,\n matched.length - suffix_len,\n );\n let display_new = new_text.substring(\n prefix_len,\n new_text.length - suffix_len,\n );\n context_before = context_before + matched.substring(0, prefix_len);\n if (suffix_len) {\n context_after = matched.substring(matched.length - suffix_len) + context_after;\n }\n\n display_target = truncate_middle(display_target, PREVIEW_TEXT_CAP);\n display_new = truncate_middle(display_new, PREVIEW_TEXT_CAP);\n let critic_markup: string;\n if (!display_target && !display_new) {\n // Comment-only edit (text unchanged): highlight the anchor instead of\n // rendering an empty change.\n const anchor = truncate_middle(matched, PREVIEW_TEXT_CAP);\n const body = anchor ? `{==${anchor}==}` : \"\";\n critic_markup = `${context_before.substring(0, context_before.length - matched.length)}${body}${context_after}`;\n } else {\n const deletion = display_target ? `{--${display_target}--}` : \"\";\n const insertion = display_new ? `{++${display_new}++}` : \"\";\n critic_markup = `${context_before}${deletion}${insertion}${context_after}`;\n }\n\n let clean_text = critic_markup;\n clean_text = clean_text.replace(/\\{>>[\\s\\S]*?<<\\}/g, \"\");\n clean_text = clean_text.replace(/\\{--[\\s\\S]*?--\\}/g, \"\");\n clean_text = clean_text.replace(/\\{\\+\\+([\\s\\S]*?)\\+\\+\\}/g, \"$1\");\n return [critic_markup, clean_text];\n }\n\n /**\n * The \"new text\" a batch report should show for an edit. InsertTableRow has\n * no new_text field — surface its cell contents rather than a misleading\n * empty string (QA M4).\n */\n private static _report_new_text(edit: any): string {\n if (edit && edit.type === \"insert_row\" && Array.isArray(edit.cells)) {\n return edit.cells.join(\" | \");\n }\n return (edit && edit.new_text) || \"\";\n }\n\n private _build_edit_context_previews(\n edit: any,\n ): [string | null, string | null] {\n if (edit.type !== \"modify\") return [null, null];\n if (edit._preview_span && edit._preview_context) {\n return this._build_full_match_preview(edit);\n }\n if (edit._resolved_proxy_edit) {\n edit = edit._resolved_proxy_edit;\n }\n let start_idx = edit._resolved_start_idx;\n if (start_idx === undefined || start_idx === null) return [null, null];\n let target_text = edit.target_text || \"\";\n let new_text = edit.new_text || \"\";\n\n const [clean_target, target_style] =\n this._parse_markdown_style(target_text);\n if (target_style && target_style.startsWith(\"Heading\")) {\n const prefix_len = target_text.length - clean_target.length;\n start_idx += prefix_len;\n target_text = clean_target;\n }\n\n const [clean_new, new_style] = this._parse_markdown_style(new_text);\n if (new_style && new_style.startsWith(\"Heading\")) {\n new_text = clean_new;\n }\n\n const length = target_text.length;\n let context_before: string;\n let context_after: string;\n if (edit._preview_context) {\n [context_before, context_after] = edit._preview_context;\n } else {\n // Fallback for callers that never went through apply_edits. Only safe\n // while the mapper still reflects the pre-apply document.\n const active_mapper = edit._active_mapper_ref || this.mapper;\n const full_text = active_mapper.full_text;\n if (!full_text) return [null, null];\n context_before = RedlineEngine._tidy_preview_context(\n full_text.substring(\n Math.max(0, start_idx - PREVIEW_CONTEXT_CHARS),\n start_idx,\n ),\n \"before\",\n );\n context_after = RedlineEngine._tidy_preview_context(\n full_text.substring(\n start_idx + length,\n start_idx + length + PREVIEW_CONTEXT_CHARS,\n ),\n \"after\",\n );\n }\n\n // Bound the echoed edit values: previews flow into LLM context windows\n // and must not multiply an oversized new_text/target_text (QA C2).\n const display_target = truncate_middle(target_text, PREVIEW_TEXT_CAP);\n const display_new = truncate_middle(new_text, PREVIEW_TEXT_CAP);\n const insertion = display_new ? `{++${display_new}++}` : \"\";\n const critic_markup = `${context_before}{--${display_target}--}${insertion}${context_after}`;\n\n let clean_text = critic_markup;\n clean_text = clean_text.replace(/\\{>>.*?<<\\}/gs, \"\");\n clean_text = clean_text.replace(/\\{--.*?--\\}/gs, \"\");\n clean_text = clean_text.replace(/\\{\\+\\+(.*?)\\+\\+\\}/gs, \"$1\");\n\n return [critic_markup, clean_text];\n }\n\n private _scan_existing_ids(): number {\n let maxId = 0;\n for (const tag of [\"w:ins\", \"w:del\"]) {\n const elements = findAllDescendants(this.doc.element, tag);\n for (const el of elements) {\n const val = parseInt(el.getAttribute(\"w:id\") || \"0\", 10);\n if (!isNaN(val) && val > maxId) maxId = val;\n }\n }\n return maxId;\n }\n\n private _get_heading_path_and_page(\n start_idx: number,\n text: string,\n page_offsets: number[],\n ): [string, number] {\n let page = 1;\n for (let i = 0; i < page_offsets.length; i++) {\n if (start_idx >= page_offsets[i]) {\n page = i + 1;\n } else {\n break;\n }\n }\n\n const textBefore = text.substring(0, start_idx);\n const lines = textBefore.split(\"\\n\");\n const path: string[] = [];\n let current_level = 999;\n\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i];\n const m = line.match(/^(#{1,6})\\s+(.*)/);\n if (m) {\n const level = m[1].length;\n if (level < current_level) {\n let cleanHeading = m[2]\n .replace(/\\*\\*|__|[*_]/g, \"\")\n .replace(/\\{#[^}]+\\}/g, \"\")\n .trim();\n if (cleanHeading.length > 80) {\n cleanHeading = cleanHeading.substring(0, 80) + \"...\";\n }\n path.unshift(cleanHeading);\n current_level = level;\n if (level === 1) break;\n }\n }\n }\n return [path.join(\" > \"), page];\n }\n\n public accept_all_revisions() {\n const parts_to_process: Element[] = [this.doc.element];\n\n for (const part of this.doc.pkg.parts) {\n if (part === this.doc.part) continue;\n if (\n part.contentType.includes(\"wordprocessingml\") &&\n part.contentType.endsWith(\"+xml\")\n ) {\n parts_to_process.push(part._element);\n }\n }\n\n for (const root_element of parts_to_process) {\n const insNodes = findAllDescendants(root_element, \"w:ins\");\n for (const ins of insNodes) {\n this._clean_wrapping_comments(ins);\n const parent = ins.parentNode as Element | null;\n if (!parent) continue;\n\n if (parent.tagName === \"w:trPr\") {\n parent.removeChild(ins);\n continue;\n }\n\n while (ins.firstChild) {\n parent.insertBefore(ins.firstChild, ins);\n }\n parent.removeChild(ins);\n }\n\n const pNodes = findAllDescendants(root_element, \"w:p\");\n for (const p of pNodes) {\n const pPr = findChild(p, \"w:pPr\");\n if (pPr) {\n const rPr = findChild(pPr, \"w:rPr\");\n const delMark = rPr ? findChild(rPr, \"w:del\") : null;\n if (rPr && delMark) {\n let has_content = false;\n for (const tag of [\"w:t\", \"w:tab\", \"w:br\"]) {\n for (const child of findAllDescendants(p, tag)) {\n if (tag === \"w:t\" && !child.textContent) continue;\n\n let is_deleted = false;\n let curr = child.parentNode as Element | null;\n while (curr && curr !== p) {\n if (curr.tagName === \"w:del\") {\n is_deleted = true;\n break;\n }\n curr = curr.parentNode as Element | null;\n }\n if (!is_deleted) {\n has_content = true;\n break;\n }\n }\n if (has_content) {\n break;\n }\n }\n if (has_content) {\n rPr.removeChild(delMark);\n } else {\n this._clean_wrapping_comments(p);\n this._delete_comments_in_element(p);\n if (p.parentNode) {\n p.parentNode.removeChild(p);\n }\n }\n }\n }\n }\n\n const delNodes = findAllDescendants(root_element, \"w:del\");\n for (const d of delNodes) {\n this._clean_wrapping_comments(d);\n this._delete_comments_in_element(d);\n const parent = d.parentNode as Element | null;\n if (parent) {\n if (parent.tagName === \"w:trPr\") {\n const row = parent.parentNode as Element | null;\n if (row && row.parentNode) {\n row.parentNode.removeChild(row);\n }\n } else {\n parent.removeChild(d);\n }\n }\n }\n }\n\n // Final pass: completely eject all comments, anchors, and parts\n for (const root_element of parts_to_process) {\n for (const tag of [\"w:commentRangeStart\", \"w:commentRangeEnd\"]) {\n for (const el of findAllDescendants(root_element, tag)) {\n el.parentNode?.removeChild(el);\n }\n }\n\n const refs = findAllDescendants(root_element, \"w:commentReference\");\n for (const ref of refs) {\n const parent = ref.parentNode as Element | null;\n if (parent) {\n if (parent.tagName === \"w:r\" || parent.tagName.endsWith(\":r\")) {\n const nonRprChildren = Array.from(parent.childNodes).filter(\n (c) =>\n c.nodeType === 1 &&\n (c as Element).tagName !== \"w:rPr\" &&\n (c as Element).tagName !== \"rPr\",\n );\n if (nonRprChildren.length <= 1) {\n parent.parentNode?.removeChild(parent);\n } else {\n parent.removeChild(ref);\n }\n } else {\n parent.removeChild(ref);\n }\n }\n }\n }\n\n const pkg = this.doc.pkg;\n const comment_partnames = new Set<string>();\n for (const part of pkg.parts) {\n if (part.partname.toLowerCase().includes(\"comments\")) {\n comment_partnames.add(part.partname);\n const withSlash = part.partname.startsWith(\"/\")\n ? part.partname\n : \"/\" + part.partname;\n const withoutSlash = part.partname.startsWith(\"/\")\n ? part.partname.substring(1)\n : part.partname;\n comment_partnames.add(withSlash);\n comment_partnames.add(withoutSlash);\n }\n }\n\n if (comment_partnames.size > 0) {\n // Sever relationships referencing comments\n for (const part of pkg.parts) {\n if (part.partname.endsWith(\".rels\")) {\n const rels = findAllDescendants(part._element, \"Relationship\");\n const toRemove: Element[] = [];\n for (const rel of rels) {\n const target = rel.getAttribute(\"Target\") || \"\";\n if (target.toLowerCase().includes(\"comments\")) {\n toRemove.push(rel);\n\n const sourcePath = part.partname\n .replace(\"/_rels/\", \"/\")\n .replace(\".rels\", \"\");\n const sourcePart = pkg.getPartByPath(sourcePath);\n if (sourcePart) {\n const relId = rel.getAttribute(\"Id\");\n if (relId) sourcePart.rels.delete(relId);\n }\n }\n }\n for (const relEl of toRemove) {\n relEl.parentNode?.removeChild(relEl);\n }\n }\n }\n\n // Remove overrides from [Content_Types].xml\n const ctPart = pkg.getPartByPath(\"[Content_Types].xml\");\n if (ctPart) {\n const overrides = findAllDescendants(ctPart._element, \"Override\");\n const toRemove: Element[] = [];\n for (const override of overrides) {\n const partName = override.getAttribute(\"PartName\") || \"\";\n if (\n comment_partnames.has(partName) ||\n partName.toLowerCase().includes(\"comments\")\n ) {\n toRemove.push(override);\n }\n }\n for (const overrideEl of toRemove) {\n overrideEl.parentNode?.removeChild(overrideEl);\n }\n }\n\n // Remove comment parts from pkg.parts\n pkg.parts = pkg.parts.filter(\n (p) => !p.partname.toLowerCase().includes(\"comments\"),\n );\n\n // Remove comment files from pkg.unzipped\n for (const key of Object.keys(pkg.unzipped)) {\n if (key.toLowerCase().includes(\"comments\")) {\n delete pkg.unzipped[key];\n }\n }\n }\n }\n\n /**\n * Revert every tracked change, returning the document to the state it had\n * before any revision was proposed. The exact inverse of\n * accept_all_revisions:\n *\n * - <w:ins> -> removed together with all of its content (the proposed\n * insertion never existed); an inserted row (<w:ins> in\n * <w:trPr>) drops the whole row.\n * - <w:del> -> unwrapped, restoring the original text (<w:delText> becomes\n * <w:t> again); a row-deletion mark in <w:trPr> is removed so\n * the row survives.\n * - paragraph-mark <w:del> in pPr/rPr -> removed, undoing a proposed merge.\n *\n * Comments are annotations, not revisions, so standalone comments are left in\n * place; only anchors stranded inside a rejected insertion are cleaned up.\n *\n * Insertions are reverted before deletions are restored so a deletion nested\n * inside a foreign author's insertion is removed wholesale with the insertion\n * — the contingent text disappears rather than being promoted to committed\n * body text.\n *\n * Known limitation: tracked paragraph STRUCTURE changes (a split recorded as a\n * pilcrow <w:ins>, or a merge recorded as a pilcrow <w:del>) are reverted only\n * to the extent of dropping/keeping the mark; the original paragraph boundary\n * is not reconstructed, because the merge protocol coalesces paragraphs\n * destructively at edit time. Reverting run-level insertions/deletions (the\n * common case) is exact. This limitation is shared with the Python engine.\n */\n public reject_all_revisions() {\n const parts_to_process: Element[] = [this.doc.element];\n\n for (const part of this.doc.pkg.parts) {\n if (part === this.doc.part) continue;\n if (\n part.contentType.includes(\"wordprocessingml\") &&\n part.contentType.endsWith(\"+xml\")\n ) {\n parts_to_process.push(part._element);\n }\n }\n\n for (const root_element of parts_to_process) {\n // 1. Reject insertions: drop the <w:ins> and everything inside it.\n // Document order means an outer <w:ins> is handled before a nested\n // one; removing the outer detaches the inner (guarded below).\n const insNodes = findAllDescendants(root_element, \"w:ins\");\n for (const ins of insNodes) {\n const parent = ins.parentNode as Element | null;\n if (!parent) continue;\n this._clean_wrapping_comments(ins);\n this._delete_comments_in_element(ins);\n if (parent.tagName === \"w:trPr\") {\n const row = parent.parentNode as Element | null;\n if (row && row.parentNode) {\n row.parentNode.removeChild(row);\n }\n } else {\n parent.removeChild(ins);\n }\n }\n\n // 2. Reject paragraph-mark deletions: keep the paragraph break.\n const pNodes = findAllDescendants(root_element, \"w:p\");\n for (const p of pNodes) {\n const pPr = findChild(p, \"w:pPr\");\n if (pPr) {\n const rPr = findChild(pPr, \"w:rPr\");\n const delMark = rPr ? findChild(rPr, \"w:del\") : null;\n if (rPr && delMark) {\n rPr.removeChild(delMark);\n }\n }\n }\n\n // 3. Reject deletions: restore the original text.\n const delNodes = findAllDescendants(root_element, \"w:del\");\n for (const d of delNodes) {\n const parent = d.parentNode as Element | null;\n if (!parent) continue;\n this._clean_wrapping_comments(d);\n if (parent.tagName === \"w:trPr\") {\n parent.removeChild(d);\n continue;\n }\n const delTexts = Array.from(d.getElementsByTagName(\"w:delText\"));\n for (const dt of delTexts) {\n const t = d.ownerDocument!.createElement(\"w:t\");\n t.textContent = dt.textContent;\n if (dt.hasAttribute(\"xml:space\"))\n t.setAttribute(\"xml:space\", \"preserve\");\n dt.parentNode?.replaceChild(t, dt);\n }\n while (d.firstChild) {\n parent.insertBefore(d.firstChild, d);\n }\n parent.removeChild(d);\n }\n }\n }\n\n private _getNextId(): string {\n this.current_id++;\n return this.current_id.toString();\n }\n\n private _create_track_change_tag(\n tagName: string,\n author: string = \"\",\n reuseId: string | null = null,\n ): Element {\n const xmlDoc = this.doc.part._element.ownerDocument!;\n const tag = xmlDoc.createElement(tagName);\n const wid = reuseId !== null ? reuseId : this._getNextId();\n tag.setAttribute(\"w:id\", wid);\n tag.setAttribute(\"w:author\", author || this.author);\n tag.setAttribute(\"w:date\", this.timestamp);\n tag.setAttribute(\"w16du:dateUtc\", this.timestamp);\n return tag;\n }\n\n private _set_text_content(element: Element, text: string) {\n element.textContent = text;\n if (text.trim() !== text) {\n element.setAttribute(\"xml:space\", \"preserve\");\n }\n }\n\n /**\n * Walks `element` to its XML root element. Word (and LibreOffice, which\n * refuses to LOAD such files) only supports comment ranges in the main\n * document story (\"w:document\") — never in headers, footers, footnotes or\n * endnotes (QA 2026-07-18 H4/C1).\n */\n private _comment_anchor_in_main_story(element: Element): boolean {\n let root: Element = element;\n while (root.parentNode && root.parentNode.nodeType === 1) {\n root = root.parentNode as Element;\n }\n return root.tagName === \"w:document\";\n }\n\n /**\n * When the anchor lives outside the main document story, records a\n * user-visible warning and returns true (caller must skip the comment).\n * The tracked change itself still applies — only the bubble is dropped.\n */\n private _skip_comment_outside_main_story(\n element: Element,\n text: string,\n ): boolean {\n if (this._comment_anchor_in_main_story(element)) return false;\n let root: Element = element;\n while (root.parentNode && root.parentNode.nodeType === 1) {\n root = root.parentNode as Element;\n }\n const story =\n (\n {\n \"w:ftr\": \"footer\",\n \"w:hdr\": \"header\",\n \"w:footnotes\": \"footnote\",\n \"w:endnotes\": \"endnote\",\n } as Record<string, string>\n )[root.tagName] || \"non-body\";\n const msg =\n `- Warning: the comment \"${text.substring(0, 60)}\" was NOT attached: Word does not support ` +\n `comments inside a ${story} part, and writing one produces a document other ` +\n \"applications cannot open. The tracked change itself was applied.\";\n this.skipped_details.push(msg);\n console.error(\n `Comment anchor outside main story; comment dropped (story=${story})`,\n );\n return true;\n }\n\n /**\n * Attaches a comment that wraps a contiguous range within a single paragraph.\n * start_element and end_element must both be direct children of parent_element\n * and start_element must come before (or equal) end_element in document order.\n * Ported from Python `RedlineEngine._attach_comment`.\n */\n private _attach_comment(\n parent_element: Element,\n start_element: Element,\n end_element: Element,\n text: string,\n ) {\n if (!text) return;\n if (!parent_element || !start_element || !end_element) return;\n if (this._skip_comment_outside_main_story(parent_element, text)) return;\n\n const comment_id = this.comments_manager.addComment(this.author, text);\n const xmlDoc = parent_element.ownerDocument!;\n\n const range_start = xmlDoc.createElement(\"w:commentRangeStart\");\n range_start.setAttribute(\"w:id\", comment_id);\n\n const range_end = xmlDoc.createElement(\"w:commentRangeEnd\");\n range_end.setAttribute(\"w:id\", comment_id);\n\n const ref_run = xmlDoc.createElement(\"w:r\");\n const rPr = xmlDoc.createElement(\"w:rPr\");\n const rStyle = xmlDoc.createElement(\"w:rStyle\");\n rStyle.setAttribute(\"w:val\", \"CommentReference\");\n rPr.appendChild(rStyle);\n ref_run.appendChild(rPr);\n\n const ref = xmlDoc.createElement(\"w:commentReference\");\n ref.setAttribute(\"w:id\", comment_id);\n ref_run.appendChild(ref);\n\n // Insert <w:commentRangeStart> immediately before start_element.\n // Insert <w:commentRangeEnd> immediately after end_element.\n // Insert <w:r><w:commentReference/></w:r> immediately after the range end.\n parent_element.insertBefore(range_start, start_element);\n\n // After insertBefore above, sibling positions shifted. Re-find end_element's next sibling.\n const after_end = end_element.nextSibling;\n if (after_end) {\n parent_element.insertBefore(range_end, after_end);\n parent_element.insertBefore(ref_run, range_end.nextSibling);\n } else {\n parent_element.appendChild(range_end);\n parent_element.appendChild(ref_run);\n }\n }\n\n /**\n * Attaches a comment that spans across two different paragraphs (or other block\n * containers). start_element lives inside start_p, end_element lives inside end_p,\n * and the comment is open from start_element through end_element.\n * Ported from Python `RedlineEngine._attach_comment_spanning`.\n */\n private _attach_comment_spanning(\n start_p: Element,\n start_el: Element,\n end_p: Element,\n end_el: Element,\n text: string,\n ) {\n if (!text) return;\n if (!start_p || !end_p) return;\n if (\n this._skip_comment_outside_main_story(start_p, text) ||\n this._skip_comment_outside_main_story(end_p, text)\n )\n return;\n\n const comment_id = this.comments_manager.addComment(this.author, text);\n const xmlDocStart = start_p.ownerDocument!;\n const xmlDocEnd = end_p.ownerDocument!;\n\n const range_start = xmlDocStart.createElement(\"w:commentRangeStart\");\n range_start.setAttribute(\"w:id\", comment_id);\n\n const range_end = xmlDocEnd.createElement(\"w:commentRangeEnd\");\n range_end.setAttribute(\"w:id\", comment_id);\n\n const ref_run = xmlDocEnd.createElement(\"w:r\");\n const rPr = xmlDocEnd.createElement(\"w:rPr\");\n const rStyle = xmlDocEnd.createElement(\"w:rStyle\");\n rStyle.setAttribute(\"w:val\", \"CommentReference\");\n rPr.appendChild(rStyle);\n ref_run.appendChild(rPr);\n\n const ref = xmlDocEnd.createElement(\"w:commentReference\");\n ref.setAttribute(\"w:id\", comment_id);\n ref_run.appendChild(ref);\n\n // Place range start before start_el.\n start_p.insertBefore(range_start, start_el);\n\n // Place range end + reference run after end_el.\n const after_end = end_el.nextSibling;\n if (after_end) {\n end_p.insertBefore(range_end, after_end);\n end_p.insertBefore(ref_run, range_end.nextSibling);\n } else {\n end_p.appendChild(range_end);\n end_p.appendChild(ref_run);\n }\n }\n\n /**\n * Inserts `text` as one or more tracked paragraphs anchored relative to\n * either an existing run or a paragraph. Returns:\n * { first_node, last_p, last_ins, used_block_mode }\n * where:\n * - first_node: the first <w:ins> (for inline mode) OR the first new <w:p>\n * (for block mode). The caller uses this for splicing into the DOM and\n * for anchoring comments.\n * - last_p: the last new <w:p> created, if any. null when entirely inline.\n * - last_ins: the last <w:ins> created (inside the last new <w:p>, or the\n * sole inline ins). Used as the comment's end anchor.\n * - used_block_mode: true when the first line carried a heading/list style\n * marker and we created a new paragraph for it (rather than inlining it).\n *\n * Multi-paragraph rules (only when text contains '\\n'):\n * - Each additional line becomes a new <w:p>, inserted after the anchor\n * paragraph in document order.\n * - Each new <w:p> gets a copy of the anchor paragraph's <w:pPr> (so list\n * numbering / indentation are preserved) unless the line itself starts\n * with a markdown heading or list marker, which overrides the style.\n * - Each new <w:p> carries a tracked paragraph-break marker\n * (<w:pPr><w:rPr><w:ins/></w:rPr></w:pPr>) so Word natively tracks the\n * paragraph break.\n * - Each new <w:p>'s content is wrapped in a <w:ins>, with inline bold/\n * italic markdown parsed via _parse_inline_markdown.\n *\n * The first line:\n * - If it carries a heading / list marker AND we have a paragraph anchor,\n * we drop into \"block mode\": no inline <w:ins>; the first line itself\n * becomes the first new <w:p>.\n * - Otherwise we emit a single inline <w:ins> for the first line (current\n * behaviour) and treat the remaining lines as block extensions.\n *\n * Does NOT attach comments; callers handle that.\n */\n private _track_insert_multiline(\n text: string,\n anchor_run: Run | null,\n anchor_paragraph: Paragraph | null,\n reuse_id: string,\n // The attached DOM element the insertion physically follows. anchor_run\n // supplies STYLING and may already be detached (the deletion step clones\n // runs into <w:del> and replaces the originals); suffix relocation for\n // paragraph-splitting insertions keys on this element instead.\n positional_anchor_el: Element | null = null,\n // When the edit declares explicit emphasis markers, the markers are\n // authoritative: strip inherited bold/italic from the anchor style\n // (QA 2026-07-19 F-02).\n suppress_emphasis: boolean = false,\n // True when the caller will attach the insertion BEFORE the anchor\n // (paragraph-start insertions): the anchor itself then belongs to the\n // relocating suffix (hunt-profile counterexample, 2026-07-19 —\n // \"00.\" + insert \"0.\\n\\n0 \" must read \"0.\\n\\n0 00.\", never\n // \"0.00.\\n\\n0 \"). Mirrors the Python engine.\n insert_before: boolean = false,\n ): {\n first_node: Element | null;\n last_p: Element | null;\n last_ins: Element | null;\n used_block_mode: boolean;\n } {\n if (!text) {\n return {\n first_node: null,\n last_p: null,\n last_ins: null,\n used_block_mode: false,\n };\n }\n\n const xmlDoc = this.doc.part._element.ownerDocument!;\n const lines = text.split(/[\\r\\n]+/);\n\n // Resolve the containing <w:p> (current_p) for the anchor.\n let current_p: Element | null = null;\n if (anchor_paragraph !== null) {\n current_p = anchor_paragraph._element;\n } else if (anchor_run !== null) {\n let walker: Element | null = anchor_run._element;\n while (walker && walker.tagName !== \"w:p\") {\n walker = walker.parentNode as Element | null;\n }\n current_p = walker;\n }\n\n // Suffix nodes: content that follows the anchor inside current_p. When\n // the inserted text carries paragraph breaks, this content belongs in\n // the LAST new paragraph. The positional anchor is attached to the\n // DOM, and the insertion lands immediately after it, so its following\n // child-of-paragraph siblings are exactly the suffix.\n const suffix_nodes: Element[] = [];\n const relocatable = new Set([\"w:r\", \"w:ins\", \"w:del\"]);\n // insert_before with a RUN anchor: the insertion precedes the anchor, so\n // the anchor run itself is part of the suffix. (The explicit\n // positional_anchor_el is only passed by flows that insert AFTER it.)\n const pos_from_positional =\n positional_anchor_el && positional_anchor_el.parentNode\n ? positional_anchor_el\n : null;\n const pos_from_anchor_run =\n anchor_run !== null && anchor_run._element.parentNode\n ? anchor_run._element\n : null;\n const pos_source = pos_from_positional ?? pos_from_anchor_run;\n const suffix_includes_anchor =\n insert_before && pos_from_positional === null && pos_from_anchor_run !== null;\n if (current_p !== null && pos_source !== null) {\n let pos_anchor: Element | null = pos_source;\n while (pos_anchor && pos_anchor.parentNode !== current_p) {\n pos_anchor = pos_anchor.parentNode as Element | null;\n if (pos_anchor === current_p) {\n pos_anchor = null;\n break;\n }\n }\n if (pos_anchor) {\n let nxt: Node | null = suffix_includes_anchor\n ? pos_anchor\n : pos_anchor.nextSibling;\n while (nxt) {\n if (nxt.nodeType === 1 && relocatable.has((nxt as Element).tagName)) {\n suffix_nodes.push(nxt as Element);\n }\n nxt = nxt.nextSibling;\n }\n }\n } else if (current_p !== null && insert_before) {\n // No attached anchor run at all (paragraph-anchored insertion at\n // paragraph START): everything in the host paragraph follows the\n // insertion point, so it all relocates (mirrors the Python engine).\n let child = current_p.firstChild;\n while (child) {\n if (\n child.nodeType === 1 &&\n relocatable.has((child as Element).tagName)\n ) {\n suffix_nodes.push(child as Element);\n }\n child = child.nextSibling;\n }\n }\n\n // Drop the trailing empty line ONLY when there is no suffix to relocate.\n // \"foo\\n\\nbar\\n\\n\" splits to ['foo', '', 'bar', '']; without a suffix\n // the trailing empty is just a terminator, but with one it is the fresh\n // destination paragraph the suffix moves into.\n while (\n lines.length > 1 &&\n lines[lines.length - 1] === \"\" &&\n suffix_nodes.length === 0\n ) {\n lines.pop();\n }\n if (lines.length === 0) {\n return {\n first_node: null,\n last_p: null,\n last_ins: null,\n used_block_mode: false,\n };\n }\n\n // Inspect the first line for heading/list markers.\n const [first_clean, first_style] = this._parse_markdown_style(lines[0]);\n const have_paragraph_context = current_p !== null;\n const block_mode = first_style !== null && have_paragraph_context;\n\n let first_node: Element | null = null;\n let inline_ins: Element | null = null;\n\n // ---- INLINE PATH for the first line (when NOT in block mode) ----\n if (!block_mode) {\n inline_ins = this._build_tracked_ins_for_line(\n first_clean === lines[0] ? lines[0] : lines[0],\n anchor_run,\n reuse_id,\n xmlDoc,\n suppress_emphasis,\n );\n first_node = inline_ins;\n // Caller will attach `inline_ins` to the DOM later — keep it for now.\n }\n\n // ---- BLOCK PATH for the first line (when in block mode) ----\n // Block-mode first line is just the first extension paragraph below.\n const remaining_lines = block_mode ? lines : lines.slice(1);\n\n // If there's nothing to do beyond inline, we're done.\n if (remaining_lines.length === 0) {\n return {\n first_node,\n last_p: null,\n last_ins: inline_ins,\n used_block_mode: false,\n };\n }\n\n if (!current_p) {\n // Multi-paragraph insertion needs a paragraph context. Without one, fall\n // back to the inline result we already built.\n return {\n first_node,\n last_p: null,\n last_ins: inline_ins,\n used_block_mode: false,\n };\n }\n\n const parent_body = current_p.parentNode as Element | null;\n if (!parent_body) {\n return {\n first_node,\n last_p: null,\n last_ins: inline_ins,\n used_block_mode: false,\n };\n }\n\n const insertAfterEl = (newNode: Element, ref: Element) => {\n parent_body.insertBefore(newNode, ref.nextSibling);\n };\n\n let last_p: Element | null = null;\n let last_ins: Element | null = null;\n let after: Element = current_p;\n\n for (let i = 0; i < remaining_lines.length; i++) {\n const raw_line = remaining_lines[i];\n const [clean_text, style_name] = this._parse_markdown_style(raw_line);\n\n const new_p = xmlDoc.createElement(\"w:p\");\n\n if (style_name) {\n // Heading or list style was explicitly authored: replace pPr entirely.\n this._set_paragraph_style(new_p, style_name);\n } else {\n // Inherit pPr from the anchor paragraph (preserves list numbering).\n const existing_pPr = findChild(current_p, \"w:pPr\");\n if (existing_pPr) {\n new_p.appendChild(existing_pPr.cloneNode(true));\n }\n }\n\n // Track the paragraph break itself as an insertion.\n let pPr = findChild(new_p, \"w:pPr\");\n if (!pPr) {\n pPr = xmlDoc.createElement(\"w:pPr\");\n new_p.insertBefore(pPr, new_p.firstChild);\n }\n let rPr = findChild(pPr, \"w:rPr\");\n if (!rPr) {\n rPr = xmlDoc.createElement(\"w:rPr\");\n pPr.appendChild(rPr);\n }\n const ins_mark = this._create_track_change_tag(\"w:ins\", \"\", reuse_id);\n rPr.appendChild(ins_mark);\n\n // Build the content <w:ins>.\n const content_ins = this._build_tracked_ins_for_line(\n clean_text,\n anchor_run,\n reuse_id,\n xmlDoc,\n suppress_emphasis,\n );\n if (content_ins) {\n new_p.appendChild(content_ins);\n }\n\n insertAfterEl(new_p, after);\n after = new_p;\n last_p = new_p;\n last_ins = content_ins;\n\n // In block mode (or if the inline line was completely empty), the first new paragraph IS first_node.\n if (!first_node) {\n first_node = new_p;\n }\n }\n\n // Relocate the suffix into the last new paragraph: the paragraph break\n // the insertion introduced splits current_p at the anchor, so everything\n // after the anchor continues in the final inserted paragraph.\n if (!block_mode && last_p && suffix_nodes.length > 0) {\n for (const node of suffix_nodes) {\n node.parentNode?.removeChild(node);\n last_p.appendChild(node);\n }\n }\n\n return { first_node, last_p, last_ins, used_block_mode: block_mode };\n }\n\n /**\n * Builds a single tracked-insert wrapper (<w:ins>) containing one or more\n * <w:r> elements representing the inline markdown segments of `line_text`.\n * Returns null if line_text is empty.\n */\n private _build_tracked_ins_for_line(\n line_text: string,\n anchor_run: Run | null,\n reuse_id: string,\n xmlDoc: Document,\n suppress_emphasis: boolean = false,\n ): Element | null {\n if (!line_text && line_text !== \"\") return null;\n const ins = this._create_track_change_tag(\"w:ins\", \"\", reuse_id);\n const segments = this._parse_inline_markdown(line_text);\n if (segments.length === 0) {\n return null;\n }\n for (const [segText, segProps] of segments) {\n const r = xmlDoc.createElement(\"w:r\");\n // Inherit run formatting from the anchor so partial replacements inside\n // a styled span keep the style (matching Word's type-into-selection\n // behavior and the Python engine — the old blanket strip made\n // \"Important\" -> \"Critical\" inside a bold span come out unstyled).\n if (anchor_run && anchor_run._element) {\n const anchor_rPr = findChild(anchor_run._element, \"w:rPr\");\n if (anchor_rPr) {\n const clone = anchor_rPr.cloneNode(true) as Element;\n // Always strip vanish / strike (invisible inserts) and italic\n // (BUG-23-2: an inserted replacement must not silently inherit the\n // surrounding italic styling). Bold is preserved — it usually\n // carries structural meaning (headings, defined terms) — UNLESS\n // the edit's own markers are authoritative (QA 2026-07-19 F-02):\n // `**X**` -> `_X_` must yield italic-only, `**X**` -> `X` plain.\n // Mirrors the Python engine's _track_insert_inline exactly.\n const strip_tags = [\"w:vanish\", \"w:strike\", \"w:dstrike\", \"w:i\", \"w:iCs\"];\n if (suppress_emphasis) {\n strip_tags.push(\"w:b\", \"w:bCs\");\n }\n for (const tag of strip_tags) {\n const found = findChild(clone, tag);\n if (found) clone.removeChild(found);\n }\n r.appendChild(clone);\n }\n }\n this._apply_run_props(r, segProps, false);\n const t = xmlDoc.createElement(\"w:t\");\n this._set_text_content(t, segText);\n r.appendChild(t);\n ins.appendChild(r);\n }\n return ins;\n }\n\n private _parse_markdown_style(text: string): [string, string | null] {\n const stripped_text = text.trimStart();\n\n if (stripped_text.startsWith(\"#\")) {\n let level = 0;\n let temp = stripped_text;\n while (temp.startsWith(\"#\")) {\n level++;\n temp = temp.substring(1);\n }\n if (temp.startsWith(\" \")) return [temp.trim(), `Heading ${level}`];\n }\n\n if (stripped_text.startsWith(\"* \") || stripped_text.startsWith(\"- \")) {\n return [stripped_text.substring(2).trim(), \"List Paragraph\"];\n }\n\n // Numbered lists: the projection emits ordered items with a CONSTANT\n // \"1. \" marker (Markdown renumbers), so only that exact shape converts\n // back into a list style. Any other leading number (\"2024. Year in\n // review\", \"3. Clause text\") is literal document text. Continuation\n // items inside an existing list anchor keep full \"\\d+.\" handling via\n // the list-anchored insertion path.\n const match = stripped_text.match(/^1\\.\\s+/);\n if (match) {\n return [stripped_text.substring(match[0].length).trim(), \"List Number\"];\n }\n\n return [text, null];\n }\n\n /**\n * True when this edit's target or replacement text carries explicit\n * bold/italic markers, making the markers AUTHORITATIVE for the inserted\n * runs' formatting. Replacing `**X**` with `_X_` must yield italic-only\n * text, and replacing `**X**` with `X` must yield plain text — inheriting\n * the replaced span's run properties on top of (or instead of) the\n * requested markers silently produces the wrong document while the report\n * claims success (QA 2026-07-19 F-02). Plain-text edits (no markers on\n * either side) keep inheriting the context style so partial replacements\n * inside a styled span never lose formatting.\n */\n private _edit_declares_emphasis(edit: any): boolean {\n for (const text of [edit?.target_text, edit?.new_text]) {\n if (!text || (!text.includes(\"**\") && !text.includes(\"_\"))) continue;\n const segments = this._parse_inline_markdown(text);\n if (segments.some(([, props]: [string, any]) => props && Object.keys(props).length > 0)) {\n return true;\n }\n }\n return false;\n }\n\n private _parse_inline_markdown(\n text: string,\n baseStyle: any = {},\n ): [string, any][] {\n if (!text) return [];\n\n const tokenPattern = /(\\*\\*.*?\\*\\*)|(_.*?_)/;\n const match = text.match(tokenPattern);\n\n if (!match) return [[text, baseStyle]];\n\n const start = match.index!;\n const raw = match[0];\n const end = start + raw.length;\n\n const isBold = raw.startsWith(\"**\");\n const innerContent = isBold\n ? raw.substring(2, raw.length - 2)\n : raw.substring(1, raw.length - 1);\n\n const preText = text.substring(0, start);\n const postText = text.substring(end);\n\n const results: [string, any][] = [];\n if (preText) results.push([preText, baseStyle]);\n\n const newStyle = { ...baseStyle };\n if (isBold) newStyle.bold = true;\n else newStyle.italic = true;\n\n results.push(...this._parse_inline_markdown(innerContent, newStyle));\n results.push(...this._parse_inline_markdown(postText, baseStyle));\n\n return results;\n }\n\n private _apply_run_props(\n runElement: Element,\n props: any,\n suppressInherited: boolean = false,\n ) {\n if (!props) {\n if (!suppressInherited) return;\n props = {};\n }\n\n let rPr = findChild(runElement, \"w:rPr\");\n if (!rPr && (props.bold || props.italic || suppressInherited)) {\n const doc = runElement.ownerDocument!;\n rPr = doc.createElement(\"w:rPr\");\n runElement.appendChild(rPr);\n }\n\n if (rPr) {\n const doc = runElement.ownerDocument!;\n if (props.bold) {\n let b = findChild(rPr, \"w:b\");\n if (!b) {\n b = doc.createElement(\"w:b\");\n rPr.appendChild(b);\n }\n b.setAttribute(\"w:val\", \"1\");\n } else if (suppressInherited) {\n const b = findChild(rPr, \"w:b\");\n if (b) rPr.removeChild(b);\n }\n\n if (props.italic) {\n let i = findChild(rPr, \"w:i\");\n if (!i) {\n i = doc.createElement(\"w:i\");\n rPr.appendChild(i);\n }\n i.setAttribute(\"w:val\", \"1\");\n } else if (suppressInherited) {\n const i = findChild(rPr, \"w:i\");\n if (i) rPr.removeChild(i);\n }\n }\n }\n\n /**\n * Replaces (or creates) a paragraph's <w:pPr> with a single <w:pStyle> entry\n * pointing at `style_name`. Strips any existing pPr to avoid layering a new\n * heading style on top of a previous list/heading configuration.\n *\n * In Python, the style id is resolved via doc.styles[style_name].style_id and\n * falls back to stripping spaces. Node has no equivalent style cache exposed\n * on `doc`, so we always use the simple \"strip spaces\" fallback: \"Heading 1\"\n * becomes the style id \"Heading1\", \"List Number\" becomes \"ListNumber\", etc.\n * This matches python-docx's default style-id convention for the built-in\n * paragraph styles and is what Word writes by default.\n */\n private _set_paragraph_style(p_element: Element, style_name: string) {\n const xmlDoc = p_element.ownerDocument!;\n\n const existing_pPr = findChild(p_element, \"w:pPr\");\n if (existing_pPr) {\n p_element.removeChild(existing_pPr);\n }\n\n const pPr = xmlDoc.createElement(\"w:pPr\");\n const pStyle = xmlDoc.createElement(\"w:pStyle\");\n const style_id = style_name.replace(/\\s+/g, \"\");\n pStyle.setAttribute(\"w:val\", style_id);\n pPr.appendChild(pStyle);\n\n // pPr is the first child of <w:p> per OOXML schema.\n p_element.insertBefore(pPr, p_element.firstChild);\n }\n\n private _anchor_reply_comment(parent_id: string, new_id: string) {\n const docEl = this.doc.part._element.ownerDocument!;\n\n const starts = findAllDescendants(\n this.doc.element,\n \"w:commentRangeStart\",\n ).filter((n) => n.getAttribute(\"w:id\") === parent_id);\n if (starts.length === 0) return;\n const parent_start = starts[0];\n\n const new_start = docEl.createElement(\"w:commentRangeStart\");\n new_start.setAttribute(\"w:id\", new_id);\n insertAfter(new_start, parent_start);\n\n const ends = findAllDescendants(\n this.doc.element,\n \"w:commentRangeEnd\",\n ).filter((n) => n.getAttribute(\"w:id\") === parent_id);\n if (ends.length === 0) return;\n const parent_end = ends[0];\n\n const parent_refs = findAllDescendants(\n this.doc.element,\n \"w:commentReference\",\n ).filter((n) => n.getAttribute(\"w:id\") === parent_id);\n\n let insertion_point = parent_end;\n if (parent_refs.length > 0) {\n const ref_el = parent_refs[0];\n if (\n ref_el.parentNode &&\n (ref_el.parentNode as Element).tagName === \"w:r\"\n ) {\n insertion_point = ref_el.parentNode as Element;\n }\n }\n\n const new_end = docEl.createElement(\"w:commentRangeEnd\");\n new_end.setAttribute(\"w:id\", new_id);\n insertAfter(new_end, insertion_point);\n\n const ref_run = docEl.createElement(\"w:r\");\n const rPr = docEl.createElement(\"w:rPr\");\n const rStyle = docEl.createElement(\"w:rStyle\");\n rStyle.setAttribute(\"w:val\", \"CommentReference\");\n rPr.appendChild(rStyle);\n ref_run.appendChild(rPr);\n\n const ref = docEl.createElement(\"w:commentReference\");\n ref.setAttribute(\"w:id\", new_id);\n ref_run.appendChild(ref);\n\n insertAfter(ref_run, new_end);\n }\n /**\n * Read a comment's author directly from the comments part. Used by\n * _clean_wrapping_comments to decide whether a wrapping comment belongs to\n * another author (and must be preserved when its anchored change is\n * accepted/rejected) or to us (safe to delete). Reads the part rather than\n * the mapper because the mapper's comments_map is not rebuilt between review\n * actions, so it can be stale mid-batch. Returns null if not found.\n */\n private _get_comment_author(c_id: string): string | null {\n const part = this.doc.pkg.parts.find(\n (p) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\",\n );\n if (!part) return null;\n const comments = findAllDescendants(part._element, \"w:comment\");\n for (const c of comments) {\n if (c.getAttribute(\"w:id\") === c_id) {\n return c.getAttribute(\"w:author\");\n }\n }\n return null;\n }\n private _clean_wrapping_comments(element: Element) {\n let first_node: Element = element;\n while (true) {\n const prev = getPreviousElement(first_node);\n if (prev && (prev.tagName === \"w:ins\" || prev.tagName === \"w:del\")) {\n first_node = prev;\n } else {\n break;\n }\n }\n\n let last_node: Element = element;\n while (true) {\n const nxt = getNextElement(last_node);\n if (nxt && (nxt.tagName === \"w:ins\" || nxt.tagName === \"w:del\")) {\n last_node = nxt;\n } else {\n break;\n }\n }\n\n const starts_to_remove: Element[] = [];\n let prev = getPreviousElement(first_node);\n while (prev) {\n if (prev.tagName === \"w:commentRangeStart\") {\n starts_to_remove.push(prev);\n prev = getPreviousElement(prev);\n } else if (prev.tagName === \"w:rPr\" || prev.tagName === \"w:pPr\") {\n prev = getPreviousElement(prev);\n } else {\n break;\n }\n }\n\n const ends_to_remove: Element[] = [];\n let nxt = getNextElement(last_node);\n while (nxt) {\n if (nxt.tagName === \"w:commentRangeEnd\") {\n ends_to_remove.push(nxt);\n nxt = getNextElement(nxt);\n } else if (\n nxt.tagName === \"w:r\" &&\n findAllDescendants(nxt, \"w:commentReference\").length > 0\n ) {\n ends_to_remove.push(nxt);\n nxt = getNextElement(nxt);\n } else if (nxt.tagName === \"w:commentReference\") {\n ends_to_remove.push(nxt);\n nxt = getNextElement(nxt);\n } else {\n break;\n }\n }\n\n const end_ids = new Set<string>();\n for (const e of ends_to_remove) {\n if (e.tagName === \"w:commentRangeEnd\") {\n const eid = e.getAttribute(\"w:id\");\n if (eid) end_ids.add(eid);\n } else {\n let ref = findAllDescendants(e, \"w:commentReference\")[0];\n if (!ref && e.tagName === \"w:commentReference\") ref = e;\n if (ref) {\n const eid = ref.getAttribute(\"w:id\");\n if (eid) end_ids.add(eid);\n }\n }\n }\n\n for (const s of starts_to_remove) {\n const c_id = s.getAttribute(\"w:id\");\n if (c_id && end_ids.has(c_id)) {\n // Author-aware preservation. A comment that merely WRAPS the change\n // being accepted/rejected is a separate annotation — often the\n // counterparty's note explaining the very edit we are resolving.\n // Deleting it silently destroys their provenance (and, e.g., fails a\n // \"keep the counterparty's comment\" review requirement). So: always\n // detach the range markers (leaving no orphaned anchor, which lets the\n // accept/reject proceed cleanly), but only delete the comment BODY when\n // it is ours. Foreign-authored comment bodies are kept in the comments\n // part. When the author can't be read we default to preserving, since\n // deletion is the irreversible, higher-cost mistake.\n const author = this._get_comment_author(c_id);\n const is_own = author !== null && author === this.author;\n if (is_own) {\n this.comments_manager.deleteComment(c_id);\n }\n if (s.parentNode) s.parentNode.removeChild(s);\n for (const e of ends_to_remove) {\n let e_id: string | null = null;\n if (e.tagName === \"w:commentRangeEnd\") {\n e_id = e.getAttribute(\"w:id\");\n } else {\n let ref = findAllDescendants(e, \"w:commentReference\")[0];\n if (!ref && e.tagName === \"w:commentReference\") ref = e;\n if (ref) e_id = ref.getAttribute(\"w:id\");\n }\n if (e_id === c_id && e.parentNode) {\n e.parentNode.removeChild(e);\n }\n }\n }\n }\n }\n\n private _delete_comments_in_element(element: Element) {\n const refs = findAllDescendants(element, \"w:commentReference\");\n for (const ref of refs) {\n const c_id = ref.getAttribute(\"w:id\");\n if (c_id) {\n this.comments_manager.deleteComment(c_id);\n for (const tag of [\"w:commentRangeStart\", \"w:commentRangeEnd\"]) {\n const nodes = findAllDescendants(this.doc.element, tag);\n for (const node of nodes) {\n if (node.getAttribute(\"w:id\") === c_id && node.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n }\n }\n }\n }\n\n public validate_edits(edits: any[], index_offset: number = 0): string[] {\n const errors: string[] = [];\n if (!this.mapper.full_text) this.mapper[\"_build_map\"]();\n\n errors.push(...validate_edit_strings(edits, index_offset));\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n if (typeof edit !== \"object\" || edit === null) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Invalid change format. Expected a JSON object, but received a primitive ${typeof edit}. Do not pass raw strings.`,\n );\n continue;\n }\n if (!edit.target_text) continue;\n // Caller-pinned indexes (e.g. generate_edits_from_text output) resolve\n // by position, not content: ambiguity / not-found checks are meaningless\n // for them and false-positive whenever the target coincidentally matches\n // unrelated text (a comment timestamp, an earlier redline). The\n // string-shape checks above still apply.\n if (\n (edit._match_start_index !== undefined &&\n edit._match_start_index !== null) ||\n (edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null)\n )\n continue;\n\n const is_regex = (edit as any).regex || false;\n const match_mode = (edit as any).match_mode || \"strict\";\n\n if (is_regex) {\n // An unparsable pattern must be diagnosed as a regex problem. Without\n // this check it falls through the matcher's silent guard and surfaces\n // as \"target text not found\", sending the user hunting for a typo in\n // the document instead of in the pattern (QA 2026-07-19 F-13).\n try {\n new RegExp(edit.target_text);\n } catch (regex_err: any) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text is not a valid regular expression ` +\n `(${regex_err?.message ?? regex_err}). Fix the pattern, or set \"regex\": false to ` +\n \"match the text literally.\",\n );\n continue;\n }\n }\n\n let matches = this.mapper.find_all_match_indices(\n edit.target_text,\n is_regex,\n );\n let activeText = this.mapper.full_text;\n let target_mapper = this.mapper;\n\n if (matches.length === 0) {\n if (!this.clean_mapper)\n this.clean_mapper = new DocumentMapper(this.doc, true);\n matches = this.clean_mapper.find_all_match_indices(\n edit.target_text,\n is_regex,\n );\n if (matches.length > 0) {\n activeText = this.clean_mapper.full_text;\n target_mapper = this.clean_mapper;\n }\n }\n\n // BUG-23-5: a copy of the target that lives entirely inside a tracked\n // deletion (<w:del>) is not a live, editable occurrence and must not\n // count toward ambiguity. Drop matches whose overlapping real text is\n // exclusively deleted. Only applies to the raw mapper (the clean mapper\n // already omits deleted text).\n if (activeText === this.mapper.full_text && matches.length > 0) {\n const liveMatches = matches.filter(([start, length]) => {\n const realSpans = this.mapper.spans.filter(\n (s) => s.run !== null && s.end > start && s.start < start + length,\n );\n if (realSpans.length === 0) return true; // virtual-only; keep\n // Keep only if at least one overlapping real span is live (not\n // part of a tracked deletion).\n return realSpans.some((s) => !s.del_id);\n });\n matches = liveMatches;\n }\n\n let is_deleted_text = false;\n const deleted_authors = new Set<string>();\n\n if (matches.length === 0) {\n if (!this.original_mapper) {\n this.original_mapper = new DocumentMapper(this.doc, false, true);\n }\n const orig_matches = this.original_mapper.find_all_match_indices(\n edit.target_text,\n is_regex,\n );\n if (orig_matches.length > 0) {\n is_deleted_text = true;\n for (const [start, length] of orig_matches) {\n const spans = this.original_mapper.spans.filter(\n (s) => s.end > start && s.start < start + length,\n );\n for (const s of spans) {\n if (s.run !== null) {\n let parent = s.run._element as Node | null;\n while (parent) {\n if (\n parent.nodeType === 1 &&\n (parent as Element).tagName === \"w:del\"\n ) {\n const auth = (parent as Element).getAttribute(\"w:author\");\n if (auth) {\n deleted_authors.add(auth);\n }\n break;\n }\n parent = parent.parentNode;\n }\n }\n }\n }\n }\n }\n\n if (matches.length === 0) {\n if (is_deleted_text) {\n const author_phrase =\n deleted_authors.size > 0\n ? `by ${Array.from(deleted_authors).sort().join(\", \")}`\n : \"by an existing revision\";\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Target text matches text inside a tracked deletion ${author_phrase}. Reject/accept that change first or target the active replacement text instead.`,\n );\n } else {\n const hint = this._nearest_match_hint(edit.target_text, is_regex);\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Target text not found in document:\\n \"${truncate_middle(edit.target_text, REPORT_ECHO_CAP)}\"${hint}`,\n );\n }\n } else if (matches.length > 1 && match_mode === \"strict\") {\n if (edit.target_text.includes(\"|\")) {\n matches = matches.slice(0, 1);\n } else {\n const positions: [number, number][] = matches.map(\n ([start, length]) => [start, start + length],\n );\n errors.push(\n format_ambiguity_error(\n i + 1 + index_offset,\n edit.target_text,\n activeText,\n positions,\n ),\n );\n }\n }\n\n // BUG-23-4: when the effective (context-trimmed) target spans a\n // paragraph boundary with real body text on BOTH sides, we must reject\n // the modification to prevent silent corruption of the paragraph structure.\n if (matches.length === 1) {\n const [m_start, m_len] = matches[0];\n const matched = activeText.substring(m_start, m_start + m_len);\n const [pfx, sfx] = trim_common_context(matched, edit.new_text || \"\");\n const t_end = matched.length - sfx;\n const final_target = matched.substring(pfx, t_end);\n const final_new = (edit.new_text || \"\").substring(\n pfx,\n (edit.new_text || \"\").length - sfx,\n );\n\n // QA 2026-07-18 C1: the projection flattens headers, body, footers\n // and notes into one string, but a text edit whose matched span\n // covers real text from two different OPC parts cannot be applied\n // without putting content in the wrong part — including the\n // insertion shape, whose anchor point at the part gap is inherently\n // ambiguous. Refuse the RAW match range outright and ask for a\n // single-part anchor. (Single-part documents skip the scan.)\n const multi_part_doc =\n target_mapper.part_ranges.filter((r) => r[1] > r[0]).length > 1;\n const raw_span_parts = multi_part_doc\n ? Array.from(\n new Set(\n target_mapper.spans\n .filter(\n (s) =>\n s.run !== null &&\n s.end > m_start &&\n s.start < m_start + m_len,\n )\n .map((s) => s.part_index),\n ),\n ).sort((a, b) => a - b)\n : [];\n if (raw_span_parts.length > 1) {\n const kinds = raw_span_parts\n .map((pi) => target_mapper.part_kind_of(pi) || \"?\")\n .join(\" → \");\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text spans a structural document-part ` +\n `boundary (${kinds}). Headers, body, footers and footnotes are separate ` +\n \"Word parts — an edit cannot cross between them. Anchor the edit on text \" +\n \"within a single part (split it into one edit per part if both sides \" +\n \"must change).\",\n );\n }\n\n // QA 2026-07-18 M5: image markers are read-only projections. Only\n // the CHANGED span matters — markers sitting untouched in the\n // shared context are fine.\n const eff_start = m_start + pfx;\n const eff_end = m_start + m_len - sfx;\n if (eff_end > eff_start) {\n const overlapping = target_mapper.spans.filter(\n (s) =>\n s.end > eff_start &&\n s.start < eff_end &&\n (s.run !== null || s.text.trim() !== \"\"),\n );\n if (overlapping.some((s) => (s as any).is_image_marker)) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: the target overlaps a read-only image marker ` +\n \"(). Images cannot be edited or removed via text \" +\n \"replacement — target the text around the image instead.\",\n );\n }\n }\n\n // QA 2026-07-18 H4: comments can only be anchored in the main\n // document story. A comment-only edit (target == new) whose match\n // lives in a header/footer/footnote has no effect Word or\n // LibreOffice could render — refuse it clearly.\n if (edit.comment && (edit.new_text || \"\") === (edit.target_text || \"\")) {\n const kind_here = target_mapper.part_kind_at(m_start);\n if (kind_here !== null && kind_here !== \"body\") {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: comments cannot be anchored inside a ${kind_here} ` +\n \"part — Word only supports comments in the main document body. Comment on \" +\n \"the related body text instead.\",\n );\n }\n }\n\n // QA 2026-07-18 C2: a replacement may not smuggle new pipe-delimited\n // row lines into a table cell. Rows are structural; adding one\n // requires the insert_row operation.\n if (\n RedlineEngine._introduces_table_row_text(\n target_mapper,\n m_start,\n m_len,\n final_target,\n final_new,\n )\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: new_text introduces a pipe-delimited row line inside ` +\n \"a table. Text replacement cannot create table rows — use the structured \" +\n `'insert_row' operation instead (e.g. {\"type\": \"insert_row\", ` +\n `\"target_text\": \"<anchor row text>\", \"cells\": [\"...\", \"...\"]}).`,\n );\n }\n\n if (final_target.includes(\"\\n\\n\")) {\n // A *balanced* multi-paragraph modification (target and replacement\n // carry the same number of paragraph breaks) is safe: it is split\n // into one sub-edit per paragraph segment and applied, leaving the\n // structural \\n\\n breaks untouched. Only reject when the paragraph\n // structure would actually change (a merge or split), which cannot be\n // expressed as a per-paragraph text replacement. See\n // _pre_resolve_heuristic_edit.\n const balanced =\n matched.split(\"\\n\\n\").length ===\n (edit.new_text || \"\").split(\"\\n\\n\").length;\n if (!balanced) {\n if (final_new.includes(\"\\n\\n\")) {\n const parts = matched.split(\"\\n\\n\");\n if (\n parts.length >= 2 &&\n parts[0].trim() !== \"\" &&\n parts[parts.length - 1].trim() !== \"\"\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text spans a paragraph boundary with body text on both sides. The paragraph break is a structural element, not literal text, so it cannot be replaced as a single span without corrupting the document. Split this into one edit per paragraph.`,\n );\n }\n } else {\n const parts = final_target.split(\"\\n\\n\");\n if (\n parts.length >= 2 &&\n parts[0].trim() !== \"\" &&\n parts[parts.length - 1].trim() !== \"\"\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text spans a paragraph boundary with body text on both sides. The paragraph break is a structural element, not literal text, so it cannot be replaced as a single span without corrupting the document. Split this into one edit per paragraph.`,\n );\n }\n }\n }\n }\n }\n\n for (const [start, length] of matches) {\n // Filter spans from the SAME mapper the match indices came from\n // (target_mapper may be the clean mapper); using this.mapper.spans here\n // would read a different coordinate space and miss the foreign <w:ins>\n // overlap for clean-mapper-resolved targets — silently letting a\n // partial straddle through. (Python filters target_mapper.spans too.)\n const spans = target_mapper.spans.filter(\n (s) => s.end > start && s.start < start + length,\n );\n const insAuthors = new Set<string>();\n const commentAuthors = new Set<string>();\n // Does any real (run-backed) text in the target lie OUTSIDE a foreign\n // insertion? If so the target only partially overlaps the insertion and\n // replacing it as one span would straddle the <w:ins> boundary — that\n // case must still be refused.\n let hasNonForeignRealText = false;\n for (const s of spans) {\n if (s.run === null) continue;\n let isForeignIns = false;\n if (s.ins_id) {\n const insNodes = findAllDescendants(\n this.doc.element,\n \"w:ins\",\n ).filter((n) => n.getAttribute(\"w:id\") === s.ins_id);\n if (insNodes.length > 0) {\n const auth = insNodes[0].getAttribute(\"w:author\");\n if (auth && auth !== this.author) {\n insAuthors.add(auth);\n isForeignIns = true;\n }\n }\n }\n if (!isForeignIns) hasNonForeignRealText = true;\n }\n for (const s of spans) {\n if (s.comment_ids) {\n for (const cid of s.comment_ids) {\n const c_data = this.mapper.comments_map[cid];\n if (c_data && c_data.author && c_data.author !== this.author) {\n commentAuthors.add(c_data.author);\n }\n }\n }\n }\n if (insAuthors.size > 0) {\n // A single (strict/first) modification whose target lies ENTIRELY\n // inside foreign-authored insertion(s) is allowed: track_delete_run\n // splits the enclosing <w:ins> and nests the change, producing valid\n // tracked-change XML. Refuse the remaining cases — match_mode \"all\"\n // fan-outs and partial overlaps that straddle the insertion\n // boundary.\n const fullyWithinForeignIns = !hasNonForeignRealText;\n if (\n !(\n (match_mode === \"strict\" || match_mode === \"first\") &&\n fullyWithinForeignIns\n )\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Modification targets an active insertion from another author (${Array.from(insAuthors).join(\", \")}). Accept that change first or scope your edit outside of it.`,\n );\n continue;\n }\n }\n // Foreign comment ranges do NOT block deliberate single-occurrence\n // edits: amending body text under a colleague's comment is a normal\n // review workflow, and the comment anchor survives the tracked change.\n // Only blind match_mode=\"all\" fan-outs are refused, so a bulk\n // replacement cannot silently sweep through another author's\n // annotations (transactional rollback).\n if (commentAuthors.size > 0 && match_mode === \"all\") {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: match_mode=\"all\" would sweep through a comment range from another author (${Array.from(commentAuthors).join(\", \")}). Target the commented text deliberately with match_mode \"strict\" or \"first\", or scope your edit outside of it.`,\n );\n }\n }\n\n // Structural table edits: verify the anchor really is a table row, and\n // that insert_row does not provide more cells than the row has columns —\n // extra cells must never produce a structurally inconsistent row (QA M3).\n if (\n (edit.type === \"insert_row\" || edit.type === \"delete_row\") &&\n matches.length > 0\n ) {\n const [start, length] = matches[0];\n const n_cols = RedlineEngine._column_count_at(\n target_mapper,\n start,\n length,\n );\n if (n_cols === null) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: ${edit.type} target text was found, but it is not inside a table row. Anchor the operation on text that appears within the table.`,\n );\n } else if (\n edit.type === \"insert_row\" &&\n Array.isArray(edit.cells) &&\n edit.cells.length > n_cols\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: insert_row provides ${edit.cells.length} cells but the target table has ${n_cols} column(s). The extra cell(s) would be dropped. Provide at most ${n_cols} cells — rows given fewer cells are padded with empty ones.`,\n );\n }\n }\n }\n return errors;\n }\n\n /**\n * Number of columns (w:tc elements) in the table row containing the text at\n * [start, start+length) in `mapper`, or null if that text is not inside a\n * table row.\n */\n /**\n * True when a replacement anchored in a table would ADD line-separated\n * pipe-delimited content — the text shape of a table row. Writing that\n * into a cell renders a fake row inside one cell while the real grid\n * stays unchanged (QA 2026-07-18 C2); such edits must use insert_row.\n */\n private static _introduces_table_row_text(\n mapper: DocumentMapper,\n start: number,\n length: number,\n final_target: string,\n final_new: string,\n ): boolean {\n if (!final_new.includes(\"\\n\") || !final_new.includes(\" | \")) return false;\n const new_pipe_lines = final_new\n .split(\"\\n\")\n .filter((line) => line.includes(\" | \")).length;\n const old_pipe_lines = final_target\n .split(\"\\n\")\n .filter((line) => line.includes(\" | \")).length;\n if (new_pipe_lines <= old_pipe_lines) return false;\n return (\n RedlineEngine._column_count_at(mapper, start, Math.max(length, 1)) !==\n null\n );\n }\n\n private static _column_count_at(\n mapper: DocumentMapper,\n start: number,\n length: number,\n ): number | null {\n for (const s of mapper.spans) {\n if (s.run === null || s.end <= start || s.start >= start + length) {\n continue;\n }\n let curr: Node | null = s.run._element;\n while (curr) {\n if (curr.nodeType === 1 && (curr as Element).tagName === \"w:tr\") {\n return findAllDescendants(curr as Element, \"w:tc\").filter(\n (tc) => tc.parentNode === curr,\n ).length;\n }\n curr = curr.parentNode;\n }\n }\n return null;\n }\n\n public validate_review_actions(actions: any[]): string[] {\n const errors: string[] = [];\n\n // Document-context-free shape checks (QA 2026-07-19 v8 F-07), mirroring\n // Python's validate_review_action_batch: blank replies render as empty\n // Word comment bubbles; a duplicated or conflicting accept/reject on one\n // target_id either double-counts as \"applied\" or contradicts itself.\n // Distinct IDs one action resolves as a group (a modification's del+ins\n // pair) stay legitimate, as do DIFFERENT replies to the same comment.\n const seen_resolutions = new Map<string, [number, string]>();\n const seen_replies = new Set<string>();\n for (let i = 0; i < actions.length; i++) {\n const action = actions[i];\n const type = action.type;\n const target_id = action.target_id ?? \"\";\n if (type === \"reply\") {\n if (!String(action.text ?? \"\").trim()) {\n errors.push(\n `- Action ${i + 1} Failed: reply text for ${target_id} is empty or ` +\n `whitespace-only. Word would show a blank comment bubble — provide the ` +\n `reply content in 'text'.`,\n );\n continue;\n }\n const reply_key = `${target_id}\u0000${String(action.text).trim()}`;\n if (seen_replies.has(reply_key)) {\n errors.push(\n `- Action ${i + 1} Failed: duplicate reply — this batch already replies to ` +\n `${target_id} with the same text. Remove the duplicate action.`,\n );\n }\n seen_replies.add(reply_key);\n } else if (type === \"accept\" || type === \"reject\") {\n const prior = seen_resolutions.get(target_id);\n if (prior !== undefined) {\n const [first_idx, first_type] = prior;\n if (first_type === type) {\n errors.push(\n `- Action ${i + 1} Failed: duplicate action — Action ${first_idx + 1} in this ` +\n `batch already applies '${type}' to ${target_id}. A change can only be ` +\n `resolved once; remove the duplicate action.`,\n );\n } else {\n errors.push(\n `- Action ${i + 1} Failed: conflicting actions — Action ${first_idx + 1} in ` +\n `this batch applies '${first_type}' to ${target_id}, but this action applies ` +\n `'${type}'. Decide the outcome and keep exactly one of them.`,\n );\n }\n } else {\n seen_resolutions.set(target_id, [i, type]);\n }\n }\n }\n if (errors.length > 0) return errors;\n\n for (let i = 0; i < actions.length; i++) {\n const action = actions[i];\n const type = action.type;\n\n if (type === \"reply\") {\n const cid = action.target_id.replace(\"Com:\", \"\");\n let found = false;\n const part = this.doc.pkg.parts.find(\n (p) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\",\n );\n if (part) {\n const comments = findAllDescendants(part._element, \"w:comment\");\n found = comments.some((c) => c.getAttribute(\"w:id\") === cid);\n }\n if (!found) {\n errors.push(\n `- Action ${i + 1} Failed: Target comment ID ${action.target_id} not found.`,\n );\n }\n } else if (type === \"accept\" || type === \"reject\") {\n const target_id = action.target_id.replace(\"Chg:\", \"\");\n const all_ins = findAllDescendants(this.doc.element, \"w:ins\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n const all_del = findAllDescendants(this.doc.element, \"w:del\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n if (all_ins.length === 0 && all_del.length === 0) {\n errors.push(\n `- Action ${i + 1} Failed: Target ID ${action.target_id} not found.`,\n );\n }\n }\n }\n return errors;\n }\n\n public process_batch(\n changes: DocumentChange[],\n dry_run: boolean = false,\n ): any {\n // Defensive sanitization: some LLM clients \"double-serialize\" nested\n // arrays, delivering each element of `changes` as a JSON string instead of\n // a parsed object. Downstream code mutates state trackers (e.g.\n // `edit._applied_status`) and reads `change.type` on these elements, which\n // throws a TypeError on string primitives. Parse stringified elements back\n // into objects here, leaving genuine objects (and unparseable strings)\n // untouched so validation can surface a clear error rather than crashing.\n if (Array.isArray(changes)) {\n changes = changes.map((item: any) => {\n if (typeof item === \"string\") {\n try {\n const parsed = JSON.parse(item);\n // Only swap in the parsed value if it is an object; a string that\n // parses to a scalar (e.g. \"42\") is not a valid change.\n if (parsed !== null && typeof parsed === \"object\") {\n return parsed;\n }\n return item;\n } catch {\n // Leave malformed strings as-is; the validation pass downstream\n // will report them rather than crashing on a raw TypeError.\n return item;\n }\n }\n return item;\n }) as DocumentChange[];\n }\n\n if (dry_run) {\n const snapshot = takeSnapshot(this.doc);\n const originalCurrentId = this.current_id;\n try {\n return this._process_batch_internal(changes, true);\n } finally {\n restoreSnapshot(this.doc, snapshot);\n this.current_id = originalCurrentId;\n this.mapper = new DocumentMapper(this.doc);\n this.comments_manager = new CommentsManager(this.doc);\n this.clean_mapper = null;\n }\n } else {\n return this._process_batch_internal(changes, false);\n }\n }\n\n private _process_batch_internal(\n changes: DocumentChange[],\n dry_run_mode: boolean = false,\n ): any {\n // Pre-process edits: strip identical leading heading hashes from target_text and new_text\n for (const c of changes) {\n if (\n c &&\n typeof c === \"object\" &&\n (c as any).type === \"modify\" &&\n (c as any).target_text &&\n (c as any).new_text\n ) {\n const [strippedTarget, strippedNew] = stripMatchingHeadingHashes(\n (c as any).target_text,\n (c as any).new_text,\n );\n (c as any).target_text = strippedTarget;\n (c as any).new_text = strippedNew;\n }\n }\n\n this.skipped_details = [];\n\n const actions = changes.filter(\n (c) =>\n c !== null &&\n typeof c === \"object\" &&\n [\"accept\", \"reject\", \"reply\"].includes(c.type),\n );\n const edits = changes.filter(\n (c) =>\n c === null ||\n typeof c !== \"object\" ||\n ![\"accept\", \"reject\", \"reply\"].includes(c.type),\n );\n\n // Never pre-unwrap a foreign author's <w:ins> to make a partially\n // straddling edit fit: that turns their tracked-inserted text into\n // untracked committed body text before the edit applies, destroying\n // their provenance. A partial straddle surfaces the standard validation\n // error (\"Modification targets an active insertion from another author\n // …\") via validate_edits, matching the Python engine. An edit fully\n // CONTAINED inside a foreign <w:ins> is allowed and handled by nesting\n // the <w:del> inside that <w:ins> (see _apply_single_edit_indexed /\n // _insert_and_split_ins).\n\n // BUG-7: Unified single-pass validation in wet-run / standard mode.\n if (!dry_run_mode) {\n const action_errors =\n actions.length > 0 ? this.validate_review_actions(actions) : [];\n const validate_edits_now = edits.length > 0 && action_errors.length > 0;\n const edit_errors = validate_edits_now ? this.validate_edits(edits) : [];\n const all_errors = [...action_errors, ...edit_errors];\n if (all_errors.length > 0) {\n throw new BatchValidationError(all_errors);\n }\n } else {\n if (actions.length > 0) {\n const action_errors = this.validate_review_actions(actions);\n if (action_errors.length > 0) {\n throw new BatchValidationError(action_errors);\n }\n }\n }\n\n let applied_actions = 0;\n let skipped_actions = 0;\n if (actions.length > 0) {\n const res = this.apply_review_actions(actions);\n applied_actions = res[0];\n skipped_actions = res[1];\n if (skipped_actions > 0) {\n throw new BatchValidationError(this.skipped_details);\n }\n if (applied_actions > 0) {\n this.mapper[\"_build_map\"]();\n if (this.clean_mapper) this.clean_mapper[\"_build_map\"]();\n }\n }\n\n const [body_text] = split_structural_appendix(this.mapper.full_text);\n const pag_res = paginate(body_text, \"\");\n const page_offsets = pag_res.body_page_offsets;\n\n const edits_reports: any[] = [];\n let applied_edits = 0;\n let skipped_edits = 0;\n\n if (edits.length > 0) {\n // Sequential application rebuilds the mapper after every applied edit,\n // shifting every position at/after that edit. Caller-pinned indexes\n // (_match_start_index / _resolved_start_idx, e.g. generate_edits_from_text\n // output) are coordinates in the INITIAL document state, so apply indexed\n // edits bottom-up first — positions below an applied edit never move (the\n // same invariant apply_edits' reverse sweep relies on) — then let\n // text-anchored edits re-resolve against the mutated text as before.\n // Reports are keyed by `i` so they stay in batch order.\n const pinned_idx = (e: any): number | null => {\n if (\n e._resolved_start_idx !== undefined &&\n e._resolved_start_idx !== null\n )\n return e._resolved_start_idx;\n if (\n e._match_start_index !== undefined &&\n e._match_start_index !== null\n )\n return e._match_start_index;\n return null;\n };\n const ordered_edits = edits\n .map((edit, i) => ({ edit: edit as any, i }))\n .sort((a, b) => {\n const ka = pinned_idx(a.edit);\n const kb = pinned_idx(b.edit);\n if (ka === null && kb === null) return a.i - b.i;\n if (ka === null) return 1;\n if (kb === null) return -1;\n return kb - ka || a.i - b.i;\n });\n\n if (dry_run_mode) {\n const reports_by_input: any[] = new Array(edits.length);\n // Indexes that failed VALIDATION (not runtime skips): if any exist,\n // the real run rejects the whole batch, so the dry-run report must\n // not claim any edit \"applied\" (transactional parity with Python).\n const validation_failed_idx = new Set<number>();\n for (const { edit, i } of ordered_edits) {\n let single_errors: string[];\n try {\n single_errors = this.validate_edits([edit], i);\n } catch (e) {\n // A pathological user pattern must fail as a clean per-edit\n // validation error, never a hang or crash (QA 2026-07-17 F5).\n if (!(e instanceof RegexTimeoutError)) throw e;\n single_errors = [`- Edit ${i + 1} Failed: ${e.message}`];\n }\n if (single_errors.length > 0) {\n if (applied_edits > 0) {\n const hint = sequential_context_hint(applied_edits);\n single_errors = single_errors.map((err) => err + hint);\n }\n validation_failed_idx.add(i);\n skipped_edits++;\n // Only surface the punctuation-anchor warning when the edit actually\n // failed. A clean apply already returns the redline preview, so the\n // warning is pure noise on success — and it misleads agents into\n // hunting for a \"cleaner\" anchor that was never needed (e.g. on\n // placeholders/dates where the punctuation IS the literal target).\n const warning = this._check_punctuation_warning(\n (edit as any).target_text || \"\",\n );\n reports_by_input[i] = {\n status: \"failed\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: warning,\n error: single_errors.join(\"\\n\"),\n critic_markup: null,\n clean_text: null,\n };\n continue;\n }\n const res = this.apply_edits([edit], page_offsets);\n if ((edit as any)._applied_status) {\n applied_edits++;\n const previews = this._build_edit_context_previews(edit);\n reports_by_input[i] = {\n status: \"applied\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: null,\n error: null,\n critic_markup: previews[0],\n clean_text: previews[1],\n pages: (edit as any)._pages || [],\n heading_path: (edit as any)._heading_path || \"\",\n occurrences_modified: (edit as any)._occurrences_modified || 0,\n match_mode: (edit as any).match_mode || \"strict\",\n };\n this.mapper = new DocumentMapper(this.doc);\n this.clean_mapper = null;\n } else {\n skipped_edits++;\n const error_msg =\n this.skipped_details.length > 0\n ? this.skipped_details[this.skipped_details.length - 1]\n : \"Failed to apply edit\";\n const warning = this._check_punctuation_warning(\n (edit as any).target_text || \"\",\n );\n reports_by_input[i] = {\n status: \"failed\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: warning,\n error: error_msg,\n critic_markup: null,\n clean_text: null,\n };\n }\n }\n if (validation_failed_idx.size > 0) {\n // Dry-run mirrors the real run's transactional rejection: no edit\n // will be applied by the real run, so none may be reported as\n // applied here. Edits that only failed at runtime keep their own\n // error; edits that would have applied get the transactional note.\n applied_edits = 0;\n skipped_edits = edits.length;\n for (let i = 0; i < reports_by_input.length; i++) {\n const report = reports_by_input[i];\n if (!report || validation_failed_idx.has(i)) continue;\n if (report.status === \"applied\") {\n reports_by_input[i] = {\n status: \"failed\",\n target_text: report.target_text,\n new_text: report.new_text,\n warning: null,\n error: TRANSACTIONAL_NOT_APPLIED_ERROR,\n critic_markup: null,\n clean_text: null,\n };\n }\n }\n }\n edits_reports.push(...reports_by_input);\n } else {\n // Simulated dry-run sequentially for wet-run validation parity\n const snapshot = takeSnapshot(this.doc);\n const originalCurrentId = this.current_id;\n try {\n const sequential_errors: string[] = [];\n let applied_so_far = 0;\n for (const { edit, i } of ordered_edits) {\n let single_errors: string[];\n try {\n single_errors = this.validate_edits([edit], i);\n } catch (e) {\n // Clean per-edit failure for time-budget violations (QA F5).\n if (!(e instanceof RegexTimeoutError)) throw e;\n single_errors = [`- Edit ${i + 1} Failed: ${e.message}`];\n }\n if (single_errors.length > 0) {\n if (applied_so_far > 0) {\n const hint = sequential_context_hint(applied_so_far);\n single_errors = single_errors.map((err) => err + hint);\n }\n sequential_errors.push(...single_errors);\n } else {\n this.apply_edits([edit], page_offsets);\n if ((edit as any)._applied_status) {\n applied_so_far++;\n }\n this.mapper = new DocumentMapper(this.doc);\n this.clean_mapper = null;\n }\n }\n if (sequential_errors.length > 0) {\n throw new BatchValidationError(sequential_errors);\n }\n } catch (err) {\n restoreSnapshot(this.doc, snapshot);\n this.current_id = originalCurrentId;\n this.mapper = new DocumentMapper(this.doc);\n this.comments_manager = new CommentsManager(this.doc);\n this.clean_mapper = null;\n throw err;\n }\n\n applied_edits = edits.filter((e) => (e as any)._applied_status).length;\n skipped_edits = edits.length - applied_edits;\n\n for (const edit of edits) {\n const success = (edit as any)._applied_status || false;\n const error_msg = (edit as any)._error_msg || null;\n let critic_markup = null;\n let clean_text = null;\n // Punctuation-anchor warning is failure-context only: on success the\n // redline preview below already reports the change cleanly.\n let warning: string | null = null;\n if (success) {\n const previews = this._build_edit_context_previews(edit);\n critic_markup = previews[0];\n clean_text = previews[1];\n } else {\n warning = this._check_punctuation_warning(\n (edit as any).target_text || \"\",\n );\n }\n edits_reports.push({\n status: success ? \"applied\" : \"failed\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: warning,\n error: error_msg,\n critic_markup: critic_markup,\n clean_text: clean_text,\n pages: (edit as any)._pages || [],\n heading_path: (edit as any)._heading_path || \"\",\n occurrences_modified: (edit as any)._occurrences_modified || 0,\n match_mode: (edit as any).match_mode || \"strict\",\n });\n }\n }\n }\n return {\n actions_applied: applied_actions,\n actions_skipped: skipped_actions,\n edits_applied: applied_edits,\n edits_skipped: skipped_edits,\n // edits_applied counts change OBJECTS; this is the total number of\n // document occurrences they modified (match_mode=\"all\" fan-out), so\n // automation never has to guess which of the two a count means\n // (QA 2026-07-19 F-21).\n occurrences_modified: edits_reports.reduce(\n (sum: number, r: any) => sum + (r.occurrences_modified || 0),\n 0,\n ),\n skipped_details: this.skipped_details,\n edits: edits_reports,\n engine: \"node\",\n version: \"1.18.2\",\n };\n }\n\n public apply_edits(\n edits: any[],\n page_offsets: number[] = [],\n ): [number, number] {\n let applied = 0;\n let skipped = 0;\n\n if (!page_offsets || page_offsets.length === 0) {\n const [body_text] = split_structural_appendix(this.mapper.full_text);\n page_offsets = paginate(body_text, \"\").body_page_offsets;\n }\n const resolved_edits: [any, string | null][] = [];\n\n for (const edit of edits) {\n if (typeof edit !== \"object\" || edit === null) {\n skipped++;\n continue;\n }\n edit._applied_status = false;\n edit._error_msg = null;\n edit._any_sub_failure = false;\n }\n\n for (const edit of edits) {\n if (typeof edit !== \"object\" || edit === null) continue;\n\n if (\n edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null\n ) {\n resolved_edits.push([edit, edit.new_text || null]);\n } else if (\n edit._match_start_index !== undefined &&\n edit._match_start_index !== null\n ) {\n edit._resolved_start_idx = edit._match_start_index;\n resolved_edits.push([edit, edit.new_text || null]);\n } else if (edit.type === \"insert_row\" || edit.type === \"delete_row\") {\n let matches = this.mapper.find_all_match_indices(edit.target_text);\n let resolved_mapper = this.mapper;\n if (matches.length === 0) {\n if (!this.clean_mapper) {\n this.clean_mapper = new DocumentMapper(this.doc, true);\n }\n matches = this.clean_mapper.find_all_match_indices(edit.target_text);\n resolved_mapper = this.clean_mapper;\n }\n\n if (matches.length > 0) {\n // Record WHICH mapper produced the offset: a clean-view index\n // resolved against the raw mapper lands rows at the wrong position\n // once earlier edits in the batch put tracked changes in the\n // anchor row.\n edit._resolved_start_idx = matches[0][0];\n edit._active_mapper_ref = resolved_mapper;\n resolved_edits.push([edit, null]);\n } else {\n skipped++;\n edit._applied_status = false;\n const target_snippet = (edit.target_text || \"\")\n .trim()\n .substring(0, 40);\n const msg = `- Failed to locate row target: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n }\n } else {\n let resolved: any;\n try {\n resolved = this._pre_resolve_heuristic_edit(edit);\n } catch (e) {\n // Direct apply_edits callers bypass validate_edits; the time\n // budget must still fail cleanly here (QA F5).\n if (!(e instanceof RegexTimeoutError)) throw e;\n skipped++;\n edit._applied_status = false;\n const msg = `- Failed to apply edit targeting: '${(edit.target_text || \"\").substring(0, 40)}...' (${e.message})`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n continue;\n }\n if (resolved) {\n if (Array.isArray(resolved)) {\n for (const r of resolved) {\n r._resolved_start_idx = r._match_start_index;\n r._parent_edit_ref = edit;\n if (\n edit._resolved_start_idx === undefined ||\n edit._resolved_start_idx === null\n ) {\n edit._resolved_start_idx = r._resolved_start_idx;\n }\n if (!edit._resolved_proxy_edit) {\n edit._resolved_proxy_edit = r;\n }\n resolved_edits.push([r, r.new_text]);\n }\n } else {\n resolved._resolved_start_idx = resolved._match_start_index;\n resolved._parent_edit_ref = edit;\n edit._resolved_start_idx = resolved._resolved_start_idx;\n edit._resolved_proxy_edit = resolved;\n resolved_edits.push([resolved, (resolved as any).new_text]);\n }\n } else {\n skipped++;\n edit._applied_status = false;\n const display_text = edit.target_text || \"insertion\";\n const target_snippet = display_text.trim().substring(0, 40);\n const msg = `- Failed to apply edit targeting: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n }\n }\n }\n\n resolved_edits.sort(\n (a, b) =>\n (b[0]._resolved_start_idx || 0) - (a[0]._resolved_start_idx || 0),\n );\n\n // Snapshot preview context now, while every resolved offset still refers\n // to the untouched document. The sweep below mutates the DOM and rebuilds\n // the map, shifting offsets and injecting tracked-change markup —\n // slicing full_text at report time garbles previews (QA H1).\n for (const [res_edit] of resolved_edits) {\n this._capture_preview_context(res_edit);\n if (res_edit._parent_edit_ref) {\n this._capture_parent_preview_context(res_edit._parent_edit_ref);\n }\n }\n\n const occupied_ranges: [number, number][] = [];\n // Sub-edits split from one balanced multi-paragraph modification share a\n // _split_group_id; count the group as a single applied edit (and a single\n // occurrence), even though it touches several paragraphs.\n const counted_split_groups = new Set<number>();\n\n for (const [edit, orig_new] of resolved_edits) {\n const start = edit._resolved_start_idx || 0;\n // An insert_row does not consume its anchor text — it adds an adjacent\n // row. Give it a zero-width range so several inserts sharing one\n // anchor (consecutive new rows) never flag each other as overlapping.\n const end =\n edit.type === \"insert_row\"\n ? start\n : start + (edit.target_text ? edit.target_text.length : 0);\n\n const overlaps = occupied_ranges.some(\n ([occ_start, occ_end]) => start < occ_end && end > occ_start,\n );\n if (overlaps) {\n skipped++;\n const display_text = edit.target_text || \"insertion\";\n const target_snippet = display_text.trim().substring(0, 40);\n const msg = `- Skipped overlapping edit targeting: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._applied_status = false;\n edit._error_msg = msg;\n edit._any_sub_failure = true;\n const parent = edit._parent_edit_ref;\n if (parent) {\n parent._applied_status = false;\n parent._error_msg = msg;\n parent._any_sub_failure = true;\n }\n continue;\n }\n\n let success = false;\n if (edit.type === \"modify\") {\n // Never rebuild the map inside the sweep: sub-edits apply in strictly\n // descending offset order, and every DOM mutation (run splits, w:del\n // wraps, w:ins insertions, bottom-up paragraph merges) happens at or\n // above the current offset, so spans below it stay valid in the stale\n // map. Rebuilding here made regex + match_mode=\"all\"\n // O(occurrences × document) (QA 2026-07-19 F-06).\n success = this._apply_single_edit_indexed(edit, orig_new, false);\n } else if (edit.type === \"insert_row\" || edit.type === \"delete_row\") {\n success = this._apply_table_edit(edit, false);\n }\n\n if (success) {\n // A balanced multi-paragraph split fans one logical edit into several\n // paragraph sub-edits sharing a _split_group_id; count it once. Edits\n // with no group id (the common case) always count.\n const group_id = edit._split_group_id;\n const first_in_group =\n group_id === undefined ||\n group_id === null ||\n !counted_split_groups.has(group_id);\n if (first_in_group && group_id !== undefined && group_id !== null) {\n counted_split_groups.add(group_id);\n }\n if (first_in_group) applied++;\n occupied_ranges.push([start, end]);\n edit._applied_status = true;\n const parent = edit._parent_edit_ref;\n if (parent) {\n parent._applied_status = true;\n if (first_in_group) {\n parent._occurrences_modified =\n (parent._occurrences_modified || 0) + 1;\n }\n const [path, page] = this._get_heading_path_and_page(\n start,\n this.mapper.full_text,\n page_offsets,\n );\n const pages: number[] = parent._pages || [];\n if (!pages.includes(page)) pages.unshift(page);\n parent._pages = pages;\n parent._heading_path = path;\n } else {\n if (first_in_group) {\n edit._occurrences_modified = (edit._occurrences_modified || 0) + 1;\n }\n const [path, page] = this._get_heading_path_and_page(\n start,\n this.mapper.full_text,\n page_offsets,\n );\n const pages: number[] = edit._pages || [];\n if (!pages.includes(page)) pages.unshift(page);\n edit._pages = pages;\n edit._heading_path = path;\n }\n } else {\n skipped++;\n const display_text = edit.target_text || \"insertion\";\n const target_snippet = display_text.trim().substring(0, 40);\n const msg = `- Failed to apply edit targeting: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._applied_status = false;\n edit._error_msg = msg;\n edit._any_sub_failure = true;\n const parent = edit._parent_edit_ref;\n if (parent) {\n parent._any_sub_failure = true;\n if (!parent._applied_status) {\n parent._applied_status = false;\n parent._error_msg = msg;\n }\n }\n }\n }\n\n // Return LOGICAL edit counts over the caller's input list: one\n // match_mode=\"all\" edit over N occurrences is one applied edit (its\n // occurrence count lives in _occurrences_modified / the report), never N\n // (QA 2026-07-19 F-21). An edit with any failed or skipped sub-edit\n // counts as skipped so the all-or-nothing batch contract is unchanged.\n let applied_logical = 0;\n let skipped_logical = 0;\n for (const input_edit of edits) {\n if (typeof input_edit !== \"object\" || input_edit === null) {\n skipped_logical++;\n continue;\n }\n if (input_edit._applied_status && !input_edit._any_sub_failure) {\n applied_logical++;\n } else {\n skipped_logical++;\n }\n }\n return [applied_logical, skipped_logical];\n }\n\n public apply_review_actions(actions: any[]): [number, number] {\n let applied = 0;\n let skipped = 0;\n\n for (const action of actions) {\n const type = action.type;\n if (type === \"reply\") {\n const cid = action.target_id.replace(\"Com:\", \"\");\n const new_id = this.comments_manager.addComment(\n this.author,\n action.text,\n cid,\n );\n this._anchor_reply_comment(cid, new_id);\n applied++;\n continue;\n }\n\n const target_id = action.target_id.replace(\"Chg:\", \"\");\n const all_ins = findAllDescendants(this.doc.element, \"w:ins\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n const all_del = findAllDescendants(this.doc.element, \"w:del\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n const all_nodes = [...all_ins, ...all_del];\n\n if (all_nodes.length === 0) {\n skipped++;\n this.skipped_details.push(\n `- Failed to apply action: Target ID ${action.target_id} not found.`,\n );\n continue;\n }\n\n // Refuse accept/reject on a w:id shared by revisions from DIFFERENT\n // authors. Uniqueness of w:id is assumed but not guaranteed for\n // externally produced documents (merges, cross-document copy-paste),\n // where one action would silently resolve several unrelated changes\n // (QA 2026-07-17 F9). Same-author reuse is legitimate — this engine\n // itself mints one id across every element of a single logical edit —\n // so authorship is the discriminator.\n const dup_authors = Array.from(\n new Set(all_nodes.map((n) => n.getAttribute(\"w:author\") || \"Unknown\")),\n ).sort();\n if (dup_authors.length > 1) {\n skipped++;\n this.skipped_details.push(\n `- Failed to apply action: ${type} on Chg:${target_id} is ambiguous. The document ` +\n `contains ${all_nodes.length} tracked-change elements sharing w:id=${target_id} from ` +\n `different authors (${dup_authors.join(\", \")}) — duplicate revision IDs produced ` +\n `outside this engine (e.g. by a document merge or copy-paste). Acting on this ID ` +\n `would resolve all of them at once. Resolve these changes individually in Word, or ` +\n `apply the intended outcome as an explicit text edit instead.`,\n );\n continue;\n }\n\n for (const node of all_nodes) {\n const is_ins = node.tagName === \"w:ins\";\n const parent_tag = node.parentNode\n ? (node.parentNode as Element).tagName\n : \"\";\n const is_trPr = parent_tag === \"w:trPr\";\n\n if (type === \"accept\") {\n if (is_ins) {\n this._clean_wrapping_comments(node);\n if (is_trPr) node.parentNode?.removeChild(node);\n else {\n while (node.firstChild)\n node.parentNode?.insertBefore(node.firstChild, node);\n node.parentNode?.removeChild(node);\n }\n } else {\n this._clean_wrapping_comments(node);\n this._delete_comments_in_element(node);\n if (is_trPr) {\n const tr = node.parentNode?.parentNode;\n tr?.parentNode?.removeChild(tr);\n } else {\n node.parentNode?.removeChild(node);\n }\n }\n } else if (type === \"reject\") {\n if (is_ins) {\n this._clean_wrapping_comments(node);\n this._delete_comments_in_element(node);\n if (is_trPr) {\n const tr = node.parentNode?.parentNode;\n tr?.parentNode?.removeChild(tr);\n } else node.parentNode?.removeChild(node);\n } else {\n this._clean_wrapping_comments(node);\n if (is_trPr) node.parentNode?.removeChild(node);\n else {\n const delTexts = Array.from(\n node.getElementsByTagName(\"w:delText\"),\n );\n for (const dt of delTexts) {\n const t = dt.ownerDocument!.createElement(\"w:t\");\n t.textContent = dt.textContent;\n if (dt.hasAttribute(\"xml:space\"))\n t.setAttribute(\"xml:space\", \"preserve\");\n dt.parentNode?.replaceChild(t, dt);\n }\n while (node.firstChild)\n node.parentNode?.insertBefore(node.firstChild, node);\n node.parentNode?.removeChild(node);\n }\n }\n }\n }\n applied++;\n }\n return [applied, skipped];\n }\n\n private _apply_table_edit(edit: any, rebuild_map: boolean): boolean {\n const start_idx =\n edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null\n ? edit._resolved_start_idx\n : edit._match_start_index || 0;\n // The offset must be looked up in the coordinate space it was resolved\n // in: a clean-view offset applied to the raw\n // mapper points at earlier text once tracked changes exist.\n const active_mapper: DocumentMapper = edit._active_mapper_ref || this.mapper;\n const [anchor_run, anchor_para] = active_mapper.get_insertion_anchor(\n start_idx,\n rebuild_map,\n );\n\n let target_element: Element | null = null;\n if (anchor_run) target_element = anchor_run._element;\n else if (anchor_para) target_element = anchor_para._element;\n\n if (!target_element) return false;\n\n let tr: Element | null = target_element;\n while (tr && tr.tagName !== \"w:tr\") tr = tr.parentNode as Element;\n if (!tr) return false;\n\n if (edit.type === \"delete_row\") {\n let trPr = findChild(tr, \"w:trPr\");\n if (!trPr) {\n trPr = tr.ownerDocument!.createElement(\"w:trPr\");\n tr.insertBefore(trPr, tr.firstChild);\n }\n trPr.appendChild(this._create_track_change_tag(\"w:del\"));\n return true;\n } else if (edit.type === \"insert_row\") {\n const new_tr = tr.ownerDocument!.createElement(\"w:tr\");\n const trPr = tr.ownerDocument!.createElement(\"w:trPr\");\n new_tr.appendChild(trPr);\n trPr.appendChild(this._create_track_change_tag(\"w:ins\"));\n // The new row must carry exactly as many cells as the anchor row has\n // columns: pad missing cells with empty strings and drop extras\n // (validation already rejects overfilled batches upfront, QA M3) so a\n // mismatched `cells` list can never produce a structurally\n // inconsistent table row.\n const anchor_cols = findAllDescendants(tr, \"w:tc\").filter(\n (tc) => tc.parentNode === tr,\n ).length;\n let cell_values: string[] = Array.isArray(edit.cells)\n ? [...edit.cells]\n : [];\n if (anchor_cols > 0) {\n while (cell_values.length < anchor_cols) cell_values.push(\"\");\n cell_values = cell_values.slice(0, anchor_cols);\n }\n for (const cellText of cell_values) {\n const tc = tr.ownerDocument!.createElement(\"w:tc\");\n const p = tr.ownerDocument!.createElement(\"w:p\");\n const r = tr.ownerDocument!.createElement(\"w:r\");\n const t = tr.ownerDocument!.createElement(\"w:t\");\n t.textContent = cellText;\n if (cellText.trim() !== cellText)\n t.setAttribute(\"xml:space\", \"preserve\");\n r.appendChild(t);\n p.appendChild(r);\n tc.appendChild(p);\n new_tr.appendChild(tc);\n }\n if (edit.position === \"above\") tr.parentNode?.insertBefore(new_tr, tr);\n else insertAfter(new_tr, tr);\n return true;\n }\n return false;\n }\n\n private _pre_resolve_heuristic_edit(edit: any): any {\n if (!edit.target_text) return null;\n\n const is_regex = edit.regex || false;\n const match_mode = edit.match_mode || \"strict\";\n\n let matches = this.mapper.find_all_match_indices(\n edit.target_text,\n is_regex,\n );\n let use_clean_map = false;\n\n if (matches.length === 0) {\n if (!this.clean_mapper)\n this.clean_mapper = new DocumentMapper(this.doc, true);\n matches = this.clean_mapper.find_all_match_indices(\n edit.target_text,\n is_regex,\n );\n if (matches.length > 0) use_clean_map = true;\n else return null;\n }\n\n const active_mapper = use_clean_map ? this.clean_mapper! : this.mapper;\n\n let live_matches: [number, number][] = [];\n for (const [s, match_len] of matches) {\n const realSpans = active_mapper.spans.filter(\n (span) =>\n span.run !== null && span.end > s && span.start < s + match_len,\n );\n if (realSpans.length === 0 || realSpans.some((span) => !span.del_id)) {\n live_matches.push([s, match_len]);\n }\n }\n\n if (live_matches.length === 0) return null;\n\n if (match_mode === \"strict\" || match_mode === \"first\") {\n live_matches = live_matches.slice(0, 1);\n }\n\n const all_sub_edits: any[] = [];\n\n for (const [start_idx, match_len] of live_matches) {\n const actual_doc_text = active_mapper.full_text.substring(\n start_idx,\n start_idx + match_len,\n );\n let current_effective_new_text = edit.new_text || \"\";\n\n // Cell anchors ({#cell:<paraId>}) are pure position markers with no real\n // content — they let the model address an empty (or any) table cell that\n // has no run to diff against. Treat such a target as a clean INSERTION at\n // the anchor's paragraph: never delete the marker, never run trim_common_context\n // (which refuses to split inside {#...} markup and yields a no-op MODIFICATION).\n // Strip any echoed anchor from new_text so the model can send either\n // \"June 22, 2026\" or \"June 22, 2026{#cell:...}\" and get the same result.\n if (/^\\{#cell:[^}]+\\}$/.test(actual_doc_text.trim())) {\n let ins_text = current_effective_new_text;\n // Drop a leading/trailing copy of the same anchor token if echoed.\n ins_text = ins_text.split(actual_doc_text.trim()).join(\"\");\n if (ins_text) {\n all_sub_edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: ins_text,\n comment: edit.comment,\n // Insert at the anchor token's start so the new run lands inside\n // the cell paragraph that get_insertion_anchor resolves there.\n _match_start_index: start_idx,\n _internal_op: \"INSERTION\",\n _active_mapper_ref: active_mapper,\n });\n } else if (edit.comment) {\n // Anchor target with empty effective new_text but a comment: attach\n // the comment to the cell paragraph.\n all_sub_edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: \"\",\n comment: edit.comment,\n _match_start_index: start_idx,\n _internal_op: \"COMMENT_ONLY\",\n _active_mapper_ref: active_mapper,\n });\n }\n continue;\n }\n\n if (is_regex && current_effective_new_text) {\n try {\n current_effective_new_text = actual_doc_text.replace(\n new RegExp(edit.target_text),\n current_effective_new_text,\n );\n } catch (e) {}\n }\n\n // Stash the first occurrence's full match for the report preview, so it\n // can show the complete logical change rather than only the first\n // word-diff sub-edit (e.g. \"{--two--}{++five++} (2) years\" for a\n // \"two (2) years\" -> \"five (5) years\" edit). Mirrors Python (QA H1).\n if (!edit._preview_span) {\n edit._preview_span = [start_idx, match_len];\n edit._preview_matched_text = actual_doc_text;\n edit._preview_new_text = current_effective_new_text;\n edit._preview_mapper_ref = active_mapper;\n }\n\n const [edit_target_clean, edit_target_style] = this._parse_markdown_style(\n edit.target_text,\n );\n const [edit_new_clean, edit_new_style] = this._parse_markdown_style(\n current_effective_new_text,\n );\n\n if (edit_target_style !== edit_new_style) {\n const [actual_clean] = this._parse_markdown_style(actual_doc_text);\n const final_target = actual_clean;\n const final_new = edit_new_clean;\n const style_op =\n final_target === final_new ? \"STYLE_ONLY\" : \"STYLE_AND_TEXT\";\n const prefix_offset = actual_doc_text.indexOf(actual_clean);\n const effective_start_idx =\n start_idx + (prefix_offset !== -1 ? prefix_offset : 0);\n const resolved_style =\n edit_new_style !== null ? edit_new_style : \"Normal\";\n\n all_sub_edits.push({\n type: \"modify\",\n target_text: final_target,\n new_text: final_new,\n comment: edit.comment,\n _match_start_index: effective_start_idx,\n _internal_op: style_op,\n _new_style: resolved_style,\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n if (\n actual_doc_text === current_effective_new_text ||\n edit.target_text === current_effective_new_text\n ) {\n all_sub_edits.push({\n type: \"modify\",\n target_text: actual_doc_text,\n new_text: actual_doc_text,\n comment: edit.comment,\n _match_start_index: start_idx,\n _internal_op: \"COMMENT_ONLY\",\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n let overlaps_virtual_pipe = false;\n if (active_mapper) {\n overlaps_virtual_pipe = active_mapper.spans.some(\n (s: any) =>\n s.text === \" | \" &&\n (s.run === null || s.run === undefined) &&\n s.start < start_idx + match_len &&\n s.end > start_idx,\n );\n }\n\n if (overlaps_virtual_pipe) {\n const actual_cells = actual_doc_text.split(\"|\");\n const new_cells = current_effective_new_text.split(\"|\");\n\n if (actual_cells.length !== new_cells.length) {\n throw new BatchValidationError([\n `Target text spans ${actual_cells.length} table cells, but replacement provides ${new_cells.length}. To modify text without altering table structure (rows or columns), ensure the replacement contains the exact same number of '|' separators (e.g., replace with 'CellC | ' to empty the second cell).`\n ]);\n }\n\n if (actual_cells.length > 1) {\n const sub_edits: any[] = [];\n\n // actual_doc_text IS the document slice at\n // [start_idx, start_idx + len): per-cell offsets are exact\n // arithmetic over that slice — never a search of mapper.full_text,\n // which cannot distinguish repeated cell text and lands in the\n // wrong cell when the matched range starts inside a \" | \"\n // separator.\n let cell_start_in_target = 0;\n\n // Determine which cell receives the comment\n let target_comment_idx = 0;\n for (let idx = 0; idx < actual_cells.length; idx++) {\n if (actual_cells[idx].trim() !== new_cells[idx].trim()) {\n target_comment_idx = idx;\n break;\n }\n }\n\n for (let cell_idx = 0; cell_idx < actual_cells.length; cell_idx++) {\n const a_cell = actual_cells[cell_idx];\n const n_cell = new_cells[cell_idx];\n const a_clean = a_cell.trim();\n const n_clean = n_cell.trim();\n const actual_start =\n start_idx +\n cell_start_in_target +\n (a_clean ? a_cell.indexOf(a_clean) : 0);\n\n const should_attach_comment = (edit.comment !== null && edit.comment !== undefined) && (cell_idx === target_comment_idx);\n\n if (a_clean !== n_clean || should_attach_comment) {\n const cell_sub_edits = this._word_diff_sub_edits(\n a_clean,\n n_clean,\n actual_start,\n should_attach_comment ? edit.comment : null,\n true,\n active_mapper,\n );\n for (const se of cell_sub_edits) {\n se._original_target_text = edit.target_text;\n se._split_group_id = start_idx;\n sub_edits.push(se);\n }\n }\n\n cell_start_in_target += a_cell.length + 1; // +1 for the '|'\n }\n\n for (const sub of sub_edits) {\n all_sub_edits.push(sub);\n }\n continue;\n }\n // Exactly one \"cell\": the target merely brushes a separator (its\n // match range starts or ends inside \" | \") without crossing into\n // another cell's text. That is an ordinary in-cell edit — fall\n // through to the standard resolution.\n }\n\n let has_markdown = false;\n if (edit.target_text && (edit.target_text.includes(\"**\") || edit.target_text.includes(\"_\"))) {\n has_markdown = true;\n }\n if (current_effective_new_text && (current_effective_new_text.includes(\"**\") || current_effective_new_text.includes(\"_\"))) {\n has_markdown = true;\n }\n\n let effective_op = \"\";\n let final_target = \"\";\n let final_new = \"\";\n let effective_start_idx = start_idx;\n\n if (current_effective_new_text.startsWith(actual_doc_text)) {\n effective_op = \"INSERTION\";\n final_new = current_effective_new_text.substring(actual_doc_text.length);\n effective_start_idx = start_idx + match_len;\n } else {\n const [prefix_len, suffix_len] = trim_common_context(\n actual_doc_text,\n current_effective_new_text,\n );\n const t_end = actual_doc_text.length - suffix_len;\n const n_end = current_effective_new_text.length - suffix_len;\n\n final_target = actual_doc_text.substring(prefix_len, t_end);\n final_new = current_effective_new_text.substring(prefix_len, n_end);\n effective_start_idx = start_idx + prefix_len;\n }\n\n if (has_markdown) {\n if (!final_target && final_new) {\n effective_op = \"INSERTION\";\n } else if (final_target && !final_new) {\n effective_op = \"DELETION\";\n } else if (final_target && final_new) {\n effective_op = \"MODIFICATION\";\n } else {\n all_sub_edits.push({\n type: \"modify\",\n target_text: final_target,\n new_text: final_new,\n comment: edit.comment,\n _match_start_index: effective_start_idx,\n _internal_op: \"COMMENT_ONLY\",\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n all_sub_edits.push({\n type: \"modify\",\n target_text: final_target,\n new_text: final_new,\n comment: edit.comment,\n _resolved_start_idx: effective_start_idx,\n _match_start_index: effective_start_idx,\n _internal_op: effective_op,\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n // Balanced multi-paragraph modification: the matched span crosses one or\n // more paragraph breaks and the replacement preserves the same number of\n // breaks. Apply it as one independent sub-edit per paragraph segment so\n // the structural \\n\\n breaks are left intact. Each sub-edit shares a\n // _split_group_id (the occurrence's start index) so the batch report\n // counts it as a single applied edit. Unbalanced cases (a genuine\n // paragraph merge or split) fall through to the single-span path and are\n // rejected by validate_edits.\n const target_segs = actual_doc_text.split(\"\\n\\n\");\n const new_segs = current_effective_new_text.split(\"\\n\\n\");\n if (\n actual_doc_text.includes(\"\\n\\n\") &&\n target_segs.length === new_segs.length\n ) {\n const split_sub_edits: any[] = [];\n let seg_offset = start_idx;\n let comment_assigned = false;\n for (let k = 0; k < target_segs.length; k++) {\n const t_seg = target_segs[k];\n const n_seg = new_segs[k];\n if (t_seg !== n_seg) {\n const seg_comment =\n edit.comment && !comment_assigned ? edit.comment : null;\n const seg_sub_edits = this._word_diff_sub_edits(\n t_seg,\n n_seg,\n seg_offset,\n seg_comment,\n false,\n active_mapper,\n );\n if (seg_sub_edits.some((se) => se.comment !== null && se.comment !== undefined)) {\n comment_assigned = true;\n }\n for (const se of seg_sub_edits) {\n se._split_group_id = start_idx;\n split_sub_edits.push(se);\n }\n }\n // Advance past this segment plus its \"\\n\\n\" separator span.\n seg_offset += t_seg.length + 2;\n }\n if (split_sub_edits.length > 0) {\n for (const sub of split_sub_edits) all_sub_edits.push(sub);\n continue;\n }\n }\n\n // After trimming shared context, an edit whose target remainder is\n // EMPTY is a pure insertion with exactly one hunk. Resolve it\n // directly at the effective offset instead of word-diffing the full\n // strings: dmp's alignment can cross-match punctuation between the\n // shared context and the inserted text (pairing the period of \"two.\"\n // with \"marker.\") and split the insertion apart.\n if (!final_target && final_new) {\n all_sub_edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: final_new,\n comment: edit.comment,\n _resolved_start_idx: effective_start_idx,\n _match_start_index: effective_start_idx,\n _internal_op: \"INSERTION\",\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n const sub_edits = this._word_diff_sub_edits(\n actual_doc_text,\n current_effective_new_text,\n start_idx,\n edit.comment,\n false,\n active_mapper,\n );\n for (const se of sub_edits) {\n se._split_group_id = start_idx;\n all_sub_edits.push(se);\n }\n }\n\n if (all_sub_edits.length === 0) return null;\n if (match_mode === \"all\" || all_sub_edits.length > 1) return all_sub_edits;\n return all_sub_edits[0];\n }\n\n /**\n * Split a <w:ins> so that everything up to and INCLUDING split_after stays in\n * a left <w:ins>, new_elem is placed between, and the remainder moves to a\n * right <w:ins> — all at the grandparent level. Used when revising another\n * author's pending insertion: the <w:del> stays nested in their <w:ins> while\n * our replacement <w:ins> lands as a sibling, so we never nest <w:ins> in\n * <w:ins>.\n */\n private _insert_and_split_ins(\n parent_ins: Element,\n anchor: Element,\n new_elem: Element,\n split_before: boolean = false,\n ) {\n const grandparent = parent_ins.parentNode as Element | null;\n if (!grandparent) return;\n // cloneNode(false) copies the attributes (author/id/date) onto both halves.\n // The split lands after `anchor` by default; with split_before the anchor\n // itself goes to the right half so new_elem ends up in front of it.\n const left = parent_ins.cloneNode(false) as Element;\n const right = parent_ins.cloneNode(false) as Element;\n let toRight = false;\n for (const kid of Array.from(parent_ins.childNodes)) {\n parent_ins.removeChild(kid);\n if (split_before && kid === anchor) toRight = true;\n if (!toRight) {\n left.appendChild(kid);\n if (kid === anchor) toRight = true;\n } else {\n right.appendChild(kid);\n }\n }\n if (left.childNodes.length > 0) grandparent.insertBefore(left, parent_ins);\n grandparent.insertBefore(new_elem, parent_ins);\n if (right.childNodes.length > 0)\n grandparent.insertBefore(right, parent_ins);\n grandparent.removeChild(parent_ins);\n }\n\n private _apply_single_edit_indexed(\n edit: any,\n orig_new: string | null,\n rebuild_map: boolean,\n ): boolean {\n let op = edit._internal_op;\n const active_mapper = edit._active_mapper_ref || this.mapper;\n const start_idx =\n edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null\n ? edit._resolved_start_idx\n : edit._match_start_index || 0;\n const length = edit.target_text ? edit.target_text.length : 0;\n\n // Indexed edits (caller-supplied _match_start_index, e.g. straight from\n // generate_edits_from_text) bypass _pre_resolve_heuristic_edit — the only\n // place _internal_op is normally assigned. Without this fallback the\n // deletion sweep below still runs but no insertion branch does: a\n // replacement silently degrades to a pure tracked deletion and a pure\n // insertion fails. Mirrors the Python engine.\n if (op === undefined || op === null) {\n if (!edit.target_text && edit.new_text) {\n op = \"INSERTION\";\n } else if (edit.target_text && !edit.new_text) {\n op = \"DELETION\";\n } else {\n op = \"MODIFICATION\";\n }\n }\n\n // Explicit bold/italic markers in the edit make the markers\n // authoritative: inserted runs must not additionally inherit the replaced\n // span's emphasis (QA 2026-07-19 F-02). Keys on THIS resolved edit's\n // post-trim fields: identical markers on both sides were absorbed into\n // context (formatting unchanged — keep inheriting), and plain edits\n // fuzzy-matched onto styled text never receive marker hunks at all.\n const suppress_emphasis = this._edit_declares_emphasis(edit);\n\n if (op === \"STYLE_ONLY\" || op === \"STYLE_AND_TEXT\") {\n const [anchor_run, anchor_para] = active_mapper.get_insertion_anchor(\n start_idx,\n rebuild_map,\n );\n let target_para_el: Element | null = null;\n if (anchor_para) {\n target_para_el = anchor_para._element;\n } else if (anchor_run) {\n let walker: Element | null = anchor_run._element;\n while (walker && walker.tagName !== \"w:p\") {\n walker = walker.parentNode as Element | null;\n }\n target_para_el = walker;\n }\n\n if (target_para_el && edit._new_style) {\n this._set_paragraph_style(target_para_el, edit._new_style);\n }\n\n if (op === \"STYLE_ONLY\") {\n if (edit.comment) {\n const target_runs = active_mapper.find_target_runs_by_index(\n start_idx,\n length,\n rebuild_map,\n );\n if (target_runs.length > 0) {\n const first_el = target_runs[0]._element;\n const last_el = target_runs[target_runs.length - 1]._element;\n let start_p: Element | null = first_el;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element;\n let end_p: Element | null = last_el;\n while (end_p && end_p.tagName !== \"w:p\")\n end_p = end_p.parentNode as Element;\n if (start_p && end_p) {\n const ascend_to_paragraph_child = (\n el: Element,\n p: Element,\n ): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n const first_anchor = ascend_to_paragraph_child(first_el, start_p);\n const last_anchor = ascend_to_paragraph_child(last_el, end_p);\n if (start_p === end_p) {\n this._attach_comment(\n start_p,\n first_anchor,\n last_anchor,\n edit.comment,\n );\n } else {\n this._attach_comment_spanning(\n start_p,\n first_anchor,\n end_p,\n last_anchor,\n edit.comment,\n );\n }\n }\n }\n }\n return true;\n }\n\n if (edit.target_text && edit.new_text) {\n op = \"MODIFICATION\";\n } else if (!edit.target_text && edit.new_text) {\n op = \"INSERTION\";\n } else if (edit.target_text && !edit.new_text) {\n op = \"DELETION\";\n } else {\n op = \"COMMENT_ONLY\";\n }\n }\n\n const del_id = [\"DELETION\", \"MODIFICATION\"].includes(op)\n ? this._getNextId()\n : null;\n const ins_id = [\"INSERTION\", \"MODIFICATION\"].includes(op)\n ? this._getNextId()\n : null;\n\n if (op === \"COMMENT_ONLY\") {\n // Resolve the runs covering [start_idx, start_idx+length) and attach a\n // comment around them. No tracked-change is produced.\n const target_runs = active_mapper.find_target_runs_by_index(\n start_idx,\n length,\n rebuild_map,\n );\n if (target_runs.length === 0) return false;\n if (!edit.comment) return true;\n\n const first_el = target_runs[0]._element;\n const last_el = target_runs[target_runs.length - 1]._element;\n\n // Walk up from the first/last run to their containing <w:p>.\n let start_p: Element | null = first_el;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element;\n let end_p: Element | null = last_el;\n while (end_p && end_p.tagName !== \"w:p\")\n end_p = end_p.parentNode as Element;\n if (!start_p || !end_p) return false;\n\n // first_el / last_el may live inside a <w:ins> or <w:del>. We need their\n // top-level child-of-paragraph ancestor so the comment markers become\n // siblings of those wrappers, not children.\n const ascend_to_paragraph_child = (el: Element, p: Element): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n const first_anchor = ascend_to_paragraph_child(first_el, start_p);\n const last_anchor = ascend_to_paragraph_child(last_el, end_p);\n\n if (start_p === end_p) {\n this._attach_comment(start_p, first_anchor, last_anchor, edit.comment);\n } else {\n this._attach_comment_spanning(\n start_p,\n first_anchor,\n end_p,\n last_anchor,\n edit.comment,\n );\n }\n return true;\n }\n if (op === \"INSERTION\") {\n let final_new_text = edit.new_text || \"\";\n\n // A MACHINE-PINNED pure insertion (diff/text round-trip output:\n // authored with an empty target and no parent edit) positioned in the\n // separator gap between the body and a following part anchors to the\n // end of the BODY with forced new-paragraph semantics — anchoring on\n // the next part's first paragraph writes the new final body paragraph\n // into word/footer1.xml. Insertions DERIVED from a target-anchored\n // edit (parent ref set — e.g. prepending \"DRAFT \" to \"FOOTER MARKER\")\n // keep the user's chosen anchor: their context names the part they\n // meant.\n let boundary_anchor: TextSpan | null = null;\n const boundary =\n typeof (active_mapper as any).part_boundary_at === \"function\"\n ? active_mapper.part_boundary_at(start_idx)\n : null;\n const is_machine_pure_insertion =\n !edit.target_text &&\n (edit._parent_edit_ref === undefined || edit._parent_edit_ref === null);\n if (boundary !== null && is_machine_pure_insertion) {\n const [prev_i, next_i] = boundary;\n const prev_kind = active_mapper.part_kind_of(prev_i);\n const next_kind = active_mapper.part_kind_of(next_i);\n if (prev_kind === \"body\" && next_kind !== \"body\") {\n const real_before = active_mapper.spans.filter(\n (s: TextSpan) => s.run !== null && s.part_index === prev_i,\n );\n if (real_before.length > 0) {\n boundary_anchor = real_before[real_before.length - 1];\n }\n }\n }\n\n let anchor_run: Run | null;\n let anchor_para: Paragraph | null;\n if (boundary_anchor !== null) {\n anchor_run = boundary_anchor.run;\n anchor_para = boundary_anchor.paragraph;\n if (!final_new_text.startsWith(\"\\n\")) {\n final_new_text = \"\\n\\n\" + final_new_text;\n }\n } else {\n [anchor_run, anchor_para] = active_mapper.get_insertion_anchor(\n start_idx,\n rebuild_map,\n );\n }\n if (!anchor_run && !anchor_para) return false;\n\n // QA 2026-07-18 C2 (apply-level backstop, pinned edits bypass\n // validate_edits): refuse insertions that would write row-shaped pipe\n // text into a table cell.\n if (\n RedlineEngine._introduces_table_row_text(\n active_mapper,\n start_idx,\n 1,\n \"\",\n final_new_text,\n )\n ) {\n return false;\n }\n\n // BUG-23-3: a prefix insertion whose new_text ends in a paragraph break\n // (e.g. \"Summary\\n\\n\" inserted before \"Conclusion\") must become a NEW\n // paragraph placed BEFORE the anchor paragraph, not inline text merged\n // into a neighbouring paragraph. _track_insert_multiline drops the\n // trailing break and inlines the remainder, which both loses the\n // paragraph boundary and mis-orders the content. Handle this case here.\n // (Skipped when the C1 boundary re-anchor above took over the anchor.)\n const _bug233_new = final_new_text;\n const _bug233_trailing_break =\n boundary_anchor === null && /\\n\\s*$/.test(_bug233_new);\n let _bug233_target_para: Element | null = null;\n {\n const startingSpans = active_mapper.spans.filter(\n (s: TextSpan) => s.paragraph !== null && s.start === start_idx,\n );\n if (startingSpans.length > 0 && startingSpans[0].paragraph) {\n _bug233_target_para = startingSpans[0].paragraph._element;\n }\n }\n if (\n _bug233_trailing_break &&\n _bug233_target_para &&\n _bug233_target_para.parentNode\n ) {\n const body = _bug233_target_para.parentNode as Element;\n const xmlDoc = this.doc.part._element.ownerDocument!;\n const lines = _bug233_new\n .split(/[\\r\\n]+/)\n .filter((l: string) => l !== \"\");\n let firstNew: Element | null = null;\n let lastNew: Element | null = null;\n let lastIns: Element | null = null;\n for (const raw_line of lines) {\n const [clean_text, style_name] = this._parse_markdown_style(raw_line);\n const new_p = xmlDoc.createElement(\"w:p\");\n if (style_name) {\n this._set_paragraph_style(new_p, style_name);\n } else {\n const existing_pPr = findChild(_bug233_target_para, \"w:pPr\");\n if (existing_pPr) new_p.appendChild(existing_pPr.cloneNode(true));\n }\n let pPr = findChild(new_p, \"w:pPr\");\n if (!pPr) {\n pPr = xmlDoc.createElement(\"w:pPr\");\n new_p.insertBefore(pPr, new_p.firstChild);\n }\n let rPr = findChild(pPr, \"w:rPr\");\n if (!rPr) {\n rPr = xmlDoc.createElement(\"w:rPr\");\n pPr.appendChild(rPr);\n }\n rPr.appendChild(this._create_track_change_tag(\"w:ins\", \"\", ins_id!));\n const content_ins = this._build_tracked_ins_for_line(\n clean_text,\n anchor_run,\n ins_id!,\n xmlDoc,\n suppress_emphasis,\n );\n if (content_ins) new_p.appendChild(content_ins);\n body.insertBefore(new_p, _bug233_target_para);\n if (!firstNew) firstNew = new_p;\n lastNew = new_p;\n lastIns = content_ins;\n }\n if (firstNew) {\n if (edit.comment && lastNew && lastIns) {\n const ascend = (el: Element, p: Element): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p)\n cur = cur.parentNode as Element;\n return cur;\n };\n const startIns =\n findAllDescendants(firstNew, \"w:ins\")[0] || firstNew;\n this._attach_comment_spanning(\n firstNew,\n ascend(startIns, firstNew),\n lastNew,\n ascend(lastIns, lastNew),\n edit.comment,\n );\n }\n return true;\n }\n }\n\n const result = this._track_insert_multiline(\n final_new_text,\n anchor_run,\n anchor_para,\n ins_id!,\n null,\n suppress_emphasis,\n // Paragraph-start insertions attach BEFORE the anchor (see\n // before_anchor below): the suffix relocation must know.\n start_idx === 0,\n );\n\n if (!result.first_node) return false;\n\n // Place the inline <w:ins> (or block-mode first paragraph) into the DOM.\n // Block-mode first_node is already a freshly-inserted <w:p>; only the\n // inline case needs DOM splicing here.\n const is_inline_first = result.first_node.tagName === \"w:ins\";\n if (is_inline_first) {\n if (anchor_run) {\n let anchor_el: Element = anchor_run._element;\n let anchor_parent = anchor_el.parentNode as Element | null;\n // A tracked-deleted anchor (run inside <w:del>) cannot host the\n // new <w:ins> as a child — an insertion nested inside a deletion\n // is invalid revision XML. Lift the anchor to the <w:del> wrapper\n // so the insert lands beside the whole block (mirrors the Python\n // engine).\n if (anchor_parent && anchor_parent.tagName === \"w:del\") {\n anchor_el = anchor_parent;\n anchor_parent = anchor_el.parentNode as Element | null;\n }\n // get_insertion_anchor(0) resolves to the document's FIRST run: the\n // insertion point precedes it, so the new <w:ins> must land before\n // the anchor, not after (mirrors the Python engine's insert_before\n // path).\n const before_anchor = start_idx === 0;\n if (anchor_parent && anchor_parent.tagName === \"w:ins\") {\n // Inserting inside another author's pending <w:ins>: split it so our\n // new <w:ins> lands as a sibling right next to the anchor run, never\n // <w:ins> nested in <w:ins> (mirrors the MODIFICATION path and the\n // Python engine).\n this._insert_and_split_ins(\n anchor_parent,\n anchor_el,\n result.first_node,\n before_anchor,\n );\n } else if (before_anchor && anchor_parent) {\n anchor_parent.insertBefore(result.first_node, anchor_el);\n } else {\n insertAfter(result.first_node, anchor_el);\n }\n } else if (anchor_para) {\n // Paragraph-anchored insertion: the anchor resolves to a paragraph\n // (not a run) for zero-width paragraph-start spans — e.g. index 0 of\n // the document. The insertion point is the START of the paragraph\n // content, so land right after pPr, mirroring the Python engine;\n // appendChild would drop the text at the paragraph's END.\n const para_el = anchor_para._element;\n let ref: Node | null = para_el.firstChild;\n while (ref && (ref as Element).tagName === \"w:pPr\") {\n ref = ref.nextSibling;\n }\n para_el.insertBefore(result.first_node, ref);\n }\n }\n\n // Attach the comment if requested. Anchor depends on whether we created\n // additional paragraphs.\n if (edit.comment) {\n const ascend_to_paragraph_child = (\n el: Element,\n p: Element,\n ): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n\n if (result.last_p && result.last_ins) {\n // Multi-paragraph: anchor from first_node (in its host paragraph)\n // through last_ins (inside last_p).\n let start_p: Element | null = result.first_node;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element;\n if (start_p) {\n let first_anchor_target = result.first_node;\n if (result.first_node.tagName === \"w:p\") {\n first_anchor_target =\n findAllDescendants(result.first_node, \"w:ins\")[0] ||\n result.first_node;\n }\n const start_anchor = ascend_to_paragraph_child(\n first_anchor_target,\n start_p,\n );\n const end_anchor = ascend_to_paragraph_child(\n result.last_ins,\n result.last_p,\n );\n this._attach_comment_spanning(\n start_p,\n start_anchor,\n result.last_p,\n end_anchor,\n edit.comment,\n );\n }\n } else {\n // Inline only: anchor around first_node in its host paragraph.\n let host_p: Element | null = result.first_node;\n while (host_p && host_p.tagName !== \"w:p\")\n host_p = host_p.parentNode as Element;\n if (host_p) {\n let first_anchor_target = result.first_node;\n if (result.first_node.tagName === \"w:p\") {\n first_anchor_target =\n findAllDescendants(result.first_node, \"w:ins\")[0] ||\n result.first_node;\n }\n const anchor = ascend_to_paragraph_child(\n first_anchor_target,\n host_p,\n );\n this._attach_comment(host_p, anchor, anchor, edit.comment);\n }\n }\n }\n return true;\n }\n\n // QA 2026-07-18 C1 (apply-level backstop, pinned edits bypass\n // validate_edits): a modification/deletion may never mutate real text\n // from two different OPC parts in one span. Single-part documents skip\n // the scan.\n if (\n (op === \"DELETION\" || op === \"MODIFICATION\") &&\n length &&\n active_mapper.part_ranges.filter((r: [number, number, string]) => r[1] > r[0]).length > 1\n ) {\n const crossed_parts = new Set<number>();\n for (const s of active_mapper.spans) {\n if (s.run !== null && s.end > start_idx && s.start < start_idx + length) {\n crossed_parts.add(s.part_index);\n }\n }\n if (crossed_parts.size > 1) {\n console.error(\n `Refusing edit that spans OPC part boundary (start=${start_idx}, parts=${Array.from(crossed_parts).sort().join(\",\")})`,\n );\n return false;\n }\n }\n\n // DELETION / MODIFICATION\n const target_runs = active_mapper.find_target_runs_by_index(\n start_idx,\n length,\n rebuild_map,\n );\n const virtual_spans = active_mapper.get_virtual_spans_in_range(\n start_idx,\n length,\n );\n\n if (target_runs.length === 0 && virtual_spans.length === 0) return false;\n\n const affected_ps = new Set<Element>();\n for (const run of target_runs) {\n let p: Element | null = run._element.parentNode as Element;\n while (p && p.tagName !== \"w:p\") p = p.parentNode as Element;\n if (p) affected_ps.add(p);\n }\n\n let first_del: Element | null = null;\n let last_del: Element | null = null;\n for (const run of target_runs) {\n const del_tag = this._create_track_change_tag(\"w:del\", \"\", del_id);\n const new_run = run._element.cloneNode(true) as Element;\n\n const tNodes = Array.from(new_run.getElementsByTagName(\"w:t\"));\n tNodes.forEach((t) => {\n const delText = new_run.ownerDocument!.createElement(\"w:delText\");\n delText.textContent = t.textContent;\n if (t.hasAttribute(\"xml:space\"))\n delText.setAttribute(\"xml:space\", \"preserve\");\n new_run.replaceChild(delText, t);\n });\n\n del_tag.appendChild(new_run);\n run._element.parentNode?.replaceChild(del_tag, run._element);\n if (first_del === null) first_del = del_tag;\n last_del = del_tag;\n }\n\n let ins_elem: Element | null = null;\n let mod_last_p: Element | null = null;\n let mod_last_ins: Element | null = null;\n\n if (op === \"MODIFICATION\" && edit.new_text && last_del) {\n // Resolve a paragraph anchor: the <w:p> hosting last_del.\n let mod_anchor_para_el: Element | null = last_del;\n while (mod_anchor_para_el && mod_anchor_para_el.tagName !== \"w:p\") {\n mod_anchor_para_el = mod_anchor_para_el.parentNode as Element | null;\n }\n const mod_anchor_para: Paragraph | null = mod_anchor_para_el\n ? new Paragraph(mod_anchor_para_el, null)\n : null;\n\n // The \"anchor run\" for style inheritance is the run we just deleted; reuse\n // the deleted run's rPr by sourcing the original target run if available.\n const style_source_run: Run | null =\n target_runs.length > 0 ? target_runs[target_runs.length - 1] : null;\n\n const result = this._track_insert_multiline(\n edit.new_text,\n style_source_run,\n mod_anchor_para,\n ins_id!,\n // The insertion physically follows the deletion block; the style\n // run was detached when the deletion cloned it into <w:del>.\n last_del,\n suppress_emphasis,\n );\n\n if (result.first_node) {\n const is_inline_first = result.first_node.tagName === \"w:ins\";\n if (is_inline_first) {\n const del_parent = last_del!.parentNode as Element | null;\n if (del_parent && del_parent.tagName === \"w:ins\") {\n // Revising another author's pending insertion: keep the <w:del>\n // nested in their <w:ins> and splice our new <w:ins> in right after\n // it by splitting their <w:ins>, so we never nest <w:ins> in\n // <w:ins>.\n this._insert_and_split_ins(\n del_parent,\n last_del!,\n result.first_node,\n );\n } else {\n // Inline: place the first <w:ins> immediately after last_del.\n insertAfter(result.first_node, last_del!);\n }\n ins_elem = result.first_node;\n } else {\n // Block-mode first paragraph was already inserted after the anchor\n // paragraph by the helper. We still need ins_elem for comment fallback.\n ins_elem = result.last_ins;\n }\n mod_last_p = result.last_p;\n mod_last_ins = result.last_ins;\n }\n }\n\n // PHASE 2: OOXML Paragraph Merge Protocol\n if (op === \"DELETION\" || op === \"MODIFICATION\") {\n if (\n op === \"MODIFICATION\" &&\n target_runs.length === 0 &&\n virtual_spans.length > 0 &&\n edit.new_text\n ) {\n const first_span = virtual_spans[0];\n if (first_span.paragraph) {\n const p1_el = first_span.paragraph._element;\n const last_runs = findAllDescendants(p1_el, \"w:r\");\n const anchor =\n last_runs.length > 0\n ? new Run(last_runs[last_runs.length - 1], first_span.paragraph)\n : null;\n\n const result = this._track_insert_multiline(\n edit.new_text,\n anchor,\n first_span.paragraph,\n ins_id!,\n null,\n suppress_emphasis,\n );\n if (result.first_node) {\n p1_el.appendChild(result.first_node);\n }\n }\n }\n\n for (const span of [...virtual_spans].reverse()) {\n if (span.paragraph) {\n const p1_element = span.paragraph._element;\n let p2_element = getNextElement(p1_element);\n while (p2_element && p2_element.tagName !== \"w:p\") {\n p2_element = getNextElement(p2_element);\n }\n\n if (p2_element && p2_element.tagName === \"w:p\") {\n let pPr = findChild(p1_element, \"w:pPr\");\n if (!pPr) {\n pPr = p1_element.ownerDocument!.createElement(\"w:pPr\") as Element;\n p1_element.insertBefore(\n pPr,\n p1_element.firstChild as Node | null,\n );\n }\n let rPr = findChild(pPr!, \"w:rPr\");\n if (!rPr) {\n rPr = p1_element.ownerDocument!.createElement(\"w:rPr\") as Element;\n pPr!.appendChild(rPr);\n }\n const del_mark = this._create_track_change_tag(\"w:del\");\n rPr!.appendChild(del_mark);\n\n const children = Array.from(p2_element.childNodes);\n for (const child of children) {\n if (\n child.nodeType === 1 &&\n (child as Element).tagName === \"w:pPr\"\n ) {\n continue;\n }\n p1_element.appendChild(child);\n }\n\n if (p2_element.parentNode) {\n p2_element.parentNode.removeChild(p2_element);\n }\n }\n }\n }\n }\n\n // Attach comment around the modification or deletion if requested.\n if (edit.comment && first_del !== null) {\n // Resolve the comment END anchor. For multi-paragraph modifications,\n // the end anchor lives in the LAST inserted paragraph (mod_last_p);\n // otherwise it's the inline ins/del in the source paragraph.\n let end_anchor_el: Element;\n let end_p: Element | null;\n\n if (mod_last_p && mod_last_ins) {\n end_anchor_el = mod_last_ins;\n end_p = mod_last_p;\n } else {\n const final_anchor: Element = ins_elem !== null ? ins_elem : last_del!;\n end_anchor_el = final_anchor;\n end_p = final_anchor;\n while (end_p && end_p.tagName !== \"w:p\")\n end_p = end_p.parentNode as Element | null;\n }\n\n let start_p: Element | null = first_del;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element | null;\n if (!start_p || !end_p) return true;\n\n const ascend_to_paragraph_child = (el: Element, p: Element): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n const start_anchor = ascend_to_paragraph_child(first_del, start_p);\n const end_anchor = ascend_to_paragraph_child(end_anchor_el, end_p);\n\n if (start_p === end_p) {\n this._attach_comment(start_p, start_anchor, end_anchor, edit.comment);\n } else {\n this._attach_comment_spanning(\n start_p,\n start_anchor,\n end_p,\n end_anchor,\n edit.comment,\n );\n }\n }\n\n // PHASE 2: Check for orphaned paragraphs with zero visible content remaining\n for (const p_elem of affected_ps) {\n let has_visible = false;\n for (const tag of [\"w:t\", \"w:tab\", \"w:br\"]) {\n const nodes = findAllDescendants(p_elem, tag);\n for (const node of nodes) {\n let is_deleted = false;\n let curr = node.parentNode as Element | null;\n while (curr && curr !== p_elem.parentNode) {\n if (curr.tagName === \"w:del\") {\n is_deleted = true;\n break;\n }\n curr = curr.parentNode as Element | null;\n }\n if (!is_deleted) {\n if (tag === \"w:t\" && !node.textContent) continue;\n has_visible = true;\n break;\n }\n }\n if (has_visible) break;\n }\n\n if (!has_visible) {\n let pPr = findChild(p_elem, \"w:pPr\");\n if (!pPr) {\n pPr = p_elem.ownerDocument!.createElement(\"w:pPr\") as Element;\n p_elem.insertBefore(pPr, p_elem.firstChild as Node | null);\n }\n let rPr = findChild(pPr!, \"w:rPr\");\n if (!rPr) {\n rPr = p_elem.ownerDocument!.createElement(\"w:rPr\") as Element;\n pPr!.appendChild(rPr);\n }\n if (!findChild(rPr!, \"w:del\")) {\n const del_mark = this._create_track_change_tag(\"w:del\");\n rPr!.appendChild(del_mark);\n }\n }\n }\n\n return true;\n }\n}\n","import { DocumentObject, Part } from '../docx/bridge.js';\nimport { findAllDescendants, findChild, findChildren } from '../docx/dom.js';\nimport { extract_comments_data, CommentsManager } from '../comments.js';\nimport { RedlineEngine } from '../engine.js';\n\nexport function findDescendantsByLocalName(element: Element, localName: string): Element[] {\n const result: Element[] = [];\n const all = element.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n const tag = all[i].tagName;\n if (tag === localName || tag.endsWith(':' + localName)) {\n result.push(all[i]);\n }\n }\n return result;\n}\n\nexport function coalesce_runs(doc: DocumentObject): string[] {\n let count = 0;\n\n function areRunsIdentical(rPr1: Element | null, rPr2: Element | null): boolean {\n const xml1 = rPr1 ? rPr1.toString() : '';\n const xml2 = rPr2 ? rPr2.toString() : '';\n return xml1 === xml2;\n }\n\n function hasSpecialContent(run: Element): boolean {\n const safeTags = ['w:t', 'w:tab', 'w:br', 'w:cr', 'w:delText', 'w:rPr'];\n for (let i = 0; i < run.childNodes.length; i++) {\n const child = run.childNodes[i];\n if (child.nodeType === 1) {\n const tag = (child as Element).tagName;\n if (!safeTags.includes(tag)) return true;\n }\n }\n return false;\n }\n\n function coalesceContainer(container: Element) {\n const children = Array.from(container.childNodes).filter(n => n.nodeType === 1) as Element[];\n let i = 0;\n while (i < children.length - 1) {\n const curr = children[i];\n const nxt = children[i + 1];\n\n if (curr.tagName === 'w:r' && nxt.tagName === 'w:r') {\n if (!hasSpecialContent(curr) && !hasSpecialContent(nxt)) {\n const rPr1 = findChild(curr, 'w:rPr');\n const rPr2 = findChild(nxt, 'w:rPr');\n if (areRunsIdentical(rPr1, rPr2)) {\n let last_t: Element | null = null;\n for (let c = 0; c < curr.childNodes.length; c++) {\n const child = curr.childNodes[c];\n if (child.nodeType === 1 && ((child as Element).tagName === 'w:t' || (child as Element).tagName === 'w:delText')) {\n last_t = child as Element;\n }\n }\n\n const nxtChildren = Array.from(nxt.childNodes).filter(n => n.nodeType === 1) as Element[];\n for (const child of nxtChildren) {\n if (child.tagName === 'w:rPr') continue;\n if ((child.tagName === 'w:t' || child.tagName === 'w:delText') && last_t && last_t.tagName === child.tagName) {\n const t1 = last_t.textContent || '';\n const t2 = child.textContent || '';\n const combined = t1 + t2;\n last_t.textContent = combined;\n if (combined.trim() !== combined) {\n last_t.setAttribute('xml:space', 'preserve');\n }\n } else {\n curr.appendChild(child);\n if (child.tagName === 'w:t' || child.tagName === 'w:delText') {\n last_t = child;\n }\n }\n }\n container.removeChild(nxt);\n children.splice(i + 1, 1);\n count++;\n continue; \n }\n }\n }\n\n if (['w:ins', 'w:del', 'w:hyperlink', 'w:sdt', 'w:smartTag', 'w:fldSimple', 'w:sdtContent'].includes(curr.tagName)) {\n coalesceContainer(curr);\n }\n i++;\n }\n \n if (children.length > 0) {\n const last = children[children.length - 1];\n if (['w:ins', 'w:del', 'w:hyperlink', 'w:sdt', 'w:smartTag', 'w:fldSimple', 'w:sdtContent'].includes(last.tagName)) {\n coalesceContainer(last);\n }\n }\n }\n\n const paragraphs = findAllDescendants(doc.element, 'w:p');\n for (const p of paragraphs) coalesceContainer(p);\n\n return count ? [`Adjacent identical runs coalesced: ${count}`] : [];\n}\n\nexport function strip_rsid(doc: DocumentObject): string[] {\n let count = 0;\n const rsidAttrs = ['w:rsidR', 'w:rsidRPr', 'w:rsidRDefault', 'w:rsidP', 'w:rsidDel', 'w:rsidSect', 'w:rsidTr'];\n \n const all = doc.element.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n for (const attr of rsidAttrs) {\n if (all[i].hasAttribute(attr)) {\n all[i].removeAttribute(attr);\n count++;\n }\n }\n }\n \n const rsidsElements = findAllDescendants(doc.element, 'w:rsids');\n for (const el of rsidsElements) {\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n count++;\n }\n }\n \n return count ? [`rsid attributes: ${count} removed`] : [];\n}\n\nexport function strip_para_ids(doc: DocumentObject): string[] {\n let count = 0;\n const attrs = ['w14:paraId', 'w14:textId'];\n const all = doc.element.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n for (const attr of attrs) {\n if (all[i].hasAttribute(attr)) {\n all[i].removeAttribute(attr);\n count++;\n }\n }\n }\n return count ? [`Paragraph/text IDs: ${count} removed`] : [];\n}\n\nexport function strip_proof_errors(doc: DocumentObject): string[] {\n const elements = findAllDescendants(doc.element, 'w:proofErr');\n elements.forEach(el => el.parentNode?.removeChild(el));\n return elements.length ? [`Spell check markers: ${elements.length} removed`] : [];\n}\n\nexport function strip_empty_properties(doc: DocumentObject): string[] {\n let count = 0;\n for (const tag of ['w:rPr', 'w:pPr']) {\n const elements = findAllDescendants(doc.element, tag);\n for (const el of elements) {\n if (el.childNodes.length === 0 || (el.childNodes.length === 1 && el.childNodes[0].nodeType === 3 && !el.childNodes[0].textContent?.trim())) {\n el.parentNode?.removeChild(el);\n count++;\n }\n }\n }\n return count ? [`Empty property elements: ${count} removed`] : [];\n}\n\nexport function strip_hidden_text(doc: DocumentObject): string[] {\n let count = 0;\n const elements = findAllDescendants(doc.element, 'w:rPr');\n for (const rPr of elements) {\n if (findChild(rPr, 'w:vanish') || findChild(rPr, 'w:webHidden')) {\n const run = rPr.parentNode as Element;\n if (run && run.tagName === 'w:r' && run.parentNode) {\n run.parentNode.removeChild(run);\n count++;\n }\n }\n }\n return count ? [`Hidden text runs: ${count} removed`] : [];\n}\n\nexport function count_tracked_changes(doc: DocumentObject): [number, number, number] {\n const ins = findAllDescendants(doc.element, 'w:ins').length;\n const del = findAllDescendants(doc.element, 'w:del').length;\n const fmt = findAllDescendants(doc.element, 'w:rPrChange').length +\n findAllDescendants(doc.element, 'w:pPrChange').length +\n findAllDescendants(doc.element, 'w:sectPrChange').length;\n return [ins, del, fmt];\n}\n\nexport function get_track_change_authors(doc: DocumentObject): Set<string> {\n const authors = new Set<string>();\n for (const tag of ['w:ins', 'w:del', 'w:rPrChange', 'w:pPrChange', 'w:sectPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n const author = el.getAttribute('w:author');\n if (author) authors.add(author);\n }\n }\n return authors;\n}\n\nfunction _getElementText(el: Element): string {\n const texts: string[] = [];\n const ts = findAllDescendants(el, 'w:t');\n for (const t of ts) if (t.textContent) texts.push(t.textContent);\n const dts = findAllDescendants(el, 'w:delText');\n for (const dt of dts) if (dt.textContent) texts.push(dt.textContent);\n return texts.join('');\n}\n\nexport function _truncate(text: string, maxLen: number = 60): string {\n const clean = text.replace(/\\n/g, ' ').trim();\n if (clean.length <= maxLen) return clean;\n return clean.substring(0, maxLen - 3) + \"...\";\n}\n\nexport function accept_all_tracked_changes(doc: DocumentObject): string[] {\n const lines: string[] = [];\n const insEls = findAllDescendants(doc.element, 'w:ins');\n const delEls = findAllDescendants(doc.element, 'w:del');\n \n for (const ins of insEls) {\n const text = _getElementText(ins).trim();\n if (text) lines.push(` Accepted insertion: \"${_truncate(text, 60)}\"`);\n }\n for (const del of delEls) {\n const text = _getElementText(del).trim();\n if (text) lines.push(` Accepted deletion of: \"${_truncate(text, 60)}\"`);\n }\n\n const engine = new RedlineEngine(doc);\n engine.accept_all_revisions();\n\n for (const tag of ['w:rPrChange', 'w:pPrChange', 'w:sectPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n el.parentNode?.removeChild(el);\n }\n }\n\n const total = insEls.length + delEls.length;\n if (total) {\n return [`Tracked changes auto-accepted: ${total}`].concat(lines);\n }\n return [];\n}\n\nexport function get_comments_summary(doc: DocumentObject): any {\n const data = extract_comments_data(doc.pkg);\n const comments = [];\n let openCount = 0;\n let resolvedCount = 0;\n\n for (const [cId, info] of Object.entries(data)) {\n if (info.resolved) resolvedCount++;\n else openCount++;\n comments.push({ id: cId, ...info });\n }\n\n return { total: comments.length, open: openCount, resolved: resolvedCount, comments };\n}\n\nexport function remove_all_comments(doc: DocumentObject): string[] {\n const data = extract_comments_data(doc.pkg);\n const keys = Object.keys(data);\n if (keys.length === 0) return [];\n\n const lines: string[] = [];\n const cm = new CommentsManager(doc);\n\n for (const [cId, info] of Object.entries(data)) {\n const status = info.resolved ? \"[Resolved]\" : \"[Open]\";\n lines.push(` ${status} \"${_truncate(info.text || '', 60)}\" (${info.author || 'Unknown'})`);\n cm.deleteComment(cId);\n }\n\n for (const tag of ['w:commentRangeStart', 'w:commentRangeEnd']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n el.parentNode?.removeChild(el);\n }\n }\n\n const refs = findAllDescendants(doc.element, 'w:commentReference');\n for (const ref of refs) {\n const parent = ref.parentNode as Element | null;\n if (parent) {\n if (parent.tagName === 'w:r' || parent.tagName.endsWith(':r')) {\n const nonRprChildren = Array.from(parent.childNodes).filter(\n (c) => c.nodeType === 1 && (c as Element).tagName !== 'w:rPr' && (c as Element).tagName !== 'rPr'\n );\n if (nonRprChildren.length <= 1) {\n parent.parentNode?.removeChild(parent);\n } else {\n parent.removeChild(ref);\n }\n } else {\n parent.removeChild(ref);\n }\n }\n }\n\n const resolvedCount = Object.values(data).filter(c => c.resolved).length;\n const openCount = Object.values(data).filter(c => !c.resolved).length;\n return [`Comments removed: ${keys.length} (${resolvedCount} resolved, ${openCount} open)`].concat(lines);\n}\n\nexport function eject_comment_parts(doc: DocumentObject) {\n const pkg = doc.pkg;\n \n // 1. Find all comment-related partnames\n const comment_partnames = new Set<string>();\n for (const part of pkg.parts) {\n if (part.partname.toLowerCase().includes(\"comments\")) {\n comment_partnames.add(part.partname);\n const withSlash = part.partname.startsWith(\"/\") ? part.partname : \"/\" + part.partname;\n const withoutSlash = part.partname.startsWith(\"/\") ? part.partname.substring(1) : part.partname;\n comment_partnames.add(withSlash);\n comment_partnames.add(withoutSlash);\n }\n }\n\n if (comment_partnames.size === 0) return;\n\n // 2. Sever relationships referencing these parts from all parts in the package\n for (const part of pkg.parts) {\n if (part.partname.endsWith(\".rels\")) {\n const rels = findAllDescendants(part._element, \"Relationship\");\n const toRemove: Element[] = [];\n for (const rel of rels) {\n const target = rel.getAttribute(\"Target\") || \"\";\n if (target.toLowerCase().includes(\"comments\")) {\n toRemove.push(rel);\n \n const sourcePath = part.partname.replace(\"/_rels/\", \"/\").replace(\".rels\", \"\");\n const sourcePart = pkg.getPartByPath(sourcePath);\n if (sourcePart) {\n const relId = rel.getAttribute(\"Id\");\n if (relId) sourcePart.rels.delete(relId);\n }\n }\n }\n for (const relEl of toRemove) {\n relEl.parentNode?.removeChild(relEl);\n }\n }\n }\n\n // 3. Remove overrides from [Content_Types].xml\n const ctPart = pkg.getPartByPath(\"[Content_Types].xml\");\n if (ctPart) {\n const overrides = findAllDescendants(ctPart._element, \"Override\");\n const toRemove: Element[] = [];\n for (const override of overrides) {\n const partName = override.getAttribute(\"PartName\") || \"\";\n if (comment_partnames.has(partName) || partName.toLowerCase().includes(\"comments\")) {\n toRemove.push(override);\n }\n }\n for (const overrideEl of toRemove) {\n overrideEl.parentNode?.removeChild(overrideEl);\n }\n }\n\n // 4. Remove comment parts from pkg.parts\n pkg.parts = pkg.parts.filter(p => !p.partname.toLowerCase().includes(\"comments\"));\n\n // 5. Remove comment files from pkg.unzipped as well\n for (const key of Object.keys(pkg.unzipped)) {\n if (key.toLowerCase().includes(\"comments\")) {\n delete pkg.unzipped[key];\n }\n }\n}\n\nexport function replace_comment_authors(doc: DocumentObject, newAuthor: string): string[] {\n const cm = new CommentsManager(doc);\n if (!cm.commentsPart) return [];\n\n const original = new Set<string>();\n const comments = findAllDescendants(cm.commentsPart._element, 'w:comment');\n for (const c of comments) {\n const author = c.getAttribute('w:author');\n if (author) {\n original.add(author);\n c.setAttribute('w:author', newAuthor);\n }\n if (c.hasAttribute('w:initials')) {\n const initials = newAuthor.split(' ').filter(Boolean).map(p => p[0]).join('').toUpperCase();\n c.setAttribute('w:initials', initials);\n }\n }\n return original.size ? [`Comment authors replaced: ${Array.from(original).sort().join(', ')} → \"${newAuthor}\"`] : [];\n}\n\nexport function replace_change_authors(doc: DocumentObject, newAuthor: string): string[] {\n const original = new Set<string>();\n for (const tag of ['w:ins', 'w:del', 'w:rPrChange', 'w:pPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n const author = el.getAttribute('w:author');\n if (author) {\n original.add(author);\n el.setAttribute('w:author', newAuthor);\n }\n }\n }\n return original.size ? [`Track change authors replaced: ${Array.from(original).sort().join(', ')} → \"${newAuthor}\"`] : [];\n}\n\nexport function normalize_change_dates(doc: DocumentObject): string[] {\n let count = 0;\n const fixed = \"2025-01-01T00:00:00Z\";\n for (const tag of ['w:ins', 'w:del', 'w:rPrChange', 'w:pPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n if (el.hasAttribute('w:date')) {\n el.setAttribute('w:date', fixed);\n count++;\n }\n }\n }\n return count ? [`Track change timestamps: ${count} normalized`] : [];\n}\n\n/**\n * Normalize timestamps on RETAINED comments to the fixed sanitize date.\n * Keep-markup sanitize normalized core and tracked-change timestamps but\n * left the original comment timestamps in word/comments.xml (w:date) and\n * word/commentsExtensible.xml (w16cex:dateUtc) — visible through any\n * extraction and carrying exactly the when-did-they-work signal the other\n * normalizations remove (QA 2026-07-19 F-09).\n */\nexport function normalize_comment_dates(doc: DocumentObject): string[] {\n let count = 0;\n const fixed = \"2025-01-01T00:00:00Z\";\n for (const part of doc.pkg.parts) {\n if (!part.contentType.includes('comments')) continue;\n for (const el of findAllDescendants(part._element, 'w:comment')) {\n if (el.hasAttribute('w:date')) {\n el.setAttribute('w:date', fixed);\n count++;\n }\n }\n for (const el of findAllDescendants(part._element, 'w16cex:commentExtensible')) {\n if (el.hasAttribute('w16cex:dateUtc')) {\n el.setAttribute('w16cex:dateUtc', fixed);\n count++;\n }\n }\n }\n return count ? [`Comment timestamps: ${count} normalized`] : [];\n}\n\nexport function scrub_doc_properties(doc: DocumentObject): string[] {\n const lines: string[] = [];\n const corePart = doc.pkg.getPartByPath('docProps/core.xml');\n if (corePart) {\n const creators = findDescendantsByLocalName(corePart._element, 'creator');\n creators.forEach(c => { if (c.textContent) { lines.push(`Author: ${c.textContent}`); c.textContent = \"\"; }});\n\n const modifiers = findDescendantsByLocalName(corePart._element, 'lastModifiedBy');\n modifiers.forEach(c => { if (c.textContent) { lines.push(`Last modified by: ${c.textContent}`); c.textContent = \"\"; }});\n\n // Title is often intentional, but can leak. Report it, don't strip\n // (QA 2026-07-17 F4; mirrors Python).\n const titles = findDescendantsByLocalName(corePart._element, 'title');\n titles.forEach(c => { if (c.textContent) { lines.push(`Title kept (review manually): \"${c.textContent}\"`); }});\n\n // Classification-style properties are textbook leak vectors (\"Project\n // Falcon\", \"confidential,merger,...\"). Unlike title they carry no\n // legitimate outbound formatting value, so strip them and say so.\n // dc:identifier, dc:language and cp:version are scrubbed with them:\n // identifiers are DMS/matter-ID carriers.\n const leakFields: Array<[string, string]> = [\n ['category', 'Category'],\n ['keywords', 'Keywords'],\n ['subject', 'Subject'],\n ['contentStatus', 'Content status'],\n ['description', 'Description/comments'],\n ['identifier', 'Identifier'],\n ['language', 'Language'],\n ['version', 'Version'],\n ];\n for (const [local, label] of leakFields) {\n findDescendantsByLocalName(corePart._element, local).forEach(c => {\n if (c.textContent) {\n lines.push(`${label}: ${c.textContent}`);\n c.textContent = \"\";\n }\n });\n }\n\n const revisions = findDescendantsByLocalName(corePart._element, 'revision');\n revisions.forEach(c => { if (c.textContent && parseInt(c.textContent) > 1) { lines.push(`Revision count: ${c.textContent} → 1`); c.textContent = \"1\"; }});\n }\n\n const appPart = doc.pkg.getPartByPath('docProps/app.xml');\n if (appPart) {\n const docEl = appPart._element;\n const intFields = [\"TotalTime\", \"Words\", \"Characters\", \"Paragraphs\", \"Lines\", \"CharactersWithSpaces\"];\n for (const f of intFields) {\n findDescendantsByLocalName(docEl, f).forEach(el => {\n if (el.textContent && el.textContent !== \"0\") {\n if (f === \"TotalTime\") lines.push(`Total editing time: ${el.textContent} minutes`);\n el.textContent = \"0\";\n }\n });\n }\n const strFields = [\"Template\", \"Manager\", \"Company\"];\n for (const f of strFields) {\n findDescendantsByLocalName(docEl, f).forEach(el => {\n if (el.textContent) {\n lines.push(`${f}: ${el.textContent}`);\n el.textContent = \"\";\n }\n });\n }\n }\n\n return lines.length ? [\"Metadata scrubbed:\", ...lines.map(l => ` ${l}`)] : [];\n}\n\nexport function scrub_timestamps(doc: DocumentObject): string[] {\n let modified = false;\n const epoch = \"1970-01-01T00:00:00Z\";\n const corePart = doc.pkg.getPartByPath('docProps/core.xml');\n if (corePart) {\n for (const tag of ['created', 'modified', 'lastPrinted']) {\n findDescendantsByLocalName(corePart._element, tag).forEach(el => {\n if (el.textContent && el.textContent !== epoch) {\n el.textContent = epoch;\n modified = true;\n }\n });\n }\n }\n return modified ? [\"Timestamps normalized to epoch\"] : [];\n}\n\n/**\n * Fully ejects package members whose path matches `matcher`: the parsed part\n * list, the raw `pkg.unzipped` bytes (save() re-zips EVERY unzipped\n * member, so skipping this ships the original bytes in the output), the\n * [Content_Types].xml overrides, and every .rels Relationship whose\n * target matches `relTargetMatcher`.\n */\nfunction ejectPackageMembers(\n doc: DocumentObject,\n matcher: (path: string) => boolean,\n relTargetMatcher: (target: string) => boolean,\n) {\n const pkg = doc.pkg;\n const normalized = (p: string) => (p.startsWith('/') ? p.substring(1) : p);\n\n // 1. Sever relationships from every .rels part (and the in-memory rels maps)\n for (const part of pkg.parts) {\n if (!part.partname.endsWith('.rels')) continue;\n const toRemove: Element[] = [];\n for (const rel of findAllDescendants(part._element, 'Relationship')) {\n const target = rel.getAttribute('Target') || '';\n if (relTargetMatcher(target)) {\n toRemove.push(rel);\n const sourcePath = part.partname.replace('/_rels/', '/').replace('.rels', '');\n const sourcePart = pkg.getPartByPath(sourcePath);\n if (sourcePart) {\n const relId = rel.getAttribute('Id');\n if (relId) sourcePart.rels.delete(relId);\n }\n }\n }\n toRemove.forEach(r => r.parentNode?.removeChild(r));\n }\n\n // 2. Remove [Content_Types].xml overrides\n const ctPart = pkg.getPartByPath('[Content_Types].xml');\n if (ctPart) {\n const toRemove: Element[] = [];\n for (const override of findAllDescendants(ctPart._element, 'Override')) {\n const partName = override.getAttribute('PartName') || '';\n if (matcher(normalized(partName))) toRemove.push(override);\n }\n toRemove.forEach(o => o.parentNode?.removeChild(o));\n }\n\n // 3. Drop the parts from the serialization list AND the raw zip map\n pkg.parts = pkg.parts.filter(p => !matcher(normalized(p.partname)));\n for (const key of Object.keys(pkg.unzipped)) {\n if (matcher(normalized(key))) delete pkg.unzipped[key];\n }\n}\n\nexport function strip_custom_xml(doc: DocumentObject): string[] {\n const isCustomXml = (path: string) => path.startsWith('customXml/');\n const customParts = doc.pkg.parts.filter(p =>\n isCustomXml(p.partname.startsWith('/') ? p.partname.substring(1) : p.partname),\n );\n const leakedMembers = Object.keys(doc.pkg.unzipped).filter(isCustomXml);\n if (customParts.length === 0 && leakedMembers.length === 0) return [];\n\n ejectPackageMembers(doc, isCustomXml, target => target.includes('customXml'));\n\n for (const sdtPr of findAllDescendants(doc.element, 'w:sdtPr')) {\n findChildren(sdtPr, 'w:dataBinding').forEach(b => sdtPr.removeChild(b));\n }\n\n return [`Custom XML parts: ${Math.max(customParts.length, leakedMembers.length)} removed`];\n}\n\nconst CUSTOM_PROPS_PATH = 'docProps/custom.xml';\n\n/**\n * Remove the custom document properties part (docProps/custom.xml) and its\n * package relationship. Custom properties are a standard home for matter\n * numbers, client names, DMS identifiers and workflow secrets; a package\n * that keeps them can never be reported CLEAN.\n */\nexport function strip_custom_properties(doc: DocumentObject): string[] {\n const part = doc.pkg.getPartByPath(CUSTOM_PROPS_PATH);\n const leaked = Object.keys(doc.pkg.unzipped).includes(CUSTOM_PROPS_PATH);\n if (!part && !leaked) return [];\n\n // Enumerate what is being removed so the report discloses it.\n const lines: string[] = [];\n if (part) {\n for (const prop of findDescendantsByLocalName(part._element, 'property')) {\n const name = prop.getAttribute('name') || '(unnamed)';\n const value = (prop.textContent || '').trim();\n lines.push(` Custom property removed: ${name} = \"${_truncate(value, 60)}\"`);\n }\n }\n\n ejectPackageMembers(\n doc,\n path => path === CUSTOM_PROPS_PATH,\n target => target.includes('docProps/custom.xml'),\n );\n\n const count = Math.max(lines.length, 1);\n return [`Custom document properties: ${count} removed (docProps/custom.xml)`].concat(lines);\n}\n\nexport function strip_image_alt_text(doc: DocumentObject): string[] {\n let count = 0;\n for (const docPr of findDescendantsByLocalName(doc.element, 'docPr')) {\n const descr = docPr.getAttribute('descr');\n if (descr) {\n const isShort = descr.length < 10;\n const isFile = descr.includes('.') && descr.length < 60;\n if (isShort || isFile) {\n docPr.removeAttribute('descr');\n count++;\n }\n }\n }\n return count ? [`Image alt text: ${count} auto-generated descriptions removed`] : [];\n}\n\n/**\n * Detect watermark-like embedded text objects (VML shapes with a textpath,\n * Word's native watermark mechanism) in headers, footers and the body.\n * Non-destructive: returns warnings so the report never declares a document\n * fully clean while such an object silently remains (QA 2026-07-18 M3).\n */\nexport function detect_watermarks(doc: DocumentObject): string[] {\n const warnings: string[] = [];\n const seen = new Set<string>();\n\n for (const part of doc.pkg.parts) {\n const name = String(part.partname);\n let location: string;\n if (name.startsWith(\"/word/header\")) location = \"header\";\n else if (name.startsWith(\"/word/footer\")) location = \"footer\";\n else if (name === \"/word/document.xml\") location = \"body\";\n else continue;\n\n let textpaths: Element[];\n try {\n textpaths = findDescendantsByLocalName(part._element, \"textpath\");\n } catch {\n continue;\n }\n for (const tp of textpaths) {\n const text = (tp.getAttribute(\"string\") || \"\").trim();\n const key = `${location}\\x1f${text}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const label = text ? `\"${_truncate(text, 60)}\"` : \"(no text)\";\n warnings.push(\n `Watermark-like text object in ${location}: ${label} — NOT removed. ` +\n \"It remains in the document package and may render in other applications; \" +\n \"review and remove it in Word if it must not reach the counterparty.\",\n );\n }\n }\n return warnings;\n}\n\nexport function audit_hyperlinks(doc: DocumentObject): string[] {\n const internal = [\"sharepoint.com\", \"onedrive.com\", \".internal\", \"intranet\", \"localhost\", \"10.\", \"192.168.\", \"172.16.\"];\n const warnings: string[] = [];\n \n const docRels = doc.pkg.getOrCreateRelsPart(doc.part.partname);\n for (const rel of findAllDescendants(docRels._element, 'Relationship')) {\n if (rel.getAttribute('TargetMode') === 'External') {\n const url = rel.getAttribute('Target') || '';\n for (const pattern of internal) {\n if (url.toLowerCase().includes(pattern.toLowerCase())) {\n warnings.push(`Hyperlink targets internal URL: ${_truncate(url, 80)}`);\n break;\n }\n }\n }\n }\n return warnings;\n}","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Run } from \"./docx/primitives.js\";\nimport { iter_block_items, get_run_text } from \"./utils/docx.js\";\nimport { findAllDescendants } from \"./docx/dom.js\";\nimport { findDescendantsByLocalName } from \"./sanitize/transforms.js\";\n\nfunction boundedLevenshtein(a: string, b: string, maxDist: number = 2): number {\n if (a === b) return 0;\n if (Math.abs(a.length - b.length) > maxDist) return maxDist + 1;\n if (a.length === 0) return b.length <= maxDist ? b.length : maxDist + 1;\n if (b.length === 0) return a.length <= maxDist ? a.length : maxDist + 1;\n\n if (a.length > b.length) {\n const temp = a;\n a = b;\n b = temp;\n }\n\n let row = Array.from({ length: a.length + 1 }, (_, i) => i);\n\n for (let i = 1; i <= b.length; i++) {\n const newRow = [i];\n let minInRow = i;\n for (let j = 1; j <= a.length; j++) {\n const cost = a[j - 1] === b[i - 1] ? 0 : 1;\n const val = Math.min(row[j] + 1, newRow[j - 1] + 1, row[j - 1] + cost);\n newRow.push(val);\n if (val < minInRow) minInRow = val;\n }\n if (minInRow > maxDist) return maxDist + 1;\n row = newRow;\n }\n return row[a.length] <= maxDist ? row[a.length] : maxDist + 1;\n}\n\nfunction _get_paragraph_text(p: Paragraph): string {\n let text = \"\";\n const runs = findAllDescendants(p._element, \"w:r\");\n for (const r of runs) {\n text += get_run_text(new Run(r, p));\n }\n return text;\n}\n\nconst _TERM_BODY = \"[A-Z][A-Za-z0-9\\\\s\\\\-&'’]{1,60}\";\n// Definition typography, matched repeatedly within a paragraph (QA 2026-07-18\n// M7 — a paragraph defining Alpha, Beta AND Gamma must yield all three):\n// 1. paragraph-leading quoted term (optionally after a numbering token)\n// 2. sentence-leading quoted term (after . ; : ! ?)\n// 3. parenthesized inline definition — (the \"Term\")\n// The 'd' flag (ES2022 match indices) recovers each term's exact position for\n// position-keyed dedupe, mirroring Python's m.start(1).\nconst _LEADING_TERM_RE = new RegExp(\n `^(?:[\\\\d.\\\\-()a-zA-Z]+\\\\s*)?[\"“](${_TERM_BODY})[\"”]`,\n \"d\",\n);\n// Like the leading pattern, a sentence-start definition may carry a numbering\n// token ('… the product. 2.2 \"Beta\" means …').\nconst _SENTENCE_TERM_RE = new RegExp(\n `(?<=[.;:!?])\\\\s+(?:[\\\\d.\\\\-()a-zA-Z]+\\\\s+)?[\"“](${_TERM_BODY})[\"”]`,\n \"dg\",\n);\nconst _INLINE_TERM_RE = new RegExp(\n `\\\\([^)]*?[\"“](${_TERM_BODY})[\"”][^)]*?\\\\)`,\n \"dg\",\n);\n\n/**\n * All defined terms declared in one paragraph, in appearance order,\n * deduplicated. Language-agnostic: keyed on quoting typography, never on\n * English phrases like \"means\".\n */\nexport function extract_terms_from_paragraph(text: string): string[] {\n const found: [number, string][] = [];\n const leading = _LEADING_TERM_RE.exec(text) as RegExpExecArray & {\n indices?: Array<[number, number]>;\n };\n if (leading && leading.indices && leading.indices[1]) {\n found.push([leading.indices[1][0], leading[1].trim()]);\n }\n for (const m of text.matchAll(_SENTENCE_TERM_RE)) {\n const indices = (m as any).indices as Array<[number, number]> | undefined;\n if (indices && indices[1]) found.push([indices[1][0], m[1].trim()]);\n }\n for (const m of text.matchAll(_INLINE_TERM_RE)) {\n const indices = (m as any).indices as Array<[number, number]> | undefined;\n if (indices && indices[1]) found.push([indices[1][0], m[1].trim()]);\n }\n\n const terms: string[] = [];\n const seen_positions = new Set<number>();\n found.sort((a, b) => a[0] - b[0]);\n for (const [pos, term] of found) {\n if (seen_positions.has(pos)) continue;\n seen_positions.add(pos);\n terms.push(term);\n }\n return terms;\n}\n\nexport function extract_all_domain_metadata(\n doc: DocumentObject,\n base_text: string,\n): [\n Record<string, { count: number }>,\n string[],\n Record<string, { anchored_to: string; referenced_from: string[] }>,\n] {\n const definitions: Record<string, { count: number }> = {};\n const duplicates = new Set<string>();\n const raw_anchors: Record<\n string,\n { anchored_to: string; referenced_from: string[] }\n > = {};\n const raw_references: [string, string][] = [];\n\n for (const item of iter_block_items(doc)) {\n if (!(item instanceof Paragraph)) continue;\n\n const text = _get_paragraph_text(item).trim();\n if (!text) continue;\n\n // 1. Extract Definitions (every declaration in the paragraph — QA M7)\n for (const term of extract_terms_from_paragraph(text)) {\n if (definitions[term]) duplicates.add(term);\n else definitions[term] = { count: 0 };\n }\n\n const short_text = text.length > 60 ? text.substring(0, 60) + \"...\" : text;\n\n const nodes = findAllDescendants(item._element, \"*\");\n for (const node of nodes) {\n if (node.tagName === \"w:bookmarkStart\") {\n const b_name = node.getAttribute(\"w:name\");\n if (b_name && (!b_name.startsWith(\"_\") || b_name.startsWith(\"_Ref\"))) {\n if (!raw_anchors[b_name]) {\n raw_anchors[b_name] = {\n anchored_to: short_text,\n referenced_from: [],\n };\n }\n }\n }\n\n let target: string | null = null;\n if (node.tagName === \"w:fldSimple\") {\n const instr = node.getAttribute(\"w:instr\") || \"\";\n const parts = instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\") target = parts[1];\n } else if (node.tagName === \"w:instrText\") {\n const instr = node.textContent || \"\";\n const parts = instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\") target = parts[1];\n }\n\n if (target) raw_references.push([target, short_text]);\n }\n }\n\n for (const [target, ref_text] of raw_references) {\n if (raw_anchors[target]) {\n raw_anchors[target].referenced_from.push(ref_text);\n }\n }\n\n const diagnostics: string[] = [];\n\n const def_keys = Object.keys(definitions);\n if (def_keys.length > 0) {\n const sorted_terms = def_keys.sort((a, b) => b.length - a.length);\n const escapeRegExp = (str: string) =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const alt = sorted_terms.map(escapeRegExp).join(\"|\");\n const usage_pattern = new RegExp(`(?<![\"“])\\\\b(${alt})\\\\b(?![”\"])`, \"g\");\n\n for (const m of base_text.matchAll(usage_pattern)) {\n const matched_term = m[1];\n if (definitions[matched_term]) definitions[matched_term].count++;\n }\n\n // Drop unused terms from the SYMBOL TABLE only — the filter is noise\n // reduction for the Defined Terms listing, and must not gate the\n // Semantic Diagnostics: a term defined twice and never used is two\n // drafting errors, not zero (QA 2026-07-17 F6; mirrors Python). Surface\n // the orphan definition itself as a diagnostic instead.\n for (const term of def_keys) {\n if (definitions[term].count === 0) {\n delete definitions[term];\n if (!duplicates.has(term)) {\n diagnostics.push(\n `[Warning] Unused Definition: '${term}' is defined but never used.`,\n );\n }\n }\n }\n }\n\n for (const term of duplicates) {\n diagnostics.push(\n `[Error] Duplicate Definition: '${term}' is defined multiple times.`,\n );\n }\n\n const stop_words = new Set([\n \"The\",\n \"This\",\n \"That\",\n \"Such\",\n \"A\",\n \"An\",\n \"Any\",\n \"All\",\n \"Some\",\n \"No\",\n \"Every\",\n \"Each\",\n \"As\",\n \"In\",\n \"Of\",\n \"For\",\n \"To\",\n \"On\",\n \"By\",\n \"With\",\n ]);\n\n const all_cap_pattern = /\\b[A-Z][a-zA-Z]*(?:\\s+[A-Z][a-zA-Z]*)*\\b/g;\n const all_caps = new Set(base_text.match(all_cap_pattern) || []);\n\n const valid_terms = new Set(Object.keys(definitions));\n const terms_by_first_letter: Record<string, string[]> = {};\n for (const term of valid_terms) {\n const fl = term[0].toLowerCase();\n if (!terms_by_first_letter[fl]) terms_by_first_letter[fl] = [];\n terms_by_first_letter[fl].push(term);\n }\n\n const candidates_by_term: Record<string, string[]> = {};\n\n for (const raw_candidate of all_caps) {\n let candidate = raw_candidate.trim();\n const words = candidate.split(/\\s+/);\n while (words.length > 0) {\n const first = words[0];\n const title =\n first.charAt(0).toUpperCase() + first.slice(1).toLowerCase();\n if (stop_words.has(title)) words.shift();\n else break;\n }\n candidate = words.join(\" \");\n\n if (candidate.length < 4) continue;\n if (valid_terms.has(candidate)) continue;\n\n const first_letter = candidate[0].toLowerCase();\n let candidate_terms = terms_by_first_letter[first_letter] || [];\n\n if (candidate.length > 5) {\n for (const [k, v] of Object.entries(terms_by_first_letter)) {\n if (k !== first_letter) candidate_terms = candidate_terms.concat(v);\n }\n }\n\n for (const term of candidate_terms) {\n if (Math.abs(candidate.length - term.length) > 2) continue;\n if (candidate === term + \"s\" || candidate === term + \"es\") continue;\n if (term === candidate + \"s\" || term === candidate + \"es\") continue;\n\n const dist = boundedLevenshtein(candidate, term, 2);\n if (dist === 0 || dist > 2) continue;\n\n if (term.length <= 5) {\n if (dist > 1) continue;\n if (candidate[0].toLowerCase() !== term[0].toLowerCase()) continue;\n }\n\n if (!candidates_by_term[term]) candidates_by_term[term] = [];\n if (!candidates_by_term[term].includes(candidate))\n candidates_by_term[term].push(candidate);\n }\n }\n\n for (const [term, candidates] of Object.entries(candidates_by_term)) {\n candidates.sort();\n const c_str = candidates.map((c) => `'${c}'`).join(\", \");\n diagnostics.push(`[Info] Possible Typos for '${term}': Found ${c_str}`);\n }\n\n function diag_sort_key(msg: string) {\n if (msg.startsWith(\"[Error]\")) return 0;\n if (msg.startsWith(\"[Warning]\")) return 1;\n return 2;\n }\n\n diagnostics.sort((a, b) => {\n const keyA = diag_sort_key(a);\n const keyB = diag_sort_key(b);\n if (keyA !== keyB) return keyA - keyB;\n return a.localeCompare(b);\n });\n\n return [definitions, diagnostics, raw_anchors];\n}\n\n/**\n * Inspects word/settings.xml for privacy flags that cause Microsoft Word to\n * silently strip authorship metadata (w:author, w:date, w:initials) from\n * tracked changes and comments on the next save. These flags do not affect\n * what this engine writes — but they will scrub the engine's attribution the\n * next time Word opens and saves the file, breaking auditability and\n * multi-turn agent state tracking.\n *\n * Returns a list of human-readable warning lines (without leading bullets);\n * empty when no relevant flag is present or all flags are explicitly disabled.\n */\nexport function extract_document_settings_warnings(\n doc: DocumentObject,\n): string[] {\n const warnings: string[] = [];\n const settingsPart = doc.pkg.getPartByPath(\"word/settings.xml\");\n if (!settingsPart) return warnings;\n\n const isTruthy = (el: Element): boolean => {\n // OOXML boolean rule: element present with no w:val attribute defaults to true.\n // w:val of \"0\", \"false\", or \"off\" means disabled. Anything else (including\n // \"1\", \"true\", \"on\") is enabled.\n if (!el.hasAttribute(\"w:val\")) return true;\n const val = (el.getAttribute(\"w:val\") || \"\").toLowerCase();\n return val !== \"0\" && val !== \"false\" && val !== \"off\";\n };\n\n const removePersonal = findDescendantsByLocalName(\n settingsPart._element,\n \"removePersonalInformation\",\n );\n if (removePersonal.length > 0 && isTruthy(removePersonal[0])) {\n warnings.push(\n \"[Warning] Privacy flag `removePersonalInformation` is enabled in word/settings.xml. \" +\n \"Microsoft Word will strip the `w:author`, `w:initials`, and `w:date` attributes from every tracked change and comment the next time this document is opened and saved. \" +\n \"Edits made by this agent will lose attribution, breaking audit trails and any multi-turn workflow that relies on identifying prior edits.\",\n );\n }\n\n const removeDateTime = findDescendantsByLocalName(\n settingsPart._element,\n \"removeDateAndTime\",\n );\n if (removeDateTime.length > 0 && isTruthy(removeDateTime[0])) {\n warnings.push(\n \"[Warning] Privacy flag `removeDateAndTime` is enabled in word/settings.xml. \" +\n \"Microsoft Word will strip the `w:date` attribute from every tracked change and comment the next time this document is opened and saved. \" +\n \"Timestamps on this agent's edits will be lost on the next Word save.\",\n );\n }\n\n return warnings;\n}\n\nexport function build_structural_appendix(\n doc: DocumentObject,\n base_text: string,\n): string {\n const [defs, diagnostics, anchors] = extract_all_domain_metadata(\n doc,\n base_text,\n );\n const settings_warnings = extract_document_settings_warnings(doc);\n\n const lines: string[] = [\n \"\\n\\n---\",\n \"\",\n \"<!-- READONLY_BOUNDARY_START -->\",\n \"# Document Structure (Read-Only)\",\n \"The content below is metadata describing the document's reference structure. Do not include this section in any tracked changes or edits \\u2014 it is for your context only and will be discarded on write.\",\n ];\n\n let has_content = false;\n\n if (settings_warnings.length > 0) {\n has_content = true;\n lines.push(\"\\n## Document Settings\");\n for (const warning of settings_warnings) {\n lines.push(`- ${warning}`);\n }\n }\n\n if (Object.keys(defs).length > 0) {\n has_content = true;\n lines.push(\"\\n## Defined Terms\");\n for (const [term, data] of Object.entries(defs)) {\n lines.push(`- \"${term}\" \\u2014 used ${data.count} times.`);\n }\n }\n\n if (diagnostics.length > 0) {\n has_content = true;\n lines.push(\"\\n## Semantic Diagnostics\");\n for (const diag of diagnostics) {\n lines.push(`- ${diag}`);\n }\n }\n\n if (Object.keys(anchors).length > 0) {\n has_content = true;\n lines.push(\"\\n## Named Anchors\");\n for (const [b_name, data] of Object.entries(anchors)) {\n lines.push(`- ${b_name} \\u2192 Anchored to: \"${data.anchored_to}\"`);\n for (const ref of data.referenced_from) {\n lines.push(` - Referenced from: \"${ref}\"`);\n }\n }\n }\n\n if (has_content) {\n return lines.join(\"\\n\");\n }\n return \"\";\n}\n","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, Run, DocxEvent } from \"./docx/primitives.js\";\nimport {\n _get_style_cache,\n get_paragraph_prefix,\n is_heading_paragraph,\n is_native_heading,\n get_run_style_markers,\n get_run_text,\n apply_formatting_to_segments,\n iter_block_items,\n iter_document_parts_with_kind,\n iter_paragraph_content,\n} from \"./utils/docx.js\";\nimport { findChild } from \"./docx/dom.js\";\nimport { build_structural_appendix } from \"./domain.js\";\nimport { extract_comments_data } from \"./comments.js\";\n\n/** Text-space extent of one projected table row plus its cell texts. */\nexport interface RowGeometry {\n start: number;\n end: number;\n cells: string[];\n}\n\n/** Text-space extent of one projected top-level table. */\nexport interface TableGeometry {\n start: number;\n end: number;\n rows: RowGeometry[];\n}\n\n/**\n * Structural map of a projection: which offset ranges belong to which OPC\n * part, and where top-level table rows live. Produced in the SAME pass as\n * the text, so offsets always agree with it. Consumed by the diff pipeline\n * to keep generated edits from crossing part boundaries (QA 2026-07-18 C1)\n * and to emit structured row operations for table changes (QA C2).\n */\nexport interface ExtractStructure {\n part_ranges: [number, number, string][]; // [start, end, kind]\n tables: TableGeometry[];\n}\n\nexport async function extractTextFromBuffer(\n buffer: Buffer,\n cleanView = false,\n includeAppendix = true,\n): Promise<string> {\n const doc = await DocumentObject.load(buffer);\n return _extractTextFromDoc(doc, cleanView, includeAppendix) as string;\n}\n\nexport function _extractTextFromDoc(\n doc: DocumentObject,\n cleanView = false,\n includeAppendix = true,\n return_paragraph_offsets = false,\n return_structure = false,\n):\n | string\n | { text: string; paragraph_offsets: Map<any, [number, number]> }\n | { text: string; structure: ExtractStructure } {\n const comments_map = extract_comments_data(doc.pkg);\n\n const full_text: string[] = [];\n const paragraph_offsets = new Map<any, [number, number]>();\n const structure: ExtractStructure | null = return_structure\n ? { part_ranges: [], tables: [] }\n : null;\n let cursor = 0;\n\n for (const [part, part_kind] of iter_document_parts_with_kind(doc)) {\n const part_cursor = full_text.length > 0 ? cursor + 2 : cursor;\n const part_text = _extract_blocks(\n part,\n comments_map,\n cleanView,\n part_cursor,\n return_paragraph_offsets ? paragraph_offsets : undefined,\n structure ? structure.tables : undefined,\n );\n if (part_text) {\n if (full_text.length > 0) cursor += 2;\n full_text.push(part_text);\n if (structure) {\n structure.part_ranges.push([cursor, cursor + part_text.length, part_kind]);\n }\n cursor += part_text.length;\n }\n }\n\n let base_text = full_text.join(\"\\n\\n\");\n\n if (includeAppendix) {\n const appendix = build_structural_appendix(doc, base_text);\n if (appendix) base_text += appendix;\n }\n\n if (return_paragraph_offsets) {\n return { text: base_text, paragraph_offsets };\n }\n if (structure) {\n return { text: base_text, structure };\n }\n return base_text;\n}\n\n/**\n * table_acc: optional list collecting TableGeometry for TOP-LEVEL tables.\n * Deliberately not forwarded into cells — nested tables stay invisible to\n * the structured row-op diff, whose row pairing assumes one flat grid.\n */\nfunction _extract_blocks(\n container: any,\n comments_map: any,\n cleanView: boolean,\n cursor: number,\n paragraph_offsets?: Map<any, [number, number]>,\n table_acc?: TableGeometry[],\n): string {\n const part = container.part || container;\n const [style_cache, default_pstyle] = _get_style_cache(part);\n\n const blocks: string[] = [];\n let local_cursor = cursor;\n let is_first_block = true;\n let is_first_para = true;\n\n if (container.constructor && container.constructor.name === \"NotesPart\") {\n const header =\n container.note_type === \"fn\" ? \"## Footnotes\" : \"## Endnotes\";\n const sep = `---\\n${header}`;\n blocks.push(sep);\n local_cursor += sep.length;\n is_first_block = false;\n }\n\n for (const item of iter_block_items(container)) {\n if (!is_first_block) local_cursor += 2;\n const block_start = local_cursor;\n\n if (item.constructor.name === \"FootnoteItem\") {\n const fn_text = _extract_blocks(\n item,\n comments_map,\n cleanView,\n block_start,\n paragraph_offsets,\n );\n if (fn_text) {\n blocks.push(fn_text);\n local_cursor = block_start + fn_text.length;\n is_first_block = false;\n } else if (!is_first_block) {\n local_cursor -= 2;\n }\n } else if (item instanceof Paragraph) {\n let prefix = get_paragraph_prefix(item, style_cache, default_pstyle);\n if (is_first_para && container.constructor.name === \"FootnoteItem\") {\n prefix = `[^${container.note_type}-${container.id}]: ` + prefix;\n }\n const p_text = build_paragraph_text(\n item,\n comments_map,\n cleanView,\n style_cache,\n default_pstyle,\n );\n const full_block = prefix + p_text;\n blocks.push(full_block);\n if (paragraph_offsets) {\n paragraph_offsets.set(item._element, [block_start, full_block.length]);\n }\n local_cursor = block_start + full_block.length;\n is_first_para = false;\n is_first_block = false;\n } else if (item instanceof Table) {\n const geometry: TableGeometry | null = table_acc\n ? { start: block_start, end: block_start, rows: [] }\n : null;\n const table_text = extract_table(\n item,\n comments_map,\n cleanView,\n block_start,\n paragraph_offsets,\n geometry,\n );\n if (table_text) {\n blocks.push(table_text);\n local_cursor = block_start + table_text.length;\n is_first_block = false;\n if (geometry && table_acc) {\n geometry.end = block_start + table_text.length;\n table_acc.push(geometry);\n }\n } else if (!is_first_block) {\n local_cursor -= 2;\n }\n is_first_para = false;\n }\n }\n\n return blocks.join(\"\\n\\n\");\n}\n\nexport function extract_table(\n table: Table,\n comments_map: any,\n cleanView: boolean,\n cursor: number,\n paragraph_offsets?: Map<any, [number, number]>,\n geometry?: TableGeometry | null,\n): string {\n const rows_text: string[] = [];\n let rows_processed = 0;\n let local_cursor = cursor;\n\n for (const row of table.rows) {\n const cell_texts: string[] = [];\n const seen_cells = new Set();\n\n const trPr = findChild(row._element, \"w:trPr\");\n const ins = trPr ? findChild(trPr, \"w:ins\") : null;\n const del_node = trPr ? findChild(trPr, \"w:del\") : null;\n\n if (cleanView && del_node) continue;\n\n const row_start = local_cursor + (rows_processed > 0 ? 1 : 0);\n const wrapper_prefix_len =\n !cleanView && ins ? 4 : !cleanView && del_node ? 4 : 0;\n\n let cell_cursor = row_start + wrapper_prefix_len;\n let first_cell = true;\n\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n if (!first_cell) cell_cursor += 3;\n\n let cell_content = _extract_blocks(\n cell,\n comments_map,\n cleanView,\n cell_cursor,\n paragraph_offsets,\n );\n // Emit a stable, document-native anchor for this cell so empty/short\n // value cells are addressable by the engine. Reuses the {#...} bookmark\n // projection (already protected by validate_edit_strings and resolvable\n // via the mapper). We key on the cell's first paragraph w14:paraId, which\n // Word assigns and keeps stable across reads.\n if (!cleanView) {\n const firstP = cell._element.getElementsByTagName(\"w:p\")[0] as\n | Element\n | undefined;\n const paraId = firstP ? firstP.getAttribute(\"w14:paraId\") : null;\n if (paraId) {\n const anchor = `{#cell:${paraId}}`;\n cell_content = cell_content + anchor;\n }\n }\n cell_texts.push(cell_content);\n cell_cursor += cell_content.length;\n first_cell = false;\n }\n\n let row_str = cell_texts.join(\" | \");\n\n if (!cleanView) {\n if (ins) row_str = `{++ ${row_str} |Chg:${ins.getAttribute(\"w:id\")}++}`;\n else if (del_node)\n row_str = `{-- ${row_str} |Chg:${del_node.getAttribute(\"w:id\")}--}`;\n }\n\n rows_text.push(row_str);\n local_cursor = row_start + row_str.length;\n if (geometry) {\n geometry.rows.push({\n start: row_start,\n end: local_cursor,\n cells: [...cell_texts],\n });\n }\n rows_processed++;\n }\n\n return rows_text.join(\"\\n\");\n}\n\nexport function build_paragraph_text(\n paragraph: Paragraph,\n comments_map: any,\n cleanView: boolean,\n style_cache?: any,\n default_pstyle?: string | null,\n): string {\n const parts: string[] = [];\n const active_ins: Record<string, DocxEvent> = {};\n const active_del: Record<string, DocxEvent> = {};\n const active_comments: Set<string> = new Set();\n const active_fmt: Record<string, DocxEvent> = {};\n const deferred_meta_states: any[] = [];\n\n let pending_text = \"\";\n let current_wrappers: [string, string] = [\"\", \"\"];\n let current_style: [string, string] = [\"\", \"\"];\n\n const items = Array.from(iter_paragraph_content(paragraph));\n const is_heading = is_heading_paragraph(\n paragraph,\n style_cache,\n default_pstyle,\n );\n const native_heading = is_native_heading(\n paragraph,\n style_cache,\n default_pstyle,\n );\n let leading_strip_active = is_heading;\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n\n if (item instanceof Run) {\n const [prefix, suffix] = get_run_style_markers(item, native_heading);\n const text = get_run_text(item);\n\n if (cleanView && Object.keys(active_del).length > 0) continue;\n\n if (leading_strip_active) {\n if (!text || !text.trim()) continue;\n leading_strip_active = false;\n }\n\n const seg = apply_formatting_to_segments(text, prefix, suffix);\n if (seg) {\n const new_wrappers = cleanView\n ? ([\"\", \"\"] as [string, string])\n : _get_wrappers(active_ins, active_del, active_comments, active_fmt);\n const new_style: [string, string] = [prefix, suffix];\n\n if (\n pending_text &&\n new_wrappers[0] === current_wrappers[0] &&\n new_wrappers[1] === current_wrappers[1]\n ) {\n // Hoisted leading whitespace may sit before the incoming segment's\n // opening marker (\"**A**\" + \" **B**\" -> \"**A B**\"), mirroring the\n // mapper's part-level elision exactly (QA 2026-07-19 F-03).\n const escaped_prefix = new_style[0].replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const lead_match =\n new_style[0] !== \"\" || new_style[1] !== \"\"\n ? seg.match(new RegExp(\"^(\\\\s*)\" + escaped_prefix))\n : null;\n if (\n new_style[0] === current_style[0] &&\n new_style[1] === current_style[1] &&\n current_style[0] !== \"\" &&\n pending_text.endsWith(current_style[1]) &&\n lead_match !== null\n ) {\n pending_text =\n pending_text.slice(0, -current_style[1].length) +\n lead_match[1] +\n seg.slice(lead_match[0].length);\n } else {\n pending_text += seg;\n }\n current_style = new_style;\n } else {\n if (pending_text)\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = seg;\n current_wrappers = new_wrappers;\n current_style = new_style;\n }\n\n if (!cleanView) {\n const has_meta =\n Object.keys(active_ins).length > 0 ||\n Object.keys(active_del).length > 0 ||\n active_comments.size > 0 ||\n Object.keys(active_fmt).length > 0;\n if (has_meta) {\n deferred_meta_states.push([\n { ...active_ins },\n { ...active_del },\n new Set(active_comments),\n { ...active_fmt },\n ]);\n }\n\n let should_defer = false;\n const has_any_meta =\n Object.keys(active_ins).length > 0 ||\n Object.keys(active_del).length > 0 ||\n Object.keys(active_fmt).length > 0 ||\n active_comments.size > 0;\n\n if (has_any_meta) {\n let j = i + 1;\n let next_has_meta = false;\n let temp_ins = Object.keys(active_ins).length;\n let temp_del = Object.keys(active_del).length;\n let temp_fmt = Object.keys(active_fmt).length;\n const temp_comments = new Set(active_comments);\n\n while (j < items.length) {\n const next_item = items[j];\n if (next_item instanceof Run) {\n if (!get_run_text(next_item)) {\n j++;\n continue;\n }\n if (\n temp_ins > 0 ||\n temp_del > 0 ||\n temp_fmt > 0 ||\n temp_comments.size > 0\n )\n next_has_meta = true;\n break;\n } else {\n const ev = next_item as DocxEvent;\n if (ev.type === \"ins_start\") temp_ins++;\n else if (ev.type === \"ins_end\")\n temp_ins = Math.max(0, temp_ins - 1);\n else if (ev.type === \"del_start\") temp_del++;\n else if (ev.type === \"del_end\")\n temp_del = Math.max(0, temp_del - 1);\n else if (ev.type === \"fmt_start\") temp_fmt++;\n else if (ev.type === \"fmt_end\")\n temp_fmt = Math.max(0, temp_fmt - 1);\n else if (ev.type === \"start\") temp_comments.add(ev.id);\n else if (ev.type === \"end\") temp_comments.delete(ev.id);\n }\n j++;\n }\n if (next_has_meta) should_defer = true;\n }\n\n if (!should_defer && deferred_meta_states.length > 0) {\n const meta_block = _build_merged_meta_block(\n deferred_meta_states,\n comments_map,\n );\n if (meta_block) {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`{>>${meta_block}<<}`);\n }\n deferred_meta_states.length = 0; // clear\n }\n }\n }\n } else {\n const ev = item as DocxEvent;\n leading_strip_active = false;\n\n if (\n ![\n \"ins_start\",\n \"ins_end\",\n \"del_start\",\n \"del_end\",\n \"fmt_start\",\n \"fmt_end\",\n ].includes(ev.type)\n ) {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n }\n\n if (ev.type === \"start\") active_comments.add(ev.id);\n else if (ev.type === \"end\") active_comments.delete(ev.id);\n else if (ev.type === \"ins_start\") active_ins[ev.id] = ev;\n else if (ev.type === \"ins_end\") delete active_ins[ev.id];\n else if (ev.type === \"del_start\") active_del[ev.id] = ev;\n else if (ev.type === \"del_end\") delete active_del[ev.id];\n else if (ev.type === \"fmt_start\") active_fmt[ev.id] = ev;\n else if (ev.type === \"fmt_end\") delete active_fmt[ev.id];\n else if (ev.type === \"image\") {\n // Read-only image marker (QA 2026-07-18 M5); hidden with its run in\n // clean view when it sits inside an active tracked deletion.\n if (!(cleanView && Object.keys(active_del).length > 0)) {\n const alt = (ev.date || \"image\")\n .replace(/\\]/g, \")\")\n .replace(/\\n/g, \" \");\n parts.push(``);\n }\n } else if (ev.type === \"footnote\" || ev.type === \"endnote\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`[^${ev.type === \"footnote\" ? \"fn\" : \"en\"}-${ev.id}]`);\n } else if (ev.type === \"hyperlink_start\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(\"[\");\n } else if (ev.type === \"hyperlink_end\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`](${ev.date})`);\n } else if (ev.type === \"xref_start\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(\"[~\");\n } else if (ev.type === \"xref_end\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`~](#${ev.id})`);\n } else if (ev.type === \"bookmark\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`{#${ev.id}}`);\n }\n }\n }\n\n if (pending_text)\n parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);\n\n if (deferred_meta_states.length > 0) {\n const meta_block = _build_merged_meta_block(\n deferred_meta_states,\n comments_map,\n );\n if (meta_block) parts.push(`{>>${meta_block}<<}`);\n }\n\n return parts.join(\"\");\n}\n\nfunction _get_wrappers(\n ins: any,\n del: any,\n comments: Set<string>,\n fmt: any,\n): [string, string] {\n if (Object.keys(del).length > 0) return [\"{--\", \"--}\"];\n if (Object.keys(ins).length > 0) return [\"{++\", \"++}\"];\n if (comments.size > 0 || Object.keys(fmt).length > 0) return [\"{==\", \"==}\"];\n return [\"\", \"\"];\n}\n\nfunction _build_merged_meta_block(\n states_list: any[],\n comments_map: any,\n): string {\n const change_lines: string[] = [];\n const comment_lines: string[] = [];\n const seen_sigs = new Set<string>();\n\n for (const [ins_map, del_map, comments_set, fmt_map] of states_list) {\n for (const [uid, meta] of Object.entries(\n ins_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n change_lines.push(`[${sig} insert] ${meta.author || \"Unknown\"}`);\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n del_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n change_lines.push(`[${sig} delete] ${meta.author || \"Unknown\"}`);\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n fmt_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n change_lines.push(`[${sig} format] ${meta.author || \"Unknown\"}`);\n seen_sigs.add(sig);\n }\n }\n\n // Threaded Comment Resolution Tree\n const children_map: Record<string, string[]> = {};\n for (const [c_id, data] of Object.entries(\n comments_map as Record<string, any>,\n )) {\n const p_id = data.parent_id;\n if (p_id) {\n if (!children_map[p_id]) children_map[p_id] = [];\n children_map[p_id].push(c_id);\n }\n }\n\n function render_comment(cid: string) {\n if (!comments_map[cid]) return;\n const sig = `Com:${cid}`;\n if (seen_sigs.has(sig)) return;\n\n const data = comments_map[cid];\n let header = `[${sig}] ${data.author}`;\n if (data.date) header += ` @ ${data.date}`;\n if (data.resolved) header += `(RESOLVED)`;\n comment_lines.push(`${header}: ${data.text}`);\n seen_sigs.add(sig);\n\n if (children_map[cid]) {\n const children = children_map[cid].sort((a, b) =>\n (comments_map[a]?.date || \"\").localeCompare(\n comments_map[b]?.date || \"\",\n ),\n );\n for (const child_id of children) {\n render_comment(child_id);\n }\n }\n }\n\n const sorted_ids = Array.from(comments_set as Set<string>).sort();\n for (const c_id of sorted_ids) {\n render_comment(c_id);\n }\n }\n\n return [...change_lines, ...comment_lines].join(\"\\n\");\n}\n","/**\n * Structural outline extractor.\n */\n\nimport { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, DocxEvent } from \"./docx/primitives.js\";\nimport { build_paragraph_text, extract_table } from \"./ingest.js\";\nimport { extract_comments_data } from \"./comments.js\";\nimport { findChild } from \"./docx/dom.js\";\nimport {\n _get_style_cache,\n get_paragraph_prefix,\n iter_block_items,\n iter_document_parts,\n iter_paragraph_content,\n} from \"./utils/docx.js\";\n\nconst _HEADING_PREFIX_RE = /^(#{1,6}) /;\nconst _HEURISTIC_MIN_WORDS = 3;\n\nexport interface OutlineNode {\n level: number;\n text: string;\n page: number;\n style: string;\n has_table: boolean;\n footnote_ids: string[];\n}\n\ninterface _BlockRecord {\n item: any;\n is_paragraph: boolean;\n is_table: boolean;\n start_offset: number;\n projected_length: number;\n}\n\nexport function extract_outline(\n doc: DocumentObject,\n projected_body: string,\n body_pages: string[],\n body_page_offsets: number[],\n paragraph_offsets: Record<string, [number, number]> | Map<any, [number, number]> | null = null,\n): OutlineNode[] {\n if (body_pages.length !== body_page_offsets.length) {\n throw new Error(\"body_pages and body_page_offsets length mismatch\");\n }\n\n if (paragraph_offsets) {\n return _extract_outline_fast(doc, projected_body, body_page_offsets, paragraph_offsets);\n }\n\n const comments_map = extract_comments_data(doc.pkg);\n const block_records = _walk_doc_body(doc, comments_map);\n\n const heading_indices: number[] = [];\n for (let idx = 0; idx < block_records.length; idx++) {\n const rec = block_records[idx];\n if (!(rec.is_paragraph && _is_heading(rec.item))) continue;\n if (!_heading_passes_quality_filter(rec.item, comments_map)) continue;\n heading_indices.push(idx);\n }\n\n if (heading_indices.length === 0) return [];\n\n const nodes: OutlineNode[] = [];\n for (let h_pos = 0; h_pos < heading_indices.length; h_pos++) {\n const rec_idx = heading_indices[h_pos];\n const rec = block_records[rec_idx];\n const paragraph = rec.item as Paragraph;\n\n const level = _heading_level(paragraph);\n const text = _heading_text(paragraph, comments_map);\n const style = _determine_heading_style(paragraph);\n\n const owned_end = _find_owned_end(\n block_records,\n heading_indices,\n h_pos,\n level,\n );\n const owned_blocks = block_records.slice(rec_idx + 1, owned_end);\n\n const has_table = _direct_has_table(block_records, rec_idx + 1, owned_end);\n const footnote_ids = _collect_footnote_ids(owned_blocks);\n\n const page_num = _offset_to_page(rec.start_offset, body_page_offsets);\n\n nodes.push({ level, text, page: page_num, style, has_table, footnote_ids });\n }\n\n return nodes;\n}\n\nfunction _direct_has_table(\n block_records: _BlockRecord[],\n range_start: number,\n range_end: number,\n): boolean {\n for (let idx = range_start; idx < range_end; idx++) {\n const rec = block_records[idx];\n if (rec.is_paragraph && _is_heading(rec.item)) return false;\n if (rec.is_table) return true;\n }\n return false;\n}\n\nfunction _walk_doc_body(\n doc: DocumentObject,\n comments_map: any,\n): _BlockRecord[] {\n const parts = Array.from(iter_document_parts(doc));\n let body_start_offset = 0;\n let body_part: any = null;\n\n for (const part of parts) {\n if (part === doc) {\n body_part = part;\n break;\n }\n const part_text = _project_part(part, comments_map);\n if (part_text) {\n if (body_start_offset > 0) body_start_offset += 2;\n body_start_offset += part_text.length;\n }\n }\n\n if (!body_part) {\n body_part = doc;\n body_start_offset = 0;\n } else {\n if (body_start_offset > 0) body_start_offset += 2;\n }\n\n const records: _BlockRecord[] = [];\n let cursor = body_start_offset;\n let is_first_block = true;\n\n for (const item of iter_block_items(body_part)) {\n if (item instanceof Paragraph) {\n const prefix = get_paragraph_prefix(item);\n const p_text = build_paragraph_text(item, comments_map, false);\n const block_len = (prefix + p_text).length;\n\n if (!is_first_block) cursor += 2;\n\n records.push({\n item,\n is_paragraph: true,\n is_table: false,\n start_offset: cursor,\n projected_length: block_len,\n });\n cursor += block_len;\n is_first_block = false;\n } else if (item instanceof Table) {\n const table_text = extract_table(item, comments_map, false, 0);\n const block_len = table_text ? table_text.length : 0;\n\n if (!is_first_block) cursor += 2;\n\n const table_start = cursor;\n records.push({\n item,\n is_paragraph: false,\n is_table: true,\n start_offset: table_start,\n projected_length: block_len,\n });\n _record_table_inner_blocks_lite(item, table_start, records, comments_map);\n cursor += block_len;\n is_first_block = false;\n }\n }\n\n return records;\n}\n\nfunction _compute_inner_block_offset(\n table: Table,\n target_paragraph: Paragraph,\n table_start_offset: number,\n comments_map: any,\n): number {\n const target_el = target_paragraph._element;\n let cursor = table_start_offset;\n let rows_processed = 0;\n\n for (const row of table.rows) {\n if (rows_processed > 0) cursor += 1;\n\n const seen_cells = new Set();\n let cells_in_row = 0;\n\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n if (cells_in_row > 0) cursor += 3;\n\n const [new_cursor, found] = _walk_cell_for_offset(\n cell,\n target_el,\n cursor,\n comments_map,\n );\n if (found) return new_cursor;\n cursor = new_cursor;\n\n cells_in_row++;\n }\n rows_processed++;\n }\n\n return table_start_offset;\n}\n\nfunction _walk_cell_for_offset(\n cell: any,\n target_el: any,\n cell_start_cursor: number,\n comments_map: any,\n): [number, boolean] {\n let cursor = cell_start_cursor;\n let is_first_block = true;\n\n for (const inner_item of iter_block_items(cell)) {\n if (!is_first_block) cursor += 2;\n\n if (inner_item instanceof Paragraph) {\n if (inner_item._element === target_el) return [cursor, true];\n const prefix = get_paragraph_prefix(inner_item);\n const p_text = build_paragraph_text(inner_item, comments_map, false);\n cursor += (prefix + p_text).length;\n } else if (inner_item instanceof Table) {\n const nested_offset = _compute_inner_block_offset(\n inner_item,\n new Paragraph(target_el, null),\n cursor,\n comments_map,\n );\n if (nested_offset !== cursor) {\n if (_element_is_descendant(target_el, inner_item._element))\n return [nested_offset, true];\n }\n const table_text = extract_table(inner_item, comments_map, false, 0);\n cursor += table_text ? table_text.length : 0;\n }\n is_first_block = false;\n }\n return [cursor, false];\n}\n\nfunction _element_is_descendant(\n target_el: Element,\n ancestor_el: Element,\n): boolean {\n let cur: Node | null = target_el.parentNode;\n while (cur) {\n if (cur === ancestor_el) return true;\n cur = cur.parentNode;\n }\n return false;\n}\n\nfunction _record_table_inner_blocks_lite(\n table: Table,\n inherited_offset: number,\n records: _BlockRecord[],\n comments_map: any,\n) {\n const seen_cells = new Set();\n for (const row of table.rows) {\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n for (const inner_item of iter_block_items(cell)) {\n if (inner_item instanceof Paragraph) {\n const true_offset = _is_heading(inner_item)\n ? _compute_inner_block_offset(\n table,\n inner_item,\n inherited_offset,\n comments_map,\n )\n : inherited_offset;\n records.push({\n item: inner_item,\n is_paragraph: true,\n is_table: false,\n start_offset: true_offset,\n projected_length: 0,\n });\n } else if (inner_item instanceof Table) {\n records.push({\n item: inner_item,\n is_paragraph: false,\n is_table: true,\n start_offset: inherited_offset,\n projected_length: 0,\n });\n _record_table_inner_blocks_lite(\n inner_item,\n inherited_offset,\n records,\n comments_map,\n );\n }\n }\n }\n }\n}\n\nfunction _project_part(part: any, comments_map: any): string {\n const blocks: string[] = [];\n const c_type = part.constructor.name;\n\n if (c_type === \"NotesPart\") {\n const header = part.note_type === \"fn\" ? \"## Footnotes\" : \"## Endnotes\";\n blocks.push(`---\\n${header}`);\n }\n\n let is_first_para = true;\n for (const item of iter_block_items(part)) {\n if (item.constructor.name === \"FootnoteItem\") {\n const fn_text = _project_part(item, comments_map);\n if (fn_text) blocks.push(fn_text);\n } else if (item instanceof Paragraph) {\n let prefix = get_paragraph_prefix(item);\n if (is_first_para && c_type === \"FootnoteItem\")\n prefix = `[^${part.note_type}-${part.id}]: ${prefix}`;\n const p_text = build_paragraph_text(item, comments_map, false);\n blocks.push(prefix + p_text);\n is_first_para = false;\n } else if (item instanceof Table) {\n const table_text = extract_table(item, comments_map, false, 0);\n if (table_text) blocks.push(table_text);\n is_first_para = false;\n }\n }\n\n return blocks.join(\"\\n\\n\");\n}\n\nfunction _is_heading(paragraph: Paragraph): boolean {\n return _HEADING_PREFIX_RE.test(get_paragraph_prefix(paragraph));\n}\n\nfunction _heading_passes_quality_filter(\n paragraph: Paragraph,\n comments_map: any,\n): boolean {\n const style = _determine_heading_style(paragraph);\n if (style !== \"(heuristic)\") return true;\n const text = _heading_text(paragraph, comments_map);\n if (!text) return false;\n const word_count = (text.match(/\\w+/g) || []).length;\n return word_count >= _HEURISTIC_MIN_WORDS;\n}\n\nfunction _heading_level(paragraph: Paragraph): number {\n const match = _HEADING_PREFIX_RE.exec(get_paragraph_prefix(paragraph));\n return match ? Math.min(match[1].length, 6) : 1;\n}\n\nfunction _heading_text(paragraph: Paragraph, comments_map: any): string {\n const p_text = build_paragraph_text(paragraph, comments_map, false);\n let cleaned = _strip_critic_markup(p_text);\n cleaned = _strip_inline_formatting(cleaned);\n return cleaned.trim();\n}\n\nfunction _strip_critic_markup(text: string): string {\n if (!text) return \"\";\n text = text.replace(/\\{--[\\s\\S]*?--\\}/g, \"\");\n text = text.replace(/\\{>>[\\s\\S]*?<<\\}/g, \"\");\n text = text.replace(/\\{\\+\\+([\\s\\S]*?)\\+\\+\\}/g, \"$1\");\n text = text.replace(/\\{==([\\s\\S]*?)==\\}/g, \"$1\");\n return text;\n}\n\nfunction _strip_inline_formatting(text: string): string {\n if (!text) return \"\";\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, \"$1\");\n text = text.replace(/__(.+?)__/g, \"$1\");\n text = text.replace(/(?<!\\w)_(\\S(?:.*?\\S)?)_(?!\\w)/g, \"$1\");\n return text;\n}\n\nfunction _determine_heading_style(paragraph: Paragraph): string {\n const [style_cache, default_pstyle] = _get_style_cache(\n paragraph._parent.part || paragraph._parent,\n );\n const pPr = findChild(paragraph._element, \"w:pPr\");\n let style_id = default_pstyle;\n\n if (pPr) {\n const pStyle = findChild(pPr, \"w:pStyle\");\n if (pStyle) style_id = pStyle.getAttribute(\"w:val\") || default_pstyle;\n }\n\n let outline_level: number | null = null;\n let outline_level_from_style = false;\n if (pPr) {\n const oLvl = findChild(pPr, \"w:outlineLvl\");\n if (oLvl && /^\\d+$/.test(oLvl.getAttribute(\"w:val\") || \"\")) {\n outline_level = parseInt(oLvl.getAttribute(\"w:val\") as string, 10);\n }\n }\n \n if (outline_level === null && style_id && style_cache && style_cache[style_id]) {\n outline_level = style_cache[style_id].outline_level;\n outline_level_from_style = true;\n }\n\n const style_name =\n style_id && style_cache && style_cache[style_id]\n ? style_cache[style_id].name\n : style_id;\n\n let normalized_style_name = style_name;\n if (normalized_style_name && typeof normalized_style_name === \"string\") {\n if (normalized_style_name.toLowerCase().startsWith(\"heading\")) {\n normalized_style_name = normalized_style_name.replace(/^heading/i, \"Heading\");\n } else if (normalized_style_name.toLowerCase() === \"title\") {\n normalized_style_name = \"Title\";\n }\n }\n\n if (outline_level_from_style && outline_level !== null) {\n const is_heading_or_title =\n normalized_style_name &&\n (normalized_style_name.startsWith(\"Heading\") || normalized_style_name === \"Title\");\n if (!is_heading_or_title) {\n outline_level = null;\n }\n }\n\n if (outline_level !== null && outline_level >= 0 && outline_level <= 8) {\n if (normalized_style_name && (normalized_style_name.startsWith(\"Heading\") || normalized_style_name === \"Title\")) {\n return normalized_style_name;\n }\n return \"(outline_level)\";\n }\n\n if (\n normalized_style_name &&\n (normalized_style_name.startsWith(\"Heading\") || normalized_style_name === \"Title\")\n )\n return normalized_style_name;\n\n if (normalized_style_name && /Heading[ ]?([1-6])(?![0-9])/.test(normalized_style_name))\n return normalized_style_name;\n\n return \"(heuristic)\";\n}\n\nfunction _safe_style_name(\n paragraph: Paragraph,\n style_cache: any,\n default_pstyle: any,\n): string | null {\n const pPr = findChild(paragraph._element, \"w:pPr\");\n let style_id = default_pstyle;\n if (pPr) {\n const pStyle = findChild(pPr, \"w:pStyle\");\n if (pStyle) style_id = pStyle.getAttribute(\"w:val\") || default_pstyle;\n }\n return style_id && style_cache && style_cache[style_id]\n ? style_cache[style_id].name\n : style_id;\n}\n\nfunction _find_owned_end(\n block_records: _BlockRecord[],\n heading_indices: number[],\n current_h_pos: number,\n current_level: number,\n): number {\n for (\n let next_h_pos = current_h_pos + 1;\n next_h_pos < heading_indices.length;\n next_h_pos++\n ) {\n const next_idx = heading_indices[next_h_pos];\n if (_heading_level(block_records[next_idx].item) <= current_level)\n return next_idx;\n }\n return block_records.length;\n}\n\nfunction _collect_footnote_ids(owned_blocks: _BlockRecord[]): string[] {\n const seen = new Set<string>();\n const ordered: string[] = [];\n for (const rec of owned_blocks) {\n if (!rec.is_paragraph) continue;\n for (const event of iter_paragraph_content(rec.item)) {\n if (!(\"type\" in event)) continue;\n let fn_id = \"\";\n if (event.type === \"footnote\") fn_id = `fn-${event.id}`;\n else if (event.type === \"endnote\") fn_id = `en-${event.id}`;\n else continue;\n\n if (!seen.has(fn_id)) {\n seen.add(fn_id);\n ordered.push(fn_id);\n }\n }\n }\n return ordered;\n}\n\nfunction _offset_to_page(offset: number, body_page_offsets: number[]): number {\n if (!body_page_offsets || body_page_offsets.length === 0) return 1;\n let page = 1;\n for (let i = 0; i < body_page_offsets.length; i++) {\n if (offset >= body_page_offsets[i]) page = i + 1;\n else break;\n }\n return page;\n}\n\nfunction _extract_outline_fast(\n doc: DocumentObject,\n projected_body: string,\n body_page_offsets: number[],\n paragraph_offsets: Map<any, [number, number]> | Record<string, [number, number]>,\n): OutlineNode[] {\n const paragraphs_and_tables: [\"p\" | \"t\", any][] = [];\n const seen_cells = new Set<any>();\n\n function walk(container: any) {\n for (const item of iter_block_items(container)) {\n const i_type = item.constructor.name;\n if (i_type === \"FootnoteItem\") {\n walk(item);\n } else if (item instanceof Paragraph) {\n paragraphs_and_tables.push([\"p\", item]);\n } else if (item instanceof Table) {\n paragraphs_and_tables.push([\"t\", item]);\n for (const row of item.rows) {\n for (const cell of row.cells) {\n if (seen_cells.has(cell._element)) {\n continue;\n }\n seen_cells.add(cell._element);\n walk(cell);\n }\n }\n }\n }\n }\n\n walk(doc);\n\n const heading_indices: number[] = [];\n for (let idx = 0; idx < paragraphs_and_tables.length; idx++) {\n const [kind, item] = paragraphs_and_tables[idx];\n if (kind !== \"p\") continue;\n\n let hasOffset = false;\n if (paragraph_offsets instanceof Map) {\n hasOffset = paragraph_offsets.has(item._element);\n } else {\n hasOffset = item._element in (paragraph_offsets as any);\n }\n if (!hasOffset) {\n continue;\n }\n\n if (!_is_heading(item)) continue;\n if (!_heading_passes_quality_filter_fast(item, projected_body, paragraph_offsets)) continue;\n\n heading_indices.push(idx);\n }\n\n if (heading_indices.length === 0) return [];\n\n const nodes: OutlineNode[] = [];\n for (let h_pos = 0; h_pos < heading_indices.length; h_pos++) {\n const item_idx = heading_indices[h_pos];\n const paragraph = paragraphs_and_tables[item_idx][1] as Paragraph;\n const level = _heading_level(paragraph);\n const text = _heading_text_fast(paragraph, projected_body, paragraph_offsets);\n const style = _determine_heading_style(paragraph);\n\n // Owned range: items strictly between this heading and the next equal-or-higher heading.\n let owned_end = item_idx;\n for (let next_h_pos = h_pos + 1; next_h_pos < heading_indices.length; next_h_pos++) {\n const next_idx = heading_indices[next_h_pos];\n const next_paragraph = paragraphs_and_tables[next_idx][1] as Paragraph;\n if (_heading_level(next_paragraph) <= level) {\n owned_end = next_idx;\n break;\n }\n }\n if (owned_end === item_idx) {\n owned_end = paragraphs_and_tables.length;\n }\n\n const owned = paragraphs_and_tables.slice(item_idx + 1, owned_end);\n\n // has_table: nearest-claim semantics (no bubbling to ancestors).\n let has_table = false;\n for (const [kind2, item2] of owned) {\n if (kind2 === \"p\" && _is_heading(item2)) {\n break;\n }\n if (kind2 === \"t\") {\n has_table = true;\n break;\n }\n }\n\n // Footnote IDs in document order, deduped.\n const footnote_ids = _collect_footnote_ids_fast(owned);\n\n // Page resolution from the paragraph's known offset.\n let para_offset: [number, number] | undefined;\n if (paragraph_offsets instanceof Map) {\n para_offset = paragraph_offsets.get(paragraph._element);\n } else {\n para_offset = paragraph_offsets[paragraph._element as any];\n }\n\n let page_num = 1;\n if (para_offset !== undefined) {\n const [start_offset] = para_offset;\n page_num = _offset_to_page(start_offset, body_page_offsets);\n }\n\n nodes.push({\n level,\n text,\n page: page_num,\n style,\n has_table,\n footnote_ids,\n });\n }\n\n return nodes;\n}\n\nfunction _heading_passes_quality_filter_fast(\n paragraph: Paragraph,\n projected_body: string,\n paragraph_offsets: Map<any, [number, number]> | Record<string, [number, number]>,\n): boolean {\n const style = _determine_heading_style(paragraph);\n if (style !== \"(heuristic)\") return true;\n\n const text = _heading_text_fast(paragraph, projected_body, paragraph_offsets);\n if (!text) return false;\n const words = text.match(/\\w+/g) || [];\n return words.length >= _HEURISTIC_MIN_WORDS;\n}\n\nfunction _heading_text_fast(\n paragraph: Paragraph,\n projected_body: string,\n paragraph_offsets: Map<any, [number, number]> | Record<string, [number, number]>,\n): string {\n let offset: [number, number] | undefined;\n if (paragraph_offsets instanceof Map) {\n offset = paragraph_offsets.get(paragraph._element);\n } else {\n offset = paragraph_offsets[paragraph._element as any];\n }\n\n if (offset === undefined) {\n return \"\";\n }\n const [start, length] = offset;\n const raw = projected_body.substring(start, start + length);\n let cleaned = _strip_critic_markup(raw);\n cleaned = _strip_inline_formatting(cleaned);\n cleaned = cleaned.replace(/^#+\\s+/, \"\");\n return cleaned.trim();\n}\n\nfunction _collect_footnote_ids_fast(owned_items: [\"p\" | \"t\", any][]): string[] {\n const seen = new Set<string>();\n const ordered: string[] = [];\n for (const [kind, item] of owned_items) {\n if (kind !== \"p\") continue;\n for (const event of iter_paragraph_content(item)) {\n if (!(\"type\" in event)) continue;\n let fn_id = \"\";\n if (event.type === \"footnote\") fn_id = `fn-${event.id}`;\n else if (event.type === \"endnote\") fn_id = `en-${event.id}`;\n else continue;\n\n if (!seen.has(fn_id)) {\n seen.add(fn_id);\n ordered.push(fn_id);\n }\n }\n }\n return ordered;\n}\n","import { strFromU8, unzipSync } from 'fflate';\nimport { DocumentObject } from '../docx/bridge.js';\nimport { SanitizeReport } from './report.js';\nimport * as transforms from './transforms.js';\nimport { findAllDescendants, parseXml } from '../docx/dom.js';\n\nexport interface FinalizeOptions {\n filename: string;\n sanitize_mode?: 'full' | 'keep-markup' | 'baseline';\n accept_all?: boolean;\n protection_mode?: 'read_only' | 'encrypt' | null;\n password?: string | null;\n author?: string | null;\n export_pdf?: boolean;\n}\n\nexport interface FinalizeResult {\n reportText: string;\n outBuffer?: Buffer;\n}\n\nexport async function finalize_document(doc: DocumentObject, options: FinalizeOptions): Promise<FinalizeResult> {\n const report = new SanitizeReport(options.filename, options.sanitize_mode || 'full', options.author || null);\n\n if (options.sanitize_mode === 'full') {\n const counts = transforms.count_tracked_changes(doc);\n const total = counts[0] + counts[1] + counts[2];\n report.tracked_changes_found = total;\n\n if (total > 0 && !options.accept_all) {\n report.status = 'blocked';\n report.blocked_reason = `Document contains ${total} unresolved tracked changes (${counts[0]} insertions, ${counts[1]} deletions, ${counts[2]} formatting). Review in Word first, or set accept_all=true.`;\n return { reportText: report.render() };\n }\n\n if (total > 0) {\n const authors = transforms.get_track_change_authors(doc);\n if (authors.size > 1) {\n report.warnings.push(`Multiple authors detected in tracked changes: ${Array.from(authors).sort().join(', ')}. Review per-change list before sending.`);\n }\n report.add_transform_lines(transforms.accept_all_tracked_changes(doc));\n report.tracked_changes_accepted = total;\n }\n\n const commentsSummary = transforms.get_comments_summary(doc);\n report.comments_removed = commentsSummary.total;\n report.add_transform_lines(transforms.remove_all_comments(doc));\n transforms.eject_comment_parts(doc);\n } else if (options.sanitize_mode === 'keep-markup') {\n // Basic support for keep-markup in TS\n const counts = transforms.count_tracked_changes(doc);\n report.tracked_changes_found = counts[0] + counts[1] + counts[2];\n report.tracked_changes_kept = report.tracked_changes_found;\n\n if (options.author) {\n report.add_transform_lines(transforms.replace_comment_authors(doc, options.author));\n report.add_transform_lines(transforms.replace_change_authors(doc, options.author));\n }\n }\n\n // Common transforms\n report.add_transform_lines(transforms.strip_rsid(doc));\n report.add_transform_lines(transforms.strip_para_ids(doc));\n report.add_transform_lines(transforms.strip_proof_errors(doc));\n report.add_transform_lines(transforms.strip_empty_properties(doc));\n report.add_transform_lines(transforms.strip_hidden_text(doc));\n report.add_transform_lines(transforms.coalesce_runs(doc));\n report.add_transform_lines(transforms.scrub_doc_properties(doc));\n report.add_transform_lines(transforms.scrub_timestamps(doc));\n report.add_transform_lines(transforms.strip_custom_xml(doc));\n report.add_transform_lines(transforms.strip_custom_properties(doc));\n report.add_transform_lines(transforms.strip_image_alt_text(doc));\n \n const warnings = transforms.audit_hyperlinks(doc);\n for (const w of warnings) report.warnings.push(w);\n // Audit (non-destructive — just warnings): watermark-like VML text objects\n // must never let the report declare the document clean (QA 2026-07-18 M3).\n for (const w of transforms.detect_watermarks(doc)) report.warnings.push(w);\n\n report.add_transform_lines(transforms.normalize_change_dates(doc));\n // Retained comments carry the same when-did-they-work signal in\n // word/comments.xml as tracked changes do in the body (QA 2026-07-19 F-09).\n report.add_transform_lines(transforms.normalize_comment_dates(doc));\n\n // Protection (Settings injection)\n if (options.protection_mode === 'read_only' || options.protection_mode === 'encrypt') {\n if (options.protection_mode === 'encrypt') {\n report.warnings.push(\"Encryption mode (AES compound wrappers) is strictly unsupported in the zero-dependency Node engine. Falling back to native Word Read-Only lock.\");\n }\n \n const settingsPart = doc.pkg.getPartByPath('word/settings.xml');\n if (settingsPart) {\n const docEl = settingsPart._element.ownerDocument!;\n let prot = transforms.findDescendantsByLocalName(settingsPart._element, 'documentProtection')[0];\n if (!prot) {\n prot = docEl.createElement('w:documentProtection');\n // Word expects documentProtection to be inserted before elements like w:autoFormatOverride, w:styleLockTheme, etc.\n // For standard robustness without complex XSD enforcement, appendChild generally works.\n settingsPart._element.appendChild(prot);\n }\n prot.setAttribute('w:edit', 'readOnly');\n prot.setAttribute('w:enforcement', '1');\n report.structural_lines.push(\"Document locked (Read-Only enforcement injected into settings.xml)\");\n }\n }\n\n if (options.export_pdf) {\n report.warnings.push(\"PDF export requires the Python/Word COM environment and is skipped in this zero-dependency Node agent.\");\n }\n\n // Clean up leaked Microsoft namespaces\n for (const part of doc.pkg.parts) {\n // Match the exact injection condition from RedlineEngine constructor\n if (part === doc.part || (part.contentType.includes('wordprocessingml') && part.contentType.endsWith('+xml'))) {\n if (part._element.hasAttribute('xmlns:w16du')) {\n let hasW16du = false;\n // Check root element attributes (excluding the xmlns declaration itself)\n if (Array.from(part._element.attributes || []).some(a => a.name.startsWith('w16du:') && a.name !== 'xmlns:w16du')) {\n hasW16du = true;\n }\n if (!hasW16du) {\n const allNodes = findAllDescendants(part._element, '*');\n for (const n of allNodes) {\n if (n.tagName.startsWith('w16du:') || Array.from(n.attributes || []).some(a => a.name.startsWith('w16du:'))) {\n hasW16du = true;\n break;\n }\n }\n }\n if (!hasW16du) part._element.removeAttribute('xmlns:w16du');\n }\n }\n }\n\n if (report.warnings.length > 0) report.status = 'clean_with_warnings';\n\n const outBuffer = await doc.save();\n verifySanitizedPackage(outBuffer);\n return { reportText: report.render(), outBuffer };\n}\n\n// Core-property elements the pipeline claims to scrub; the post-sanitize\n// verification re-checks each one in the SAVED bytes.\nconst VERIFIED_CORE_FIELDS: Array<[string, string]> = [\n ['creator', 'author (dc:creator)'],\n ['lastModifiedBy', 'last modified by (cp:lastModifiedBy)'],\n ['identifier', 'identifier (dc:identifier)'],\n ['description', 'description (dc:description)'],\n ['keywords', 'keywords (cp:keywords)'],\n ['category', 'category (cp:category)'],\n ['subject', 'subject (dc:subject)'],\n ['contentStatus', 'content status (cp:contentStatus)'],\n ['language', 'language (dc:language)'],\n ['version', 'version (cp:version)'],\n];\n\n/**\n * Post-sanitize package scan: re-open the SAVED bytes —\n * bypassing every in-memory caching layer — and verify the claims the report\n * is about to make. A \"Result: CLEAN\" verdict over a package that still\n * carries custom properties or an identifier is worse than no sanitizer.\n */\nexport function verifySanitizedPackage(outBuffer: Buffer): void {\n const unzipped = unzipSync(new Uint8Array(outBuffer));\n const names = Object.keys(unzipped);\n const problems: string[] = [];\n\n if (names.includes('docProps/custom.xml')) {\n problems.push('docProps/custom.xml (custom document properties) is still in the package');\n }\n if (names.some(n => n.startsWith('customXml/'))) {\n problems.push('customXml/* parts are still in the package');\n }\n if (names.includes('docProps/core.xml')) {\n const core = parseXml(strFromU8(unzipped['docProps/core.xml']));\n for (const [local, label] of VERIFIED_CORE_FIELDS) {\n for (const el of transforms.findDescendantsByLocalName(core.documentElement! as unknown as Element, local)) {\n if ((el.textContent || '').trim()) {\n problems.push(`core property ${label} still contains a value`);\n }\n }\n }\n }\n\n if (problems.length > 0) {\n throw new Error(\n 'Sanitize integrity check failed — the saved package still contains metadata this run ' +\n 'claims to remove:\\n - ' +\n problems.join('\\n - ') +\n '\\nRefusing to report a clean document.',\n );\n }\n}","export class SanitizeReport {\n public filename: string;\n public mode: string;\n public author: string | null;\n\n public tracked_changes_found: number = 0;\n public tracked_changes_accepted: number = 0;\n public tracked_changes_kept: number = 0;\n public change_lines: string[] = [];\n\n public comments_removed: number = 0;\n public comments_kept: number = 0;\n public removed_comment_lines: string[] = [];\n public kept_comment_lines: string[] = [];\n\n public metadata_lines: string[] = [];\n public structural_lines: string[] = [];\n public warnings: string[] = [];\n\n public status: string = \"clean\";\n public blocked_reason: string | null = null;\n\n constructor(filename: string, mode: string = \"full\", author: string | null = null) {\n this.filename = filename;\n this.mode = mode;\n this.author = author;\n }\n\n public add_transform_lines(lines: string[]) {\n for (const line of lines) {\n const lower = line.toLowerCase();\n if (lower.includes(\"tracked change\") || lower.includes(\"insertion\") || lower.includes(\"deletion\") || lower.includes(\"accepted\")) {\n this.change_lines.push(line);\n } else if (lower.includes(\"comment\") || lower.includes(\"[open]\") || lower.includes(\"[resolved]\")) {\n if (lower.includes(\"kept\") || lower.includes(\"visible\")) {\n this.kept_comment_lines.push(line);\n } else {\n this.removed_comment_lines.push(line);\n }\n } else if (\n lower.includes(\"author\") || lower.includes(\"template\") || lower.includes(\"company\") ||\n lower.includes(\"manager\") || lower.includes(\"metadata\") || lower.includes(\"timestamp\") ||\n lower.includes(\"custom xml\") || lower.includes(\"custom propert\") || lower.includes(\"identifier\") ||\n lower.includes(\"language\") || lower.includes(\"version\") ||\n lower.includes(\"last modified by\") || lower.includes(\"revision count\") || lower.includes(\"last printed\")\n ) {\n this.metadata_lines.push(line);\n } else if (lower.includes(\"hyperlink\") || lower.includes(\"warning\")) {\n this.warnings.push(line);\n } else {\n this.structural_lines.push(line);\n }\n }\n }\n\n public render(): string {\n const sep = \"═\".repeat(50);\n const lines: string[] = [sep, `Finalization Report: ${this.filename}`];\n\n const flags: string[] = [];\n if (this.mode === \"keep-markup\") flags.push(\"--keep-markup\");\n if (this.author) flags.push(`--author \"${this.author}\"`);\n if (this.tracked_changes_accepted > 0) flags.push(\"--accept-all\");\n\n if (flags.length > 0) lines.push(flags.join(\" \"));\n lines.push(sep);\n\n if (this.status === \"blocked\") {\n lines.push(\"\");\n lines.push(`BLOCKED: ${this.blocked_reason}`);\n lines.push(sep);\n return lines.join(\"\\n\");\n }\n\n if (this.mode === \"keep-markup\" && (this.tracked_changes_kept > 0 || this.comments_kept > 0)) {\n lines.push(\"\");\n lines.push(\"VISIBLE TO COUNTERPARTY\");\n if (this.tracked_changes_kept > 0) lines.push(` Tracked changes: ${this.tracked_changes_kept}`);\n if (this.comments_kept > 0) {\n lines.push(` Open comments: ${this.comments_kept}`);\n for (const cl of this.kept_comment_lines) lines.push(` ${cl}`);\n }\n if (this.author) lines.push(` Author on all markup: \"${this.author}\"`);\n }\n\n if (this.change_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"TRACKED CHANGES\");\n for (const cl of this.change_lines) lines.push(` ${cl}`);\n }\n\n if (this.removed_comment_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"COMMENTS (stripped)\");\n for (const cl of this.removed_comment_lines) lines.push(` ${cl}`);\n }\n\n if (this.metadata_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"METADATA\");\n for (const ml of this.metadata_lines) lines.push(` ${ml}`);\n }\n\n if (this.structural_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"STRUCTURAL & PROTECTION\");\n for (const sl of this.structural_lines) lines.push(` ${sl}`);\n }\n\n if (this.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"WARNINGS\");\n for (const w of this.warnings) lines.push(` ⚠ ${w}`);\n }\n\n lines.push(\"\");\n lines.push(sep);\n if (this.warnings.length > 0) {\n lines.push(`Result: CLEAN WITH WARNINGS (${this.warnings.length} warning${this.warnings.length > 1 ? 's' : ''})`);\n } else {\n lines.push(`Result: CLEAN (${this.tracked_changes_found} changes resolved, ${this.comments_removed} comments removed)`);\n }\n lines.push(sep);\n\n return lines.join(\"\\n\");\n }\n}","export function identifyEngine() {\n return 'adeu-core-node';\n}\n\nexport { DocumentObject } from './docx/bridge.js';\nexport { DocumentMapper, TextSpan } from './mapper.js';\nexport { RedlineEngine, BatchValidationError, validate_edit_strings, describe_illegal_control_chars } from './engine.js';\nexport { generate_edits_from_text, generate_structured_edits, trim_common_context, create_unified_diff, create_word_patch_diff, collect_media_difference_warnings, DiffEdit } from './diff.js';\nexport { apply_edits_to_markdown, MarkupEditReport } from './markup.js';\nexport { paginate, split_structural_appendix, PaginationResult, PageInfo } from './pagination.js';\nexport { extract_outline, OutlineNode } from './outline.js';\nexport { extractTextFromBuffer, _extractTextFromDoc, ExtractStructure, TableGeometry, RowGeometry } from './ingest.js';\nexport { finalize_document, FinalizeOptions, FinalizeResult } from './sanitize/core.js';\nexport { RegexTimeoutError, userFindAllMatches, userSearch, USER_PATTERN_TIMEOUT_MS } from './utils/safe-regex.js';"],"mappings":"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","names":["result","matches","unzipSync","i","j","ops","prev","nxt","final_target","final_new","effective_start_idx","sub_edits","target_runs","render_comment","strFromU8","unzipSync","unzipSync","strFromU8"]}
|
|
1
|
+
{"version":3,"sources":["../src/docx/bridge.ts","../src/docx/dom.ts","../src/docx/primitives.ts","../src/comments.ts","../src/utils/safe-regex.ts","../src/utils/docx.ts","../src/mapper.ts","../src/diff.ts","../src/pagination.ts","../src/markup.ts","../src/utils/text.ts","../src/engine.ts","../src/sanitize/transforms.ts","../src/domain.ts","../src/ingest.ts","../src/outline.ts","../src/sanitize/core.ts","../src/sanitize/report.ts","../src/index.ts"],"sourcesContent":["// FILE: node/packages/core/src/docx/bridge.ts\nimport { unzipSync, zipSync, strFromU8, strToU8 } from \"fflate\";\nimport {\n parseXml,\n findChild,\n findAllDescendants,\n serializeXml,\n} from \"./dom.js\";\n\nexport class Relationship {\n constructor(\n public id: string,\n public type: string,\n public target: string,\n public isExternal: boolean,\n ) {}\n}\n\nexport class Part {\n public rels: Map<string, Relationship> = new Map();\n public _element: Element;\n public package?: DocxPackage;\n constructor(\n public partname: string,\n public blob: string,\n element: Element,\n public contentType: string,\n ) {\n this._element = element;\n }\n\n public addRelationship(\n id: string,\n type: string,\n target: string,\n isExternal: boolean = false,\n ) {\n this.rels.set(id, new Relationship(id, type, target, isExternal));\n\n // Directly append the relationship element to the document structure\n if (this.partname.endsWith(\".rels\")) {\n const doc = this._element.ownerDocument;\n if (doc) {\n // Use strict namespace to ensure it parses successfully on reload\n const relEl = doc.createElementNS(\n \"http://schemas.openxmlformats.org/package/2006/relationships\",\n \"Relationship\",\n );\n relEl.setAttribute(\"Id\", id);\n relEl.setAttribute(\"Type\", type);\n relEl.setAttribute(\"Target\", target);\n if (isExternal) relEl.setAttribute(\"TargetMode\", \"External\");\n this._element.appendChild(relEl);\n }\n }\n }\n}\n\nexport class DocxPackage {\n public parts: Part[] = [];\n public mainDocumentPart!: Part;\n\n constructor(public unzipped: Record<string, Uint8Array>) {}\n\n public getPartByPath(path: string): Part | undefined {\n // Strip leading slash for zip compat\n const searchPath = path.startsWith(\"/\") ? path.substring(1) : path;\n return this.parts.find(\n (p) => p.partname === searchPath || p.partname === \"/\" + searchPath,\n );\n }\n\n public nextPartname(pattern: string): string {\n let i = 1;\n while (true) {\n const candidate = pattern.replace(\"%d\", i === 1 ? \"\" : i.toString());\n if (!this.getPartByPath(candidate)) return candidate;\n i++;\n }\n }\n\n public addPart(\n partname: string,\n contentType: string,\n xmlString: string,\n ): Part {\n const doc = parseXml(xmlString);\n const part = new Part(\n partname,\n xmlString,\n doc.documentElement,\n contentType,\n );\n part.package = this;\n this.parts.push(part);\n\n // Update [Content_Types].xml\n const ctPart = this.getPartByPath(\"[Content_Types].xml\");\n if (ctPart) {\n const docCT = ctPart._element.ownerDocument;\n if (docCT) {\n const override = docCT.createElement(\"Override\");\n override.setAttribute(\"PartName\", partname);\n override.setAttribute(\"ContentType\", contentType);\n ctPart._element.appendChild(override);\n }\n }\n return part;\n }\n\n public getOrCreateRelsPart(sourcePartname: string): Part {\n // e.g., /word/document.xml -> /word/_rels/document.xml.rels\n const parts = sourcePartname.split(\"/\");\n const file = parts.pop();\n const relsPath = parts.join(\"/\") + \"/_rels/\" + file + \".rels\";\n\n let relsPart = this.getPartByPath(relsPath);\n if (!relsPart) {\n const xml = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"></Relationships>`;\n relsPart = this.addPart(\n relsPath,\n \"application/vnd.openxmlformats-package.relationships+xml\",\n xml,\n );\n }\n return relsPart;\n }\n}\n\nexport class DocumentObject {\n public part: Part;\n public settings: { oddAndEvenPagesHeaderFooter: boolean } = {\n oddAndEvenPagesHeaderFooter: false,\n };\n // Simplification for the TS port: sections hold header/footer refs\n public sections: any[] = [];\n\n constructor(\n public pkg: DocxPackage,\n part: Part,\n ) {\n this.part = part;\n }\n\n public get element(): Element {\n return findChild(this.part._element, \"w:body\") || this.part._element;\n }\n\n /**\n * Main entrypoint for loading a DOCX buffer into the DOM wrapper.\n */\n public static async load(\n buffer: Buffer | ArrayBuffer,\n ): Promise<DocumentObject> {\n const u8 = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n const unzipped = unzipSync(u8);\n const pkg = new DocxPackage(unzipped);\n\n // 1. Load Content Types\n const ctFile = unzipped[\"[Content_Types].xml\"];\n let contentTypes: Record<string, string> = {};\n if (ctFile) {\n const ctXml = parseXml(strFromU8(ctFile));\n const overrides = findAllDescendants(ctXml.documentElement, \"Override\");\n for (const override of overrides) {\n contentTypes[override.getAttribute(\"PartName\") || \"\"] =\n override.getAttribute(\"ContentType\") || \"\";\n }\n }\n\n // 2. Pre-load all XML parts to allow synchronous traversal later\n for (const [path, fileData] of Object.entries(unzipped)) {\n if (path.endsWith(\".xml\") || path.endsWith(\".rels\")) {\n const text = strFromU8(fileData);\n const doc = parseXml(text);\n const cType = contentTypes[\"/\" + path] || \"application/xml\";\n const part = new Part(\"/\" + path, text, doc.documentElement, cType);\n part.package = pkg;\n pkg.parts.push(part);\n }\n }\n\n // 3. Resolve Relationships for the main document\n const mainPart = pkg.getPartByPath(\"word/document.xml\");\n if (!mainPart) throw new Error(\"Invalid DOCX: Missing word/document.xml\");\n pkg.mainDocumentPart = mainPart;\n\n const relsPart = pkg.getPartByPath(\"word/_rels/document.xml.rels\");\n if (relsPart) {\n const relElements = findAllDescendants(relsPart._element, \"Relationship\");\n for (const rel of relElements) {\n const rId = rel.getAttribute(\"Id\");\n const target = rel.getAttribute(\"Target\");\n const type = rel.getAttribute(\"Type\");\n const targetMode = rel.getAttribute(\"TargetMode\");\n\n if (rId && target && type) {\n mainPart.rels.set(\n rId,\n new Relationship(rId, type, target, targetMode === \"External\"),\n );\n }\n }\n }\n\n return new DocumentObject(pkg, mainPart);\n }\n\n public relateTo(part: Part, relType: string) {\n let rId = 1;\n while (this.part.rels.has(`rId${rId}`)) rId++;\n const id = `rId${rId}`;\n\n // In DOCX, targets in .rels are relative to the source part's directory.\n // /word/document.xml relating to /word/comments.xml -> target is \"comments.xml\"\n const target = part.partname.split(\"/\").pop()!;\n\n this.part.rels.set(id, new Relationship(id, relType, target, false));\n const relsPart = this.pkg.getOrCreateRelsPart(this.part.partname);\n relsPart.addRelationship(id, relType, target, false);\n }\n\n public relateToExternal(target: string, relType: string): string {\n let rId = 1;\n while (this.part.rels.has(`rId${rId}`)) rId++;\n const id = `rId${rId}`;\n\n this.part.rels.set(id, new Relationship(id, relType, target, true));\n const relsPart = this.pkg.getOrCreateRelsPart(this.part.partname);\n relsPart.addRelationship(id, relType, target, true);\n return id;\n }\n\n public async save(): Promise<Buffer> {\n for (const part of this.pkg.parts) {\n let xmlStr = serializeXml(part._element.ownerDocument || part._element);\n // Lazily declare the w16du namespace on any part that picked up a\n // tracked change (w16du:dateUtc) without a root declaration — a\n // tracked edit in a header/footer/footnotes part would otherwise\n // serialize an undeclared prefix no parser (including ours) accepts.\n // Unmodified parts never contain \"w16du:\" and stay untouched.\n // Mirrors the Python engine's _inject_w16du_if_needed at save time.\n if (xmlStr.includes(\"w16du:\") && !xmlStr.includes(\"xmlns:w16du=\")) {\n part._element.setAttribute(\n \"xmlns:w16du\",\n \"http://schemas.microsoft.com/office/word/2023/wordml/word16du\",\n );\n xmlStr = serializeXml(part._element.ownerDocument || part._element);\n }\n if (!xmlStr.startsWith(\"<?xml\")) {\n xmlStr =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n' + xmlStr;\n }\n this.pkg.unzipped[part.partname.substring(1)] = strToU8(xmlStr); // Strip leading slash\n }\n return Buffer.from(zipSync(this.pkg.unzipped));\n }\n}\n","import { DOMParser, XMLSerializer } from \"@xmldom/xmldom\";\n\n/**\n * Simulates docx.oxml.ns.qn. In xmldom, namespaces are preserved in tagName.\n */\nexport const qn = (name: string) => name;\n\n/**\n * Simulates lxml element.find(\"w:tag\") - strictly searches DIRECT children only.\n */\nexport function findChild(element: Element, tagName: string): Element | null {\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n if (\n child.nodeType === 1 /* ELEMENT_NODE */ &&\n (child as Element).tagName === tagName\n ) {\n return child as Element;\n }\n }\n return null;\n}\n\n/**\n * Simulates lxml element.findall(\"w:tag\") - strictly searches DIRECT children only.\n */\nexport function findChildren(element: Element, tagName: string): Element[] {\n const result: Element[] = [];\n for (let i = 0; i < element.childNodes.length; i++) {\n const child = element.childNodes[i];\n if (child.nodeType === 1 && (child as Element).tagName === tagName) {\n result.push(child as Element);\n }\n }\n return result;\n}\n\n/**\n * Simulates lxml element.findall(\".//w:tag\") - searches ALL descendants.\n */\nexport function findAllDescendants(\n element: Element,\n tagName: string,\n): Element[] {\n return Array.from(element.getElementsByTagName(tagName));\n}\n\n/**\n * Parses raw XML strings into xmldom Documents.\n */\nexport function parseXml(xmlString: string): Document {\n // Strip UTF-8 BOM if present\n if (xmlString.startsWith(\"\\uFEFF\")) {\n xmlString = xmlString.slice(1);\n }\n return new DOMParser().parseFromString(xmlString, \"text/xml\") as unknown as Document;\n}\n\n/**\n * Serializes an xmldom Document or Element back to a string,\n * enforcing deterministic attribute ordering on the root element.\n */\nexport function serializeXml(node: Node): string {\n let xml = new XMLSerializer().serializeToString(node as any);\n\n // BUG-11: Deterministic namespace ordering on root elements.\n const rootTagRegex = /<([a-zA-Z0-9_:]+)(\\s+[^>]+?)(>|\\/>)/;\n const match = rootTagRegex.exec(xml);\n\n if (match && !match[1].startsWith(\"?\")) {\n const index = match.index;\n const textBefore = xml.substring(0, index);\n\n // Ensure this is the absolute root tag (only <?xml...?> allowed before it)\n const isRoot =\n !textBefore.includes(\"<\") ||\n (textBefore.trim().startsWith(\"<?xml\") &&\n (textBefore.match(/</g) || []).length === 1);\n\n if (isRoot) {\n const fullTag = match[0];\n const elemStart = `<${match[1]}`;\n const attrsStr = match[2];\n const tagEnd = match[3];\n\n // Robust extraction matching any quote style and internal spacing\n const attrRegex = /([a-zA-Z0-9_:]+)\\s*=\\s*([\"'])(.*?)\\2/g;\n const attrs: string[] = [];\n let m;\n while ((m = attrRegex.exec(attrsStr)) !== null) {\n attrs.push(m[0].trim());\n }\n\n // Sort attributes: xmlns definitions first, then standard attributes\n attrs.sort((a, b) => {\n const aName = a.split(\"=\")[0].trim();\n const bName = b.split(\"=\")[0].trim();\n const aIsXmlns = aName.startsWith(\"xmlns\");\n const bIsXmlns = bName.startsWith(\"xmlns\");\n if (aIsXmlns && !bIsXmlns) return -1;\n if (!aIsXmlns && bIsXmlns) return 1;\n return aName < bName ? -1 : aName > bName ? 1 : 0;\n });\n\n const newTag =\n attrs.length > 0\n ? `${elemStart} ${attrs.join(\" \")}${tagEnd}`\n : `${elemStart}${tagEnd}`;\n xml =\n xml.substring(0, index) +\n newTag +\n xml.substring(index + fullTag.length);\n }\n }\n\n return xml;\n}\n","import { findChild } from './dom.js';\n\nexport class Paragraph {\n constructor(public _element: Element, public _parent: any) {}\n \n get text(): string {\n let t = '';\n const texts = this._element.getElementsByTagName('w:t');\n for (let i = 0; i < texts.length; i++) {\n t += texts[i].textContent || '';\n }\n return t;\n }\n}\n\nexport class Run {\n constructor(public _element: Element, public _parent: any) {}\n}\n\nexport class Cell {\n constructor(public _element: Element, public _parent: any) {}\n}\n\nexport class Row {\n public cells: Cell[] = [];\n constructor(public _element: Element, public _parent: any) {\n const tcs = this._element.getElementsByTagName('w:tc');\n for (let i = 0; i < tcs.length; i++) {\n this.cells.push(new Cell(tcs[i], this));\n }\n }\n}\n\nexport class Table {\n public rows: Row[] = [];\n constructor(public _element: Element, public _parent: any) {\n const trs = this._element.getElementsByTagName('w:tr');\n for (let i = 0; i < trs.length; i++) {\n this.rows.push(new Row(trs[i], this));\n }\n }\n}\n\nexport class NotesPart {\n public _element: Element;\n constructor(public part: any, public note_type: 'fn' | 'en') {\n this._element = part._element;\n }\n}\n\nexport class FootnoteItem {\n public id: string;\n public part: any;\n constructor(public _element: Element, public _parent: any, public note_type: 'fn' | 'en') {\n this.id = _element.getAttribute('w:id') || '';\n this.part = _parent.part;\n }\n}\n\nexport interface DocxEvent {\n type: string;\n id: string;\n author?: string;\n date?: string;\n}","import { DocxPackage, Part, DocumentObject } from './docx/bridge.js';\nimport { findAllDescendants, findChild, parseXml } from './docx/dom.js';\n\nconst NS = {\n w: 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',\n w14: 'http://schemas.microsoft.com/office/word/2010/wordml',\n w15: 'http://schemas.microsoft.com/office/word/2012/wordml',\n w16cid: 'http://schemas.microsoft.com/office/word/2016/wordml/cid',\n w16cex: 'http://schemas.microsoft.com/office/word/2018/wordml/cex',\n mc: 'http://schemas.openxmlformats.org/markup-compatibility/2006'\n};\n\nconst CT = {\n COMMENTS: 'application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml',\n EXTENDED: 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml',\n IDS: 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsIds+xml',\n EXTENSIBLE: 'application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtensible+xml'\n};\n\nconst RT = {\n COMMENTS: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments',\n EXTENDED: 'http://schemas.microsoft.com/office/2011/relationships/commentsExtended',\n IDS: 'http://schemas.microsoft.com/office/2016/09/relationships/commentsIds',\n EXTENSIBLE: 'http://schemas.microsoft.com/office/2018/08/relationships/commentsExtensible'\n};\n\nexport class CommentsManager {\n private _commentsPart: Part | null = null;\n private _extendedPart: Part | null = null;\n private _idsPart: Part | null = null;\n private _extensiblePart: Part | null = null;\n private _nextId: number | null = null;\n\n constructor(public doc: DocumentObject) {}\n\n public get commentsPart(): Part {\n if (!this._commentsPart) {\n this._commentsPart = this._getOrCreateCommentsPart();\n this._ensureNamespaces();\n }\n return this._commentsPart!;\n }\n\n public get extendedPart(): Part {\n if (!this._extendedPart) this._extendedPart = this._getOrCreateExtendedPart();\n return this._extendedPart!;\n }\n\n public get idsPart(): Part {\n if (!this._idsPart) this._idsPart = this._getOrCreateIdsPart();\n return this._idsPart!;\n }\n\n public get extensiblePart(): Part {\n if (!this._extensiblePart) this._extensiblePart = this._getOrCreateExtensiblePart();\n return this._extensiblePart!;\n }\n\n public get nextId(): number {\n if (this._nextId === null) this._nextId = this._getNextCommentId();\n return this._nextId;\n }\n\n public set nextId(value: number) {\n this._nextId = value;\n }\n\n private _getExistingPartByType(contentType: string): Part | null {\n return this.doc.pkg.parts.find(p => p.contentType === contentType) || null;\n }\n\n private _linkPart(part: Part, relType: string): Part {\n for (const rel of this.doc.part.rels.values()) {\n if (!rel.isExternal && rel.target === part.partname.split('/').pop()) {\n return part;\n }\n }\n this.doc.relateTo(part, relType);\n return part;\n }\n\n private _getOrCreateCommentsPart(): Part {\n let part = this._getExistingPartByType(CT.COMMENTS);\n if (part) return this._linkPart(part, RT.COMMENTS);\n\n const partname = this.doc.pkg.nextPartname('/word/comments%d.xml');\n const xml = `<w:comments xmlns:w=\"${NS.w}\" xmlns:w14=\"${NS.w14}\" xmlns:w15=\"${NS.w15}\" xmlns:w16cid=\"${NS.w16cid}\" xmlns:w16cex=\"${NS.w16cex}\" xmlns:mc=\"${NS.mc}\" mc:Ignorable=\"w14 w15 w16cid w16cex\"></w:comments>`;\n part = this.doc.pkg.addPart(partname, CT.COMMENTS, xml);\n this.doc.relateTo(part, RT.COMMENTS);\n return part;\n }\n\n private _getOrCreateExtendedPart(): Part {\n let part = this._getExistingPartByType(CT.EXTENDED);\n if (part) return this._linkPart(part, RT.EXTENDED);\n\n const partname = this.doc.pkg.nextPartname('/word/commentsExtended%d.xml');\n const xml = `<w15:commentsEx xmlns:w15=\"${NS.w15}\"></w15:commentsEx>`;\n part = this.doc.pkg.addPart(partname, CT.EXTENDED, xml);\n this.doc.relateTo(part, RT.EXTENDED);\n return part;\n }\n\n private _getOrCreateIdsPart(): Part {\n let part = this._getExistingPartByType(CT.IDS);\n if (part) return this._linkPart(part, RT.IDS);\n\n const partname = this.doc.pkg.nextPartname('/word/commentsIds%d.xml');\n const xml = `<w16cid:commentsIds xmlns:w16cid=\"${NS.w16cid}\"></w16cid:commentsIds>`;\n part = this.doc.pkg.addPart(partname, CT.IDS, xml);\n this.doc.relateTo(part, RT.IDS);\n return part;\n }\n\n private _getOrCreateExtensiblePart(): Part {\n let part = this._getExistingPartByType(CT.EXTENSIBLE);\n if (part) return this._linkPart(part, RT.EXTENSIBLE);\n\n const partname = this.doc.pkg.nextPartname('/word/commentsExtensible%d.xml');\n const xml = `<w16cex:commentsExtensible xmlns:w16cex=\"${NS.w16cex}\"></w16cex:commentsExtensible>`;\n part = this.doc.pkg.addPart(partname, CT.EXTENSIBLE, xml);\n this.doc.relateTo(part, RT.EXTENSIBLE);\n return part;\n }\n\n private _ensureNamespaces() {\n // When the comments part already existed (e.g. a legacy or pandoc-produced\n // document) its root <w:comments> may omit the namespaces we rely on —\n // most importantly w14, which qualifies the w14:paraId / w14:textId\n // attributes we write on each comment paragraph. Without the declaration\n // the serialised XML is invalid (\"Namespace prefix w14 ... is not defined\").\n // Declare any missing namespace prefixes on the existing root element.\n const root = this._commentsPart?._element;\n if (!root) return;\n\n const required: [string, string][] = [\n ['xmlns:w', NS.w],\n ['xmlns:w14', NS.w14],\n ['xmlns:w15', NS.w15],\n ['xmlns:w16cid', NS.w16cid],\n ['xmlns:w16cex', NS.w16cex],\n ['xmlns:mc', NS.mc],\n ];\n for (const [attr, uri] of required) {\n if (!root.getAttribute(attr)) {\n root.setAttribute(attr, uri);\n }\n }\n }\n\n private _getNextCommentId(): number {\n const ids = [0];\n const part = this._getExistingPartByType(CT.COMMENTS);\n if (part) {\n const comments = findAllDescendants(part._element, 'w:comment');\n for (const c of comments) {\n const idStr = c.getAttribute('w:id');\n if (idStr) ids.push(parseInt(idStr, 10) || 0);\n }\n }\n return Math.max(...ids) + 1;\n }\n\n private _generateHexId(): string {\n return Math.floor(Math.random() * 0xFFFFFFFF).toString(16).toUpperCase().padStart(8, '0');\n }\n\n private _getInitials(author: string): string {\n if (!author) return '';\n return author.split(' ').filter(Boolean).map(p => p[0]).join('').toUpperCase();\n }\n\n private _findParaIdForComment(commentId: string): string | null {\n if (!this._commentsPart) return null;\n for (const c of findAllDescendants(this._commentsPart._element, 'w:comment')) {\n if (c.getAttribute('w:id') === commentId) {\n for (const p of findAllDescendants(c, 'w:p')) {\n const pid = p.getAttribute('w14:paraId');\n if (pid) return pid;\n }\n }\n }\n return null;\n }\n\n private _findThreadRootParaId(commentId: string): string | null {\n const directParaId = this._findParaIdForComment(commentId);\n const extPart = this._getExistingPartByType(CT.EXTENDED);\n if (!directParaId || !extPart) return directParaId;\n\n for (let i = 0; i < extPart._element.childNodes.length; i++) {\n const child = extPart._element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n if (child.getAttribute('w15:paraId') === directParaId) {\n const parent = child.getAttribute('w15:paraIdParent');\n if (parent) return parent;\n }\n }\n return directParaId;\n }\n\n public addComment(author: string, text: string, parentId: string | null = null): string {\n const commentId = this.nextId.toString();\n this.nextId++;\n const now = new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n\n const doc = this.commentsPart._element.ownerDocument!;\n const comment = doc.createElement('w:comment');\n comment.setAttribute('w:id', commentId);\n comment.setAttribute('w:author', author);\n comment.setAttribute('w:date', now);\n \n const initials = this._getInitials(author);\n if (initials) comment.setAttribute('w:initials', initials);\n\n const extPart = this._getExistingPartByType(CT.EXTENDED);\n if (parentId && !extPart) {\n comment.setAttribute('w15:p', parentId);\n }\n\n const paraId = this._generateHexId();\n const rsid = this._generateHexId();\n\n const p = doc.createElement('w:p');\n p.setAttribute('w14:paraId', paraId);\n p.setAttribute('w14:textId', '77777777');\n p.setAttribute('w:rsidR', rsid);\n p.setAttribute('w:rsidRDefault', rsid);\n p.setAttribute('w:rsidP', rsid);\n\n const pPr = doc.createElement('w:pPr');\n const pStyle = doc.createElement('w:pStyle');\n pStyle.setAttribute('w:val', 'CommentText');\n pPr.appendChild(pStyle);\n p.appendChild(pPr);\n\n const rRef = doc.createElement('w:r');\n const rPrRef = doc.createElement('w:rPr');\n const rStyleRef = doc.createElement('w:rStyle');\n rStyleRef.setAttribute('w:val', 'CommentReference');\n rPrRef.appendChild(rStyleRef);\n rRef.appendChild(rPrRef);\n rRef.appendChild(doc.createElement('w:annotationRef'));\n p.appendChild(rRef);\n\n const r = doc.createElement('w:r');\n const t = doc.createElement('w:t');\n t.textContent = text;\n r.appendChild(t);\n p.appendChild(r);\n comment.appendChild(p);\n\n this.commentsPart._element.appendChild(comment);\n\n if (this.extendedPart) {\n const parentParaId = parentId ? this._findThreadRootParaId(parentId) : null;\n const exDoc = this.extendedPart._element.ownerDocument!;\n const commentEx = exDoc.createElement('w15:commentEx');\n commentEx.setAttribute('w15:paraId', paraId);\n if (parentParaId) commentEx.setAttribute('w15:paraIdParent', parentParaId);\n commentEx.setAttribute('w15:done', '0');\n this.extendedPart._element.appendChild(commentEx);\n }\n\n if (this.idsPart) {\n const idsDoc = this.idsPart._element.ownerDocument!;\n const commentIdEl = idsDoc.createElement('w16cid:commentId');\n commentIdEl.setAttribute('w16cid:paraId', paraId);\n commentIdEl.setAttribute('w16cid:durableId', this._generateHexId());\n this.idsPart._element.appendChild(commentIdEl);\n }\n\n if (this.extensiblePart) {\n let durableId: string | null = null;\n for (let i = 0; i < this.idsPart._element.childNodes.length; i++) {\n const child = this.idsPart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w16cid:paraId') === paraId) {\n durableId = child.getAttribute('w16cid:durableId');\n break;\n }\n }\n if (durableId) {\n const cexDoc = this.extensiblePart._element.ownerDocument!;\n const extEl = cexDoc.createElement('w16cex:commentExtensible');\n extEl.setAttribute('w16cex:durableId', durableId);\n extEl.setAttribute('w16cex:dateUtc', now);\n this.extensiblePart._element.appendChild(extEl);\n }\n }\n\n return commentId;\n }\n\n public deleteComment(commentId: string) {\n if (!this.commentsPart) return;\n\n let commentEl: Element | null = null;\n for (const c of findAllDescendants(this.commentsPart._element, 'w:comment')) {\n if (c.getAttribute('w:id') === commentId) {\n commentEl = c;\n break;\n }\n }\n\n if (!commentEl) return;\n\n let paraId: string | null = null;\n for (const p of findAllDescendants(commentEl, 'w:p')) {\n const pid = p.getAttribute('w14:paraId');\n if (pid) {\n paraId = pid;\n break;\n }\n }\n\n if (paraId) {\n const repliesToDelete: string[] = [];\n if (this.extendedPart) {\n for (let i = 0; i < this.extendedPart._element.childNodes.length; i++) {\n const child = this.extendedPart._element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n \n if (child.getAttribute('w15:paraIdParent') === paraId) {\n const childParaId = child.getAttribute('w15:paraId');\n if (childParaId) {\n for (const c of findAllDescendants(this.commentsPart._element, 'w:comment')) {\n for (const p of findAllDescendants(c, 'w:p')) {\n if (p.getAttribute('w14:paraId') === childParaId) {\n const cid = c.getAttribute('w:id');\n if (cid) repliesToDelete.push(cid);\n break;\n }\n }\n }\n }\n }\n }\n }\n\n for (const repId of repliesToDelete) {\n this.deleteComment(repId);\n }\n\n let durableId: string | null = null;\n\n if (this.idsPart) {\n const toRemove: Element[] = [];\n for (let i = 0; i < this.idsPart._element.childNodes.length; i++) {\n const child = this.idsPart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w16cid:paraId') === paraId) {\n durableId = child.getAttribute('w16cid:durableId');\n toRemove.push(child);\n }\n }\n toRemove.forEach(c => this.idsPart!._element.removeChild(c));\n }\n\n if (this.extendedPart) {\n const toRemove: Element[] = [];\n for (let i = 0; i < this.extendedPart._element.childNodes.length; i++) {\n const child = this.extendedPart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w15:paraId') === paraId) {\n toRemove.push(child);\n }\n }\n toRemove.forEach(c => this.extendedPart!._element.removeChild(c));\n }\n\n if (durableId && this.extensiblePart) {\n const toRemove: Element[] = [];\n for (let i = 0; i < this.extensiblePart._element.childNodes.length; i++) {\n const child = this.extensiblePart._element.childNodes[i] as Element;\n if (child.nodeType === 1 && child.getAttribute('w16cex:durableId') === durableId) {\n toRemove.push(child);\n }\n }\n toRemove.forEach(c => this.extensiblePart!._element.removeChild(c));\n }\n }\n\n if (commentEl.parentNode) {\n commentEl.parentNode.removeChild(commentEl);\n }\n }\n}\n\n// Keep the global extraction function matching Python behavior\nexport function extract_comments_data(pkg: DocxPackage): Record<string, any> {\n // Temporary bridge to use the new class\n const docObj = {\n pkg,\n part: pkg.mainDocumentPart,\n relateTo: () => {} // Mock since extraction is read-only\n } as unknown as DocumentObject;\n \n const mgr = new CommentsManager(docObj);\n const data: Record<string, any> = {};\n \n const part = pkg.parts.find(p => p.contentType === CT.COMMENTS);\n if (!part) return data;\n\n const para_id_to_cid: Record<string, string> = {};\n const comments = findAllDescendants(part._element, 'w:comment');\n\n for (const c of comments) {\n const c_id = c.getAttribute('w:id');\n if (!c_id) continue;\n\n const c_author = c.getAttribute('w:author') || 'Unknown';\n const c_date = c.getAttribute('w:date') || '';\n \n let is_resolved = false;\n const val = c.getAttribute('w15:done');\n if (val === '1' || val === 'true' || val === 'on') is_resolved = true;\n\n let parent_id = c.getAttribute('w15:p') || null;\n\n const p_elems = findAllDescendants(c, 'w:p');\n for (const p of p_elems) {\n const pid = p.getAttribute('w14:paraId');\n if (pid) para_id_to_cid[pid] = c_id;\n }\n\n const text_parts: string[] = [];\n for (const p of p_elems) {\n const t_elems = findAllDescendants(p, 'w:t');\n for (const t of t_elems) {\n if (t.textContent) text_parts.push(t.textContent);\n }\n text_parts.push('\\n');\n }\n const full_text = text_parts.join('').trim();\n\n data[c_id] = {\n author: c_author,\n text: full_text,\n date: c_date,\n resolved: is_resolved,\n parent_id: parent_id,\n };\n }\n\n const extPart = pkg.parts.find(p => p.contentType === CT.EXTENDED);\n if (extPart) {\n const children = extPart._element.childNodes;\n for (let i = 0; i < children.length; i++) {\n const child = children[i] as Element;\n if (child.nodeType !== 1) continue;\n\n const para_id = child.getAttribute('w15:paraId');\n const parent_para_id = child.getAttribute('w15:paraIdParent');\n const done_val = child.getAttribute('w15:done');\n\n if (para_id) {\n const c_id = para_id_to_cid[para_id];\n if (c_id && data[c_id]) {\n if (parent_para_id) {\n const p_id = para_id_to_cid[parent_para_id];\n if (p_id) data[c_id].parent_id = p_id;\n }\n if (done_val === '1' || done_val === 'true' || done_val === 'on') {\n data[c_id].resolved = true;\n }\n }\n }\n }\n }\n\n return data;\n}","// FILE: src/utils/safe-regex.ts\n/**\n * Time-budgeted execution of USER/LLM-supplied regular expressions.\n *\n * `regex: true` on a ModifyText edit and `search_regex` on read_docx hand an\n * LLM-controlled pattern to V8's backtracking engine. A pathological pattern\n * like `(a|a)*$` against a run of repeated characters hangs the event loop\n * indefinitely (QA 2026-07-17 F5 — ReDoS; mirrors the Python fix).\n *\n * JS regexes cannot be interrupted in-thread, but V8 CAN interrupt regex\n * execution running inside a `vm` context with a `timeout` — that is the\n * mechanism used here. `node:vm` is a builtin, preserving the zero-dependency\n * bundle constraint.\n *\n * Only USER-SUPPLIED patterns belong here. The engine's own generated\n * patterns (fuzzy matchers etc.) are built to be linear-time.\n */\n\nimport * as vm from \"node:vm\";\n\nexport const USER_PATTERN_TIMEOUT_MS = 2000;\n\nexport class RegexTimeoutError extends Error {\n public pattern: string;\n constructor(pattern: string) {\n super(\n `Regular expression exceeded the ${USER_PATTERN_TIMEOUT_MS / 1000}s matching time budget ` +\n `(catastrophic backtracking). Simplify the pattern — nested quantifiers like (a+)+ ` +\n `are the usual cause — or use a literal target instead.`,\n );\n this.name = \"RegexTimeoutError\";\n this.pattern = pattern;\n }\n}\n\nfunction runBudgeted<T>(pattern: string, script: string, sandbox: object): T {\n try {\n return vm.runInNewContext(script, sandbox, {\n timeout: USER_PATTERN_TIMEOUT_MS,\n }) as T;\n } catch (e: any) {\n if (e && e.code === \"ERR_SCRIPT_EXECUTION_TIMEOUT\") {\n throw new RegexTimeoutError(pattern);\n }\n throw e;\n }\n}\n\n/**\n * All non-overlapping matches of a user pattern, under the wall-clock budget.\n * Invalid patterns throw SyntaxError exactly like `new RegExp(...)` would.\n * The budget covers the ENTIRE scan, not just the first match.\n */\nexport function userFindAllMatches(\n pattern: string,\n text: string,\n flags: string = \"\",\n): Array<{ start: number; end: number }> {\n const normalized = flags.includes(\"g\") ? flags : flags + \"g\";\n const re = new RegExp(pattern, normalized); // throws SyntaxError on bad pattern\n const raw = runBudgeted<Array<{ start: number; end: number }>>(\n pattern,\n `{\n const out = [];\n let m;\n while ((m = re.exec(text)) !== null) {\n out.push({ start: m.index, end: m.index + m[0].length });\n if (m.index === re.lastIndex) re.lastIndex++;\n }\n out;\n }`,\n { re, text },\n );\n // Re-materialize in this realm (vm objects come from another context).\n return raw.map((r) => ({ start: r.start, end: r.end }));\n}\n\n/** First match of a user pattern under the wall-clock budget, or null. */\nexport function userSearch(pattern: string, text: string, flags: string = \"\"): { start: number; end: number } | null {\n const re = new RegExp(pattern, flags.replace(\"g\", \"\"));\n const raw = runBudgeted<{ start: number; end: number } | null>(\n pattern,\n `{\n const m = re.exec(text);\n m ? { start: m.index, end: m.index + m[0].length } : null;\n }`,\n { re, text },\n );\n return raw ? { start: raw.start, end: raw.end } : null;\n}\n","import { qn, findChild, findAllDescendants } from \"../docx/dom.js\";\nimport {\n Paragraph,\n Table,\n Run,\n NotesPart,\n FootnoteItem,\n DocxEvent,\n} from \"../docx/primitives.js\";\n\nexport const QN_W_P = \"w:p\";\nexport const QN_W_R = \"w:r\";\nexport const QN_W_T = \"w:t\";\nexport const QN_W_DELTEXT = \"w:delText\";\nexport const QN_W_TAB = \"w:tab\";\nexport const QN_W_BR = \"w:br\";\nexport const QN_W_CR = \"w:cr\";\nexport const QN_W_RPR = \"w:rPr\";\nexport const QN_W_RPRCHANGE = \"w:rPrChange\";\nexport const QN_W_COMMENTREFERENCE = \"w:commentReference\";\nexport const QN_W_FOOTNOTEREFERENCE = \"w:footnoteReference\";\nexport const QN_W_ENDNOTEREFERENCE = \"w:endnoteReference\";\nexport const QN_W_FLDCHAR = \"w:fldChar\";\nexport const QN_W_FLDCHARTYPE = \"w:fldCharType\";\nexport const QN_W_INSTRTEXT = \"w:instrText\";\nexport const QN_W_INS = \"w:ins\";\nexport const QN_W_DEL = \"w:del\";\nexport const QN_W_ID = \"w:id\";\nexport const QN_W_AUTHOR = \"w:author\";\nexport const QN_W_DATE = \"w:date\";\nexport const QN_W_COMMENTRANGESTART = \"w:commentRangeStart\";\nexport const QN_W_COMMENTRANGEEND = \"w:commentRangeEnd\";\nexport const QN_W_HYPERLINK = \"w:hyperlink\";\nexport const QN_R_ID = \"r:id\";\nexport const QN_W_FLDSIMPLE = \"w:fldSimple\";\nexport const QN_W_INSTR = \"w:instr\";\nexport const QN_W_BOOKMARKSTART = \"w:bookmarkStart\";\nexport const QN_W_NAME = \"w:name\";\nexport const QN_W_SDT = \"w:sdt\";\nexport const QN_W_SMARTTAG = \"w:smartTag\";\nexport const QN_W_SDTCONTENT = \"w:sdtContent\";\nexport const QN_W_B = \"w:b\";\nexport const QN_W_I = \"w:i\";\nexport const QN_W_VAL = \"w:val\";\nexport const QN_W_PPR = \"w:pPr\";\nexport const QN_W_PSTYLE = \"w:pStyle\";\nexport const QN_W_OUTLINELVL = \"w:outlineLvl\";\nexport const QN_W_NUMPR = \"w:numPr\";\nexport const QN_W_NUMID = \"w:numId\";\nexport const QN_W_ILVL = \"w:ilvl\";\nexport const QN_W_DRAWING = \"w:drawing\";\nexport const QN_W_OBJECT = \"w:object\";\nexport const QN_W_PICT = \"w:pict\";\nexport const QN_WP_DOCPR = \"wp:docPr\";\nexport const QN_V_IMAGEDATA = \"v:imagedata\";\nexport const QN_O_TITLE = \"o:title\";\n\nconst _CUSTOM_HEADING_NAME_RE = /Heading[ ]?([1-6])(?![0-9])/;\n\n/**\n * Resolves the DocxPackage owning `obj`, whatever wrapper it is (Part,\n * DocumentObject, Cell/Row/Table/NotesPart chains). Returns null when no\n * package is reachable.\n */\nfunction _resolve_package(obj: any): any {\n let cur = obj;\n const seen = new Set<any>();\n while (cur && !seen.has(cur)) {\n seen.add(cur);\n if (cur.package) return cur.package;\n if (cur.pkg) return cur.pkg;\n if (cur.part && (cur.part.package || cur.part.pkg)) {\n return cur.part.package || cur.part.pkg;\n }\n cur = cur._parent || cur.part || null;\n }\n return null;\n}\n\nexport function _get_style_cache(\n part: any,\n): [Record<string, any>, string | null] {\n const pkg = part.package || part.pkg || (part.part ? part.part.pkg : null);\n if (pkg && pkg._adeu_style_cache) {\n return pkg._adeu_style_cache;\n }\n\n const cache: Record<string, any> = {};\n let default_pstyle: string | null = null;\n const raw_styles: Record<string, any> = {};\n\n const stylesPart = pkg?.getPartByPath(\"word/styles.xml\");\n if (!stylesPart) {\n const result: [Record<string, any>, string | null] = [cache, null];\n if (pkg) pkg._adeu_style_cache = result;\n return result;\n }\n\n const styles = findAllDescendants(stylesPart._element, \"w:style\");\n for (const s of styles) {\n const s_id = s.getAttribute(\"w:styleId\");\n if (!s_id) continue;\n\n const s_type = s.getAttribute(\"w:type\");\n const is_default =\n s.getAttribute(\"w:default\") === \"1\" ||\n s.getAttribute(\"w:default\") === \"true\";\n\n if (s_type === \"paragraph\" && is_default) default_pstyle = s_id;\n\n const name_el = findChild(s, \"w:name\");\n let name = name_el ? name_el.getAttribute(\"w:val\") : s_id;\n\n if (name && typeof name === \"string\") {\n if (name.toLowerCase().startsWith(\"heading\")) {\n name = name.replace(/^heading/i, \"Heading\");\n } else if (name.toLowerCase() === \"title\") {\n name = \"Title\";\n }\n }\n\n const based_on_el = findChild(s, \"w:basedOn\");\n const based_on = based_on_el ? based_on_el.getAttribute(\"w:val\") : null;\n\n let outline_lvl: number | null = null;\n let num_id: string | null = null;\n let num_ilvl: number | null = null;\n const pPr = findChild(s, \"w:pPr\");\n if (pPr) {\n const oLvl = findChild(pPr, \"w:outlineLvl\");\n if (oLvl) {\n const val = oLvl.getAttribute(\"w:val\");\n if (val && /^\\d+$/.test(val)) outline_lvl = parseInt(val, 10);\n }\n // Style-level list binding: Word's built-in \"List Bullet\" /\n // \"List Number\" styles carry <w:numPr> in styles.xml, not on the\n // paragraph. Without this, style-based lists project as plain\n // paragraphs and the agent loses ordered-vs-unordered semantics\n // (QA 2026-07-18 M4).\n const numPr = findChild(pPr, \"w:numPr\");\n if (numPr) {\n const numId_el = findChild(numPr, \"w:numId\");\n if (numId_el) {\n const n_val = numId_el.getAttribute(\"w:val\");\n if (n_val && n_val !== \"0\") num_id = n_val;\n }\n const ilvl_el = findChild(numPr, \"w:ilvl\");\n if (ilvl_el) {\n const i_val = ilvl_el.getAttribute(\"w:val\");\n if (i_val && /^\\d+$/.test(i_val)) num_ilvl = parseInt(i_val, 10);\n }\n }\n }\n\n let bold: boolean | null = null;\n const rPr = findChild(s, \"w:rPr\");\n if (rPr) {\n const b = findChild(rPr, \"w:b\");\n if (b) {\n const val = b.getAttribute(\"w:val\");\n bold = val !== \"0\" && val !== \"false\" && val !== \"off\";\n }\n }\n\n raw_styles[s_id] = {\n name,\n based_on,\n outline_level: outline_lvl,\n bold,\n num_id,\n num_ilvl,\n };\n }\n\n const resolve_style = (s_id: string, visited: Set<string>): any => {\n if (cache[s_id]) return cache[s_id];\n if (visited.has(s_id) || !raw_styles[s_id])\n return {\n name: s_id,\n outline_level: null,\n bold: false,\n num_id: null,\n num_ilvl: null,\n };\n\n visited.add(s_id);\n const raw = raw_styles[s_id];\n const based_on_id = raw.based_on;\n\n let o_lvl = raw.outline_level;\n let bold_val = raw.bold !== null ? raw.bold : false;\n let n_id = raw.num_id;\n let n_ilvl = raw.num_ilvl;\n\n if (based_on_id) {\n const parent = resolve_style(based_on_id, visited);\n if (o_lvl === null) o_lvl = parent.outline_level;\n if (raw.bold === null) bold_val = parent.bold;\n if (n_id === null) n_id = parent.num_id ?? null;\n if (n_ilvl === null) n_ilvl = parent.num_ilvl ?? null;\n }\n\n const resolved = {\n name: raw.name,\n outline_level: o_lvl,\n bold: bold_val,\n num_id: n_id,\n num_ilvl: n_ilvl,\n };\n cache[s_id] = resolved;\n return resolved;\n };\n\n for (const s_id in raw_styles) resolve_style(s_id, new Set());\n\n const result: [Record<string, any>, string | null] = [cache, default_pstyle];\n if (pkg) pkg._adeu_style_cache = result;\n return result;\n}\n\n/**\n * Parses word/numbering.xml once per package into\n * {numId: {ilvl: numFmt}} (e.g. {\"5\": {0: \"decimal\", 1: \"lowerLetter\"}}).\n *\n * Used to distinguish bullet lists from ordered lists in the projection\n * (QA 2026-07-18 M4). Missing part / malformed XML yields an empty cache,\n * which projects every list with the bullet marker (the historical default).\n */\nexport function _get_numbering_cache(\n part: any,\n): Record<string, Record<number, string>> {\n const pkg = _resolve_package(part);\n if (!pkg) return {};\n if (pkg._adeu_numbering_cache) return pkg._adeu_numbering_cache;\n\n const cache: Record<string, Record<number, string>> = {};\n let numbering_root: Element | null = null;\n try {\n const numberingPart = (pkg.parts || []).find((p: any) =>\n String(p.partname).endsWith(\"/numbering.xml\"),\n );\n if (numberingPart) numbering_root = numberingPart._element;\n } catch {\n numbering_root = null;\n }\n\n if (numbering_root) {\n const abstract_fmts: Record<string, Record<number, string>> = {};\n for (const abstract of findAllDescendants(numbering_root, \"w:abstractNum\")) {\n const a_id = abstract.getAttribute(\"w:abstractNumId\");\n if (a_id === null) continue;\n const lvl_map: Record<number, string> = {};\n for (const lvl of findAllDescendants(abstract, \"w:lvl\")) {\n const ilvl_val = lvl.getAttribute(\"w:ilvl\");\n const fmt_el = findChild(lvl, \"w:numFmt\");\n if (ilvl_val !== null && /^-?\\d+$/.test(ilvl_val) && fmt_el) {\n const fmt = fmt_el.getAttribute(\"w:val\");\n if (fmt) lvl_map[parseInt(ilvl_val, 10)] = fmt;\n }\n }\n abstract_fmts[a_id] = lvl_map;\n }\n\n for (const num of findAllDescendants(numbering_root, \"w:num\")) {\n const n_id = num.getAttribute(\"w:numId\");\n const a_ref = findChild(num, \"w:abstractNumId\");\n if (n_id === null || !a_ref) continue;\n const a_id = a_ref.getAttribute(\"w:val\");\n if (a_id !== null && abstract_fmts[a_id] !== undefined) {\n cache[n_id] = abstract_fmts[a_id];\n }\n }\n }\n\n pkg._adeu_numbering_cache = cache;\n return cache;\n}\n\n/**\n * Markdown marker for a list paragraph: '* ' for bullets, '1. ' for every\n * numbered format (Markdown renderers renumber sequentially). Unknown\n * numbering (no numbering.xml entry) keeps the historical '* '.\n */\nexport function get_list_marker(\n paragraph_part: any,\n num_id: string | null,\n ilvl: number,\n): string {\n let fmt: string | null = null;\n if (num_id !== null && num_id !== undefined) {\n const lvl_map = _get_numbering_cache(paragraph_part)[num_id];\n if (lvl_map && Object.keys(lvl_map).length > 0) {\n fmt = lvl_map[ilvl] !== undefined ? lvl_map[ilvl] : null;\n if (fmt === null) {\n // Fall back to the nearest defined level at or below ilvl.\n for (let lookup = ilvl; lookup >= 0; lookup--) {\n if (lvl_map[lookup] !== undefined) {\n fmt = lvl_map[lookup];\n break;\n }\n }\n }\n }\n }\n if (fmt !== null && fmt !== \"bullet\") return \"1. \";\n return \"* \";\n}\n\nfunction _detect_heading_level_from_name(name: string): number | null {\n if (!name) return null;\n const match = name.match(_CUSTOM_HEADING_NAME_RE);\n return match ? parseInt(match[1], 10) : null;\n}\n\nexport function is_native_heading(\n paragraph: Paragraph,\n style_cache?: Record<string, any>,\n default_pstyle?: string | null,\n): boolean {\n if (!style_cache) {\n [style_cache, default_pstyle] = _get_style_cache(\n paragraph._parent.part || paragraph._parent,\n );\n }\n const pPr = findChild(paragraph._element, QN_W_PPR);\n\n if (pPr) {\n const oLvl = findChild(pPr, QN_W_OUTLINELVL);\n if (oLvl) {\n const val = oLvl.getAttribute(QN_W_VAL);\n if (val && /^\\d+$/.test(val)) {\n const lvl = parseInt(val, 10);\n if (lvl >= 0 && lvl <= 8) return true;\n }\n }\n }\n\n let style_id = default_pstyle;\n if (pPr) {\n const pStyle = findChild(pPr, QN_W_PSTYLE);\n if (pStyle) style_id = pStyle.getAttribute(QN_W_VAL) || default_pstyle;\n }\n\n const style_info = style_id && style_cache ? style_cache[style_id] : null;\n if (\n style_info &&\n style_info.outline_level !== null &&\n style_info.outline_level >= 0 &&\n style_info.outline_level <= 8\n ) {\n return true;\n }\n\n let style_name = style_info ? style_info.name : style_id; // FALLBACK TO ID\n if (style_name && typeof style_name === \"string\" && style_name.toLowerCase().startsWith(\"heading\")) {\n style_name = style_name.replace(/^heading/i, \"Heading\");\n }\n if (style_name?.startsWith(\"Heading\")) return true;\n if (style_name === \"Title\") return true;\n if (style_name && style_name !== \"Normal\") {\n if (_detect_heading_level_from_name(style_name) !== null) return true;\n }\n\n return false;\n}\nexport function get_paragraph_prefix(\n paragraph: Paragraph,\n style_cache?: Record<string, any>,\n default_pstyle?: string | null,\n): string {\n if (!style_cache) {\n [style_cache, default_pstyle] = _get_style_cache(\n paragraph._parent.part || paragraph._parent,\n );\n }\n const pPr = findChild(paragraph._element, QN_W_PPR);\n\n if (pPr) {\n const oLvl = findChild(pPr, QN_W_OUTLINELVL);\n if (oLvl) {\n const val = oLvl.getAttribute(QN_W_VAL);\n if (val && /^\\d+$/.test(val)) {\n const lvl = parseInt(val, 10);\n if (lvl >= 0 && lvl <= 8) return \"#\".repeat(lvl + 1) + \" \";\n }\n }\n }\n\n let style_id = default_pstyle;\n if (pPr) {\n const pStyle = findChild(pPr, QN_W_PSTYLE);\n if (pStyle) style_id = pStyle.getAttribute(QN_W_VAL) || default_pstyle;\n }\n\n const style_info = style_id && style_cache ? style_cache[style_id] : null;\n if (\n style_info &&\n style_info.outline_level !== null &&\n style_info.outline_level >= 0 &&\n style_info.outline_level <= 8\n ) {\n return \"#\".repeat(style_info.outline_level + 1) + \" \";\n }\n\n let style_name = style_info ? style_info.name : style_id; // FALLBACK TO ID\n if (style_name && typeof style_name === \"string\" && style_name.toLowerCase().startsWith(\"heading\")) {\n style_name = style_name.replace(/^heading/i, \"Heading\");\n }\n if (style_name?.startsWith(\"Heading\")) {\n const match = style_name.replace(\"Heading\", \"\").trim();\n if (/^\\d+$/.test(match)) return \"#\".repeat(parseInt(match, 10)) + \" \";\n }\n\n if (style_name === \"Title\") return \"# \";\n\n // Check for List Formatting (direct paragraph numPr first, then the\n // style chain — Word's built-in List Bullet/List Number styles keep their\n // numPr in styles.xml, QA 2026-07-18 M4).\n let list_num_id: string | null = null;\n let list_ilvl: number | null = null;\n let numbering_disabled = false;\n if (pPr) {\n const numPr = findChild(pPr, QN_W_NUMPR);\n if (numPr) {\n const numId = findChild(numPr, QN_W_NUMID);\n if (numId) {\n const val = numId.getAttribute(QN_W_VAL);\n if (val === \"0\") {\n // ECMA-376 §17.9.15: a direct numId of 0 REMOVES the numbering a\n // style would otherwise apply.\n numbering_disabled = true;\n } else if (val) {\n list_num_id = val;\n const ilvl = findChild(numPr, QN_W_ILVL);\n if (ilvl) {\n const valAttr = ilvl.getAttribute(QN_W_VAL);\n if (valAttr !== null && /^\\d+$/.test(valAttr)) {\n list_ilvl = parseInt(valAttr, 10);\n }\n }\n }\n }\n }\n }\n if (list_num_id === null && !numbering_disabled && style_info) {\n const style_num_id = style_info.num_id;\n if (style_num_id) {\n list_num_id = style_num_id;\n if (list_ilvl === null) {\n list_ilvl =\n style_info.num_ilvl !== undefined ? style_info.num_ilvl : null;\n }\n }\n }\n if (list_num_id !== null) {\n const level = list_ilvl !== null ? list_ilvl : 0;\n const marker = get_list_marker(\n paragraph._parent ? paragraph._parent.part || paragraph._parent : null,\n list_num_id,\n level,\n );\n return \" \".repeat(level) + marker;\n }\n\n if (style_name && style_name !== \"Normal\") {\n const custom_level = _detect_heading_level_from_name(style_name);\n if (custom_level !== null) return \"#\".repeat(custom_level) + \" \";\n }\n\n if (!style_name || style_name === \"Normal\") {\n let is_inside_tc = false;\n let curr: Element | null = paragraph._element;\n while (curr) {\n if (curr.tagName === \"w:tc\") {\n is_inside_tc = true;\n break;\n }\n curr = curr.parentNode as Element | null;\n }\n if (is_inside_tc) {\n return \"\";\n }\n\n const text = paragraph.text.trim();\n if (text && text.length < 100 && text === text.toUpperCase()) {\n let is_bold = false;\n if (style_info?.bold) {\n is_bold = true;\n } else {\n const runs = findAllDescendants(paragraph._element, QN_W_R);\n for (const r of runs) {\n const tList = findAllDescendants(r, QN_W_T);\n const tText = tList.map((t) => t.textContent || \"\").join(\"\");\n if (tText.trim()) {\n const rPr_run = findChild(r, QN_W_RPR);\n if (rPr_run) {\n const b = findChild(rPr_run, QN_W_B);\n if (\n b &&\n b.getAttribute(QN_W_VAL) !== \"0\" &&\n b.getAttribute(QN_W_VAL) !== \"false\"\n ) {\n is_bold = true;\n }\n }\n break;\n }\n }\n }\n if (is_bold) return \"## \";\n }\n }\n\n return \"\";\n}\n\nexport function is_heading_paragraph(\n paragraph: Paragraph,\n style_cache?: Record<string, any>,\n default_pstyle?: string | null,\n): boolean {\n const prefix = get_paragraph_prefix(paragraph, style_cache, default_pstyle);\n if (!prefix) return false;\n const stripped = prefix.trimEnd();\n return stripped.length > 0 && stripped === \"#\".repeat(stripped.length);\n}\n\nexport function get_run_style_markers(\n run: Run,\n is_heading: boolean | null = null,\n): [string, string] {\n let prefix = \"\";\n let suffix = \"\";\n\n const rPr = findChild(run._element, QN_W_RPR);\n let is_bold = false;\n let is_italic = false;\n\n if (rPr) {\n const b = findChild(rPr, QN_W_B);\n if (\n b &&\n b.getAttribute(QN_W_VAL) !== \"0\" &&\n b.getAttribute(QN_W_VAL) !== \"false\"\n )\n is_bold = true;\n\n const i = findChild(rPr, QN_W_I);\n if (\n i &&\n i.getAttribute(QN_W_VAL) !== \"0\" &&\n i.getAttribute(QN_W_VAL) !== \"false\"\n )\n is_italic = true;\n }\n\n if (is_heading === null) {\n const parent = run._parent;\n is_heading =\n parent instanceof Paragraph ? is_native_heading(parent) : false;\n }\n\n if (is_bold && !is_heading) {\n prefix += \"**\";\n suffix = \"**\" + suffix;\n }\n\n if (is_italic) {\n prefix += \"_\";\n suffix = \"_\" + suffix;\n }\n\n return [prefix, suffix];\n}\n\n/**\n * Splits `text` into [leading_ws, core, trailing_ws]. Emphasis markers must\n * wrap only the core: `**The Supplier **` (a bold run with a trailing space)\n * is malformed Markdown — CommonMark requires the closing delimiter to hug\n * non-whitespace — and it poisons every downstream CriticMarkup consumer\n * (QA 2026-07-19 F-03/F-10). Fully-whitespace text yields [\"\", \"\", text] so\n * callers skip the markers entirely.\n */\nexport function split_boundary_whitespace(\n text: string,\n): [string, string, string] {\n const core = text.trim();\n if (!core) return [\"\", \"\", text];\n const lead_len = text.length - text.trimStart().length;\n return [\n text.substring(0, lead_len),\n text.substring(lead_len, lead_len + core.length),\n text.substring(lead_len + core.length),\n ];\n}\n\n/**\n * Maps each tracked-change id in a merged meta bubble to the OTHER ids of its\n * resolution group, rendered ready for the bubble line suffix\n * (`uid -> \"Chg:2\"` / `uid -> \"Chg:2, Chg:3\"`).\n *\n * A replacement is stored as a contiguous same-author <w:del> + <w:ins> pair\n * with two distinct w:id values, but both engines resolve such a group as ONE\n * unit — accepting or rejecting either side decides the whole replacement.\n * Projecting the two ids side by side with no linkage implied they were\n * independently resolvable (QA 2026-07-19 ADEU-QA-004); every meta-block\n * builder (Python/Node ingest + mapper) uses this map to annotate grouped\n * lines as `(pairs with Chg:N)`.\n *\n * Grouping mirrors the engines' `_get_paired_nodes` walk: consecutive ins/del\n * ids in bubble order group while the author stays the same; any state\n * carrying NO active ins/del (a comment- or format-only run between changes —\n * physical text separating the elements) breaks the group. `states_list`\n * entries are [ins_map, del_map, comments_set, fmt_map] snapshots in document\n * order, as accumulated by the ingest/mapper state machines.\n */\nexport function compute_change_pair_map(\n states_list: any[],\n): Record<string, string> {\n const groups: Array<Array<[string, string]>> = [];\n let current: Array<[string, string]> = [];\n const seen_ids = new Set<string>();\n\n for (const [ins_map, del_map] of states_list) {\n const ins_entries = Object.entries(ins_map as Record<string, any>);\n const del_entries = Object.entries(del_map as Record<string, any>);\n if (ins_entries.length === 0 && del_entries.length === 0) {\n // A run with only comment/format meta sits between the tracked\n // elements: they are not siblings, the engine will not group them.\n if (current.length > 0) {\n groups.push(current);\n current = [];\n }\n continue;\n }\n const state_new: Array<[string, string]> = [];\n for (const [uid, meta] of ins_entries) {\n if (!seen_ids.has(uid)) {\n state_new.push([uid, (meta && meta.author) || \"Unknown\"]);\n }\n }\n for (const [uid, meta] of del_entries) {\n if (!seen_ids.has(uid)) {\n state_new.push([uid, (meta && meta.author) || \"Unknown\"]);\n }\n }\n for (const [uid, author] of state_new) {\n seen_ids.add(uid);\n if (current.length > 0 && current[current.length - 1][1] !== author) {\n groups.push(current);\n current = [];\n }\n current.push([uid, author]);\n }\n }\n if (current.length > 0) groups.push(current);\n\n const pair_map: Record<string, string> = {};\n for (const group of groups) {\n if (group.length < 2) continue;\n for (const [uid] of group) {\n pair_map[uid] = group\n .filter(([u]) => u !== uid)\n .map(([u]) => `Chg:${u}`)\n .join(\", \");\n }\n }\n return pair_map;\n}\n\nexport function apply_formatting_to_segments(\n text: string,\n prefix: string,\n suffix: string,\n): string {\n if (!prefix && !suffix) return text;\n if (!text) return \"\";\n\n const wrap = (segment: string): string => {\n const [lead, core, trail] = split_boundary_whitespace(segment);\n if (!core) return segment;\n return `${lead}${prefix}${core}${suffix}${trail}`;\n };\n\n if (!text.includes(\"\\n\")) return wrap(text);\n\n const parts = text.split(\"\\n\");\n return parts.map((p) => (p ? wrap(p) : \"\")).join(\"\\n\");\n}\n\nexport function get_run_text(run: Run): string {\n let text = \"\";\n for (let i = 0; i < run._element.childNodes.length; i++) {\n const child = run._element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n if (child.tagName === QN_W_T || child.tagName === QN_W_DELTEXT) {\n const raw = child.textContent || \"\";\n text += raw.replace(/\\t/g, \" \");\n } else if (child.tagName === QN_W_TAB) {\n text += \" \";\n } else if (child.tagName === QN_W_BR || child.tagName === QN_W_CR) {\n text += \"\\n\";\n }\n }\n return text;\n}\n\nexport function* iter_block_items(\n parent: any,\n): Generator<Paragraph | Table | FootnoteItem> {\n const parent_elm = parent._element || parent.element || parent;\n\n if (parent.constructor.name === \"NotesPart\") {\n const tag = parent.note_type === \"fn\" ? \"w:footnote\" : \"w:endnote\";\n const notes = findAllDescendants(parent_elm, tag);\n for (const child of notes) {\n if (\n child.getAttribute(\"w:type\") === \"separator\" ||\n child.getAttribute(\"w:type\") === \"continuationSeparator\"\n )\n continue;\n // Word reserves non-positive note ids (-1 separator, 0 continuation\n // separator). Some generators omit the w:type attribute on them, so\n // filter by id as well — they must never surface as user footnotes\n // like \"[^fn--1]:\" (QA 2026-07-18 M6).\n const note_id = child.getAttribute(\"w:id\");\n if (\n note_id !== null &&\n /^\\s*[-+]?\\d+\\s*$/.test(note_id) &&\n parseInt(note_id, 10) <= 0\n )\n continue;\n yield new FootnoteItem(child, parent, parent.note_type);\n }\n return;\n }\n\n for (let i = 0; i < parent_elm.childNodes.length; i++) {\n const child = parent_elm.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n if (child.tagName === QN_W_P) {\n yield new Paragraph(child, parent);\n } else if (child.tagName === \"w:tbl\") {\n yield new Table(child, parent);\n }\n }\n}\n\nexport function* iter_document_parts(doc: any): Generator<any> {\n for (const [container] of iter_document_parts_with_kind(doc)) {\n yield container;\n }\n}\n\n/**\n * Like iter_document_parts, but yields [container, kind] where kind is one\n * of \"header\" / \"body\" / \"footer\" / \"footnotes\" / \"endnotes\".\n *\n * The kind sequence defines the document's structural part layout. The\n * projection flattens all parts into one string, so diff/apply need these\n * kinds to refuse (or correctly re-anchor) edits that would otherwise cross\n * an OPC part boundary — the QA 2026-07-18 C1 failure wrote a final body\n * paragraph into word/footer1.xml.\n */\nexport function* iter_document_parts_with_kind(\n doc: any,\n): Generator<[any, string]> {\n // 1. Headers\n const headers = doc.pkg.parts.filter(\n (p: any) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml\",\n );\n for (const h of headers) yield [h, \"header\"];\n\n // 2. Main Document Body\n yield [doc, \"body\"];\n\n // 3. Footers\n const footers = doc.pkg.parts.filter(\n (p: any) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\",\n );\n for (const f of footers) yield [f, \"footer\"];\n\n // 4. Notes\n const fnPart = doc.pkg.getPartByPath(\"word/footnotes.xml\");\n const enPart = doc.pkg.getPartByPath(\"word/endnotes.xml\");\n\n if (fnPart) yield [new NotesPart(fnPart, \"fn\"), \"footnotes\"];\n if (enPart) yield [new NotesPart(enPart, \"en\"), \"endnotes\"];\n}\n\nfunction _is_page_instr(instr: string): boolean {\n if (!instr) return false;\n const parts = instr.toUpperCase().trim().split(/\\s+/);\n return parts.length > 0 && (parts[0] === \"PAGE\" || parts[0] === \"NUMPAGES\");\n}\n\nexport function _get_part(parent: any): any {\n if (!parent) return null;\n if (parent.part) return parent.part;\n if (parent.pkg && parent.pkg.mainDocumentPart)\n return parent.pkg.mainDocumentPart;\n if (parent._parent) return _get_part(parent._parent);\n return null;\n}\n\nexport function* iter_paragraph_content(\n paragraph: Paragraph,\n): Generator<Run | DocxEvent> {\n let in_complex_field = false;\n let current_instr = \"\";\n let hide_result = false;\n\n function* process_run_element(\n r_element: Element,\n ): Generator<Run | DocxEvent> {\n let c_id: string | null = null;\n const rPr = findChild(r_element, QN_W_RPR);\n if (rPr) {\n const rPrChange = findChild(rPr, QN_W_RPRCHANGE);\n if (rPrChange) {\n c_id = rPrChange.getAttribute(QN_W_ID);\n yield {\n type: \"fmt_start\",\n id: c_id!,\n author: rPrChange.getAttribute(QN_W_AUTHOR) || undefined,\n date: rPrChange.getAttribute(QN_W_DATE) || undefined,\n };\n }\n }\n\n for (let i = 0; i < r_element.childNodes.length; i++) {\n const child = r_element.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n const tag = child.tagName;\n if (tag === QN_W_DRAWING || tag === QN_W_OBJECT) {\n // Inline image/object: project a read-only marker so the agent can\n // see that a material element exists here (QA 2026-07-18 M5).\n // id/date carry (docPr id, alt text) — the marker renders as\n // .\n const doc_pr = findAllDescendants(child, QN_WP_DOCPR)[0] || null;\n let alt = \"\";\n let img_id = \"0\";\n if (doc_pr) {\n alt = doc_pr.getAttribute(\"descr\") || doc_pr.getAttribute(\"title\") || \"\";\n img_id = doc_pr.getAttribute(\"id\") || \"0\";\n }\n yield { type: \"image\", id: img_id, date: alt };\n } else if (tag === QN_W_PICT) {\n // Legacy VML picture. Only actual images (v:imagedata) get a\n // marker; textpath-only shapes (watermarks) are reported by\n // sanitize's watermark audit instead of polluting the text.\n const imagedata = findAllDescendants(child, QN_V_IMAGEDATA)[0] || null;\n if (imagedata) {\n const alt = imagedata.getAttribute(QN_O_TITLE) || \"\";\n yield { type: \"image\", id: \"vml\", date: alt };\n }\n } else if (tag === QN_W_COMMENTREFERENCE) {\n const ref_id = child.getAttribute(QN_W_ID);\n if (ref_id) yield { type: \"ref\", id: ref_id };\n } else if (tag === QN_W_FOOTNOTEREFERENCE) {\n const f_id = child.getAttribute(QN_W_ID);\n if (f_id) yield { type: \"footnote\", id: f_id };\n } else if (tag === QN_W_ENDNOTEREFERENCE) {\n const e_id = child.getAttribute(QN_W_ID);\n if (e_id) yield { type: \"endnote\", id: e_id };\n } else if (tag === QN_W_FLDCHAR) {\n const fld_type = child.getAttribute(QN_W_FLDCHARTYPE);\n if (fld_type === \"begin\") {\n in_complex_field = true;\n current_instr = \"\";\n } else if (fld_type === \"separate\") {\n if (_is_page_instr(current_instr)) hide_result = true;\n else {\n const parts = current_instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\")\n yield { type: \"xref_start\", id: parts[1] };\n }\n } else if (fld_type === \"end\") {\n if (!hide_result) {\n const parts = current_instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\")\n yield { type: \"xref_end\", id: parts[1] };\n }\n in_complex_field = false;\n current_instr = \"\";\n hide_result = false;\n }\n } else if (tag === QN_W_INSTRTEXT && in_complex_field && !hide_result) {\n current_instr += child.textContent || \"\";\n }\n }\n\n if (!hide_result) yield new Run(r_element, paragraph);\n if (c_id !== null) yield { type: \"fmt_end\", id: c_id };\n }\n\n function* traverse_node(node: Element): Generator<Run | DocxEvent> {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i] as Element;\n if (child.nodeType !== 1) continue;\n\n const tag = child.tagName;\n if (tag === QN_W_R) yield* process_run_element(child);\n else if (tag === QN_W_INS) {\n const i_id = child.getAttribute(QN_W_ID)!;\n yield {\n type: \"ins_start\",\n id: i_id,\n author: child.getAttribute(QN_W_AUTHOR) || undefined,\n date: child.getAttribute(QN_W_DATE) || undefined,\n };\n yield* traverse_node(child);\n yield { type: \"ins_end\", id: i_id };\n } else if (tag === QN_W_DEL) {\n const d_id = child.getAttribute(QN_W_ID)!;\n yield {\n type: \"del_start\",\n id: d_id,\n author: child.getAttribute(QN_W_AUTHOR) || undefined,\n date: child.getAttribute(QN_W_DATE) || undefined,\n };\n yield* traverse_node(child);\n yield { type: \"del_end\", id: d_id };\n } else if (tag === QN_W_COMMENTRANGESTART)\n yield { type: \"start\", id: child.getAttribute(QN_W_ID)! };\n else if (tag === QN_W_COMMENTRANGEEND)\n yield { type: \"end\", id: child.getAttribute(QN_W_ID)! };\n else if (tag === QN_W_HYPERLINK) {\n const rId = child.getAttribute(QN_R_ID) || child.getAttribute(\"id\");\n let url = \"\";\n const part = _get_part(paragraph._parent);\n if (rId && part) {\n const rel = part.rels.get(rId);\n if (rel && rel.isExternal) url = rel.target;\n }\n if (url) yield { type: \"hyperlink_start\", id: rId!, date: url };\n yield* traverse_node(child);\n if (url) yield { type: \"hyperlink_end\", id: rId!, date: url };\n } else if (tag === QN_W_FLDSIMPLE) {\n const instr = child.getAttribute(QN_W_INSTR) || \"\";\n const parts = instr.trim().split(/\\s+/);\n const target = parts.length > 1 && parts[0] === \"REF\" ? parts[1] : \"\";\n if (target) yield { type: \"xref_start\", id: target };\n yield* traverse_node(child);\n if (target) yield { type: \"xref_end\", id: target };\n } else if (tag === QN_W_BOOKMARKSTART) {\n const b_name = child.getAttribute(QN_W_NAME);\n if (b_name && (!b_name.startsWith(\"_\") || b_name.startsWith(\"_Ref\")))\n yield { type: \"bookmark\", id: b_name };\n } else if (\n tag === QN_W_SDT ||\n tag === QN_W_SMARTTAG ||\n tag === QN_W_SDTCONTENT\n ) {\n yield* traverse_node(child);\n }\n }\n }\n\n yield* traverse_node(paragraph._element);\n}\n","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, Run, DocxEvent } from \"./docx/primitives.js\";\nimport { findAllDescendants, findChild } from \"./docx/dom.js\";\nimport { extract_comments_data } from \"./comments.js\";\nimport { RegexTimeoutError, userFindAllMatches, userSearch } from \"./utils/safe-regex.js\";\nimport {\n _get_style_cache,\n compute_change_pair_map,\n get_paragraph_prefix,\n get_run_style_markers,\n get_run_text,\n is_heading_paragraph,\n split_boundary_whitespace,\n is_native_heading,\n iter_block_items,\n iter_document_parts_with_kind,\n iter_paragraph_content,\n} from \"./utils/docx.js\";\n\nexport interface TextSpan {\n start: number;\n end: number;\n text: string;\n run: Run | null;\n paragraph: Paragraph | null;\n ins_id?: string | null;\n del_id?: string | null;\n hyperlink_id?: string | null;\n comment_ids?: string[];\n // Which OPC part (index into DocumentMapper.part_ranges) this span was\n // projected from. Text edits may never resolve across two different\n // parts — the QA 2026-07-18 C1 corruption wrote body text into a footer.\n part_index: number;\n // True for the read-only image marker projection .\n is_image_marker?: boolean;\n // Character offset of this span's text within its run's projected text.\n // One run may back several spans: hoisting boundary whitespace outside\n // style markers (QA 2026-07-19 F-03) projects a bold \"The Supplier \" run\n // as core + trailing-space spans, and only the first starts at run\n // offset 0. All span->run local-offset arithmetic must add this.\n run_offset?: number;\n}\n\nexport function renumber_snapshot_ids(\n doc: DocumentObject,\n): [Record<string, string>, Record<string, string>] {\n const chg_remap: Record<string, string> = {};\n let next_chg = 1;\n const body_root = doc.element;\n\n const chg_elements: Element[] = [];\n const all_elements = findAllDescendants(body_root, \"*\");\n for (const el of all_elements) {\n if (el.tagName === \"w:ins\" || el.tagName === \"w:del\") {\n chg_elements.push(el);\n }\n }\n\n for (const elem of chg_elements) {\n const old_id = elem.getAttribute(\"w:id\");\n if (!old_id) continue;\n if (chg_remap[old_id]) {\n elem.setAttribute(\"w:id\", chg_remap[old_id]);\n continue;\n }\n const new_id = next_chg.toString();\n chg_remap[old_id] = new_id;\n elem.setAttribute(\"w:id\", new_id);\n next_chg++;\n }\n\n const com_remap: Record<string, string> = {};\n let next_com = 1;\n const comments_part = doc.pkg.parts.find(\n (p) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\",\n );\n\n if (comments_part) {\n const comments_root = comments_part._element;\n for (const c of findAllDescendants(comments_root, \"w:comment\")) {\n const old_id = c.getAttribute(\"w:id\");\n if (!old_id) continue;\n if (com_remap[old_id]) {\n c.setAttribute(\"w:id\", com_remap[old_id]);\n continue;\n }\n const new_id = next_com.toString();\n com_remap[old_id] = new_id;\n c.setAttribute(\"w:id\", new_id);\n next_com++;\n }\n }\n\n for (const elem of all_elements) {\n if (\n [\n \"w:commentReference\",\n \"w:commentRangeStart\",\n \"w:commentRangeEnd\",\n ].includes(elem.tagName)\n ) {\n const old_id = elem.getAttribute(\"w:id\");\n if (old_id && com_remap[old_id]) {\n elem.setAttribute(\"w:id\", com_remap[old_id]);\n }\n }\n }\n\n if (comments_part) {\n for (const c of findAllDescendants(comments_part._element, \"w:comment\")) {\n const parent_id = c.getAttribute(\"w15:p\");\n if (parent_id && com_remap[parent_id]) {\n c.setAttribute(\"w15:p\", com_remap[parent_id]);\n }\n }\n }\n\n return [chg_remap, com_remap];\n}\n\n// Markdown style delimiters the projection emits as VIRTUAL spans around\n// formatted runs (see get_run_style_markers). Literal asterisks/underscores\n// typed in the document live inside real (run-backed) spans and are never\n// confused with these.\nconst STYLE_MARKER_TEXTS = new Set([\"**\", \"__\", \"*\", \"_\"]);\n\nexport class DocumentMapper {\n public doc: DocumentObject;\n public clean_view: boolean;\n public original_view: boolean;\n public comments_map: Record<string, any>;\n public full_text: string = \"\";\n public spans: TextSpan[] = [];\n public appendix_start_index: number = -1;\n // [start, end, kind] per projected part, in projection order. Spans carry\n // the matching index in .part_index. Together these let the engine refuse\n // or re-anchor edits at OPC part boundaries (QA 2026-07-18 C1).\n public part_ranges: [number, number, string][] = [];\n private _current_part_index = 0;\n private _text_chunks: string[] = [];\n private _plain_projection: [string, number[]] | null = null;\n\n constructor(\n doc: DocumentObject,\n clean_view: boolean = false,\n original_view: boolean = false,\n ) {\n this.doc = doc;\n this.clean_view = clean_view;\n this.original_view = original_view;\n this.comments_map = extract_comments_data(doc.pkg);\n this._build_map();\n }\n\n private _build_map() {\n let current_offset = 0;\n this.spans = [];\n this._text_chunks = [];\n this.full_text = \"\";\n this._plain_projection = null;\n this.part_ranges = [];\n this._current_part_index = 0;\n\n let part_idx = 0;\n for (const [part, part_kind] of iter_document_parts_with_kind(this.doc)) {\n this._current_part_index = part_idx;\n const part_start = current_offset;\n current_offset = this._map_blocks(part, current_offset);\n this.part_ranges.push([part_start, current_offset, part_kind]);\n\n if (\n this.spans.length > 0 &&\n this.spans[this.spans.length - 1].text !== \"\\n\\n\"\n ) {\n this._add_virtual_text(\"\\n\\n\", current_offset, null);\n current_offset += 2;\n }\n part_idx++;\n }\n\n while (\n this.spans.length > 0 &&\n this.spans[this.spans.length - 1].text === \"\\n\\n\"\n ) {\n this.spans.pop();\n this._text_chunks.pop();\n }\n\n this.full_text = this._text_chunks.join(\"\");\n this.appendix_start_index = -1;\n }\n\n /** [part_index, start, end, kind] for parts that projected any text. */\n private _nonempty_part_ranges(): [number, number, number, string][] {\n const out: [number, number, number, string][] = [];\n for (let i = 0; i < this.part_ranges.length; i++) {\n const [s, e, k] = this.part_ranges[i];\n if (e > s) out.push([i, s, e, k]);\n }\n return out;\n }\n\n public part_kind_of(part_index: number): string | null {\n if (part_index >= 0 && part_index < this.part_ranges.length) {\n return this.part_ranges[part_index][2];\n }\n return null;\n }\n\n /** Kind of the part whose projected range contains `index`, or null. */\n public part_kind_at(index: number): string | null {\n for (const [, start, end, kind] of this._nonempty_part_ranges()) {\n if (start <= index && index <= end) return kind;\n }\n return null;\n }\n\n /**\n * When `index` falls strictly AFTER one part's text and at-or-before the\n * start of the next part's text (i.e. inside the \"\\n\\n\" separator or\n * exactly at the next part's first character), returns\n * [previous_part_index, next_part_index]. Returns null everywhere else —\n * including index == previous part's end, which is an ordinary\n * end-of-part text position, not a boundary gap.\n */\n public part_boundary_at(index: number): [number, number] | null {\n const ranges = this._nonempty_part_ranges();\n for (let j = 1; j < ranges.length; j++) {\n const [prev_i, , prev_end] = ranges[j - 1];\n const [next_i, next_start] = ranges[j];\n if (prev_end < index && index <= next_start) {\n return [prev_i, next_i];\n }\n }\n return null;\n }\n\n private _map_blocks(container: any, offset: number): number {\n let current = offset;\n const c_type = container.constructor.name;\n const part = container.part || container;\n const [style_cache, default_pstyle] = _get_style_cache(part);\n\n if (c_type === \"NotesPart\") {\n const header =\n container.note_type === \"fn\" ? \"## Footnotes\" : \"## Endnotes\";\n const sep = `---\\n${header}`;\n this._add_virtual_text(sep, current, null);\n current += sep.length;\n this._add_virtual_text(\"\\n\\n\", current, null);\n current += 2;\n }\n\n let is_first_para = true;\n let previous_item: any = null;\n\n for (const item of iter_block_items(container)) {\n const i_type = item.constructor.name;\n\n if (i_type === \"FootnoteItem\") {\n current = this._map_blocks(item, current);\n } else if (item instanceof Paragraph) {\n if (!is_first_para) {\n const prev_para =\n previous_item instanceof Paragraph ? previous_item : null;\n this._add_virtual_text(\"\\n\\n\", current, prev_para);\n current += 2;\n }\n\n let prefix = get_paragraph_prefix(item, style_cache, default_pstyle);\n if (is_first_para && c_type === \"FootnoteItem\") {\n prefix = `[^${container.note_type}-${container.id}]: ` + prefix;\n }\n if (prefix) {\n this._add_virtual_text(prefix, current, item);\n current += prefix.length;\n }\n\n current = this._map_paragraph_content(\n item,\n current,\n style_cache,\n default_pstyle,\n );\n is_first_para = false;\n previous_item = item;\n } else if (item instanceof Table) {\n if (!is_first_para) {\n const prev_para =\n previous_item instanceof Paragraph ? previous_item : null;\n this._add_virtual_text(\"\\n\\n\", current, prev_para);\n current += 2;\n }\n current = this._map_table(item, current);\n is_first_para = false;\n previous_item = item;\n }\n }\n\n return current;\n }\n\n private _map_table(table: Table, offset: number): number {\n let current = offset;\n let rows_processed = 0;\n\n for (const row of table.rows) {\n const tr = row._element;\n const trPr = findChild(tr, \"w:trPr\");\n const ins = trPr ? findChild(trPr, \"w:ins\") : null;\n const del_node = trPr ? findChild(trPr, \"w:del\") : null;\n\n if (this.clean_view && del_node) continue;\n if (this.original_view && ins) continue;\n\n if (rows_processed > 0) {\n this._add_virtual_text(\"\\n\", current, null);\n current += 1;\n }\n\n if (ins && !this.clean_view && !this.original_view) {\n this._add_virtual_text(\"{++ \", current, null);\n current += 4;\n } else if (del_node && !this.clean_view && !this.original_view) {\n this._add_virtual_text(\"{-- \", current, null);\n current += 4;\n }\n\n const seen_cells = new Set();\n let cells_processed = 0;\n\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n if (cells_processed > 0) {\n this._add_virtual_text(\" | \", current, null);\n current += 3;\n }\n\n const cell_start = current;\n current = this._map_blocks(cell, current);\n\n // Parity with ingest.extract_table: emit a {#cell:<paraId>} anchor and\n // bind a zero-width span to the cell's first paragraph so the engine\n // can resolve \"write into this cell\" even when the cell is empty\n // (pPr-only paragraph with no run).\n if (!this.clean_view && !this.original_view) {\n let firstP = cell._element.getElementsByTagName(\"w:p\")[0] as\n | Element\n | undefined;\n let paraId = firstP ? firstP.getAttribute(\"w14:paraId\") : null;\n const is_empty = current === cell_start;\n if (!paraId && is_empty) {\n if (!firstP) {\n const xmlDoc = cell._element.ownerDocument!;\n firstP = xmlDoc.createElement(\"w:p\");\n cell._element.appendChild(firstP);\n }\n const allPs = Array.from(cell._element.ownerDocument!.getElementsByTagName(\"w:p\"));\n const index = allPs.indexOf(firstP);\n let hash = 2166136261;\n const str = `fallback-paraId-${index}`;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);\n }\n paraId = (hash >>> 0).toString(16).toUpperCase().padStart(8, '0');\n firstP.setAttribute(\"w14:paraId\", paraId);\n }\n if (paraId && firstP) {\n // Zero-width span bound to the empty cell paragraph: gives\n // get_insertion_anchor a paragraph to land on. Placed at the anchor\n // token offset so resolution targets THIS cell, not a neighbour.\n const cellPara = new Paragraph(firstP, cell);\n this._add_virtual_text(\"\", current, cellPara);\n const has_content = current > cell_start;\n if (has_content) {\n this._add_virtual_text(\" \", current, cellPara);\n current += 1;\n }\n const anchor = `{#cell:${paraId}}`;\n this._add_virtual_text(anchor, current, cellPara);\n current += anchor.length;\n }\n }\n cells_processed += 1;\n }\n\n if (ins && !this.clean_view && !this.original_view) {\n const suffix = ` |Chg:${ins.getAttribute(\"w:id\")}++}`;\n this._add_virtual_text(suffix, current, null);\n current += suffix.length;\n } else if (del_node && !this.clean_view && !this.original_view) {\n const suffix = ` |Chg:${del_node.getAttribute(\"w:id\")}--}`;\n this._add_virtual_text(suffix, current, null);\n current += suffix.length;\n }\n\n rows_processed += 1;\n }\n\n return current;\n }\n\n private _strip_markdown_formatting(text: string): string {\n let result = text;\n result = result.replace(/^#+\\s*/gm, \"\");\n result = result.replace(/\\*\\*(\\w[\\w\\s]*\\w|\\w{2,})\\*\\*/g, \"$1\");\n result = result.replace(/__(\\w[\\w\\s]*\\w|\\w{2,})__/g, \"$1\");\n result = result.replace(/(?<!\\w)_(\\w[\\w\\s]*\\w|\\w{2,})_(?!\\w)/g, \"$1\");\n result = result.replace(/(?<!\\w)\\*(\\w[\\w\\s]*\\w|\\w{2,})\\*(?!\\w)/g, \"$1\");\n return result;\n }\n\n private _map_paragraph_content(\n paragraph: Paragraph,\n start_offset: number,\n style_cache?: any,\n default_pstyle?: string | null,\n ): number {\n let current = start_offset;\n\n const span: TextSpan = {\n start: current,\n end: current,\n text: \"\",\n run: null,\n paragraph,\n part_index: this._current_part_index,\n };\n this.spans.push(span);\n\n const active_ids = new Set<string>();\n const active_ins: Record<string, DocxEvent> = {};\n const active_del: Record<string, DocxEvent> = {};\n const active_fmt: Record<string, DocxEvent> = {};\n\n let deferred_meta_states: any[] = [];\n let current_wrappers: [string, string] = [\"\", \"\"];\n let current_style: [string, string] = [\"\", \"\"];\n let active_hyperlink_id: string | null = null;\n // [kind, text, run, run_offset, ins_id, del_id, comment_ids]\n let pending_runs: [\n string,\n string,\n Run | null,\n number,\n string | null,\n string | null,\n string[],\n ][] = [];\n\n const flush_pending_runs = () => {\n if (pending_runs.length === 0) return;\n const [s_tok, e_tok] = current_wrappers;\n if (s_tok) {\n this._add_virtual_text(s_tok, current, paragraph);\n current += s_tok.length;\n }\n for (const [kind, txt, r_obj, r_off, i_id, d_id, c_ids] of pending_runs) {\n if (kind === \"virtual\") {\n this._add_virtual_text(txt, current, paragraph, active_hyperlink_id);\n } else {\n const s: TextSpan = {\n start: current,\n end: current + txt.length,\n text: txt,\n run: r_obj,\n paragraph,\n ins_id: i_id || undefined,\n del_id: d_id || undefined,\n hyperlink_id: active_hyperlink_id || undefined,\n comment_ids: c_ids.length > 0 ? c_ids : undefined,\n part_index: this._current_part_index,\n run_offset: r_off,\n };\n this.spans.push(s);\n this._text_chunks.push(txt);\n }\n current += txt.length;\n }\n if (e_tok) {\n this._add_virtual_text(e_tok, current, paragraph);\n current += e_tok.length;\n }\n pending_runs = [];\n };\n\n const items = Array.from(iter_paragraph_content(paragraph));\n const is_heading = is_heading_paragraph(\n paragraph,\n style_cache,\n default_pstyle,\n );\n const native_heading = is_native_heading(\n paragraph,\n style_cache,\n default_pstyle,\n );\n let leading_strip_active = is_heading;\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n\n if (item instanceof Run) {\n const [prefix, suffix] = get_run_style_markers(item, native_heading);\n // [kind, text, run, run_offset]\n const run_parts: [string, string, Run | null, number][] = [];\n const text = get_run_text(item);\n\n if (leading_strip_active) {\n if (text === \"\" || /^\\s*$/.test(text)) continue;\n leading_strip_active = false;\n }\n\n // run_local tracks each real part's offset within the run's projected\n // text, so spans resolve back to exact run positions even when one\n // run backs several spans.\n let run_local = 0;\n const append_wrapped = (segment: string): void => {\n // Boundary whitespace stays OUTSIDE the style markers —\n // `**The Supplier **` is malformed Markdown (QA 2026-07-19 F-03).\n // Must mirror apply_formatting_to_segments exactly (the Virtual\n // Text contract).\n const [lead, core, trail] = split_boundary_whitespace(segment);\n if (!core) {\n run_parts.push([\"real\", segment, item, run_local]);\n run_local += segment.length;\n return;\n }\n if (lead) {\n run_parts.push([\"real\", lead, item, run_local]);\n run_local += lead.length;\n }\n if (prefix) run_parts.push([\"virtual\", prefix, null, 0]);\n run_parts.push([\"real\", core, item, run_local]);\n run_local += core.length;\n if (suffix) run_parts.push([\"virtual\", suffix, null, 0]);\n if (trail) {\n run_parts.push([\"real\", trail, item, run_local]);\n run_local += trail.length;\n }\n };\n\n if (text.includes(\"\\n\") && (prefix || suffix)) {\n const parts = text.split(\"\\n\");\n for (let idx = 0; idx < parts.length; idx++) {\n if (idx > 0) {\n run_parts.push([\"real\", \"\\n\", item, run_local]);\n run_local += 1;\n }\n if (parts[idx]) append_wrapped(parts[idx]);\n }\n } else if ((prefix || suffix) && text) {\n append_wrapped(text);\n } else {\n if (prefix) run_parts.push([\"virtual\", prefix, null, 0]);\n if (text) run_parts.push([\"real\", text, item, 0]);\n if (suffix) run_parts.push([\"virtual\", suffix, null, 0]);\n }\n\n if (this.clean_view && Object.keys(active_del).length > 0) {\n // pass\n }\n if (this.original_view && Object.keys(active_ins).length > 0) {\n // pass\n }\n\n const full_seg_text = run_parts.map((x) => x[1]).join(\"\");\n const curr_ins_id = Object.keys(active_ins).pop() || null;\n const curr_del_id = Object.keys(active_del).pop() || null;\n\n if (\n full_seg_text &&\n !(this.clean_view && curr_del_id) &&\n !(this.original_view && curr_ins_id)\n ) {\n const new_wrappers =\n this.clean_view || this.original_view\n ? ([\"\", \"\"] as [string, string])\n : this._get_wrappers(\n curr_ins_id,\n curr_del_id,\n active_ids,\n active_fmt,\n );\n const new_style: [string, string] = [prefix, suffix];\n\n if (\n pending_runs.length > 0 &&\n new_wrappers[0] === current_wrappers[0] &&\n new_wrappers[1] === current_wrappers[1]\n ) {\n let skip_leading_prefix = false;\n if (\n new_style[0] === current_style[0] &&\n new_style[1] === current_style[1] &&\n current_style[0] !== \"\" &&\n pending_runs[pending_runs.length - 1][0] === \"virtual\" &&\n pending_runs[pending_runs.length - 1][1] === current_style[1]\n ) {\n pending_runs.pop();\n skip_leading_prefix = true;\n }\n\n const curr_comment_ids = Array.from(active_ids);\n for (const [kind, txt, r_obj, r_off] of run_parts) {\n if (\n skip_leading_prefix &&\n kind === \"virtual\" &&\n txt === new_style[0]\n ) {\n skip_leading_prefix = false;\n continue;\n }\n pending_runs.push([\n kind,\n txt,\n r_obj,\n r_off,\n curr_ins_id,\n curr_del_id,\n curr_comment_ids,\n ]);\n }\n current_style = new_style;\n } else {\n flush_pending_runs();\n current_wrappers = new_wrappers;\n current_style = new_style;\n const curr_comment_ids = Array.from(active_ids);\n for (const [kind, txt, r_obj, r_off] of run_parts) {\n pending_runs.push([\n kind,\n txt,\n r_obj,\n r_off,\n curr_ins_id,\n curr_del_id,\n curr_comment_ids,\n ]);\n }\n }\n }\n\n if (!this.clean_view && !this.original_view) {\n const has_meta =\n Object.keys(active_ins).length > 0 ||\n Object.keys(active_del).length > 0 ||\n active_ids.size > 0 ||\n Object.keys(active_fmt).length > 0;\n if (has_meta) {\n deferred_meta_states.push([\n { ...active_ins },\n { ...active_del },\n new Set(active_ids),\n { ...active_fmt },\n ]);\n }\n\n let should_defer = false;\n const has_any_meta =\n curr_ins_id !== null ||\n curr_del_id !== null ||\n Object.keys(active_fmt).length > 0 ||\n active_ids.size > 0;\n\n if (has_any_meta) {\n let j = i + 1;\n let next_has_meta = false;\n let temp_ins_count = Object.keys(active_ins).length;\n let temp_del_count = Object.keys(active_del).length;\n let temp_fmt_count = Object.keys(active_fmt).length;\n const temp_comment_ids = new Set(active_ids);\n\n while (j < items.length) {\n const next_item = items[j];\n if (next_item instanceof Run) {\n if (!get_run_text(next_item)) {\n j++;\n continue;\n }\n if (\n temp_ins_count > 0 ||\n temp_del_count > 0 ||\n temp_fmt_count > 0 ||\n temp_comment_ids.size > 0\n ) {\n next_has_meta = true;\n }\n break;\n } else {\n const ev = next_item as DocxEvent;\n if (ev.type === \"ins_start\") temp_ins_count++;\n else if (ev.type === \"ins_end\")\n temp_ins_count = Math.max(0, temp_ins_count - 1);\n else if (ev.type === \"del_start\") temp_del_count++;\n else if (ev.type === \"del_end\")\n temp_del_count = Math.max(0, temp_del_count - 1);\n else if (ev.type === \"fmt_start\") temp_fmt_count++;\n else if (ev.type === \"fmt_end\")\n temp_fmt_count = Math.max(0, temp_fmt_count - 1);\n else if (ev.type === \"start\") temp_comment_ids.add(ev.id);\n else if (ev.type === \"end\") temp_comment_ids.delete(ev.id);\n }\n j++;\n }\n\n if (next_has_meta) should_defer = true;\n }\n\n if (!should_defer && deferred_meta_states.length > 0) {\n const meta_block =\n this._build_merged_meta_block(deferred_meta_states);\n if (meta_block) {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const full_meta = `{>>${meta_block}<<}`;\n this._add_virtual_text(full_meta, current, paragraph);\n current += full_meta.length;\n }\n deferred_meta_states = [];\n }\n }\n } else {\n const ev = item as DocxEvent;\n leading_strip_active = false;\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n\n if (ev.type === \"start\") active_ids.add(ev.id);\n else if (ev.type === \"end\") active_ids.delete(ev.id);\n else if (ev.type === \"ins_start\") active_ins[ev.id] = ev;\n else if (ev.type === \"ins_end\") delete active_ins[ev.id];\n else if (ev.type === \"del_start\") active_del[ev.id] = ev;\n else if (ev.type === \"del_end\") delete active_del[ev.id];\n else if (ev.type === \"fmt_start\") active_fmt[ev.id] = ev;\n else if (ev.type === \"fmt_end\") delete active_fmt[ev.id];\n else if (ev.type === \"image\") {\n // Read-only image marker (QA 2026-07-18 M5). Hidden when the run is\n // filtered by the active view, exactly like its neighbouring text.\n const hidden =\n (this.clean_view && Object.keys(active_del).length > 0) ||\n (this.original_view && Object.keys(active_ins).length > 0);\n if (!hidden) {\n const alt = (ev.date || \"image\")\n .replace(/\\]/g, \")\")\n .replace(/\\n/g, \" \");\n const txt = ``;\n this._add_virtual_text(txt, current, paragraph, null, true);\n current += txt.length;\n }\n } else if (ev.type === \"footnote\" || ev.type === \"endnote\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const prefix_str = ev.type === \"footnote\" ? \"fn\" : \"en\";\n const txt = `[^${prefix_str}-${ev.id}]`;\n this._add_virtual_text(txt, current, paragraph);\n current += txt.length;\n } else if (ev.type === \"hyperlink_start\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n this._add_virtual_text(\"[\", current, paragraph, ev.id);\n current += 1;\n active_hyperlink_id = ev.id;\n } else if (ev.type === \"hyperlink_end\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const txt = `](${ev.date})`;\n this._add_virtual_text(txt, current, paragraph, ev.id);\n current += txt.length;\n active_hyperlink_id = null;\n } else if (ev.type === \"xref_start\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n this._add_virtual_text(\"[~\", current, paragraph);\n current += 2;\n } else if (ev.type === \"xref_end\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const txt = `~](#${ev.id})`;\n this._add_virtual_text(txt, current, paragraph);\n current += txt.length;\n } else if (ev.type === \"bookmark\") {\n flush_pending_runs();\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n const txt = `{#${ev.id}}`;\n this._add_virtual_text(txt, current, paragraph);\n current += txt.length;\n }\n }\n }\n\n flush_pending_runs();\n\n if (deferred_meta_states.length > 0) {\n const meta_block = this._build_merged_meta_block(deferred_meta_states);\n if (meta_block) {\n const full_meta = `{>>${meta_block}<<}`;\n this._add_virtual_text(full_meta, current, paragraph);\n current += full_meta.length;\n }\n }\n\n return current;\n }\n\n private _get_wrappers(\n ins_id: string | null,\n del_id: string | null,\n active_ids: Set<string>,\n active_fmt: Record<string, DocxEvent>,\n ): [string, string] {\n if (del_id) return [\"{--\", \"--}\"];\n if (ins_id) return [\"{++\", \"++}\"];\n if (active_ids.size > 0 || Object.keys(active_fmt).length > 0)\n return [\"{==\", \"==}\"];\n return [\"\", \"\"];\n }\n\n private _build_merged_meta_block(states_list: any[]): string {\n const change_lines: string[] = [];\n const comment_lines: string[] = [];\n const seen_sigs = new Set<string>();\n\n // Must render EXACTLY as ingest's _build_merged_meta_block (Virtual Text\n // contract), including the resolution-group annotation\n // (QA 2026-07-19 ADEU-QA-004).\n const pair_map = compute_change_pair_map(states_list);\n const pairSuffix = (uid: string): string =>\n pair_map[uid] ? ` (pairs with ${pair_map[uid]})` : \"\";\n\n for (const [ins_map, del_map, comments_set, fmt_map] of states_list) {\n for (const [uid, meta] of Object.entries(\n ins_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n const auth = meta.author || \"Unknown\";\n change_lines.push(`[${sig} insert] ${auth}${pairSuffix(uid)}`);\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n del_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n const auth = meta.author || \"Unknown\";\n change_lines.push(`[${sig} delete] ${auth}${pairSuffix(uid)}`);\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n fmt_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n const auth = meta.author || \"Unknown\";\n change_lines.push(`[${sig} format] ${auth}`);\n seen_sigs.add(sig);\n }\n }\n\n const sorted_ids = Array.from(comments_set as Set<string>).sort();\n for (const c_id of sorted_ids) {\n if (!this.comments_map[c_id]) continue;\n const sig = `Com:${c_id}`;\n if (!seen_sigs.has(sig)) {\n const data = this.comments_map[c_id];\n let header = `[${sig}] ${data.author}`;\n if (data.date) header += ` @ ${data.date}`;\n if (data.resolved) header += `(RESOLVED)`;\n comment_lines.push(`${header}: ${data.text}`);\n seen_sigs.add(sig);\n }\n }\n }\n\n return [...change_lines, ...comment_lines].join(\"\\n\");\n }\n\n private _add_virtual_text(\n text: string,\n offset: number,\n context_paragraph: Paragraph | null,\n hyperlink_id: string | null = null,\n is_image_marker = false,\n ) {\n const span: TextSpan = {\n start: offset,\n end: offset + text.length,\n text,\n run: null,\n paragraph: context_paragraph,\n hyperlink_id: hyperlink_id || undefined,\n part_index: this._current_part_index,\n is_image_marker: is_image_marker || undefined,\n };\n this.spans.push(span);\n this._text_chunks.push(text);\n }\n\n private _replace_smart_quotes(text: string): string {\n return text\n .replace(/“/g, '\"')\n .replace(/”/g, '\"')\n .replace(/‘/g, \"'\")\n .replace(/’/g, \"'\");\n }\n\n private _make_fuzzy_regex(target_text: string): string {\n target_text = this._strip_markdown_formatting(target_text);\n target_text = this._replace_smart_quotes(target_text);\n\n const parts: string[] = [];\n const token_pattern = /(\\[_+\\])|(\\s+)|(['\"])|([.,;:\\/\\-\\[\\](){}+=$?*!|#^<>\\\\%&@~`_])/g;\n\n let last_idx = 0;\n let match;\n const escapeRegExp = (str: string) =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n while ((match = token_pattern.exec(target_text)) !== null) {\n const literal = target_text.substring(last_idx, match.index);\n if (literal) parts.push(escapeRegExp(literal));\n\n const g_placeholder = match[1];\n const g_space = match[2];\n const g_quote = match[3];\n const g_punct = match[4];\n\n if (g_placeholder) {\n parts.push(\"\\\\[_+\\\\]\");\n } else if (g_space) {\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n parts.push(\"\\\\s+\");\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n } else if (g_quote) {\n if (g_quote === \"'\") parts.push(\"[\\u2018\\u2019']\");\n else parts.push('[\"\\u201c\\u201d]');\n } else if (g_punct) {\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n parts.push(escapeRegExp(g_punct));\n parts.push(\"(?:\\\\*\\\\*|__|\\\\*|_)?\");\n }\n\n last_idx = token_pattern.lastIndex;\n }\n\n const remaining = target_text.substring(last_idx);\n if (remaining) parts.push(escapeRegExp(remaining));\n\n return parts.join(\"\");\n }\n\n /**\n * Returns [plain_text, offset_map] where plain_text is full_text with the\n * VIRTUAL markdown style delimiters (bold/italic markers emitted around\n * formatted runs) removed, and offset_map[i] is the full_text index of\n * plain_text[i].\n *\n * Formatting run boundaries can fall mid-word (e.g. a paragraph projected\n * as \"**Al**pha\"), where neither exact matching nor the whitespace-anchored\n * fuzzy regex can find the plain target \"Alpha\". Matching against this\n * projection and mapping the span back to full_text closes that gap (QA H2).\n *\n * Built lazily and invalidated by _build_map(): most batches never need it.\n */\n private _get_plain_projection(): [string, number[]] {\n if (this._plain_projection === null) {\n const chunks: string[] = [];\n const offsets: number[] = [];\n for (const s of this.spans) {\n if (\n s.run === null &&\n s.paragraph !== null &&\n STYLE_MARKER_TEXTS.has(s.text)\n ) {\n continue;\n }\n chunks.push(s.text);\n for (let k = s.start; k < s.end; k++) offsets.push(k);\n }\n this._plain_projection = [chunks.join(\"\"), offsets];\n }\n return this._plain_projection;\n }\n\n /**\n * Matches a markdown-stripped target against the plain projection and maps\n * each hit back to a [start, length] span in full_text. Interior style\n * markers end up inside the returned span (so \"Alpha\" over \"**Al**pha\"\n * resolves to the \"Al**pha\" range); markers just outside the matched\n * characters are excluded.\n */\n private _find_plain_projection_matches(\n target_text: string,\n ): [number, number][] {\n const [plain_text, offsets] = this._get_plain_projection();\n if (plain_text.length === this.full_text.length) {\n return []; // No virtual style markers anywhere; nothing new to find.\n }\n const norm_target = this._replace_smart_quotes(\n this._strip_markdown_formatting(target_text),\n );\n if (!norm_target) return [];\n const norm_plain = this._replace_smart_quotes(plain_text);\n const results: [number, number][] = [];\n let from = 0;\n while (true) {\n const p_start = norm_plain.indexOf(norm_target, from);\n if (p_start === -1) break;\n const p_end = p_start + norm_target.length;\n const raw_start = offsets[p_start];\n const raw_end = offsets[p_end - 1] + 1;\n results.push([raw_start, raw_end - raw_start]);\n from = p_end;\n }\n return results;\n }\n\n /**\n * True when no run-backed span overlaps [start, start+length): the range\n * covers only virtual projection text — meta bubbles (change/comment\n * headers, timestamps), style markers, list prefixes. Such text does not\n * exist in the document, so it can neither satisfy a match nor count\n * toward ambiguity (QA 2026-07-19 ADEU-QA-002 C): an edit targeting \"4\"\n * used to be rejected as \"appears 8 times\" because a comment bubble's\n * timestamp matched.\n *\n * Anchor tokens ({#Bookmark}, {#cell:paraId}) are the exception: they are\n * deliberate virtual TARGETING surfaces (empty-cell writes, bookmark\n * anchors) and must stay matchable.\n */\n public range_is_virtual_only(start: number, length: number): boolean {\n const end = start + length;\n const overlapping = this.spans.filter(\n (s) => s.end > start && s.start < end,\n );\n if (overlapping.some((s) => s.run !== null)) return false;\n return !overlapping.some(\n (s) => s.run === null && s.text.startsWith(\"{#\"),\n );\n }\n\n /** Filters find_all_match_indices output down to matches that touch at\n * least one run-backed span. See range_is_virtual_only. */\n public drop_virtual_only_matches(\n matches: [number, number][],\n ): [number, number][] {\n return matches.filter(\n ([start, length]) => !this.range_is_virtual_only(start, length),\n );\n }\n\n public find_match_index(\n target_text: string,\n is_regex: boolean = false,\n ): [number, number] {\n if (is_regex) {\n // User/LLM-supplied pattern: run it under a wall-clock budget so a\n // catastrophic pattern cannot hang the event loop (QA 2026-07-17 F5).\n // RegexTimeoutError propagates for a clean per-edit error; only\n // invalid-pattern errors mean \"no match\" here.\n try {\n const match = userSearch(target_text, this.full_text);\n if (\n match &&\n !this.range_is_virtual_only(match.start, match.end - match.start)\n ) {\n return [match.start, match.end - match.start];\n }\n } catch (e) {\n if (e instanceof RegexTimeoutError) throw e;\n }\n return [-1, 0];\n }\n\n // Exact tier: skip occurrences that cover only virtual projection text\n // (meta bubbles, markers) — they are not document text (ADEU-QA-002 C).\n let from = 0;\n while (true) {\n const idx = this.full_text.indexOf(target_text, from);\n if (idx === -1) break;\n if (!this.range_is_virtual_only(idx, target_text.length)) {\n return [idx, target_text.length];\n }\n from = idx + 1;\n }\n\n const norm_full = this._replace_smart_quotes(this.full_text);\n const norm_target = this._replace_smart_quotes(target_text);\n let start_idx = norm_full.indexOf(norm_target);\n if (start_idx !== -1) return [start_idx, target_text.length];\n\n const stripped_target = this._strip_markdown_formatting(target_text);\n if (this.full_text.includes(stripped_target)) {\n start_idx = this.full_text.indexOf(stripped_target);\n return [start_idx, stripped_target.length];\n }\n\n // 3.5 Plain-projection match: the target crosses a formatting run\n // boundary (possibly mid-word), so the projection carries style markers\n // the plain target doesn't have (QA H2).\n const plain_first = this._find_plain_projection_matches(target_text);\n if (plain_first.length > 0) return plain_first[0];\n\n try {\n const pattern = new RegExp(this._make_fuzzy_regex(target_text), \"g\");\n for (const match of this.full_text.matchAll(pattern)) {\n // Virtual-only ranges are projection chrome, not document text.\n if (!this.range_is_virtual_only(match.index!, match[0].length)) {\n return [match.index!, match[0].length];\n }\n }\n } catch (e) {}\n\n return [-1, 0];\n }\n\n public find_all_match_indices(\n target_text: string,\n is_regex: boolean = false,\n ): [number, number][] {\n if (!target_text) return [];\n\n if (is_regex) {\n // Budgeted like find_match_index above (QA 2026-07-17 F5).\n try {\n const matches = userFindAllMatches(target_text, this.full_text);\n if (matches.length > 0) return matches.map((m) => [m.start, m.end - m.start]);\n } catch (e) {\n if (e instanceof RegexTimeoutError) throw e;\n }\n return [];\n }\n // Exact tiers use plain indexOf scans, NOT RegExp: building a RegExp from\n // an arbitrarily long escaped target throws \"regular expression too\n // large\" for oversized inputs, crashing validation instead of returning\n // a clean not-found (QA C2 hardening).\n const findAllLiteral = (\n haystack: string,\n needle: string,\n ): [number, number][] => {\n const out: [number, number][] = [];\n if (!needle) return out;\n let from = 0;\n while (true) {\n const idx = haystack.indexOf(needle, from);\n if (idx === -1) break;\n out.push([idx, needle.length]);\n from = idx + needle.length;\n }\n return out;\n };\n\n let matches = findAllLiteral(this.full_text, target_text);\n if (matches.length > 0) return matches;\n\n const norm_full = this._replace_smart_quotes(this.full_text);\n const norm_target = this._replace_smart_quotes(target_text);\n matches = findAllLiteral(norm_full, norm_target);\n if (matches.length > 0) return matches;\n\n const stripped_target = this._strip_markdown_formatting(target_text);\n matches = findAllLiteral(this.full_text, stripped_target);\n if (matches.length > 0) return matches;\n\n // 3.5 Plain-projection match (target spans a bold/italic run boundary,\n // possibly mid-word). See _find_plain_projection_matches (QA H2).\n const plain_matches = this._find_plain_projection_matches(target_text);\n if (plain_matches.length > 0) return plain_matches;\n\n try {\n const pattern = new RegExp(this._make_fuzzy_regex(target_text), \"g\");\n const fuzzy = [...this.full_text.matchAll(pattern)];\n if (fuzzy.length > 0) return fuzzy.map((m) => [m.index!, m[0].length]);\n } catch (e) {}\n\n return [];\n }\n\n public find_target_runs(target_text: string): Run[] {\n const [start_idx, length] = this.find_match_index(target_text);\n if (start_idx === -1) return [];\n return this._resolve_runs_at_range(start_idx, start_idx + length);\n }\n\n public find_target_runs_by_index(\n start_index: number,\n length: number,\n rebuild_map = true,\n ): Run[] {\n return this._resolve_runs_at_range(\n start_index,\n start_index + length,\n rebuild_map,\n );\n }\n\n public get_virtual_spans_in_range(\n start_index: number,\n length: number,\n ): TextSpan[] {\n const end_index = start_index + length;\n return this.spans.filter(\n (s) =>\n s.run === null &&\n s.text === \"\\n\\n\" &&\n s.start >= start_index &&\n s.end <= end_index,\n );\n }\n\n private _resolve_runs_at_range(\n start_idx: number,\n end_idx: number,\n rebuild_map = true,\n ): Run[] {\n const affected_spans = this.spans.filter(\n (s) => s.end > start_idx && s.start < end_idx,\n );\n if (affected_spans.length === 0) return [];\n\n const real_spans = affected_spans.filter((s) => s.run !== null);\n if (real_spans.length === 0) return [];\n\n // One run may back several spans (boundary whitespace hoisted outside\n // style markers projects a run as lead/core/trail spans, QA 2026-07-19\n // F-03): deduplicate by identity or the run would be split and wrapped\n // once per span.\n const working_runs: Run[] = [];\n for (const s of real_spans) {\n if (!working_runs.some((r) => r === s.run)) {\n working_runs.push(s.run!);\n }\n }\n\n let dom_modified = false;\n\n // 1. Start Split — all local offsets are run-relative: span-relative\n // position plus the span's own offset within the run.\n const first_real_span = real_spans[0];\n let start_split_adjustment = 0;\n\n // A range may START on a virtual span (word-diff hunks absorb a style\n // marker adjacent to real changes, e.g. the `**` closing a bold run).\n // Virtual characters have no physical width: clamp to the first real\n // span's start or the subtraction goes negative and the split point\n // lands INSIDE the preceding run's kept text — the \"**The Suppli**\"\n // partial-word artifact (QA 2026-07-19 v8 F-04).\n const local_start =\n Math.max(start_idx, first_real_span.start) -\n first_real_span.start +\n (first_real_span.run_offset || 0);\n if (local_start > 0) {\n const split_source = working_runs[0];\n const [, right_run] = this._split_run_at_index(\n split_source,\n local_start,\n );\n for (let w = 0; w < working_runs.length; w++) {\n if (working_runs[w] === split_source) working_runs[w] = right_run;\n }\n dom_modified = true;\n start_split_adjustment = local_start;\n }\n\n // 2. End Split\n const last_real_span = real_spans[real_spans.length - 1];\n const is_same_run = first_real_span.run === last_real_span.run;\n const run_to_split = working_runs[working_runs.length - 1];\n const overlap_end = Math.min(last_real_span.end, end_idx);\n let local_end =\n overlap_end - last_real_span.start + (last_real_span.run_offset || 0);\n\n if (is_same_run && start_split_adjustment > 0) {\n local_end -= start_split_adjustment;\n }\n\n const run_text = get_run_text(run_to_split);\n if (local_end > 0 && local_end < run_text.length) {\n const [left_run] = this._split_run_at_index(run_to_split, local_end);\n working_runs[working_runs.length - 1] = left_run;\n dom_modified = true;\n }\n\n if (dom_modified && rebuild_map) {\n this._build_map();\n }\n\n return working_runs;\n }\n\n public get_insertion_anchor(\n index: number,\n rebuild_map = true,\n ): [Run | null, Paragraph | null] {\n const preceding = this.spans.filter((s) => s.end === index);\n if (preceding.length > 0) {\n for (let i = preceding.length - 1; i >= 0; i--) {\n if (preceding[i].run) return [preceding[i].run, preceding[i].paragraph];\n }\n for (let i = preceding.length - 1; i >= 0; i--) {\n const para = preceding[i].paragraph;\n if (para) {\n // Every span ending exactly here is virtual (CriticMarkup\n // wrappers, {>>...<<} meta blocks, prefixes). If real text\n // precedes this index in the SAME paragraph, anchor after its\n // last run: falling back to the bare paragraph would drop the\n // insertion at paragraph start, ahead of the very redlines and\n // comment ranges that fence off the true position (mirrors the\n // Python mapper).\n for (let j = this.spans.length - 1; j >= 0; j--) {\n const prev = this.spans[j];\n if (\n prev.end <= index &&\n prev.run !== null &&\n prev.paragraph === para\n ) {\n return [prev.run, prev.paragraph];\n }\n }\n return [null, para];\n }\n }\n }\n\n const containing = this.spans.filter(\n (s) => s.start < index && index < s.end,\n );\n if (containing.length > 0) {\n const span = containing[0];\n if (span.run === null) {\n if (span.paragraph === null) {\n return this.get_insertion_anchor(span.end, rebuild_map);\n }\n return [null, span.paragraph];\n } else {\n const offset = index - span.start + (span.run_offset || 0);\n const [left] = this._split_run_at_index(span.run, offset);\n if (rebuild_map) this._build_map();\n return [left, span.paragraph];\n }\n }\n\n if (index === 0 && this.spans.length > 0) {\n for (const s of this.spans) if (s.run) return [s.run, s.paragraph];\n for (const s of this.spans) if (s.paragraph) return [null, s.paragraph];\n return [null, null];\n }\n\n const preceding_gap = this.spans.filter((s) => s.end < index);\n if (preceding_gap.length > 0) {\n for (let i = preceding_gap.length - 1; i >= 0; i--) {\n if (preceding_gap[i].run)\n return [preceding_gap[i].run, preceding_gap[i].paragraph];\n }\n for (let i = preceding_gap.length - 1; i >= 0; i--) {\n if (preceding_gap[i].paragraph)\n return [null, preceding_gap[i].paragraph];\n }\n }\n\n return [null, null];\n }\n\n private _split_run_at_index(run: Run, split_index: number): [Run, Run] {\n const text = get_run_text(run);\n const left_text = text.substring(0, split_index);\n const right_text = text.substring(split_index);\n\n this._set_run_text_elements(run._element, left_text);\n\n const new_r_element = run._element.cloneNode(true) as Element;\n this._set_run_text_elements(new_r_element, right_text);\n\n if (run._element.parentNode) {\n run._element.parentNode.insertBefore(\n new_r_element,\n run._element.nextSibling,\n );\n }\n\n const new_run = new Run(new_r_element, run._parent);\n return [run, new_run];\n }\n\n private _set_run_text_elements(r_element: Element, new_text: string) {\n const to_remove: Element[] = [];\n for (let i = 0; i < r_element.childNodes.length; i++) {\n const child = r_element.childNodes[i] as Element;\n if (\n child.nodeType === 1 &&\n [\"w:t\", \"w:delText\", \"w:br\", \"w:cr\", \"w:tab\"].includes(child.tagName)\n ) {\n to_remove.push(child);\n }\n }\n for (const child of to_remove) {\n r_element.removeChild(child);\n }\n\n const doc = r_element.ownerDocument;\n if (doc) {\n const new_t = doc.createElement(\"w:t\");\n new_t.textContent = new_text;\n if (new_text.trim() !== new_text) {\n new_t.setAttribute(\"xml:space\", \"preserve\");\n }\n r_element.appendChild(new_t);\n }\n }\n\n public get_context_at_range(\n start_idx: number,\n end_idx: number,\n ): TextSpan | null {\n const real_spans = this.spans.filter(\n (s) => s.run && s.end > start_idx && s.start < end_idx,\n );\n if (real_spans.length > 0) return real_spans[0];\n return null;\n }\n}\n","import { unzipSync } from \"fflate\";\nimport diff_match_patch from \"diff-match-patch\";\nimport { DeleteTableRow, InsertTableRow, ModifyText } from \"./models.js\";\nimport type {\n ExtractStructure,\n RowGeometry,\n TableGeometry,\n} from \"./ingest.js\";\n\nexport type DiffEdit = ModifyText | InsertTableRow | DeleteTableRow;\n\nfunction _count_standalone_underscores(s: string): number {\n let count = 0;\n let i = 0;\n const n = s.length;\n const isAlnum = (char: string) => /[a-zA-Z0-9]/.test(char);\n while (i < n) {\n if (s[i] === \"_\") {\n // Is it part of \"__\"?\n let is_double = false;\n if ((i > 0 && s[i - 1] === \"_\") || (i < n - 1 && s[i + 1] === \"_\")) {\n is_double = true;\n }\n\n // Is it intra-word?\n let is_intra = false;\n if (i > 0 && isAlnum(s[i - 1]) && i < n - 1 && isAlnum(s[i + 1])) {\n is_intra = true;\n }\n\n if (!is_double && !is_intra) {\n count++;\n }\n }\n i++;\n }\n return count;\n}\n\nexport function trim_common_context(\n target: string,\n new_val: string,\n): [number, number] {\n if (!target || !new_val) return [0, 0];\n\n const isSpace = (char: string) => /\\s/.test(char);\n\n // 1. Prefix with Word Boundary Check\n let prefix_len = 0;\n let limit = Math.min(target.length, new_val.length);\n while (prefix_len < limit && target[prefix_len] === new_val[prefix_len]) {\n prefix_len++;\n }\n\n // Backtrack to nearest whitespace if we split a word\n if (prefix_len < target.length && prefix_len < new_val.length) {\n while (prefix_len > 0) {\n const target_split =\n !isSpace(target[prefix_len - 1]) && !isSpace(target[prefix_len]);\n const new_split =\n !isSpace(new_val[prefix_len - 1]) && !isSpace(new_val[prefix_len]);\n if (target_split || new_split) {\n prefix_len--;\n } else {\n break;\n }\n }\n }\n\n // Backtrack prefix to avoid splitting markdown markers\n while (prefix_len > 0) {\n if (prefix_len < target.length) {\n const charSeq = target.substring(prefix_len - 1, prefix_len + 1);\n if (charSeq === \"**\" || charSeq === \"__\") {\n prefix_len--;\n continue;\n }\n }\n\n const left = target.substring(0, prefix_len);\n const b_count = (left.match(/\\*\\*/g) || []).length;\n const u2_count = (left.match(/__/g) || []).length;\n const u1_count = _count_standalone_underscores(left);\n\n if (b_count % 2 !== 0) {\n prefix_len = left.lastIndexOf(\"**\");\n continue;\n }\n if (u2_count % 2 !== 0) {\n prefix_len = left.lastIndexOf(\"__\");\n continue;\n }\n if (u1_count % 2 !== 0) {\n let idx = left.length - 1;\n const isAlnum = (char: string) => /[a-zA-Z0-9]/.test(char);\n while (idx >= 0) {\n if (\n left[idx] === \"_\" &&\n (idx === 0 || left[idx - 1] !== \"_\") &&\n (idx === left.length - 1 || left[idx + 1] !== \"_\")\n ) {\n const is_intra = idx > 0 && isAlnum(left[idx - 1]) && idx < left.length - 1 && isAlnum(left[idx + 1]);\n if (!is_intra) {\n prefix_len = idx;\n break;\n }\n }\n idx--;\n }\n continue;\n }\n\n // Safety: Backtrack if we consumed a Markdown Header marker (#)\n let temp_len = prefix_len;\n let hit_header = false;\n while (temp_len > 0) {\n const char = target[temp_len - 1];\n if (char === \"#\") {\n prefix_len = temp_len - 1;\n while (prefix_len > 0 && target[prefix_len - 1] !== \"\\n\") {\n prefix_len--;\n }\n hit_header = true;\n break;\n }\n if (char === \"\\n\") break;\n temp_len--;\n }\n if (hit_header) continue;\n\n break;\n }\n\n // 2. Suffix with Word Boundary Check\n let suffix_len = 0;\n const target_rem_len = target.length - prefix_len;\n const new_rem_len = new_val.length - prefix_len;\n const limit_suffix = Math.min(target_rem_len, new_rem_len);\n\n while (\n suffix_len < limit_suffix &&\n target[target.length - 1 - suffix_len] ===\n new_val[new_val.length - 1 - suffix_len]\n ) {\n suffix_len++;\n }\n\n if (suffix_len > 0) {\n while (suffix_len > 0) {\n let target_split = false;\n if (suffix_len < target.length) {\n target_split =\n !isSpace(target[target.length - 1 - suffix_len]) &&\n !isSpace(target[target.length - suffix_len]);\n }\n let new_split = false;\n if (suffix_len < new_val.length) {\n new_split =\n !isSpace(new_val[new_val.length - 1 - suffix_len]) &&\n !isSpace(new_val[new_val.length - suffix_len]);\n }\n if (target_split || new_split) {\n suffix_len--;\n } else {\n break;\n }\n }\n }\n\n while (suffix_len > 0) {\n const idx = target.length - suffix_len;\n if (idx > 0) {\n const charSeq = target.substring(idx - 1, idx + 1);\n if (charSeq === \"**\" || charSeq === \"__\") {\n suffix_len--;\n continue;\n }\n }\n\n const right = target.substring(target.length - suffix_len);\n const b_count = (right.match(/\\*\\*/g) || []).length;\n const u2_count = (right.match(/__/g) || []).length;\n const u1_count = _count_standalone_underscores(right);\n\n if (b_count % 2 !== 0) {\n suffix_len -= right.indexOf(\"**\") + 2;\n continue;\n }\n if (u2_count % 2 !== 0) {\n suffix_len -= right.indexOf(\"__\") + 2;\n continue;\n }\n if (u1_count % 2 !== 0) {\n let idx_in_right = 0;\n const isAlnum = (char: string) => /[a-zA-Z0-9]/.test(char);\n while (idx_in_right < right.length) {\n if (\n right[idx_in_right] === \"_\" &&\n (idx_in_right === 0 || right[idx_in_right - 1] !== \"_\") &&\n (idx_in_right === right.length - 1 || right[idx_in_right + 1] !== \"_\")\n ) {\n const is_intra = idx_in_right > 0 && isAlnum(right[idx_in_right - 1]) && idx_in_right < right.length - 1 && isAlnum(right[idx_in_right + 1]);\n if (!is_intra) {\n suffix_len -= idx_in_right + 1;\n break;\n }\n }\n idx_in_right++;\n }\n continue;\n }\n break;\n }\n\n if (\n suffix_len > 0 &&\n /^\\s+$/.test(target.substring(target.length - suffix_len))\n ) {\n suffix_len = 0;\n }\n\n // Absorb balanced wrappers\n for (const marker of [\"**\", \"__\", \"_\"]) {\n const mlen = marker.length;\n const tgt_rem = target.substring(prefix_len, target.length - suffix_len);\n const new_rem = new_val.substring(prefix_len, new_val.length - suffix_len);\n\n if (\n tgt_rem.startsWith(marker) &&\n new_rem.startsWith(marker) &&\n tgt_rem.endsWith(marker) &&\n new_rem.endsWith(marker) &&\n tgt_rem.length >= 2 * mlen &&\n new_rem.length >= 2 * mlen\n ) {\n prefix_len += mlen;\n suffix_len += mlen;\n }\n }\n\n return [prefix_len, suffix_len];\n}\n\nfunction _words_to_chars(\n text1: string,\n text2: string,\n): [string, string, string[]] {\n const token_array: string[] = [];\n const token_hash: Record<string, number> = {};\n\n // RegExp equivalent to Python's r\"(\\s+|\\w+|[^\\w\\s])\" with unicode support\n const split_pattern = /(\\s+|[\\p{L}\\p{N}_]+|[^\\p{L}\\p{N}_\\s])/gu;\n\n const encode_text = (text: string) => {\n // Keep delimiters via capture group in split\n const tokens = text.split(split_pattern).filter(Boolean);\n let encoded_chars = \"\";\n for (const token of tokens) {\n if (token in token_hash) {\n encoded_chars += String.fromCharCode(token_hash[token]);\n } else {\n const code = token_array.length;\n token_hash[token] = code;\n token_array.push(token);\n encoded_chars += String.fromCharCode(code);\n }\n }\n return encoded_chars;\n };\n\n return [encode_text(text1), encode_text(text2), token_array];\n}\n\nexport function generate_edits_from_text(\n original_text: string,\n modified_text: string,\n): ModifyText[] {\n const dmp = new diff_match_patch.diff_match_patch();\n dmp.Diff_Timeout = 2.0; // Enforce strict 2-second timeout to prevent deep recursion hangs\n\n const [chars1, chars2, token_array] = _words_to_chars(\n original_text,\n modified_text,\n );\n const diffs = dmp.diff_main(chars1, chars2, false);\n dmp.diff_cleanupSemantic(diffs);\n\n // Manually map characters back to words to bypass prototype volatility (diff_charsToLines_)\n for (let i = 0; i < diffs.length; i++) {\n const chars = diffs[i][1];\n let text = \"\";\n for (let j = 0; j < chars.length; j++)\n text += token_array[chars.charCodeAt(j)];\n diffs[i][1] = text;\n }\n\n const edits: ModifyText[] = [];\n let current_original_index = 0;\n let pending_delete: [number, string] | null = null;\n\n for (const [op, text] of diffs) {\n if (op === 0) {\n // Equal\n if (pending_delete) {\n const [idx, del_txt] = pending_delete;\n edits.push({\n type: \"modify\",\n target_text: del_txt,\n new_text: \"\",\n comment: \"Diff: Text deleted\",\n _match_start_index: idx,\n });\n pending_delete = null;\n }\n current_original_index += text.length;\n } else if (op === -1) {\n // Delete\n pending_delete = [current_original_index, text];\n current_original_index += text.length;\n } else if (op === 1) {\n // Insert\n if (pending_delete) {\n const [idx, del_txt] = pending_delete;\n edits.push({\n type: \"modify\",\n target_text: del_txt,\n new_text: text,\n comment: \"Diff: Replacement\",\n _match_start_index: idx,\n });\n pending_delete = null;\n } else {\n edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: text,\n comment: \"Diff: Text inserted\",\n _match_start_index: current_original_index,\n });\n }\n }\n }\n\n if (pending_delete) {\n const [idx, del_txt] = pending_delete;\n edits.push({\n type: \"modify\",\n target_text: del_txt,\n new_text: \"\",\n comment: \"Diff: Text deleted\",\n _match_start_index: idx,\n });\n }\n\n return edits;\n}\n// ---------------------------------------------------------------------------\n// Structured (part- and table-aware) diff — QA 2026-07-18 C1/C2.\n// ---------------------------------------------------------------------------\n\ntype Opcode = [\n tag: \"equal\" | \"replace\" | \"delete\" | \"insert\",\n i1: number,\n i2: number,\n j1: number,\n j2: number,\n];\n\n/**\n * difflib.SequenceMatcher.get_opcodes() equivalent over string arrays,\n * LCS-based. The row-key arrays this runs on are tiny (table row counts), so\n * the O(n*m) table is negligible. Adjacent non-equal steps coalesce into one\n * \"replace\"/\"delete\"/\"insert\" block exactly like difflib's opcodes.\n */\nfunction _sequence_opcodes(a: string[], b: string[]): Opcode[] {\n const n = a.length;\n const m = b.length;\n // dp[i][j] = LCS length of a[i:] vs b[j:]\n const dp: Int32Array[] = [];\n for (let i = 0; i <= n; i++) dp.push(new Int32Array(m + 1));\n for (let i = n - 1; i >= 0; i--) {\n for (let j = m - 1; j >= 0; j--) {\n dp[i][j] =\n a[i] === b[j]\n ? dp[i + 1][j + 1] + 1\n : Math.max(dp[i + 1][j], dp[i][j + 1]);\n }\n }\n\n const ops: Opcode[] = [];\n let i = 0;\n let j = 0;\n let pend_i1 = 0;\n let pend_j1 = 0;\n let pend_del = 0;\n let pend_ins = 0;\n\n const flushPending = () => {\n if (pend_del === 0 && pend_ins === 0) return;\n const tag =\n pend_del > 0 && pend_ins > 0\n ? \"replace\"\n : pend_del > 0\n ? \"delete\"\n : \"insert\";\n ops.push([tag, pend_i1, pend_i1 + pend_del, pend_j1, pend_j1 + pend_ins]);\n pend_del = 0;\n pend_ins = 0;\n };\n\n while (i < n || j < m) {\n if (i < n && j < m && a[i] === b[j]) {\n flushPending();\n const i1 = i;\n const j1 = j;\n while (i < n && j < m && a[i] === b[j]) {\n i++;\n j++;\n }\n ops.push([\"equal\", i1, i, j1, j]);\n } else {\n if (pend_del === 0 && pend_ins === 0) {\n pend_i1 = i;\n pend_j1 = j;\n }\n if (j < m && (i === n || dp[i][j + 1] >= dp[i + 1][j])) {\n pend_ins++;\n j++;\n } else {\n pend_del++;\n i++;\n }\n }\n }\n flushPending();\n return ops;\n}\n\n/**\n * True when a \"\\n\\n\"-separated block reads as projected table rows: every\n * line carries the \" | \" cell separator. Table rows are separated by single\n * newlines, so a whole table is one block in the paragraph alignment.\n */\nfunction _is_table_blob(block: string): boolean {\n const lines = block.split(\"\\n\");\n return lines.length > 0 && lines.every((line) => line.includes(\" | \"));\n}\n\n/**\n * Pairwise row-level edits between two aligned table blobs, or null when the\n * blobs cannot be row-aligned (different row counts — a structural change the\n * text path hands to the engine's row guards). Row edits are unpinned: the\n * full row text is the anchor, and the engine's per-cell splitter resolves\n * them — word-level hunks across \" | \" separators land in the wrong cell.\n */\nfunction _table_blob_row_edits(\n orig_blob: string,\n mod_blob: string,\n): ModifyText[] | null {\n const rows_o = orig_blob.split(\"\\n\");\n const rows_m = mod_blob.split(\"\\n\");\n if (rows_o.length !== rows_m.length) return null;\n const row_edits: ModifyText[] = [];\n for (let k = 0; k < rows_o.length; k++) {\n if (rows_o[k] === rows_m[k]) continue;\n row_edits.push({\n type: \"modify\",\n target_text: rows_o[k],\n new_text: rows_m[k],\n comment: \"Diff: Table row modified\",\n _is_table_edit: true,\n });\n }\n return row_edits;\n}\n\n/**\n * Splits generated hunks the engine would reject: an UNBALANCED target\n * spanning a paragraph break with body text on both sides (\"tail of A\\n\\n\n * head of B\" — the shape dmp produces when adjacent paragraphs share a\n * prefix). Each leading paragraph piece becomes its own separator-carrying\n * deletion (an allowed merge shape) and the final piece carries the whole\n * replacement text; sequential application produces the identical merged\n * result. Without this, one such hunk poisons the entire batch — apply is\n * all-or-nothing (QA 2026-07-19 ADEU-QA-002 A).\n */\nfunction _split_cross_paragraph_hunks(edits: ModifyText[]): ModifyText[] {\n const out: ModifyText[] = [];\n for (const e of edits) {\n const target = e.target_text || \"\";\n const newText = e.new_text || \"\";\n const idx = e._match_start_index;\n if (\n idx === undefined ||\n idx === null ||\n !target.includes(\"\\n\\n\") ||\n target.split(\"\\n\\n\").length - 1 === newText.split(\"\\n\\n\").length - 1\n ) {\n out.push(e);\n continue;\n }\n const parts = target.split(\"\\n\\n\");\n if (parts.length < 2 || !parts[0].trim() || !parts[parts.length - 1].trim()) {\n // One-sided shapes (separator-carrying deletions/insertions) are the\n // engine's supported merge protocol — leave them intact.\n out.push(e);\n continue;\n }\n let offset = idx;\n for (const piece of parts.slice(0, -1)) {\n out.push({\n type: \"modify\",\n target_text: piece + \"\\n\\n\",\n new_text: \"\",\n comment: e.comment || \"Diff: Text deleted\",\n _match_start_index: offset,\n });\n offset += piece.length + 2;\n }\n out.push({\n type: \"modify\",\n target_text: parts[parts.length - 1],\n new_text: newText,\n comment: e.comment,\n _match_start_index: offset,\n });\n }\n return out;\n}\n\n/**\n * Aligns original and modified text by paragraph (using the difflib-style\n * opcodes), then performs precise word-level diffing on replaced blocks.\n * Whole-paragraph structural changes come out as engine-applicable shapes:\n * a deleted paragraph is ONE deletion per paragraph carrying its \"\\n\\n\"\n * separator, an inserted paragraph carries its separator — a raw word-level\n * diff instead legally shifts hunk boundaries across paragraphs sharing a\n * prefix (\"...arrears.\\n\\nThe \"), which the engine rightly rejects; every\n * paragraph deletion/reordering in the QA corpus failed replay that way\n * (QA 2026-07-19 ADEU-QA-002 A). Mirrors the Python engine's\n * generate_edits_via_paragraph_alignment.\n */\nexport function generate_edits_via_paragraph_alignment(\n original_text: string,\n modified_text: string,\n): ModifyText[] {\n // Normalize trailing whitespace/newlines in modified_text to match original_text\n const orig_stripped = original_text.trimEnd();\n const orig_ws = original_text.slice(orig_stripped.length);\n const mod_stripped = modified_text.trimEnd();\n modified_text = mod_stripped + orig_ws;\n\n const orig_paragraphs = original_text.split(\"\\n\\n\");\n const mod_paragraphs = modified_text.split(\"\\n\\n\");\n\n const orig_offsets: number[] = [];\n let current_offset = 0;\n for (const p of orig_paragraphs) {\n orig_offsets.push(current_offset);\n current_offset += p.length + 2;\n }\n\n const opcodes = _sequence_opcodes(orig_paragraphs, mod_paragraphs);\n const edits: ModifyText[] = [];\n\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (tag === \"equal\") continue;\n\n const offset =\n i1 < orig_offsets.length ? orig_offsets[i1] : original_text.length;\n\n if (tag === \"delete\") {\n // Multi-paragraph mid-document blocks are emitted as ONE deletion PER\n // paragraph (\"A\\n\\n\", \"B\\n\\n\"), never \"A\\n\\nB\\n\\n\": the engine's merge\n // protocol supports one deleted paragraph break per edit\n // (QA 2026-07-19 ADEU-QA-002 A). The document's trailing block takes\n // the LEADING separator instead (QA 2026-07-19 v8 F-12 fallout).\n if (i2 < orig_paragraphs.length) {\n let piece_offset = offset;\n for (let k = i1; k < i2; k++) {\n const piece = orig_paragraphs[k] + \"\\n\\n\";\n edits.push({\n type: \"modify\",\n target_text: piece,\n new_text: \"\",\n comment: \"Diff: Text deleted\",\n _match_start_index: piece_offset,\n });\n piece_offset += piece.length;\n }\n } else {\n let deleted_text = orig_paragraphs.slice(i1, i2).join(\"\\n\\n\");\n let del_offset = offset;\n if (i1 > 0) {\n deleted_text = \"\\n\\n\" + deleted_text;\n del_offset -= 2;\n }\n edits.push({\n type: \"modify\",\n target_text: deleted_text,\n new_text: \"\",\n comment: \"Diff: Text deleted\",\n _match_start_index: del_offset,\n });\n }\n } else if (tag === \"insert\") {\n // An inserted paragraph must CARRY its paragraph separator, or the\n // engine (rightly) treats the text as an inline insertion and glues it\n // to the neighboring paragraph (QA 2026-07-18 v6 H2).\n let inserted_text = mod_paragraphs.slice(j1, j2).join(\"\\n\\n\");\n if (i1 < orig_paragraphs.length) {\n inserted_text = inserted_text + \"\\n\\n\";\n } else {\n inserted_text = \"\\n\\n\" + inserted_text;\n }\n edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: inserted_text,\n comment: \"Diff: Text inserted\",\n _match_start_index: offset,\n });\n } else if (tag === \"replace\") {\n // Table blobs in equal-count replace blocks pair up positionally and\n // diff as ROW-LEVEL edits; word-level hunks over a table blob start or\n // end inside \" | \" separators and land in the wrong cell. Prose pairs\n // (and any block whose counts differ) keep the word-level chunk diff.\n if (\n i2 - i1 === j2 - j1 &&\n Array.from({ length: i2 - i1 }).some(\n (_, k) =>\n _is_table_blob(orig_paragraphs[i1 + k]) ||\n _is_table_blob(mod_paragraphs[j1 + k]),\n )\n ) {\n for (let k = 0; k < i2 - i1; k++) {\n const orig_p = orig_paragraphs[i1 + k];\n const mod_p = mod_paragraphs[j1 + k];\n if (orig_p === mod_p) continue;\n const pair_offset = orig_offsets[i1 + k];\n const row_edits =\n _is_table_blob(orig_p) && _is_table_blob(mod_p)\n ? _table_blob_row_edits(orig_p, mod_p)\n : null;\n if (row_edits !== null) {\n edits.push(...row_edits);\n continue;\n }\n const pair_edits = generate_edits_from_text(orig_p, mod_p);\n for (const ce of pair_edits) {\n ce._match_start_index = (ce._match_start_index || 0) + pair_offset;\n edits.push(ce);\n }\n }\n continue;\n }\n\n const orig_chunk = orig_paragraphs.slice(i1, i2).join(\"\\n\\n\");\n const mod_chunk = mod_paragraphs.slice(j1, j2).join(\"\\n\\n\");\n const chunk_edits = generate_edits_from_text(orig_chunk, mod_chunk);\n for (const ce of chunk_edits) {\n ce._match_start_index = (ce._match_start_index || 0) + offset;\n edits.push(ce);\n }\n }\n }\n\n // Word-level diffs over unequal replace chunks can still emit hunks that\n // straddle a paragraph break with body text on both sides; split them into\n // engine-applicable pieces (ADEU-QA-002 A).\n return _split_cross_paragraph_hunks(edits);\n}\n\nconst _IMAGE_MARKER_RE = /!\\[[^\\]]*\\]\\(docx-image:[^)]*\\)/g;\n\n/**\n * Removes generated edits whose image-marker multisets differ between\n * target and new text. The engine (validate_edit_strings) rightly refuses\n * such edits — markers are read-only projections — so emitting them would\n * make the diff pipeline reject its own output. An added/removed image is\n * reported as a warning instead of an unappliable edit.\n */\nfunction _drop_image_marker_hunks(\n edits: ModifyText[],\n warnings: string[],\n): ModifyText[] {\n const _normalized = (s: string): string =>\n s.replace(_IMAGE_MARKER_RE, \"\").replace(/\\s+/g, \" \").trim();\n\n const kept: ModifyText[] = [];\n for (const e of edits) {\n const t_imgs = ((e.target_text || \"\").match(_IMAGE_MARKER_RE) || []).sort();\n const n_imgs = ((e.new_text || \"\").match(_IMAGE_MARKER_RE) || []).sort();\n if (JSON.stringify(t_imgs) === JSON.stringify(n_imgs)) {\n kept.push(e);\n continue;\n }\n if (_normalized(e.target_text || \"\") === _normalized(e.new_text || \"\")) {\n warnings.push(\n \"An inline image was added or removed between the documents. Images cannot be \" +\n \"transferred by text edits — the image-only difference was skipped; apply it \" +\n \"manually in Word.\",\n );\n } else {\n warnings.push(\n \"A text change overlapping an added/removed inline image was skipped — images \" +\n \"cannot be transferred by text edits. Apply that section manually in Word.\",\n );\n }\n }\n return kept;\n}\n\n/**\n * Removes generated hunks whose pinned range cuts INTO a read-only image\n * marker without covering it whole — the shape an alt-text-only difference\n * produces (`RED` -> `BLUE` inside ``). The engine\n * categorically rejects such edits, so emitting them makes diff output\n * unappliable by apply (QA 2026-07-19 F-04/F-14). Hunks that contain\n * complete markers are judged by _drop_image_marker_hunks instead.\n */\nfunction _drop_marker_interior_hunks(\n edits: ModifyText[],\n text_orig: string,\n warnings: string[],\n): ModifyText[] {\n const marker_spans: [number, number][] = [];\n for (const m of text_orig.matchAll(_IMAGE_MARKER_RE)) {\n marker_spans.push([m.index!, m.index! + m[0].length]);\n }\n if (marker_spans.length === 0) return edits;\n\n const kept: ModifyText[] = [];\n let warned = false;\n for (const e of edits) {\n const idx = e._match_start_index;\n if (idx === undefined || idx === null) {\n kept.push(e);\n continue;\n }\n const end = idx + (e.target_text || \"\").length;\n const cuts_into_marker = marker_spans.some(\n ([m_start, m_end]) =>\n m_start < end && idx < m_end && !(idx <= m_start && m_end <= end),\n );\n if (!cuts_into_marker) {\n kept.push(e);\n continue;\n }\n if (!warned) {\n warnings.push(\n \"An image's alternative text differs between the documents. Image markers \" +\n \"() are read-only projections, so this difference cannot be \" +\n \"expressed as a text edit — it was skipped; update the image or its alt text \" +\n \"manually in Word.\",\n );\n warned = true;\n }\n }\n return kept;\n}\n\n/**\n * True when every projected row reads exactly as its cells joined by \" | \".\n * Rows wrapped in tracked-row CriticMarkup ({++ … ++} / {-- … --}) do not,\n * and such tables are diffed as plain text rather than as row structures.\n */\nfunction _rows_are_plain(text: string, table: TableGeometry): boolean {\n for (const row of table.rows) {\n if (text.substring(row.start, row.end) !== row.cells.join(\" | \")) {\n return false;\n }\n }\n return true;\n}\n\nconst _ROW_KEY_SEP = \"\\x1f\";\n\n/**\n * Row-level alignment opcodes between two tables, or null when the row sets\n * differ only cell-internally (no rows added/removed) — the caller then\n * keeps fine-grained word-level text edits instead of row operations.\n */\nfunction _table_row_opcodes(\n rows_o: RowGeometry[],\n rows_m: RowGeometry[],\n): Opcode[] | null {\n const keys_o = rows_o.map((r) => r.cells.join(_ROW_KEY_SEP));\n const keys_m = rows_m.map((r) => r.cells.join(_ROW_KEY_SEP));\n const opcodes = _sequence_opcodes(keys_o, keys_m);\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (\n tag === \"insert\" ||\n tag === \"delete\" ||\n (tag === \"replace\" && i2 - i1 !== j2 - j1)\n ) {\n return opcodes;\n }\n }\n return null;\n}\n\n/**\n * Emits structured operations (delete_row / insert_row / per-row modify)\n * that transform table_o's row set into table_m's, following the alignment\n * `opcodes` from _table_row_opcodes (QA 2026-07-18 C2: a generic text edit\n * cannot add or remove rows — it writes fake pipe text into one cell or is\n * rejected by the cell-count validator).\n */\nfunction _row_ops_for_table(\n table_o: TableGeometry,\n table_m: TableGeometry,\n opcodes: Opcode[],\n warnings: string[],\n): DiffEdit[] {\n const rows_o = table_o.rows;\n const rows_m = table_m.rows;\n const keys_o = rows_o.map((r) => r.cells.join(_ROW_KEY_SEP));\n\n const row_text = (r: RowGeometry): string => r.cells.join(\" | \");\n\n // Duplicate row texts make text-anchored row operations ambiguous. The\n // engine fails closed with a strict-mode ambiguity error at apply time;\n // tell the user up front so the rejection is not a surprise.\n if (new Set(keys_o).size !== keys_o.length) {\n warnings.push(\n \"A table contains rows with identical text; the generated row operations anchor by \" +\n \"row text and may be rejected as ambiguous at apply time. If that happens, apply the \" +\n \"row changes with explicit insert_row/delete_row edits.\",\n );\n }\n\n // Rows removed by the transformation (deletes + surplus rows of shrinking\n // replaces) can never anchor an insert.\n const removed = new Set<number>();\n const replaced_new_text: Record<number, string> = {};\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (tag === \"delete\") {\n for (let k = i1; k < i2; k++) removed.add(k);\n } else if (tag === \"replace\") {\n const pairs = Math.min(i2 - i1, j2 - j1);\n for (let k = i1 + pairs; k < i2; k++) removed.add(k);\n for (let k = 0; k < pairs; k++) {\n replaced_new_text[i1 + k] = row_text(rows_m[j1 + k]);\n }\n }\n }\n\n const surviving: number[] = [];\n for (let k = 0; k < rows_o.length; k++) {\n if (!removed.has(k)) surviving.push(k);\n }\n\n const anchor_text = (orig_idx: number): string => {\n // Anchor on the row's FINAL text: modified rows are matched via the\n // engine's clean-view fallback after their own edit applies.\n return replaced_new_text[orig_idx] !== undefined\n ? replaced_new_text[orig_idx]\n : row_text(rows_o[orig_idx]);\n };\n\n const insert_ops = (\n new_rows: RowGeometry[],\n at_orig_index: number,\n ): DiffEdit[] => {\n const ops: DiffEdit[] = [];\n const before = surviving.filter((k) => k < at_orig_index);\n const after = surviving.filter((k) => k >= at_orig_index);\n if (before.length > 0) {\n // Insert below the preceding surviving row. Emitting in reverse keeps\n // the final order: below-A(B), then below-A(C) yields A,C,B — so emit\n // C first.\n const anchor_idx = before[before.length - 1];\n const anchor = anchor_text(anchor_idx);\n for (const r of [...new_rows].reverse()) {\n ops.push({\n type: \"insert_row\",\n target_text: anchor,\n position: \"below\",\n cells: [...r.cells],\n // Pin to the anchor row's offset: text anchors alone are\n // ambiguous when tables share identical rows. Pins do not\n // survive JSON round-trips (the strict text match applies then,\n // failing closed with the duplicate-row warning above).\n _match_start_index: rows_o[anchor_idx].start,\n });\n }\n } else if (after.length > 0) {\n const anchor_idx = after[0];\n const anchor = anchor_text(anchor_idx);\n for (const r of new_rows) {\n ops.push({\n type: \"insert_row\",\n target_text: anchor,\n position: \"above\",\n cells: [...r.cells],\n _match_start_index: rows_o[anchor_idx].start,\n });\n }\n } else {\n warnings.push(\n \"A table gained rows but no original row survives to anchor them; \" +\n \"these row insertions were skipped — add them with explicit insert_row operations.\",\n );\n }\n return ops;\n };\n\n const ops: DiffEdit[] = [];\n for (const [tag, i1, i2, j1, j2] of opcodes) {\n if (tag === \"equal\") continue;\n if (tag === \"replace\") {\n const pairs = Math.min(i2 - i1, j2 - j1);\n for (let k = 0; k < pairs; k++) {\n const o_txt = row_text(rows_o[i1 + k]);\n const m_txt = row_text(rows_m[j1 + k]);\n if (o_txt !== m_txt) {\n ops.push({\n type: \"modify\",\n target_text: o_txt,\n new_text: m_txt,\n comment: \"Diff: Table row modified\",\n _is_table_edit: true,\n });\n }\n }\n for (let k = i1 + pairs; k < i2; k++) {\n ops.push({\n type: \"delete_row\",\n target_text: row_text(rows_o[k]),\n _match_start_index: rows_o[k].start,\n });\n }\n const surplus_new = rows_m.slice(j1 + pairs, j2);\n if (surplus_new.length > 0) {\n ops.push(...insert_ops(surplus_new, i2));\n }\n } else if (tag === \"delete\") {\n for (let k = i1; k < i2; k++) {\n ops.push({\n type: \"delete_row\",\n target_text: row_text(rows_o[k]),\n _match_start_index: rows_o[k].start,\n });\n }\n } else if (tag === \"insert\") {\n ops.push(...insert_ops(rows_m.slice(j1, j2), i1));\n }\n }\n return ops;\n}\n\n/**\n * DOCX-to-DOCX diff over projections extracted with return_structure=true.\n *\n * Improvements over a flat generate_edits_from_text pass:\n * - each OPC part (header/body/footer/notes) diffs against its\n * counterpart, so no edit can span a part boundary and content that\n * moved between parts is reported instead of hidden (QA 2026-07-18 C1);\n * - table row insertions/deletions become structured insert_row /\n * delete_row operations instead of pipe-text edits (QA C2).\n *\n * Every ModifyText keeps its _match_start_index pinned into text_orig, which\n * the engine consumes positionally (the Node engine has no\n * make_edits_self_contained JSON round trip like the Python CLI).\n *\n * Returns { edits, warnings }. Warnings describe fallbacks the caller should\n * surface (differing part layouts, unanchorable rows, …).\n */\nexport function generate_structured_edits(\n text_orig: string,\n struct_orig: ExtractStructure,\n text_mod: string,\n struct_mod: ExtractStructure,\n): { edits: DiffEdit[]; warnings: string[] } {\n const warnings: string[] = [];\n const edits: DiffEdit[] = [];\n\n const kinds_o = struct_orig.part_ranges\n .filter(([s, e]) => e > s)\n .map(([, , k]) => k);\n const kinds_m = struct_mod.part_ranges\n .filter(([s, e]) => e > s)\n .map(([, , k]) => k);\n\n if (JSON.stringify(kinds_o) !== JSON.stringify(kinds_m)) {\n warnings.push(\n `The documents have different part layouts (${kinds_o.join(\" + \") || \"none\"} vs ` +\n `${kinds_m.join(\" + \") || \"none\"}); comparing flattened text instead. Header/footer ` +\n \"additions or removals cannot be expressed as text edits.\",\n );\n const flat = _drop_marker_interior_hunks(\n _drop_image_marker_hunks(\n generate_edits_via_paragraph_alignment(text_orig, text_mod),\n warnings,\n ),\n text_orig,\n warnings,\n );\n return { edits: [...flat], warnings };\n }\n\n const ranges_o = struct_orig.part_ranges\n .filter(([s, e]) => e > s)\n .map(([s, e]) => [s, e] as [number, number]);\n const ranges_m = struct_mod.part_ranges\n .filter(([s, e]) => e > s)\n .map(([s, e]) => [s, e] as [number, number]);\n\n for (let p = 0; p < ranges_o.length; p++) {\n const [po_start, po_end] = ranges_o[p];\n const [pm_start, pm_end] = ranges_m[p];\n\n const tables_o = struct_orig.tables.filter(\n (t) => po_start <= t.start && t.end <= po_end,\n );\n const tables_m = struct_mod.tables.filter(\n (t) => pm_start <= t.start && t.end <= pm_end,\n );\n\n const tables_alignable =\n tables_o.length === tables_m.length &&\n tables_o.every((t) => _rows_are_plain(text_orig, t)) &&\n tables_m.every((t) => _rows_are_plain(text_mod, t));\n if (tables_o.length !== tables_m.length) {\n warnings.push(\n `A ${kinds_o[p]} part has ${tables_o.length} table(s) in the ` +\n `original but ${tables_m.length} in the modified document; its tables were compared as plain ` +\n \"text. Adding or removing whole tables is not supported via diff/apply.\",\n );\n }\n\n if (!tables_alignable) {\n const part_edits = generate_edits_via_paragraph_alignment(\n text_orig.substring(po_start, po_end),\n text_mod.substring(pm_start, pm_end),\n );\n for (const e of part_edits) {\n e._match_start_index = (e._match_start_index || 0) + po_start;\n }\n edits.push(...part_edits);\n continue;\n }\n\n // Walk interleaved segments: text-before-table, table, text-after…\n const boundaries_o: [number, number][] = [\n [po_start, po_start],\n ...tables_o.map((t) => [t.start, t.end] as [number, number]),\n [po_end, po_end],\n ];\n const boundaries_m: [number, number][] = [\n [pm_start, pm_start],\n ...tables_m.map((t) => [t.start, t.end] as [number, number]),\n [pm_end, pm_end],\n ];\n\n for (let seg_idx = 0; seg_idx < boundaries_o.length - 1; seg_idx++) {\n const seg_o_start = boundaries_o[seg_idx][1];\n const seg_o_end = boundaries_o[seg_idx + 1][0];\n const seg_m_start = boundaries_m[seg_idx][1];\n const seg_m_end = boundaries_m[seg_idx + 1][0];\n // Paragraph alignment, never a raw word-level diff over the whole\n // segment: dmp legally shifts hunk boundaries across paragraphs\n // sharing a prefix, and the engine rightly rejects a deletion with\n // body text on both sides of a paragraph break (ADEU-QA-002 A).\n const seg_edits = generate_edits_via_paragraph_alignment(\n text_orig.substring(seg_o_start, seg_o_end),\n text_mod.substring(seg_m_start, seg_m_end),\n );\n for (const e of seg_edits) {\n e._match_start_index = (e._match_start_index || 0) + seg_o_start;\n }\n edits.push(...seg_edits);\n\n if (seg_idx < tables_o.length) {\n const t_o = tables_o[seg_idx];\n const t_m = tables_m[seg_idx];\n const row_opcodes = _table_row_opcodes(t_o.rows, t_m.rows);\n if (row_opcodes !== null) {\n edits.push(..._row_ops_for_table(t_o, t_m, row_opcodes, warnings));\n } else {\n // Cell-internal changes only (row sets align 1:1). Emit one\n // ROW-LEVEL edit per differing row — the engine splits it into\n // per-cell sub-edits along the \" | \" boundaries. A word-level diff\n // over the whole table span produces hunks that start or end\n // inside a cell separator, which apply into the wrong cell or\n // write literal pipe text. Unpinned like every other table edit:\n // pinned application bypasses the cell splitter, and the full row\n // text is the anchor contract.\n for (let k = 0; k < t_o.rows.length; k++) {\n const o_txt = t_o.rows[k].cells.join(\" | \");\n const m_txt = t_m.rows[k].cells.join(\" | \");\n if (o_txt === m_txt) continue;\n edits.push({\n type: \"modify\",\n target_text: o_txt,\n new_text: m_txt,\n comment: \"Diff: Table row modified\",\n _is_table_edit: true,\n });\n }\n }\n }\n }\n }\n\n // Row operations anchor by row text (pins do not survive JSON): if the\n // anchor text also appears elsewhere in the document — e.g. two tables\n // sharing a header row — the strict text match at apply time is\n // ambiguous. In-process consumers ride the pinned offsets; JSON consumers\n // fail closed, so tell the user why up front.\n const countOccurrences = (haystack: string, needle: string): number => {\n let count = 0;\n let from = 0;\n while (true) {\n const idx = haystack.indexOf(needle, from);\n if (idx === -1) break;\n count++;\n from = idx + needle.length;\n }\n return count;\n };\n let ambiguous_anchor_warned = false;\n for (const e of edits) {\n if (\n (e.type === \"insert_row\" ||\n e.type === \"delete_row\" ||\n (e as any)._is_table_edit) &&\n !ambiguous_anchor_warned\n ) {\n if (e.target_text && countOccurrences(text_orig, e.target_text) > 1) {\n warnings.push(\n `The row anchor \"${e.target_text.substring(0, 60)}\" appears more than once in the document. ` +\n \"Applying this diff from its JSON output may be rejected as ambiguous — \" +\n \"make the anchor rows unique, or apply the row changes with explicit \" +\n \"insert_row/delete_row edits.\",\n );\n ambiguous_anchor_warned = true;\n }\n }\n }\n\n // Our own output must never trip the engine's read-only image-marker\n // validation: an added/removed image becomes a warning, not an edit —\n // and so does an alt-text change, whose hunk lands INSIDE a marker.\n const modify_edits = edits.filter(\n (e): e is ModifyText => e.type === \"modify\",\n );\n const kept_modifies = new Set(\n _drop_marker_interior_hunks(\n _drop_image_marker_hunks(modify_edits, warnings),\n text_orig,\n warnings,\n ),\n );\n const final_edits = edits.filter(\n (e) => e.type !== \"modify\" || kept_modifies.has(e as ModifyText),\n );\n\n return { edits: final_edits, warnings };\n}\n\n/**\n * Compares embedded media bytes (word/media/*) between two DOCX packages.\n * Adeu's diff is a text comparison: two documents whose images differ but\n * whose projections agree produce an empty diff, which reads as \"visually\n * identical\" unless the caller says otherwise (QA 2026-07-19 F-04). Returns\n * warning strings describing changed/added/removed media members; empty when\n * the media sets are byte-identical (or either package is unreadable — the\n * caller has already surfaced package-level errors).\n */\nexport function collect_media_difference_warnings(\n original_docx: Uint8Array,\n modified_docx: Uint8Array,\n): string[] {\n const media_hashes = (data: Uint8Array): Map<string, string> => {\n const hashes = new Map<string, string>();\n try {\n const unzipped = unzipSync(data);\n for (const [name, bytes] of Object.entries(unzipped)) {\n if (!name.startsWith(\"word/media/\")) continue;\n // FNV-1a over the bytes: cheap, dependency-free content fingerprint.\n let h1 = 0x811c9dc5;\n let h2 = 0xcbf29ce4;\n for (let i = 0; i < bytes.length; i++) {\n h1 = Math.imul(h1 ^ bytes[i], 0x01000193) >>> 0;\n h2 = Math.imul(h2 ^ bytes[bytes.length - 1 - i], 0x01000193) >>> 0;\n }\n hashes.set(name, `${bytes.length}:${h1.toString(16)}:${h2.toString(16)}`);\n }\n } catch {\n return new Map();\n }\n return hashes;\n };\n\n const hashes_orig = media_hashes(original_docx);\n const hashes_mod = media_hashes(modified_docx);\n\n const changed: string[] = [];\n const added: string[] = [];\n const removed: string[] = [];\n for (const [name, hash] of hashes_orig) {\n if (!hashes_mod.has(name)) removed.push(name);\n else if (hashes_mod.get(name) !== hash) changed.push(name);\n }\n for (const name of hashes_mod.keys()) {\n if (!hashes_orig.has(name)) added.push(name);\n }\n changed.sort();\n added.sort();\n removed.sort();\n if (changed.length + added.length + removed.length === 0) return [];\n\n const parts: string[] = [];\n if (changed.length) parts.push(`${changed.length} changed`);\n if (added.length) parts.push(`${added.length} added`);\n if (removed.length) parts.push(`${removed.length} removed`);\n const names = [...changed, ...added, ...removed].slice(0, 5).join(\", \");\n return [\n `The documents' embedded media differ (${parts.join(\", \")}: ${names}). This diff compares ` +\n \"TEXT only — an empty edit list does not mean the documents are visually identical. \" +\n \"Image changes must be applied manually in Word.\",\n ];\n}\n\nexport function create_unified_diff(\n original_text: string,\n modified_text: string,\n context_lines: number = 3,\n): string {\n const dmp = new diff_match_patch.diff_match_patch();\n dmp.Diff_Timeout = 2.0;\n\n const a = dmp.diff_linesToChars_(original_text, modified_text);\n const diffs = dmp.diff_main(a.chars1, a.chars2, false);\n dmp.diff_charsToLines_(diffs, a.lineArray);\n\n const output: string[] = [];\n output.push(\"--- Original\");\n output.push(\"+++ Modified\");\n\n let i = 0;\n while (i < diffs.length) {\n while (i < diffs.length && diffs[i][0] === 0) i++;\n if (i >= diffs.length) break;\n\n let start = i;\n let preContext: string[] = [];\n if (start > 0 && diffs[start - 1][0] === 0) {\n const lines = diffs[start - 1][1].replace(/\\n$/, \"\").split(\"\\n\");\n preContext = lines.slice(-context_lines);\n }\n\n const chunk: string[] = [];\n chunk.push(...preContext.map((l) => ` ${l}`));\n\n while (i < diffs.length) {\n const [op, text] = diffs[i];\n const lines = text.replace(/\\n$/, \"\").split(\"\\n\");\n\n if (op === 0) {\n if (lines.length > context_lines * 2) break;\n chunk.push(...lines.map((l) => ` ${l}`));\n } else {\n const prefix = op === -1 ? \"-\" : \"+\";\n chunk.push(...lines.map((l) => `${prefix}${l}`));\n }\n i++;\n }\n\n let postContext: string[] = [];\n if (i < diffs.length && diffs[i][0] === 0) {\n const lines = diffs[i][1].replace(/\\n$/, \"\").split(\"\\n\");\n postContext = lines.slice(0, context_lines);\n }\n chunk.push(...postContext.map((l) => ` ${l}`));\n\n output.push(\"@@ ... @@\");\n output.push(...chunk);\n }\n\n if (output.length === 2) return \"\"; // No changes\n return output.join(\"\\n\");\n}\n\nexport function create_word_patch_diff(\n original_text: string,\n modified_text: string,\n original_path: string = \"Original\",\n modified_path: string = \"Modified\"\n): string {\n const edits = generate_edits_from_text(original_text, modified_text);\n const output: string[] = [\n `--- ${original_path}`,\n `+++ ${modified_path}`,\n \"\"\n ];\n \n const CONTEXT_SIZE = 40;\n\n for (const edit of edits) {\n const raw_start = edit._match_start_index || 0;\n const raw_target = edit.target_text || \"\";\n const raw_new = edit.new_text || \"\";\n\n const [prefix_len, suffix_len] = trim_common_context(raw_target, raw_new);\n\n const target_end_in_target = raw_target.length - suffix_len;\n const new_end_in_new = raw_new.length - suffix_len;\n\n const display_target = raw_target.substring(prefix_len, target_end_in_target);\n const display_new = raw_new.substring(prefix_len, new_end_in_new);\n\n const change_start = raw_start + prefix_len;\n const change_end = change_start + display_target.length;\n\n let pre_start = Math.max(0, change_start - CONTEXT_SIZE);\n let pre_context = original_text.substring(pre_start, change_start);\n if (pre_start > 0) pre_context = \"...\" + pre_context;\n\n let post_end = Math.min(original_text.length, change_end + CONTEXT_SIZE);\n let post_context = original_text.substring(change_end, post_end);\n if (post_end < original_text.length) post_context = post_context + \"...\";\n\n pre_context = pre_context.replace(/\\n/g, \" \").replace(/\\r/g, \"\");\n post_context = post_context.replace(/\\n/g, \" \").replace(/\\r/g, \"\");\n\n output.push(\"@@ Word Patch @@\");\n output.push(` ${pre_context}`);\n if (display_target) output.push(`- ${display_target}`);\n if (display_new) output.push(`+ ${display_new}`);\n output.push(` ${post_context}`);\n output.push(\"\");\n }\n\n return output.join(\"\\n\");\n}\n","/**\n * Stateless paginator for projected DOCX Markdown.\n */\n\nconst PAGE_TARGET_CHARS = 19_000;\nconst APPENDIX_MARKER = '<!-- READONLY_BOUNDARY_START -->';\n\nconst _CRITIC_TOKENS: Record<string, string> = {\n '{++': '++}',\n '{--': '--}',\n '{==': '==}',\n '{>>': '<<}',\n};\n\nconst _CHG_ID_PATTERN = /\\bChg:(\\d+)\\b/g;\n\nexport interface PageInfo {\n page: number;\n total_pages: number;\n has_next: boolean;\n has_prev: boolean;\n tracked_change_count: number;\n page_content: string;\n}\n\nexport interface PaginationResult {\n pages: PageInfo[];\n total_pages: number;\n body_pages: string[];\n body_page_offsets: number[];\n}\n\nexport function split_structural_appendix(markdown: string): [string, string] {\n if (!markdown) return ['', ''];\n\n const idx = markdown.indexOf(APPENDIX_MARKER);\n if (idx === -1) return [markdown, ''];\n\n const line_start = markdown.lastIndexOf('\\n', idx) + 1;\n const body = markdown.substring(0, line_start).trimEnd();\n const appendix = markdown.substring(line_start);\n\n return [body, appendix];\n}\n\nexport function paginate(markdown_body: string, structural_appendix: string = ''): PaginationResult {\n if (!markdown_body) {\n const appendix_clean = structural_appendix ? structural_appendix.trim() : '';\n const content = appendix_clean;\n return {\n pages: [{\n page: 1,\n total_pages: 1,\n has_next: false,\n has_prev: false,\n tracked_change_count: _count_tracked_changes(content),\n page_content: content,\n }],\n total_pages: 1,\n body_pages: [''],\n body_page_offsets: [0],\n };\n }\n\n const block_records = _tokenize_into_atomic_blocks(markdown_body);\n const [body_pages, body_page_offsets] = _assemble_pages(block_records);\n\n let final_pages: string[];\n if (structural_appendix && structural_appendix.trim()) {\n const appendix = structural_appendix.trim();\n final_pages = body_pages.map(bp => bp ? `${bp}\\n\\n${appendix}` : appendix);\n } else {\n final_pages = [...body_pages];\n }\n\n const total = final_pages.length;\n const page_infos: PageInfo[] = final_pages.map((content, i) => ({\n page: i + 1,\n total_pages: total,\n has_next: (i + 1 < total),\n has_prev: (i + 1 > 1),\n tracked_change_count: _count_tracked_changes(content),\n page_content: content,\n }));\n\n return {\n pages: page_infos,\n total_pages: total,\n body_pages,\n body_page_offsets,\n };\n}\n\nfunction _tokenize_into_atomic_blocks(markdown_body: string): [string, number][] {\n const raw_blocks = _split_on_safe_paragraph_breaks(markdown_body);\n return _merge_footnote_sections(raw_blocks);\n}\n\nfunction _split_on_safe_paragraph_breaks(text: string): [string, number][] {\n const counters: Record<string, number> = { '++}': 0, '--}': 0, '==}': 0, '<<}': 0 };\n const blocks: [string, number][] = [];\n let block_start = 0;\n let i = 0;\n const n = text.length;\n\n while (i < n) {\n let matched_open = false;\n for (const [open_tok, close_tok] of Object.entries(_CRITIC_TOKENS)) {\n if (text.startsWith(open_tok, i)) {\n counters[close_tok]++;\n i += open_tok.length;\n matched_open = true;\n break;\n }\n }\n if (matched_open) continue;\n\n let matched_close = false;\n for (const close_tok of Object.values(_CRITIC_TOKENS)) {\n if (text.startsWith(close_tok, i)) {\n if (counters[close_tok] > 0) counters[close_tok]--;\n i += close_tok.length;\n matched_close = true;\n break;\n }\n }\n if (matched_close) continue;\n\n if (text[i] === '\\n' && i + 1 < n && text[i + 1] === '\\n') {\n if (Object.values(counters).every(c => c === 0)) {\n const block_text = text.substring(block_start, i);\n if (block_text) blocks.push([block_text, block_start]);\n\n let j = i;\n while (j < n && text[j] === '\\n') j++;\n i = j;\n block_start = i;\n continue;\n }\n }\n\n i++;\n }\n\n if (block_start < n) {\n const block_text = text.substring(block_start, n);\n if (block_text) blocks.push([block_text, block_start]);\n }\n\n return blocks;\n}\n\nfunction _merge_footnote_sections(blocks: [string, number][]): [string, number][] {\n if (!blocks.length) return blocks;\n\n const merged: [string, number][] = [];\n let i = 0;\n\n while (i < blocks.length) {\n const [block_text, block_offset] = blocks[i];\n const stripped = block_text.trimStart();\n const is_section_header = stripped.startsWith('## Footnotes') || stripped.startsWith('## Endnotes');\n\n if (!is_section_header) {\n merged.push([block_text, block_offset]);\n i++;\n continue;\n }\n\n let accumulated_text = block_text;\n let j = i + 1;\n while (j < blocks.length) {\n const [next_text] = blocks[j];\n const next_stripped = next_text.trimStart();\n if (next_stripped.startsWith('[^fn-') || next_stripped.startsWith('[^en-')) {\n accumulated_text = `${accumulated_text}\\n\\n${next_text}`;\n j++;\n } else {\n break;\n }\n }\n\n merged.push([accumulated_text, block_offset]);\n i = j;\n }\n\n return merged;\n}\n\nfunction _assemble_pages(block_records: [string, number][]): [string[], number[]] {\n if (!block_records.length) return [[''], [0]];\n\n const pages: string[] = [];\n const page_starts: number[] = [];\n\n let current_blocks: string[] = [];\n let current_size = 0;\n let current_start = -1;\n\n const flush_current = () => {\n if (current_blocks.length > 0) {\n pages.push(current_blocks.join('\\n\\n'));\n page_starts.push(current_start);\n }\n current_blocks = [];\n current_size = 0;\n current_start = -1;\n };\n\n for (const [block_text, block_offset] of block_records) {\n const block_size = block_text.length;\n const added_size = block_size + (current_blocks.length > 0 ? 2 : 0);\n\n if (current_blocks.length > 0 && current_size + added_size > PAGE_TARGET_CHARS) {\n flush_current();\n }\n\n if (current_blocks.length === 0 && block_size > PAGE_TARGET_CHARS) {\n pages.push(block_text);\n page_starts.push(block_offset);\n continue;\n }\n\n if (current_blocks.length === 0) current_start = block_offset;\n current_blocks.push(block_text);\n current_size += current_size > 0 ? added_size : block_size;\n }\n\n flush_current();\n\n if (!pages.length) return [[''], [0]];\n return [pages, page_starts];\n}\n\nfunction _count_tracked_changes(page_content: string): number {\n const matches = [...page_content.matchAll(_CHG_ID_PATTERN)];\n const distinct = new Set(matches.map(m => m[1]));\n return distinct.size;\n}","import { trim_common_context } from \"./diff.js\";\nimport { ModifyText } from \"./models.js\";\nimport { RegexTimeoutError, userFindAllMatches } from \"./utils/safe-regex.js\";\n\n/** One entry per input edit in apply_edits_to_markdown's edit_reports. */\nexport interface MarkupEditReport {\n index: number;\n status: \"applied\" | \"failed\";\n error: string | null;\n occurrences: number;\n}\nexport const AMBIGUITY_EXAMPLES_CAP = 5;\nexport const AMBIGUITY_CONTEXT_CHARS = 50;\nfunction _should_strip_markers(text: string, marker: string): boolean {\n if (!text.startsWith(marker) || !text.endsWith(marker)) return false;\n if (text.length < marker.length * 2) return false;\n\n const inner = text.substring(marker.length, text.length - marker.length);\n if (!inner) return false;\n\n if (inner.includes(marker)) return false;\n if (!/[a-zA-Z]/.test(inner)) return false;\n\n if (marker === \"__\" && /^\\w+$/.test(inner)) return false;\n if (marker === \"_\") {\n if (inner.includes(\"_\")) return false;\n if (/^[0-9_]+$/.test(inner)) return false;\n }\n\n return true;\n}\n\nfunction _strip_balanced_markers(text: string): [string, string, string] {\n let prefix_markup = \"\";\n let suffix_markup = \"\";\n let clean_text = text;\n\n const markers = [\"**\", \"__\", \"_\", \"*\"];\n\n for (const marker of markers) {\n if (_should_strip_markers(clean_text, marker)) {\n prefix_markup += marker;\n suffix_markup = marker + suffix_markup;\n clean_text = clean_text.substring(\n marker.length,\n clean_text.length - marker.length,\n );\n break;\n }\n }\n\n return [prefix_markup, clean_text, suffix_markup];\n}\n\nexport function _replace_smart_quotes(text: string): string {\n return text\n .replace(/“/g, '\"')\n .replace(/”/g, '\"')\n .replace(/‘/g, \"'\")\n .replace(/’/g, \"'\");\n}\n\n/**\n * Strips markdown formatting markers and builds a position map.\n * Returns [stripped_text, position_map] where position_map[i] = original\n * index. Mirrors Python markup._strip_markdown_for_matching.\n */\nfunction _strip_markdown_for_matching(text: string): [string, number[]] {\n const result: string[] = [];\n const position_map: number[] = [];\n let i = 0;\n\n while (i < text.length) {\n // Skip ** or __\n const pair = text.substring(i, i + 2);\n if (i < text.length - 1 && (pair === \"**\" || pair === \"__\")) {\n i += 2;\n continue;\n }\n // Skip single * or _ that look like markdown (at word boundaries)\n if (text[i] === \"*\" || text[i] === \"_\") {\n const prev_char = i > 0 ? text[i - 1] : \" \";\n const next_char = i < text.length - 1 ? text[i + 1] : \" \";\n // If at boundary (space or start/end), likely markdown\n if (\n [\" \", \"\\n\", \"\\t\"].includes(prev_char) ||\n [\" \", \"\\n\", \"\\t\"].includes(next_char)\n ) {\n i += 1;\n continue;\n }\n }\n\n position_map.push(i);\n result.push(text[i]);\n i += 1;\n }\n\n return [result.join(\"\"), position_map];\n}\n\nfunction _find_safe_boundaries(\n text: string,\n start: number,\n end: number,\n): [number, number] {\n let new_start = start;\n let new_end = end;\n\n const expand_if_unbalanced = (marker: string) => {\n const current_match = text.substring(new_start, new_end);\n const count = (\n current_match.match(new RegExp(marker.replace(/\\*/g, \"\\\\*\"), \"g\")) || []\n ).length;\n\n if (count % 2 !== 0) {\n const suffix = text.substring(new_end);\n if (suffix.startsWith(marker)) {\n new_end += marker.length;\n return;\n }\n const prefix = text.substring(0, new_start);\n if (prefix.endsWith(marker)) {\n new_start -= marker.length;\n return;\n }\n }\n };\n\n for (let i = 0; i < 2; i++) {\n expand_if_unbalanced(\"**\");\n expand_if_unbalanced(\"__\");\n expand_if_unbalanced(\"_\");\n expand_if_unbalanced(\"*\");\n }\n\n return [new_start, new_end];\n}\n\nfunction _refine_match_boundaries(\n text: string,\n start: number,\n end: number,\n): [number, number] {\n const markers = [\"**\", \"__\", \"*\", \"_\"];\n let current_text = text.substring(start, end);\n let best_start = start;\n let best_end = end;\n\n const countMarker = (str: string, mk: string) =>\n (str.match(new RegExp(mk.replace(/\\*/g, \"\\\\*\"), \"g\")) || []).length;\n\n for (const marker of markers) {\n if (current_text.startsWith(marker)) {\n const current_score = countMarker(current_text, marker) % 2;\n const trimmed_text = current_text.substring(marker.length);\n const trimmed_score = countMarker(trimmed_text, marker) % 2;\n\n if (current_score === 1 && trimmed_score === 0) {\n best_start += marker.length;\n current_text = trimmed_text;\n }\n }\n }\n\n for (const marker of markers) {\n if (current_text.endsWith(marker)) {\n const current_score = countMarker(current_text, marker) % 2;\n const trimmed_text = current_text.substring(\n 0,\n current_text.length - marker.length,\n );\n const trimmed_score = countMarker(trimmed_text, marker) % 2;\n\n if (current_score === 1 && trimmed_score === 0) {\n best_end -= marker.length;\n current_text = trimmed_text;\n }\n }\n }\n\n return [best_start, best_end];\n}\n\nexport function _make_fuzzy_regex(target_text: string): string {\n target_text = _replace_smart_quotes(target_text);\n\n const parts: string[] = [];\n const token_pattern = /(_+)|(\\s+)|(['\"])|([.,;:\\/\\-\\[\\](){}+=$?*!|#^<>\\\\%&@~`])/g;\n\n // Note: JS does not support atomic groups (?>...).\n // However, because we only match markdown characters * and _,\n // we can use a character class `[*_]*` which is mathematically equivalent\n // to `(?:\\*\\*|__|\\*|_)*` but fundamentally immune to catastrophic backtracking!\n const md_noise = \"[*_]*\";\n const structural_noise = \"(?:\\\\s*(?:[*+\\\\->]|\\\\d+\\\\.)\\\\s+|\\\\s*\\\\n\\\\s*)\";\n\n const start_list_marker = \"(?:[ \\\\t]*(?:[*+\\\\->]|\\\\d+\\\\.)\\\\s+)?\";\n parts.push(start_list_marker);\n parts.push(md_noise);\n\n let last_idx = 0;\n let match;\n\n const escapeRegExp = (str: string) =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n while ((match = token_pattern.exec(target_text)) !== null) {\n const literal = target_text.substring(last_idx, match.index);\n if (literal) {\n parts.push(escapeRegExp(literal));\n parts.push(md_noise);\n }\n\n const g_underscore = match[1];\n const g_space = match[2];\n const g_quote = match[3];\n const g_punct = match[4];\n\n if (g_underscore) {\n parts.push(\"_+\");\n } else if (g_space) {\n if (g_space.includes(\"\\n\")) {\n parts.push(`(?:${structural_noise}|\\\\s+)+`);\n } else {\n parts.push(\"\\\\s+\");\n }\n } else if (g_quote) {\n if (g_quote === \"'\") parts.push(\"[\\u2018\\u2019']\");\n else parts.push('[\"\\u201c\\u201d]');\n } else if (g_punct) {\n parts.push(escapeRegExp(g_punct));\n }\n\n parts.push(md_noise);\n last_idx = token_pattern.lastIndex;\n }\n\n const remaining = target_text.substring(last_idx);\n if (remaining) parts.push(escapeRegExp(remaining));\n\n return parts.join(\"\");\n}\n\nexport function _find_match_in_text(\n text: string,\n target: string,\n): [number, number] {\n const matches = _find_all_matches_in_text(text, target);\n if (matches.length > 0) return matches[0];\n return [-1, -1];\n}\n\n/**\n * Every non-overlapping match of `target` in `text` as [start, end] pairs,\n * using the SAME strategy ladder as the apply engine's\n * DocumentMapper.find_all_match_indices: regex (when requested) or\n * exact → smart-quote-normalized → fuzzy. Markup previews must resolve\n * matching identically to apply, or the preview lies (QA 2026-07-18 M1).\n */\nexport function _find_all_matches_in_text(\n text: string,\n target: string,\n is_regex = false,\n): [number, number][] {\n if (!target) return [];\n\n if (is_regex) {\n // Same semantics as the mapper: budgeted user regex; an invalid pattern\n // simply produces no matches (surfaced as \"not found\").\n // RegexTimeoutError propagates for a clean per-edit error.\n try {\n return userFindAllMatches(target, text).map((m) => [m.start, m.end]);\n } catch (e) {\n if (e instanceof RegexTimeoutError) throw e;\n return [];\n }\n }\n\n // Literal indexOf scans (no RegExp over an arbitrarily long escaped\n // target, mirroring the mapper's exact tiers).\n const findAllLiteral = (\n haystack: string,\n needle: string,\n ): [number, number][] => {\n const out: [number, number][] = [];\n let from = 0;\n while (true) {\n const idx = haystack.indexOf(needle, from);\n if (idx === -1) break;\n out.push([idx, idx + needle.length]);\n from = idx + needle.length;\n }\n return out;\n };\n\n // 1. Exact matches\n let spans = findAllLiteral(text, target);\n if (spans.length > 0) {\n return spans.map(([s, e]) => _find_safe_boundaries(text, s, e));\n }\n\n // 2. Smart quote normalization\n const norm_text = _replace_smart_quotes(text);\n const norm_target = _replace_smart_quotes(target);\n spans = findAllLiteral(norm_text, norm_target);\n if (spans.length > 0) {\n return spans.map(([s, e]) => _find_safe_boundaries(text, s, e));\n }\n\n // 3. Markdown-stripped match, mirroring the mapper's strip-markdown and\n // plain-projection rungs: a plain target must find text whose projection\n // carries **bold**/_italic_ markers (even mid-word), and a marked target\n // must find plain text.\n const [stripped_text, pos_map] = _strip_markdown_for_matching(norm_text);\n const [stripped_target] = _strip_markdown_for_matching(norm_target);\n if (\n stripped_target &&\n (stripped_text !== norm_text || stripped_target !== norm_target)\n ) {\n const results: [number, number][] = [];\n for (const [p_start, p_end] of findAllLiteral(stripped_text, stripped_target)) {\n const raw_start = pos_map[p_start];\n const raw_end = pos_map[p_end - 1] + 1;\n results.push(_find_safe_boundaries(text, raw_start, raw_end));\n }\n if (results.length > 0) return results;\n }\n\n // 4. Fuzzy regex matches (handles markdown noise, list markers, etc.).\n // The [*_]* character classes in _make_fuzzy_regex prevent catastrophic\n // backtracking.\n try {\n const pattern = new RegExp(_make_fuzzy_regex(target), \"g\");\n const results: [number, number][] = [];\n for (const match of text.matchAll(pattern)) {\n const [refined_start, refined_end] = _refine_match_boundaries(\n text,\n match.index!,\n match.index! + match[0].length,\n );\n results.push(_find_safe_boundaries(text, refined_start, refined_end));\n }\n if (results.length > 0) return results;\n } catch (e) {\n // Ignore regex compilation errors from edge cases\n }\n\n return [];\n}\n\nexport function _build_critic_markup(\n target_text: string,\n new_text: string,\n comment: string | null | undefined,\n edit_index: number,\n include_index: boolean,\n highlight_only: boolean,\n): string {\n const parts: string[] = [];\n\n let [prefix_markup, clean_target, suffix_markup] =\n _strip_balanced_markers(target_text);\n\n let clean_new = new_text;\n if (prefix_markup && new_text) {\n if (\n new_text.startsWith(prefix_markup) &&\n new_text.endsWith(suffix_markup)\n ) {\n const inner_len = prefix_markup.length;\n clean_new =\n new_text.length > inner_len * 2\n ? new_text.substring(inner_len, new_text.length - inner_len)\n : new_text;\n }\n }\n\n parts.push(prefix_markup);\n\n if (highlight_only) {\n parts.push(`{==${clean_target}==}`);\n } else {\n const has_target = Boolean(clean_target);\n const has_new = Boolean(clean_new);\n\n if (has_target && !has_new) parts.push(`{--${clean_target}--}`);\n else if (!has_target && has_new) parts.push(`{++${clean_new}++}`);\n else if (has_target && has_new)\n parts.push(`{--${clean_target}--}{++${clean_new}++}`);\n }\n\n parts.push(suffix_markup);\n\n const meta_parts: string[] = [];\n if (comment) meta_parts.push(comment);\n if (include_index) meta_parts.push(`[Edit:${edit_index}]`);\n\n if (meta_parts.length > 0) {\n parts.push(`{>>${meta_parts.join(\" \")}<<}`);\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Applies edits to Markdown text and returns CriticMarkup-annotated output.\n *\n * Edit resolution follows the SAME semantics as `apply` (QA 2026-07-18 M1):\n * - `regex: true` targets match as regular expressions\n * - `match_mode` is honored: \"strict\" (default) refuses ambiguous targets,\n * \"first\" marks the first occurrence, \"all\" marks every occurrence\n * - a missing target is a per-edit failure, never a silent skip\n *\n * When `edit_reports` is provided, one entry per input edit is appended:\n * { index: 0-based input position, status: \"applied\"|\"failed\",\n * error: string|null, occurrences: number }.\n */\nexport function apply_edits_to_markdown(\n markdown_text: string,\n edits: ModifyText[],\n include_index = false,\n highlight_only = false,\n edit_reports?: MarkupEditReport[],\n): string {\n if (!edits || edits.length === 0) return markdown_text;\n\n const _report = (\n idx: number,\n status: \"applied\" | \"failed\",\n error: string | null = null,\n occurrences = 0,\n ) => {\n if (edit_reports) edit_reports.push({ index: idx, status, error, occurrences });\n };\n\n // Step 1: Find match positions for each edit\n const matched_edits: [number, number, string, ModifyText, number][] = [];\n\n for (let idx = 0; idx < edits.length; idx++) {\n const edit = edits[idx];\n const target = edit.target_text || \"\";\n const match_mode = (edit as any).match_mode || \"strict\";\n const is_regex = Boolean((edit as any).regex);\n\n if (!target) {\n _report(\n idx,\n \"failed\",\n `- Edit ${idx + 1} Failed: target_text is empty. Pure insertions are expressed as a ` +\n \"replacement: put the text immediately around the insertion point in target_text and \" +\n \"repeat it (plus the new text) in new_text.\",\n );\n continue;\n }\n\n let spans: [number, number][];\n try {\n spans = _find_all_matches_in_text(markdown_text, target, is_regex);\n } catch (e) {\n if (!(e instanceof RegexTimeoutError)) throw e;\n _report(idx, \"failed\", `- Edit ${idx + 1} Failed: ${e.message}`);\n continue;\n }\n\n if (spans.length === 0) {\n _report(\n idx,\n \"failed\",\n `- Edit ${idx + 1} Failed: Target text not found in document:\\n \"${target.substring(0, 80)}\"`,\n );\n continue;\n }\n\n if (spans.length > 1 && match_mode === \"strict\") {\n _report(\n idx,\n \"failed\",\n format_ambiguity_error(idx + 1, target, markdown_text, spans),\n );\n continue;\n }\n\n const selected =\n match_mode === \"strict\" || match_mode === \"first\" ? spans.slice(0, 1) : spans;\n for (const [start, end] of selected) {\n matched_edits.push([start, end, markdown_text.substring(start, end), edit, idx]);\n }\n _report(idx, \"applied\", null, selected.length);\n }\n\n // Step 2: Check for overlapping edits\n const matched_edits_filtered: [number, number, string, ModifyText, number][] =\n [];\n const occupied_ranges: [number, number][] = [];\n\n matched_edits.sort((a, b) => a[4] - b[4]);\n\n for (const [start, end, actual_text, edit, orig_idx] of matched_edits) {\n let overlaps = false;\n for (const [occ_start, occ_end] of occupied_ranges) {\n if (start < occ_end && end > occ_start) {\n overlaps = true;\n if (edit_reports) {\n const msg = `- Edit ${orig_idx + 1} Failed: overlaps with a previously matched edit.`;\n for (const r of edit_reports) {\n if (r.index === orig_idx) {\n r.status = \"failed\";\n r.error = msg;\n r.occurrences = 0;\n }\n }\n }\n break;\n }\n }\n\n if (!overlaps) {\n matched_edits_filtered.push([start, end, actual_text, edit, orig_idx]);\n occupied_ranges.push([start, end]);\n }\n }\n\n matched_edits_filtered.sort((a, b) => b[0] - a[0]);\n\n let result = markdown_text;\n\n for (const [\n start,\n end,\n actual_text,\n edit,\n orig_idx,\n ] of matched_edits_filtered) {\n const new_txt = edit.new_text || \"\";\n const [prefix_len, suffix_len] = trim_common_context(actual_text, new_txt);\n\n const unmodified_prefix =\n prefix_len > 0 ? actual_text.substring(0, prefix_len) : \"\";\n const unmodified_suffix =\n suffix_len > 0\n ? actual_text.substring(actual_text.length - suffix_len)\n : \"\";\n\n const t_end = actual_text.length - suffix_len;\n const n_end = new_txt.length - suffix_len;\n\n const isolated_target = actual_text.substring(prefix_len, t_end);\n const isolated_new = new_txt.substring(prefix_len, n_end);\n\n const markup = _build_critic_markup(\n isolated_target,\n isolated_new,\n edit.comment,\n // 1-based, matching apply's \"Edit N\" reports and batch validation\n // errors (QA 2026-07-17 F10; mirrors Python).\n orig_idx + 1,\n include_index,\n highlight_only,\n );\n\n const full_replacement = unmodified_prefix + markup + unmodified_suffix;\n result =\n result.substring(0, start) + full_replacement + result.substring(end);\n }\n\n return result;\n}\nexport function format_ambiguity_error(\n edit_index: number,\n target_text: string,\n haystack: string,\n match_positions: [number, number][],\n): string {\n const total = match_positions.length;\n if (total < 2) {\n throw new Error(\n `format_ambiguity_error requires at least 2 matches, got ${total}`,\n );\n }\n\n const shown = match_positions.slice(0, AMBIGUITY_EXAMPLES_CAP);\n const remaining = total - shown.length;\n\n const lines: string[] = [\n `- Edit ${edit_index} Failed: Ambiguous match. Target text appears ${total} times. First ${shown.length} occurrences:`,\n ];\n\n for (let i = 0; i < shown.length; i++) {\n const [start, end] = shown[i];\n const pre_start = Math.max(0, start - AMBIGUITY_CONTEXT_CHARS);\n const post_end = Math.min(haystack.length, end + AMBIGUITY_CONTEXT_CHARS);\n\n const pre_context = haystack\n .substring(pre_start, start)\n .replace(/\\n/g, \" \");\n const post_context = haystack.substring(end, post_end).replace(/\\n/g, \" \");\n let match_text = haystack.substring(start, end).replace(/\\n/g, \" \");\n\n if (match_text.length > 50) {\n match_text =\n match_text.substring(0, 25) +\n \"...\" +\n match_text.substring(match_text.length - 20);\n }\n\n const prefix_marker = pre_start > 0 ? \"...\" : \"\";\n const suffix_marker = post_end < haystack.length ? \"...\" : \"\";\n\n lines.push(\n ` ${i + 1}. \"${prefix_marker}${pre_context}[${match_text}]${post_context}${suffix_marker}\"`,\n );\n }\n\n if (remaining > 0) {\n lines.push(` ... and ${remaining} more occurrence(s) not shown.`);\n }\n\n // Tell the agent EXACTLY how to re-call. Without this, agents loop forever\n // refining target_text/regex because they never learn that match_mode is the\n // built-in escape hatch for genuine ambiguity. The safe strategy (more\n // context) comes first: blindly switching to \"first\"/\"all\" has silently\n // modified unrelated occurrences — dates, section numbers — in real use\n // (QA C1), so those options carry an explicit verification warning.\n // Wording mirrors the Python engine's format_ambiguity_error.\n lines.push(\" To resolve, re-send this edit using ONE of these strategies:\");\n lines.push(\n \" 1. RECOMMENDED: Provide more surrounding context in your target_text to uniquely \" +\n 'identify a single location (keep the default \"match_mode\": \"strict\").',\n );\n lines.push(\n ` 2. Set \"match_mode\": \"all\" to modify ALL ${total} occurrences — only after verifying ` +\n \"from the occurrence list above that EVERY occurrence should change.\",\n );\n lines.push(\n ' 3. Set \"match_mode\": \"first\" to modify only the FIRST occurrence — only after verifying ' +\n \"the first occurrence above is the one you intend to change.\",\n );\n\n return lines.join(\"\\n\");\n}\n","// FILE: src/utils/text.ts\n// Small text helpers shared by engine output paths. Mirrors the Python\n// engine's adeu/utils/text.py so both engines bound their report output\n// identically (QA C2).\n\n// Default cap for echoing caller-supplied strings (target_text/new_text) back\n// in batch reports and error messages. Reports feed straight into LLM context\n// windows via MCP, so an oversized edit value must never be reflected in full\n// (QA C2: a 2MB new_text was echoed twice, unbounded, in the apply report).\nexport const REPORT_ECHO_CAP = 500;\n\n// Tighter cap for the inline redline preview snippets ({--...--}{++...++}),\n// which additionally carry surrounding document context.\nexport const PREVIEW_TEXT_CAP = 200;\n\n/**\n * Bounds `text` to roughly `cap` visible characters, keeping the head and\n * tail and stating how much was omitted. Returns short strings unchanged.\n */\nexport function truncate_middle(text: string, cap: number): string {\n if (text === null || text === undefined || text.length <= cap) return text;\n const head = Math.max(1, Math.floor((cap * 2) / 3));\n const tail = Math.max(1, cap - head);\n const omitted = text.length - head - tail;\n return `${text.slice(0, head)}… [${omitted.toLocaleString(\"en-US\")} chars omitted] …${text.slice(-tail)}`;\n}\n","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, Run, DocxEvent } from \"./docx/primitives.js\";\nimport { DocumentMapper, TextSpan } from \"./mapper.js\";\nimport { CommentsManager } from \"./comments.js\";\nimport {\n ModifyText,\n InsertTableRow,\n DeleteTableRow,\n AcceptChange,\n RejectChange,\n ReplyComment,\n DocumentChange,\n} from \"./models.js\";\nimport { trim_common_context, generate_edits_from_text } from \"./diff.js\";\nimport { findChild, findAllDescendants, serializeXml } from \"./docx/dom.js\";\nimport { split_structural_appendix, paginate } from \"./pagination.js\";\nimport {\n is_heading_paragraph,\n is_native_heading,\n get_run_style_markers,\n get_run_text,\n apply_formatting_to_segments,\n} from \"./utils/docx.js\";\nimport { format_ambiguity_error } from \"./markup.js\";\nimport {\n PREVIEW_TEXT_CAP,\n REPORT_ECHO_CAP,\n truncate_middle,\n} from \"./utils/text.js\";\nimport { RegexTimeoutError } from \"./utils/safe-regex.js\";\n\n// Width of the surrounding-document window shown in redline previews.\nconst PREVIEW_CONTEXT_CHARS = 30;\n\n// --- DOM Mutation Helpers for xmldom ---\nfunction getNextElement(el: Element): Element | null {\n let next = el.nextSibling;\n while (next) {\n if (next.nodeType === 1) return next as Element;\n next = next.nextSibling;\n }\n return null;\n}\n\nfunction getPreviousElement(el: Element): Element | null {\n let prev = el.previousSibling;\n while (prev) {\n if (prev.nodeType === 1) return prev as Element;\n prev = prev.previousSibling;\n }\n return null;\n}\n\nfunction insertAfter(newNode: Node, refNode: Element) {\n if (refNode.parentNode) {\n refNode.parentNode.insertBefore(newNode, refNode.nextSibling);\n }\n}\n\nfunction insertBefore(newNode: Node, refNode: Element) {\n if (refNode.parentNode) {\n refNode.parentNode.insertBefore(newNode, refNode);\n }\n}\n\nfunction insertAtIndex(parent: Element, index: number, child: Node) {\n const children = Array.from(parent.childNodes).filter(\n (n) => n.nodeType === 1,\n );\n if (index >= children.length) {\n parent.appendChild(child);\n } else {\n parent.insertBefore(child, children[index]);\n }\n}\n\nfunction safeCloneEdit(val: any, seen: WeakMap<any, any> = new WeakMap()): any {\n if (val === null || typeof val !== \"object\") {\n return val;\n }\n if (seen.has(val)) {\n return seen.get(val);\n }\n if (val.nodeType !== undefined || typeof val.cloneNode === \"function\") {\n return val;\n }\n if (Array.isArray(val)) {\n const copy: any[] = [];\n seen.set(val, copy);\n for (let i = 0; i < val.length; i++) {\n copy.push(safeCloneEdit(val[i], seen));\n }\n return copy;\n }\n const copy: any = {};\n seen.set(val, copy);\n for (const key of Object.keys(val)) {\n copy[key] = safeCloneEdit(val[key], seen);\n }\n return copy;\n}\n\nfunction takeSnapshot(doc: any): any {\n const parts = [...doc.pkg.parts];\n const unzipped = { ...doc.pkg.unzipped };\n const rels = new Map<any, Map<string, any>>();\n const elements = new Map<any, Element>();\n for (const part of parts) {\n rels.set(part, new Map(part.rels));\n if (part._element) {\n elements.set(part, part._element.cloneNode(true) as Element);\n }\n }\n return { parts, unzipped, rels, elements };\n}\n\nfunction restoreSnapshot(doc: any, snapshot: any): void {\n doc.pkg.parts = [...snapshot.parts];\n for (const key of Object.keys(doc.pkg.unzipped)) {\n delete doc.pkg.unzipped[key];\n }\n for (const [key, val] of Object.entries(snapshot.unzipped)) {\n doc.pkg.unzipped[key] = val;\n }\n for (const part of snapshot.parts) {\n part.rels = new Map(snapshot.rels.get(part)!);\n const originalEl = snapshot.elements.get(part);\n if (originalEl && part._element) {\n const xmlDoc = part._element.ownerDocument;\n if (xmlDoc && xmlDoc.documentElement) {\n xmlDoc.replaceChild(originalEl, xmlDoc.documentElement);\n }\n part._element = originalEl;\n }\n }\n}\n\nfunction stripMatchingHeadingHashes(\n target: string,\n newText: string,\n): [string, string] {\n if (!target || !newText) return [target, newText];\n const targetMatch = target.match(/^(#+)\\s+/);\n const newMatch = newText.match(/^(#+)\\s+/);\n if (targetMatch && newMatch && targetMatch[1] === newMatch[1]) {\n const hashes = targetMatch[1];\n const targetClean = target.substring(hashes.length).trimStart();\n const newClean = newText.substring(hashes.length).trimStart();\n return [targetClean, newClean];\n }\n return [target, newText];\n}\n\n// --- Validation ---\nexport class BatchValidationError extends Error {\n public errors: string[];\n constructor(errors: string[]) {\n super(\"Batch validation failed:\\n\" + errors.join(\"\\n\"));\n this.name = \"BatchValidationError\";\n this.errors = errors;\n }\n}\n\n// Appended to a validation error when earlier edits in the same batch have\n// already applied: the failing target may simply be stale under the\n// sequential batch contract. Wording mirrors the Python engine exactly.\nfunction sequential_context_hint(applied_so_far: number): string {\n return (\n `\\n Note: ${applied_so_far} earlier edit(s) in this batch were already ` +\n \"applied. Batches apply sequentially — each edit must target the document \" +\n \"text as it reads AFTER the preceding edits (e.g. target the replacement \" +\n \"text an earlier edit introduced, not the original wording).\"\n );\n}\n\n// Report placeholder for edits blocked only by OTHER edits' validation\n// failures under the transactional batch contract. Mirrors Python.\nconst TRANSACTIONAL_NOT_APPLIED_ERROR =\n \"Not applied: the batch is transactional and other edits failed \" +\n \"validation (see their errors). Fix or remove those edits and re-run.\";\n\n// Characters XML 1.0 cannot represent: C0 controls except tab/newline/CR.\n// Word refuses to open a package carrying them, and @xmldom serializes them\n// silently, so they must be rejected before they reach the DOM\n// (QA 2026-07-17 F11; mirrors Python's clean per-edit error).\nconst XML_ILLEGAL_CHARS_RE = /[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g;\n\nexport function describe_illegal_control_chars(text: string): string | null {\n if (!text) return null;\n const found = text.match(XML_ILLEGAL_CHARS_RE);\n if (!found) return null;\n const codes = Array.from(new Set(found.map((c) => `0x${c.charCodeAt(0).toString(16).padStart(2, \"0\")}`))).sort();\n return codes.join(\", \");\n}\n\nexport function validate_edit_strings(\n edits: any[],\n index_offset: number = 0,\n): string[] {\n const errors: string[] = [];\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const t_text = edit.target_text || \"\";\n const n_text = edit.new_text || \"\";\n\n // VAL-CRIT-8: XML-illegal control characters (QA 2026-07-17 F11).\n const checked_fields: Array<[string, string]> = [\n [\"target_text\", t_text],\n [\"new_text\", n_text],\n ];\n if (edit.comment) checked_fields.push([\"comment\", edit.comment]);\n (edit.cells || []).forEach((cell: string, cell_idx: number) => {\n checked_fields.push([`cells[${cell_idx}]`, cell || \"\"]);\n });\n for (const [field_name, field_value] of checked_fields) {\n const described = describe_illegal_control_chars(field_value);\n if (described) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: \\`${field_name}\\` contains control character(s) ` +\n `(${described}) that cannot be stored in a DOCX. Remove them and re-submit.`,\n );\n }\n }\n\n if (\n n_text.includes(\"{++\") ||\n n_text.includes(\"{--\") ||\n n_text.includes(\"{>>\") ||\n n_text.includes(\"{==\")\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Do not manually write CriticMarkup tags ({++, {--, {>>, {==) in \\`new_text\\`. The engine handles redlining automatically. To add a comment, use the \\`comment\\` parameter.`,\n );\n }\n\n if (t_text.includes(\"[^\") || n_text.includes(\"[^\")) {\n const t_fns = (t_text.match(/\\[\\^(?:fn|en)-[^\\]]+\\]/g) || []).sort();\n const n_fns = (n_text.match(/\\[\\^(?:fn|en)-[^\\]]+\\]/g) || []).sort();\n if (JSON.stringify(t_fns) !== JSON.stringify(n_fns)) {\n if (\n n_fns.length > t_fns.length ||\n n_fns.some(\n (f: string) =>\n n_fns.filter((x: string) => x === f).length >\n t_fns.filter((x: string) => x === f).length,\n )\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot insert footnote/endnote markers via text replace. Markers like \\`[^fn-N]\\` are read-only projections. Use Word's References menu.`,\n );\n } else {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot delete footnote/endnote references via text replace. The marker corresponds to a structural XML element.`,\n );\n }\n }\n }\n\n if (t_text.includes(\"](\") || n_text.includes(\"](\")) {\n const t_links = (t_text.match(/\\[(?!~)[^\\]]+\\]\\([^)]+\\)/g) || []).sort();\n const n_links = (n_text.match(/\\[(?!~)[^\\]]+\\]\\([^)]+\\)/g) || []).sort();\n if (t_links.length !== n_links.length) {\n if (n_links.length > t_links.length) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot insert hyperlinks via text replace. Use a dedicated structural operation.`,\n );\n } else {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot delete hyperlinks via text replace. The marker corresponds to a structural XML element.`,\n );\n }\n } else if (\n t_links.length > 1 &&\n JSON.stringify(t_links) !== JSON.stringify(n_links)\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Can only edit or retarget one hyperlink per text replacement. Please split into multiple edits.`,\n );\n }\n }\n\n if (t_text.includes(\"[~\") || n_text.includes(\"[~\")) {\n const t_xrefs = t_text.match(/\\[~[^~]+~\\]\\(#[^\\)]+\\)/g) || [];\n const n_xrefs = n_text.match(/\\[~[^~]+~\\]\\(#[^\\)]+\\)/g) || [];\n if (t_xrefs.length !== n_xrefs.length) {\n if (n_xrefs.length > t_xrefs.length) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot insert cross-references via text replace. Markers are read-only projections.`,\n );\n } else {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot delete cross-references via text replace. The marker corresponds to a structural XML element.`,\n );\n }\n } else {\n // Advanced XREF validation simplified for port scope\n if (JSON.stringify(t_xrefs) !== JSON.stringify(n_xrefs)) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Modifying or retargeting cross-reference markers is disallowed to prevent dependency corruption.`,\n );\n }\n }\n }\n\n // QA 2026-07-18 M5: image markers are read-only projections of\n // w:drawing elements. They cannot be fabricated, duplicated or removed\n // through text replacement.\n if (t_text.includes(\"docx-image:\") || n_text.includes(\"docx-image:\")) {\n const t_imgs = (t_text.match(/!\\[[^\\]]*\\]\\(docx-image:[^)]*\\)/g) || []).sort();\n const n_imgs = (n_text.match(/!\\[[^\\]]*\\]\\(docx-image:[^)]*\\)/g) || []).sort();\n if (JSON.stringify(t_imgs) !== JSON.stringify(n_imgs)) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: image markers () are read-only ` +\n \"projections of embedded images. They cannot be inserted, altered, or removed \" +\n \"via text replacement — edit the text around the image instead.\",\n );\n }\n }\n\n if (t_text.includes(\"{#\") || n_text.includes(\"{#\")) {\n const t_anchors = t_text.match(/\\{#[^\\}]+\\}/g) || [];\n const n_anchors = n_text.match(/\\{#[^\\}]+\\}/g) || [];\n for (const a of n_anchors) {\n if (\n n_anchors.filter((x: string) => x === a).length >\n t_anchors.filter((x: string) => x === a).length\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Cannot modify or insert internal anchor markers (\\`{#...}\\`). These represent structural XML bookmarks.`,\n );\n break;\n }\n }\n }\n\n if (edit.type === \"modify\" && n_text) {\n const lines = n_text.split(/[\\r\\n]+/);\n for (const line of lines) {\n const stripped = line.trimStart();\n if (stripped.startsWith(\"#######\")) {\n const level = stripped.length - stripped.replace(/^#+/, \"\").length;\n if (\n stripped.substring(level).startsWith(\" \") ||\n stripped.substring(level) === \"\"\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Heading level ${level} is not supported (maximum is 6).`,\n );\n break;\n }\n }\n }\n }\n\n if (\n t_text.includes(\"READONLY_BOUNDARY_START\") ||\n n_text.includes(\"READONLY_BOUNDARY_START\") ||\n t_text.includes(\"# Document Structure (Read-Only)\") ||\n n_text.includes(\"# Document Structure (Read-Only)\") ||\n t_text.includes(\"Document Structure (Read-Only)\") ||\n n_text.includes(\"Document Structure (Read-Only)\")\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Modification targets the read-only boundary (Structural Appendix). This section cannot be edited.`,\n );\n }\n }\n\n return errors;\n}\n\n// --- Engine ---\nexport class RedlineEngine {\n public doc: DocumentObject;\n public author: string;\n public timestamp: string;\n public current_id: number;\n public mapper: DocumentMapper;\n public comments_manager: CommentsManager;\n public clean_mapper: DocumentMapper | null = null;\n public original_mapper: DocumentMapper | null = null;\n public skipped_details: string[] = [];\n\n constructor(doc: DocumentObject, author: string = \"Adeu AI (TS)\") {\n this.doc = doc;\n this.author = author;\n this.timestamp = new Date().toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n\n const w16du_ns =\n \"http://schemas.microsoft.com/office/word/2023/wordml/word16du\";\n for (const part of this.doc.pkg.parts) {\n if (part === this.doc.part) {\n if (!part._element.hasAttribute(\"xmlns:w16du\")) {\n part._element.setAttribute(\"xmlns:w16du\", w16du_ns);\n }\n }\n }\n\n this.current_id = this._scan_existing_ids();\n this.mapper = new DocumentMapper(this.doc);\n this.comments_manager = new CommentsManager(this.doc);\n }\n\n /**\n * Return a hint when a short, single-token anchor contains punctuation that\n * can split awkwardly, else null.\n *\n * Surface this ONLY for edits that actually failed to match/apply. On a\n * successful edit the batch report already carries the redline preview, so\n * emitting this would be a false positive: the punctuation (dates,\n * `[_name_]` placeholders, `____` blanks) is frequently the literal target\n * and the edit succeeds despite it. Mirrors the Python engine.\n */\n private _check_punctuation_warning(target_text: string): string | null {\n if (!target_text) return null;\n if (target_text.length > 20 || target_text.includes(\" \")) return null;\n if (target_text.includes(\"_\") || target_text.includes(\"-\")) {\n return `Warning: target_text '${target_text}' contains tokenization-splitting punctuation ('_' or '-'). This can trigger mid-word splits in the diff engine. Consider using a longer plain-prose anchor.`;\n }\n return null;\n }\n\n private _word_diff_sub_edits(\n target_str: string,\n new_str: string,\n base_offset: number,\n parent_comment: string | null = null,\n is_table: boolean = false,\n active_mapper: any = null,\n ): any[] {\n let raw_sub_edits: any[] = [];\n try {\n raw_sub_edits = generate_edits_from_text(target_str, new_str);\n } catch (e) {\n console.error(\"generate_edits_from_text failed, falling back to wholesale edit\", e);\n raw_sub_edits = [];\n }\n\n // Hunks made purely of style markers are projection artifacts, never\n // user intent: they arise when a PLAIN target fuzzy-matched styled\n // document text (\"Net 90 Days\" against \"**Net 90 Days**\"), and the\n // resulting `**`-deletion sub-edits target virtual spans that can never\n // apply — phantom skips while the formatting silently stays (QA\n // 2026-07-19 F-02 sibling). Edits that DO declare markers never reach\n // this word-diff path (they resolve as whole-span markdown proxies).\n const _marker_only = (text: string): boolean => {\n const stripped = text.trim();\n return stripped.length > 0 && /^[*_]+$/.test(stripped);\n };\n raw_sub_edits = raw_sub_edits.filter(\n (e: any) =>\n !(\n (!e.target_text || _marker_only(e.target_text)) &&\n (!e.new_text || _marker_only(e.new_text)) &&\n (e.target_text || e.new_text)\n ),\n );\n\n if (!raw_sub_edits || raw_sub_edits.length === 0) {\n const fallback_edit: any = {\n type: \"modify\",\n target_text: target_str,\n new_text: new_str,\n comment: parent_comment,\n };\n fallback_edit._resolved_start_idx = base_offset;\n fallback_edit._match_start_index = base_offset;\n fallback_edit._active_mapper_ref = active_mapper;\n if (is_table) {\n fallback_edit._is_table_edit = true;\n }\n if (target_str === new_str) {\n fallback_edit._internal_op = \"COMMENT_ONLY\";\n } else if (!target_str && new_str) {\n fallback_edit._internal_op = \"INSERTION\";\n } else if (target_str && !new_str) {\n fallback_edit._internal_op = \"DELETION\";\n } else if (target_str && new_str) {\n fallback_edit._internal_op = \"MODIFICATION\";\n } else {\n fallback_edit._internal_op = \"COMMENT_ONLY\";\n }\n return [fallback_edit];\n }\n\n const sub_edits: any[] = [];\n let comment_assigned = false;\n for (const raw_edit of raw_sub_edits) {\n const sub_start = base_offset + (raw_edit._match_start_index || 0);\n const should_attach_comment = (parent_comment !== null) && !comment_assigned;\n if (should_attach_comment) {\n comment_assigned = true;\n }\n\n const sub_edit: any = {\n type: \"modify\",\n target_text: raw_edit.target_text,\n new_text: raw_edit.new_text,\n comment: should_attach_comment ? parent_comment : null,\n };\n sub_edit._resolved_start_idx = sub_start;\n sub_edit._match_start_index = sub_start;\n sub_edit._active_mapper_ref = active_mapper;\n if (is_table) {\n sub_edit._is_table_edit = true;\n }\n\n const t_val = raw_edit.target_text;\n const n_val = raw_edit.new_text;\n if (!t_val && n_val) {\n sub_edit._internal_op = \"INSERTION\";\n } else if (t_val && !n_val) {\n sub_edit._internal_op = \"DELETION\";\n } else if (t_val && n_val) {\n sub_edit._internal_op = \"MODIFICATION\";\n } else {\n sub_edit._internal_op = \"COMMENT_ONLY\";\n }\n\n sub_edits.push(sub_edit);\n }\n\n return sub_edits;\n }\n /**\n * Best-effort \"did you mean\" hint for a failed target. The common loop trap\n * (observed in the field) is an anchored regex like `^\\( x \\)$` against a\n * mid-document string: ^/$ bind to the whole full_text, so it never matches\n * even though the literal `( x )` is present. We strip regex anchoring/escapes\n * and probe full_text for a literal occurrence; if found, we tell the model\n * the exact literal that WOULD match so it drops the anchors instead of\n * escalating the regex further.\n */\n private _nearest_match_hint(\n target_text: string | undefined,\n is_regex: boolean,\n ): string {\n if (!target_text) return \"\";\n let probe = target_text;\n if (is_regex) {\n // Strip leading/trailing anchors and surrounding \\s* the model tends to add.\n probe = probe.replace(/^\\^/, \"\").replace(/\\$$/, \"\");\n probe = probe.replace(/^\\\\s\\*/, \"\").replace(/\\\\s\\*$/, \"\");\n // Unescape the common literal escapes so \"\\( x \\)\" -> \"( x )\".\n probe = probe.replace(/\\\\([.^$*+?()[\\]{}|\\\\/])/g, \"$1\");\n }\n probe = probe.trim();\n if (!probe || probe === target_text) {\n // No anchors to strip, or nothing changed: nothing useful to suggest.\n if (!is_regex) return \"\";\n }\n const idx = this.mapper.full_text.indexOf(probe);\n if (idx !== -1) {\n const ctx_start = Math.max(0, idx - 15);\n const ctx_end = Math.min(\n this.mapper.full_text.length,\n idx + probe.length + 15,\n );\n const ctx = this.mapper.full_text\n .substring(ctx_start, ctx_end)\n .replace(/\\n/g, \" \");\n return (\n `\\n Did you mean the literal \"${probe}\"? It appears in the document` +\n ` (…${ctx}…). If you used a regex, drop the ^/$ anchors — they match` +\n ` the start/end of the entire document, not a line.`\n );\n }\n return \"\";\n }\n // CriticMarkup wrapper pairs used when tidying preview context windows.\n private static readonly _PREVIEW_WRAPPER_PAIRS: [string, string][] = [\n [\"{--\", \"--}\"],\n [\"{++\", \"++}\"],\n [\"{==\", \"==}\"],\n [\"{>>\", \"<<}\"],\n ];\n\n /**\n * Makes a fixed-width slice of the raw-view projection presentable: drops\n * complete {>>...<<} meta blocks (annotations of pre-existing changes, not\n * part of this edit) and any wrapper fragments the window boundary chopped\n * in half. Without this, previews leak internal scaffolding like\n * \"[Chg:5 delete]\" (QA H1). Mirrors the Python engine.\n */\n private static _tidy_preview_context(\n snippet: string,\n side: \"before\" | \"after\",\n ): string {\n snippet = snippet.replace(/\\{>>[\\s\\S]*?<<\\}/g, \"\");\n\n for (const [open_tok, close_tok] of RedlineEngine._PREVIEW_WRAPPER_PAIRS) {\n if (side === \"before\") {\n // Cut through the last closer whose opener lies left of the window.\n let depth = 0;\n let cut = 0;\n let i = 0;\n while (i < snippet.length) {\n if (snippet.startsWith(open_tok, i)) {\n depth += 1;\n i += open_tok.length;\n } else if (snippet.startsWith(close_tok, i)) {\n if (depth === 0) cut = i + close_tok.length;\n else depth -= 1;\n i += close_tok.length;\n } else {\n i += 1;\n }\n }\n snippet = snippet.substring(cut);\n } else {\n // Cut from the first opener whose closer lies right of the window.\n const opens: number[] = [];\n let i = 0;\n while (i < snippet.length) {\n if (snippet.startsWith(open_tok, i)) {\n opens.push(i);\n i += open_tok.length;\n } else if (snippet.startsWith(close_tok, i)) {\n if (opens.length > 0) opens.pop();\n i += close_tok.length;\n } else {\n i += 1;\n }\n }\n if (opens.length > 0) snippet = snippet.substring(0, opens[0]);\n }\n }\n\n // 1-2 char remnants of a 3-char wrapper token chopped by the window edge.\n if (side === \"before\") {\n snippet = snippet.replace(/^[-+=<>]{0,2}\\}/, \"\");\n } else {\n snippet = snippet.replace(/\\{[-+=<>]{0,2}$/, \"\");\n }\n return snippet;\n }\n\n /**\n * Snapshots the document text around a resolved edit BEFORE anything is\n * applied. Previews rendered after the batch mutates the DOM cannot slice\n * full_text at the stored offsets: applied edits shift offsets and inject\n * tracked-change markup, garbling previews with unrelated edits and\n * internal scaffolding (QA H1).\n */\n private _capture_preview_context(edit: any): void {\n if (edit.type !== \"modify\") return;\n const start_idx = edit._resolved_start_idx;\n if (start_idx === undefined || start_idx === null) return;\n const active_mapper = edit._active_mapper_ref || this.mapper;\n const full_text = active_mapper.full_text;\n if (!full_text) return;\n const length = (edit.target_text || \"\").length;\n const before = full_text.substring(\n Math.max(0, start_idx - PREVIEW_CONTEXT_CHARS),\n start_idx,\n );\n const after = full_text.substring(\n start_idx + length,\n start_idx + length + PREVIEW_CONTEXT_CHARS,\n );\n edit._preview_context = [\n RedlineEngine._tidy_preview_context(before, \"before\"),\n RedlineEngine._tidy_preview_context(after, \"after\"),\n ];\n }\n\n /**\n * Like _capture_preview_context, but snapshots the context around the\n * ORIGINAL edit's full matched span (stashed by _pre_resolve_heuristic_edit),\n * so the report preview can present the complete logical change of a\n * compound modification instead of its first sub-edit.\n */\n private _capture_parent_preview_context(parent: any): void {\n if (!parent || parent.type !== \"modify\") return;\n if (parent._preview_context || !parent._preview_span) return;\n const [start_idx, match_len] = parent._preview_span;\n const active_mapper = parent._preview_mapper_ref || this.mapper;\n const full_text = active_mapper.full_text;\n if (!full_text) return;\n const before = full_text.substring(\n Math.max(0, start_idx - PREVIEW_CONTEXT_CHARS),\n start_idx,\n );\n const after = full_text.substring(\n start_idx + match_len,\n start_idx + match_len + PREVIEW_CONTEXT_CHARS,\n );\n parent._preview_context = [\n RedlineEngine._tidy_preview_context(before, \"before\"),\n RedlineEngine._tidy_preview_context(after, \"after\"),\n ];\n }\n\n /**\n * Renders the preview from the edit's full matched span. The common\n * prefix/suffix between matched and replacement text is moved into the\n * surrounding context so the {--...--}{++...++} block shows the minimal\n * complete change.\n */\n private _build_full_match_preview(edit: any): [string | null, string | null] {\n let [context_before, context_after] = edit._preview_context as [\n string,\n string,\n ];\n let matched: string = edit._preview_matched_text || \"\";\n let new_text: string =\n edit._preview_new_text !== undefined && edit._preview_new_text !== null\n ? edit._preview_new_text\n : edit.new_text || \"\";\n\n // Heading markdown prefixes are projection artifacts, not literal\n // document text — keep them out of the {--...--}/{++...++} body.\n const [matched_clean, matched_style] = this._parse_markdown_style(matched);\n const [new_clean, new_style] = this._parse_markdown_style(new_text);\n if (matched_style && matched_style.startsWith(\"Heading\")) {\n context_before = context_before + matched.substring(0, matched.length - matched_clean.length);\n matched = matched_clean;\n }\n if (new_style && new_style.startsWith(\"Heading\")) {\n new_text = new_clean;\n }\n\n const [prefix_len, suffix_len] = trim_common_context(matched, new_text);\n let display_target = matched.substring(\n prefix_len,\n matched.length - suffix_len,\n );\n let display_new = new_text.substring(\n prefix_len,\n new_text.length - suffix_len,\n );\n context_before = context_before + matched.substring(0, prefix_len);\n if (suffix_len) {\n context_after = matched.substring(matched.length - suffix_len) + context_after;\n }\n\n display_target = truncate_middle(display_target, PREVIEW_TEXT_CAP);\n display_new = truncate_middle(display_new, PREVIEW_TEXT_CAP);\n let critic_markup: string;\n if (!display_target && !display_new) {\n // Comment-only edit (text unchanged): highlight the anchor instead of\n // rendering an empty change.\n const anchor = truncate_middle(matched, PREVIEW_TEXT_CAP);\n const body = anchor ? `{==${anchor}==}` : \"\";\n critic_markup = `${context_before.substring(0, context_before.length - matched.length)}${body}${context_after}`;\n } else {\n const deletion = display_target ? `{--${display_target}--}` : \"\";\n const insertion = display_new ? `{++${display_new}++}` : \"\";\n critic_markup = `${context_before}${deletion}${insertion}${context_after}`;\n }\n\n let clean_text = critic_markup;\n clean_text = clean_text.replace(/\\{>>[\\s\\S]*?<<\\}/g, \"\");\n clean_text = clean_text.replace(/\\{--[\\s\\S]*?--\\}/g, \"\");\n clean_text = clean_text.replace(/\\{\\+\\+([\\s\\S]*?)\\+\\+\\}/g, \"$1\");\n return [critic_markup, clean_text];\n }\n\n /**\n * The \"new text\" a batch report should show for an edit. InsertTableRow has\n * no new_text field — surface its cell contents rather than a misleading\n * empty string (QA M4).\n */\n private static _report_new_text(edit: any): string {\n if (edit && edit.type === \"insert_row\" && Array.isArray(edit.cells)) {\n return edit.cells.join(\" | \");\n }\n return (edit && edit.new_text) || \"\";\n }\n\n private _build_edit_context_previews(\n edit: any,\n ): [string | null, string | null] {\n if (edit.type !== \"modify\") return [null, null];\n if (edit._preview_span && edit._preview_context) {\n return this._build_full_match_preview(edit);\n }\n if (edit._resolved_proxy_edit) {\n edit = edit._resolved_proxy_edit;\n }\n let start_idx = edit._resolved_start_idx;\n if (start_idx === undefined || start_idx === null) return [null, null];\n let target_text = edit.target_text || \"\";\n let new_text = edit.new_text || \"\";\n\n const [clean_target, target_style] =\n this._parse_markdown_style(target_text);\n if (target_style && target_style.startsWith(\"Heading\")) {\n const prefix_len = target_text.length - clean_target.length;\n start_idx += prefix_len;\n target_text = clean_target;\n }\n\n const [clean_new, new_style] = this._parse_markdown_style(new_text);\n if (new_style && new_style.startsWith(\"Heading\")) {\n new_text = clean_new;\n }\n\n const length = target_text.length;\n let context_before: string;\n let context_after: string;\n if (edit._preview_context) {\n [context_before, context_after] = edit._preview_context;\n } else {\n // Fallback for callers that never went through apply_edits. Only safe\n // while the mapper still reflects the pre-apply document.\n const active_mapper = edit._active_mapper_ref || this.mapper;\n const full_text = active_mapper.full_text;\n if (!full_text) return [null, null];\n context_before = RedlineEngine._tidy_preview_context(\n full_text.substring(\n Math.max(0, start_idx - PREVIEW_CONTEXT_CHARS),\n start_idx,\n ),\n \"before\",\n );\n context_after = RedlineEngine._tidy_preview_context(\n full_text.substring(\n start_idx + length,\n start_idx + length + PREVIEW_CONTEXT_CHARS,\n ),\n \"after\",\n );\n }\n\n // Bound the echoed edit values: previews flow into LLM context windows\n // and must not multiply an oversized new_text/target_text (QA C2).\n const display_target = truncate_middle(target_text, PREVIEW_TEXT_CAP);\n const display_new = truncate_middle(new_text, PREVIEW_TEXT_CAP);\n const insertion = display_new ? `{++${display_new}++}` : \"\";\n const critic_markup = `${context_before}{--${display_target}--}${insertion}${context_after}`;\n\n let clean_text = critic_markup;\n clean_text = clean_text.replace(/\\{>>.*?<<\\}/gs, \"\");\n clean_text = clean_text.replace(/\\{--.*?--\\}/gs, \"\");\n clean_text = clean_text.replace(/\\{\\+\\+(.*?)\\+\\+\\}/gs, \"$1\");\n\n return [critic_markup, clean_text];\n }\n\n private _scan_existing_ids(): number {\n let maxId = 0;\n for (const tag of [\"w:ins\", \"w:del\"]) {\n const elements = findAllDescendants(this.doc.element, tag);\n for (const el of elements) {\n const val = parseInt(el.getAttribute(\"w:id\") || \"0\", 10);\n if (!isNaN(val) && val > maxId) maxId = val;\n }\n }\n return maxId;\n }\n\n private _get_heading_path_and_page(\n start_idx: number,\n text: string,\n page_offsets: number[],\n ): [string, number] {\n let page = 1;\n for (let i = 0; i < page_offsets.length; i++) {\n if (start_idx >= page_offsets[i]) {\n page = i + 1;\n } else {\n break;\n }\n }\n\n const textBefore = text.substring(0, start_idx);\n const lines = textBefore.split(\"\\n\");\n const path: string[] = [];\n let current_level = 999;\n\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i];\n const m = line.match(/^(#{1,6})\\s+(.*)/);\n if (m) {\n const level = m[1].length;\n if (level < current_level) {\n let cleanHeading = m[2]\n .replace(/\\*\\*|__|[*_]/g, \"\")\n .replace(/\\{#[^}]+\\}/g, \"\")\n .trim();\n if (cleanHeading.length > 80) {\n cleanHeading = cleanHeading.substring(0, 80) + \"...\";\n }\n path.unshift(cleanHeading);\n current_level = level;\n if (level === 1) break;\n }\n }\n }\n return [path.join(\" > \"), page];\n }\n\n public accept_all_revisions() {\n const parts_to_process: Element[] = [this.doc.element];\n\n for (const part of this.doc.pkg.parts) {\n if (part === this.doc.part) continue;\n if (\n part.contentType.includes(\"wordprocessingml\") &&\n part.contentType.endsWith(\"+xml\")\n ) {\n parts_to_process.push(part._element);\n }\n }\n\n // Pre-count revisions before mutating. Unit is REVISION ELEMENTS, matching\n // the Python engine and sanitize's count_tracked_changes so no two surfaces\n // report different totals for one document.\n let accepted_insertions = 0;\n let accepted_deletions = 0;\n let accepted_formatting = 0;\n for (const root_element of parts_to_process) {\n accepted_insertions += findAllDescendants(root_element, \"w:ins\").length;\n accepted_deletions += findAllDescendants(root_element, \"w:del\").length;\n for (const tag of [\"w:rPrChange\", \"w:pPrChange\", \"w:sectPrChange\"]) {\n accepted_formatting += findAllDescendants(root_element, tag).length;\n }\n }\n\n // Counted as it happens below, not pre-read from the comments part: this\n // method only deletes the bodies of OUR OWN comments wrapping a resolved\n // revision (foreign ones keep their body by design), so the document's\n // comment total would claim removals that never happened.\n let removed_comments = 0;\n\n for (const root_element of parts_to_process) {\n const insNodes = findAllDescendants(root_element, \"w:ins\");\n for (const ins of insNodes) {\n removed_comments += this._clean_wrapping_comments(ins);\n const parent = ins.parentNode as Element | null;\n if (!parent) continue;\n\n if (parent.tagName === \"w:trPr\") {\n parent.removeChild(ins);\n continue;\n }\n\n while (ins.firstChild) {\n parent.insertBefore(ins.firstChild, ins);\n }\n parent.removeChild(ins);\n }\n\n const pNodes = findAllDescendants(root_element, \"w:p\");\n for (const p of pNodes) {\n const pPr = findChild(p, \"w:pPr\");\n if (pPr) {\n const rPr = findChild(pPr, \"w:rPr\");\n const delMark = rPr ? findChild(rPr, \"w:del\") : null;\n if (rPr && delMark) {\n let has_content = false;\n for (const tag of [\"w:t\", \"w:tab\", \"w:br\"]) {\n for (const child of findAllDescendants(p, tag)) {\n if (tag === \"w:t\" && !child.textContent) continue;\n\n let is_deleted = false;\n let curr = child.parentNode as Element | null;\n while (curr && curr !== p) {\n if (curr.tagName === \"w:del\") {\n is_deleted = true;\n break;\n }\n curr = curr.parentNode as Element | null;\n }\n if (!is_deleted) {\n has_content = true;\n break;\n }\n }\n if (has_content) {\n break;\n }\n }\n if (has_content) {\n rPr.removeChild(delMark);\n } else {\n removed_comments += this._clean_wrapping_comments(p);\n removed_comments += this._delete_comments_in_element(p);\n if (p.parentNode) {\n p.parentNode.removeChild(p);\n }\n }\n }\n }\n }\n\n const delNodes = findAllDescendants(root_element, \"w:del\");\n for (const d of delNodes) {\n removed_comments += this._clean_wrapping_comments(d);\n removed_comments += this._delete_comments_in_element(d);\n const parent = d.parentNode as Element | null;\n if (parent) {\n if (parent.tagName === \"w:trPr\") {\n const row = parent.parentNode as Element | null;\n if (row && row.parentNode) {\n row.parentNode.removeChild(row);\n }\n } else {\n parent.removeChild(d);\n }\n }\n }\n }\n\n // Final pass: completely eject all comments, anchors, and parts\n for (const root_element of parts_to_process) {\n for (const tag of [\"w:commentRangeStart\", \"w:commentRangeEnd\"]) {\n for (const el of findAllDescendants(root_element, tag)) {\n el.parentNode?.removeChild(el);\n }\n }\n\n const refs = findAllDescendants(root_element, \"w:commentReference\");\n for (const ref of refs) {\n const parent = ref.parentNode as Element | null;\n if (parent) {\n if (parent.tagName === \"w:r\" || parent.tagName.endsWith(\":r\")) {\n const nonRprChildren = Array.from(parent.childNodes).filter(\n (c) =>\n c.nodeType === 1 &&\n (c as Element).tagName !== \"w:rPr\" &&\n (c as Element).tagName !== \"rPr\",\n );\n if (nonRprChildren.length <= 1) {\n parent.parentNode?.removeChild(parent);\n } else {\n parent.removeChild(ref);\n }\n } else {\n parent.removeChild(ref);\n }\n }\n }\n }\n\n const pkg = this.doc.pkg;\n const comment_partnames = new Set<string>();\n for (const part of pkg.parts) {\n if (part.partname.toLowerCase().includes(\"comments\")) {\n comment_partnames.add(part.partname);\n const withSlash = part.partname.startsWith(\"/\")\n ? part.partname\n : \"/\" + part.partname;\n const withoutSlash = part.partname.startsWith(\"/\")\n ? part.partname.substring(1)\n : part.partname;\n comment_partnames.add(withSlash);\n comment_partnames.add(withoutSlash);\n }\n }\n\n if (comment_partnames.size > 0) {\n // Sever relationships referencing comments\n for (const part of pkg.parts) {\n if (part.partname.endsWith(\".rels\")) {\n const rels = findAllDescendants(part._element, \"Relationship\");\n const toRemove: Element[] = [];\n for (const rel of rels) {\n const target = rel.getAttribute(\"Target\") || \"\";\n if (target.toLowerCase().includes(\"comments\")) {\n toRemove.push(rel);\n\n const sourcePath = part.partname\n .replace(\"/_rels/\", \"/\")\n .replace(\".rels\", \"\");\n const sourcePart = pkg.getPartByPath(sourcePath);\n if (sourcePart) {\n const relId = rel.getAttribute(\"Id\");\n if (relId) sourcePart.rels.delete(relId);\n }\n }\n }\n for (const relEl of toRemove) {\n relEl.parentNode?.removeChild(relEl);\n }\n }\n }\n\n // Remove overrides from [Content_Types].xml\n const ctPart = pkg.getPartByPath(\"[Content_Types].xml\");\n if (ctPart) {\n const overrides = findAllDescendants(ctPart._element, \"Override\");\n const toRemove: Element[] = [];\n for (const override of overrides) {\n const partName = override.getAttribute(\"PartName\") || \"\";\n if (\n comment_partnames.has(partName) ||\n partName.toLowerCase().includes(\"comments\")\n ) {\n toRemove.push(override);\n }\n }\n for (const overrideEl of toRemove) {\n overrideEl.parentNode?.removeChild(overrideEl);\n }\n }\n\n // Remove comment parts from pkg.parts\n pkg.parts = pkg.parts.filter(\n (p) => !p.partname.toLowerCase().includes(\"comments\"),\n );\n\n // Remove comment files from pkg.unzipped\n for (const key of Object.keys(pkg.unzipped)) {\n if (key.toLowerCase().includes(\"comments\")) {\n delete pkg.unzipped[key];\n }\n }\n }\n\n return {\n accepted_insertions,\n accepted_deletions,\n accepted_formatting,\n removed_comments,\n };\n }\n\n /**\n * Revert every tracked change, returning the document to the state it had\n * before any revision was proposed. The exact inverse of\n * accept_all_revisions:\n *\n * - <w:ins> -> removed together with all of its content (the proposed\n * insertion never existed); an inserted row (<w:ins> in\n * <w:trPr>) drops the whole row.\n * - <w:del> -> unwrapped, restoring the original text (<w:delText> becomes\n * <w:t> again); a row-deletion mark in <w:trPr> is removed so\n * the row survives.\n * - paragraph-mark <w:del> in pPr/rPr -> removed, undoing a proposed merge.\n *\n * Comments are annotations, not revisions, so standalone comments are left in\n * place; only anchors stranded inside a rejected insertion are cleaned up.\n *\n * Insertions are reverted before deletions are restored so a deletion nested\n * inside a foreign author's insertion is removed wholesale with the insertion\n * — the contingent text disappears rather than being promoted to committed\n * body text.\n *\n * Known limitation: tracked paragraph STRUCTURE changes (a split recorded as a\n * pilcrow <w:ins>, or a merge recorded as a pilcrow <w:del>) are reverted only\n * to the extent of dropping/keeping the mark; the original paragraph boundary\n * is not reconstructed, because the merge protocol coalesces paragraphs\n * destructively at edit time. Reverting run-level insertions/deletions (the\n * common case) is exact. This limitation is shared with the Python engine.\n */\n public reject_all_revisions() {\n const parts_to_process: Element[] = [this.doc.element];\n\n for (const part of this.doc.pkg.parts) {\n if (part === this.doc.part) continue;\n if (\n part.contentType.includes(\"wordprocessingml\") &&\n part.contentType.endsWith(\"+xml\")\n ) {\n parts_to_process.push(part._element);\n }\n }\n\n for (const root_element of parts_to_process) {\n // 1. Reject insertions: drop the <w:ins> and everything inside it.\n // Document order means an outer <w:ins> is handled before a nested\n // one; removing the outer detaches the inner (guarded below).\n const insNodes = findAllDescendants(root_element, \"w:ins\");\n for (const ins of insNodes) {\n const parent = ins.parentNode as Element | null;\n if (!parent) continue;\n this._clean_wrapping_comments(ins);\n this._delete_comments_in_element(ins);\n if (parent.tagName === \"w:trPr\") {\n const row = parent.parentNode as Element | null;\n if (row && row.parentNode) {\n row.parentNode.removeChild(row);\n }\n } else {\n parent.removeChild(ins);\n }\n }\n\n // 2. Reject paragraph-mark deletions: keep the paragraph break.\n const pNodes = findAllDescendants(root_element, \"w:p\");\n for (const p of pNodes) {\n const pPr = findChild(p, \"w:pPr\");\n if (pPr) {\n const rPr = findChild(pPr, \"w:rPr\");\n const delMark = rPr ? findChild(rPr, \"w:del\") : null;\n if (rPr && delMark) {\n rPr.removeChild(delMark);\n }\n }\n }\n\n // 3. Reject deletions: restore the original text.\n const delNodes = findAllDescendants(root_element, \"w:del\");\n for (const d of delNodes) {\n const parent = d.parentNode as Element | null;\n if (!parent) continue;\n this._clean_wrapping_comments(d);\n if (parent.tagName === \"w:trPr\") {\n parent.removeChild(d);\n continue;\n }\n const delTexts = Array.from(d.getElementsByTagName(\"w:delText\"));\n for (const dt of delTexts) {\n const t = d.ownerDocument!.createElement(\"w:t\");\n t.textContent = dt.textContent;\n if (dt.hasAttribute(\"xml:space\"))\n t.setAttribute(\"xml:space\", \"preserve\");\n dt.parentNode?.replaceChild(t, dt);\n }\n while (d.firstChild) {\n parent.insertBefore(d.firstChild, d);\n }\n parent.removeChild(d);\n }\n }\n }\n\n private _getNextId(): string {\n this.current_id++;\n return this.current_id.toString();\n }\n\n private _create_track_change_tag(\n tagName: string,\n author: string = \"\",\n reuseId: string | null = null,\n ): Element {\n const xmlDoc = this.doc.part._element.ownerDocument!;\n const tag = xmlDoc.createElement(tagName);\n const wid = reuseId !== null ? reuseId : this._getNextId();\n tag.setAttribute(\"w:id\", wid);\n tag.setAttribute(\"w:author\", author || this.author);\n tag.setAttribute(\"w:date\", this.timestamp);\n tag.setAttribute(\"w16du:dateUtc\", this.timestamp);\n return tag;\n }\n\n private _set_text_content(element: Element, text: string) {\n element.textContent = text;\n if (text.trim() !== text) {\n element.setAttribute(\"xml:space\", \"preserve\");\n }\n }\n\n /**\n * Walks `element` to its XML root element. Word (and LibreOffice, which\n * refuses to LOAD such files) only supports comment ranges in the main\n * document story (\"w:document\") — never in headers, footers, footnotes or\n * endnotes (QA 2026-07-18 H4/C1).\n */\n private _comment_anchor_in_main_story(element: Element): boolean {\n let root: Element = element;\n while (root.parentNode && root.parentNode.nodeType === 1) {\n root = root.parentNode as Element;\n }\n return root.tagName === \"w:document\";\n }\n\n /**\n * When the anchor lives outside the main document story, records a\n * user-visible warning and returns true (caller must skip the comment).\n * The tracked change itself still applies — only the bubble is dropped.\n */\n private _skip_comment_outside_main_story(\n element: Element,\n text: string,\n ): boolean {\n if (this._comment_anchor_in_main_story(element)) return false;\n let root: Element = element;\n while (root.parentNode && root.parentNode.nodeType === 1) {\n root = root.parentNode as Element;\n }\n const story =\n (\n {\n \"w:ftr\": \"footer\",\n \"w:hdr\": \"header\",\n \"w:footnotes\": \"footnote\",\n \"w:endnotes\": \"endnote\",\n } as Record<string, string>\n )[root.tagName] || \"non-body\";\n const msg =\n `- Warning: the comment \"${text.substring(0, 60)}\" was NOT attached: Word does not support ` +\n `comments inside a ${story} part, and writing one produces a document other ` +\n \"applications cannot open. The tracked change itself was applied.\";\n this.skipped_details.push(msg);\n console.error(\n `Comment anchor outside main story; comment dropped (story=${story})`,\n );\n return true;\n }\n\n /**\n * Attaches a comment that wraps a contiguous range within a single paragraph.\n * start_element and end_element must both be direct children of parent_element\n * and start_element must come before (or equal) end_element in document order.\n * Ported from Python `RedlineEngine._attach_comment`.\n */\n private _attach_comment(\n parent_element: Element,\n start_element: Element,\n end_element: Element,\n text: string,\n ) {\n if (!text) return;\n if (!parent_element || !start_element || !end_element) return;\n if (this._skip_comment_outside_main_story(parent_element, text)) return;\n\n const comment_id = this.comments_manager.addComment(this.author, text);\n const xmlDoc = parent_element.ownerDocument!;\n\n const range_start = xmlDoc.createElement(\"w:commentRangeStart\");\n range_start.setAttribute(\"w:id\", comment_id);\n\n const range_end = xmlDoc.createElement(\"w:commentRangeEnd\");\n range_end.setAttribute(\"w:id\", comment_id);\n\n const ref_run = xmlDoc.createElement(\"w:r\");\n const rPr = xmlDoc.createElement(\"w:rPr\");\n const rStyle = xmlDoc.createElement(\"w:rStyle\");\n rStyle.setAttribute(\"w:val\", \"CommentReference\");\n rPr.appendChild(rStyle);\n ref_run.appendChild(rPr);\n\n const ref = xmlDoc.createElement(\"w:commentReference\");\n ref.setAttribute(\"w:id\", comment_id);\n ref_run.appendChild(ref);\n\n // Insert <w:commentRangeStart> immediately before start_element.\n // Insert <w:commentRangeEnd> immediately after end_element.\n // Insert <w:r><w:commentReference/></w:r> immediately after the range end.\n parent_element.insertBefore(range_start, start_element);\n\n // After insertBefore above, sibling positions shifted. Re-find end_element's next sibling.\n const after_end = end_element.nextSibling;\n if (after_end) {\n parent_element.insertBefore(range_end, after_end);\n parent_element.insertBefore(ref_run, range_end.nextSibling);\n } else {\n parent_element.appendChild(range_end);\n parent_element.appendChild(ref_run);\n }\n }\n\n /**\n * Attaches a comment that spans across two different paragraphs (or other block\n * containers). start_element lives inside start_p, end_element lives inside end_p,\n * and the comment is open from start_element through end_element.\n * Ported from Python `RedlineEngine._attach_comment_spanning`.\n */\n private _attach_comment_spanning(\n start_p: Element,\n start_el: Element,\n end_p: Element,\n end_el: Element,\n text: string,\n ) {\n if (!text) return;\n if (!start_p || !end_p) return;\n if (\n this._skip_comment_outside_main_story(start_p, text) ||\n this._skip_comment_outside_main_story(end_p, text)\n )\n return;\n\n const comment_id = this.comments_manager.addComment(this.author, text);\n const xmlDocStart = start_p.ownerDocument!;\n const xmlDocEnd = end_p.ownerDocument!;\n\n const range_start = xmlDocStart.createElement(\"w:commentRangeStart\");\n range_start.setAttribute(\"w:id\", comment_id);\n\n const range_end = xmlDocEnd.createElement(\"w:commentRangeEnd\");\n range_end.setAttribute(\"w:id\", comment_id);\n\n const ref_run = xmlDocEnd.createElement(\"w:r\");\n const rPr = xmlDocEnd.createElement(\"w:rPr\");\n const rStyle = xmlDocEnd.createElement(\"w:rStyle\");\n rStyle.setAttribute(\"w:val\", \"CommentReference\");\n rPr.appendChild(rStyle);\n ref_run.appendChild(rPr);\n\n const ref = xmlDocEnd.createElement(\"w:commentReference\");\n ref.setAttribute(\"w:id\", comment_id);\n ref_run.appendChild(ref);\n\n // Place range start before start_el.\n start_p.insertBefore(range_start, start_el);\n\n // Place range end + reference run after end_el.\n const after_end = end_el.nextSibling;\n if (after_end) {\n end_p.insertBefore(range_end, after_end);\n end_p.insertBefore(ref_run, range_end.nextSibling);\n } else {\n end_p.appendChild(range_end);\n end_p.appendChild(ref_run);\n }\n }\n\n /**\n * Inserts `text` as one or more tracked paragraphs anchored relative to\n * either an existing run or a paragraph. Returns:\n * { first_node, last_p, last_ins, used_block_mode }\n * where:\n * - first_node: the first <w:ins> (for inline mode) OR the first new <w:p>\n * (for block mode). The caller uses this for splicing into the DOM and\n * for anchoring comments.\n * - last_p: the last new <w:p> created, if any. null when entirely inline.\n * - last_ins: the last <w:ins> created (inside the last new <w:p>, or the\n * sole inline ins). Used as the comment's end anchor.\n * - used_block_mode: true when the first line carried a heading/list style\n * marker and we created a new paragraph for it (rather than inlining it).\n *\n * Multi-paragraph rules (only when text contains '\\n'):\n * - Each additional line becomes a new <w:p>, inserted after the anchor\n * paragraph in document order.\n * - Each new <w:p> gets a copy of the anchor paragraph's <w:pPr> (so list\n * numbering / indentation are preserved) unless the line itself starts\n * with a markdown heading or list marker, which overrides the style.\n * - Each new <w:p> carries a tracked paragraph-break marker\n * (<w:pPr><w:rPr><w:ins/></w:rPr></w:pPr>) so Word natively tracks the\n * paragraph break.\n * - Each new <w:p>'s content is wrapped in a <w:ins>, with inline bold/\n * italic markdown parsed via _parse_inline_markdown.\n *\n * The first line:\n * - If it carries a heading / list marker AND we have a paragraph anchor,\n * we drop into \"block mode\": no inline <w:ins>; the first line itself\n * becomes the first new <w:p>.\n * - Otherwise we emit a single inline <w:ins> for the first line (current\n * behaviour) and treat the remaining lines as block extensions.\n *\n * Does NOT attach comments; callers handle that.\n */\n private _clone_pPr_scrubbing_headings(existing_pPr: Element): Element {\n const pPr_clone = existing_pPr.cloneNode(true) as Element;\n const pStyle_el = findChild(pPr_clone, \"w:pStyle\");\n if (pStyle_el) {\n const style_val = pStyle_el.getAttribute(\"w:val\");\n if (style_val) {\n const is_heading =\n style_val.startsWith(\"Heading\") ||\n style_val === \"Title\" ||\n style_val.replace(/\\s+/g, \"\").startsWith(\"Heading\");\n if (is_heading) {\n pPr_clone.removeChild(pStyle_el);\n }\n }\n }\n const outlineLvl_el = findChild(pPr_clone, \"w:outlineLvl\");\n if (outlineLvl_el) {\n pPr_clone.removeChild(outlineLvl_el);\n }\n return pPr_clone;\n }\n\n private _track_insert_multiline(\n text: string,\n anchor_run: Run | null,\n anchor_paragraph: Paragraph | null,\n reuse_id: string,\n // The attached DOM element the insertion physically follows. anchor_run\n // supplies STYLING and may already be detached (the deletion step clones\n // runs into <w:del> and replaces the originals); suffix relocation for\n // paragraph-splitting insertions keys on this element instead.\n positional_anchor_el: Element | null = null,\n // When the edit declares explicit emphasis markers, the markers are\n // authoritative: strip inherited bold/italic from the anchor style\n // (QA 2026-07-19 F-02).\n suppress_emphasis: boolean = false,\n // True when the caller will attach the insertion BEFORE the anchor\n // (paragraph-start insertions): the anchor itself then belongs to the\n // relocating suffix (hunt-profile counterexample, 2026-07-19 —\n // \"00.\" + insert \"0.\\n\\n0 \" must read \"0.\\n\\n0 00.\", never\n // \"0.00.\\n\\n0 \"). Mirrors the Python engine.\n insert_before: boolean = false,\n ): {\n first_node: Element | null;\n last_p: Element | null;\n last_ins: Element | null;\n used_block_mode: boolean;\n } {\n if (!text) {\n return {\n first_node: null,\n last_p: null,\n last_ins: null,\n used_block_mode: false,\n };\n }\n\n const xmlDoc = this.doc.part._element.ownerDocument!;\n const lines = text.split(/[\\r\\n]+/);\n\n // Resolve the containing <w:p> (current_p) for the anchor.\n let current_p: Element | null = null;\n if (anchor_paragraph !== null) {\n current_p = anchor_paragraph._element;\n } else if (anchor_run !== null) {\n let walker: Element | null = anchor_run._element;\n while (walker && walker.tagName !== \"w:p\") {\n walker = walker.parentNode as Element | null;\n }\n current_p = walker;\n }\n\n // Suffix nodes: content that follows the anchor inside current_p. When\n // the inserted text carries paragraph breaks, this content belongs in\n // the LAST new paragraph. The positional anchor is attached to the\n // DOM, and the insertion lands immediately after it, so its following\n // child-of-paragraph siblings are exactly the suffix.\n const suffix_nodes: Element[] = [];\n const relocatable = new Set([\"w:r\", \"w:ins\", \"w:del\"]);\n // insert_before with a RUN anchor: the insertion precedes the anchor, so\n // the anchor run itself is part of the suffix. (The explicit\n // positional_anchor_el is only passed by flows that insert AFTER it.)\n const pos_from_positional =\n positional_anchor_el && positional_anchor_el.parentNode\n ? positional_anchor_el\n : null;\n const pos_from_anchor_run =\n anchor_run !== null && anchor_run._element.parentNode\n ? anchor_run._element\n : null;\n const pos_source = pos_from_positional ?? pos_from_anchor_run;\n const suffix_includes_anchor =\n insert_before && pos_from_positional === null && pos_from_anchor_run !== null;\n if (current_p !== null && pos_source !== null) {\n let pos_anchor: Element | null = pos_source;\n while (pos_anchor && pos_anchor.parentNode !== current_p) {\n pos_anchor = pos_anchor.parentNode as Element | null;\n if (pos_anchor === current_p) {\n pos_anchor = null;\n break;\n }\n }\n if (pos_anchor) {\n let nxt: Node | null = suffix_includes_anchor\n ? pos_anchor\n : pos_anchor.nextSibling;\n while (nxt) {\n if (nxt.nodeType === 1 && relocatable.has((nxt as Element).tagName)) {\n suffix_nodes.push(nxt as Element);\n }\n nxt = nxt.nextSibling;\n }\n }\n } else if (current_p !== null && insert_before) {\n // No attached anchor run at all (paragraph-anchored insertion at\n // paragraph START): everything in the host paragraph follows the\n // insertion point, so it all relocates (mirrors the Python engine).\n let child = current_p.firstChild;\n while (child) {\n if (\n child.nodeType === 1 &&\n relocatable.has((child as Element).tagName)\n ) {\n suffix_nodes.push(child as Element);\n }\n child = child.nextSibling;\n }\n }\n\n // Drop the trailing empty line ONLY when there is no suffix to relocate.\n // \"foo\\n\\nbar\\n\\n\" splits to ['foo', '', 'bar', '']; without a suffix\n // the trailing empty is just a terminator, but with one it is the fresh\n // destination paragraph the suffix moves into.\n while (\n lines.length > 1 &&\n lines[lines.length - 1] === \"\" &&\n suffix_nodes.length === 0\n ) {\n lines.pop();\n }\n if (lines.length === 0) {\n return {\n first_node: null,\n last_p: null,\n last_ins: null,\n used_block_mode: false,\n };\n }\n\n // Inspect the first line for heading/list markers.\n const [first_clean, first_style] = this._parse_markdown_style(lines[0]);\n const have_paragraph_context = current_p !== null;\n const block_mode = first_style !== null && have_paragraph_context;\n\n let first_node: Element | null = null;\n let inline_ins: Element | null = null;\n\n // ---- INLINE PATH for the first line (when NOT in block mode) ----\n if (!block_mode) {\n inline_ins = this._build_tracked_ins_for_line(\n first_clean === lines[0] ? lines[0] : lines[0],\n anchor_run,\n reuse_id,\n xmlDoc,\n suppress_emphasis,\n );\n first_node = inline_ins;\n // Caller will attach `inline_ins` to the DOM later — keep it for now.\n }\n\n // ---- BLOCK PATH for the first line (when in block mode) ----\n // Block-mode first line is just the first extension paragraph below.\n const remaining_lines = block_mode ? lines : lines.slice(1);\n\n // If there's nothing to do beyond inline, we're done.\n if (remaining_lines.length === 0) {\n return {\n first_node,\n last_p: null,\n last_ins: inline_ins,\n used_block_mode: false,\n };\n }\n\n if (!current_p) {\n // Multi-paragraph insertion needs a paragraph context. Without one, fall\n // back to the inline result we already built.\n return {\n first_node,\n last_p: null,\n last_ins: inline_ins,\n used_block_mode: false,\n };\n }\n\n const parent_body = current_p.parentNode as Element | null;\n if (!parent_body) {\n return {\n first_node,\n last_p: null,\n last_ins: inline_ins,\n used_block_mode: false,\n };\n }\n\n const insertAfterEl = (newNode: Element, ref: Element) => {\n parent_body.insertBefore(newNode, ref.nextSibling);\n };\n\n let last_p: Element | null = null;\n let last_ins: Element | null = null;\n let after: Element = current_p;\n\n for (let i = 0; i < remaining_lines.length; i++) {\n const raw_line = remaining_lines[i];\n const [clean_text, style_name] = this._parse_markdown_style(raw_line);\n\n const new_p = xmlDoc.createElement(\"w:p\");\n\n if (style_name) {\n // Heading or list style was explicitly authored: replace pPr entirely.\n this._set_paragraph_style(new_p, style_name);\n } else {\n // Inherit pPr from the anchor paragraph (preserves list numbering).\n const existing_pPr = findChild(current_p, \"w:pPr\");\n if (existing_pPr) {\n new_p.appendChild(this._clone_pPr_scrubbing_headings(existing_pPr));\n }\n }\n\n // Track the paragraph break itself as an insertion.\n let pPr = findChild(new_p, \"w:pPr\");\n if (!pPr) {\n pPr = xmlDoc.createElement(\"w:pPr\");\n new_p.insertBefore(pPr, new_p.firstChild);\n }\n let rPr = findChild(pPr, \"w:rPr\");\n if (!rPr) {\n rPr = xmlDoc.createElement(\"w:rPr\");\n pPr.appendChild(rPr);\n }\n const ins_mark = this._create_track_change_tag(\"w:ins\", \"\", reuse_id);\n rPr.appendChild(ins_mark);\n\n // Build the content <w:ins>.\n const content_ins = this._build_tracked_ins_for_line(\n clean_text,\n anchor_run,\n reuse_id,\n xmlDoc,\n suppress_emphasis,\n );\n if (content_ins) {\n new_p.appendChild(content_ins);\n }\n\n insertAfterEl(new_p, after);\n after = new_p;\n last_p = new_p;\n last_ins = content_ins;\n\n // In block mode (or if the inline line was completely empty), the first new paragraph IS first_node.\n if (!first_node) {\n first_node = new_p;\n }\n }\n\n // Relocate the suffix into the last new paragraph: the paragraph break\n // the insertion introduced splits current_p at the anchor, so everything\n // after the anchor continues in the final inserted paragraph.\n if (!block_mode && last_p && suffix_nodes.length > 0) {\n for (const node of suffix_nodes) {\n node.parentNode?.removeChild(node);\n last_p.appendChild(node);\n }\n }\n\n return { first_node, last_p, last_ins, used_block_mode: block_mode };\n }\n\n /**\n * Builds a single tracked-insert wrapper (<w:ins>) containing one or more\n * <w:r> elements representing the inline markdown segments of `line_text`.\n * Returns null if line_text is empty.\n */\n private _build_tracked_ins_for_line(\n line_text: string,\n anchor_run: Run | null,\n reuse_id: string,\n xmlDoc: Document,\n suppress_emphasis: boolean = false,\n ): Element | null {\n if (!line_text && line_text !== \"\") return null;\n const ins = this._create_track_change_tag(\"w:ins\", \"\", reuse_id);\n const segments = this._parse_inline_markdown(line_text);\n if (segments.length === 0) {\n return null;\n }\n for (const [segText, segProps] of segments) {\n const r = xmlDoc.createElement(\"w:r\");\n // Inherit run formatting from the anchor so partial replacements inside\n // a styled span keep the style (matching Word's type-into-selection\n // behavior and the Python engine — the old blanket strip made\n // \"Important\" -> \"Critical\" inside a bold span come out unstyled).\n if (anchor_run && anchor_run._element) {\n const anchor_rPr = findChild(anchor_run._element, \"w:rPr\");\n if (anchor_rPr) {\n const clone = anchor_rPr.cloneNode(true) as Element;\n // Always strip vanish / strike (invisible inserts) and italic\n // (BUG-23-2: an inserted replacement must not silently inherit the\n // surrounding italic styling). Bold is preserved — it usually\n // carries structural meaning (headings, defined terms) — UNLESS\n // the edit's own markers are authoritative (QA 2026-07-19 F-02):\n // `**X**` -> `_X_` must yield italic-only, `**X**` -> `X` plain.\n // Mirrors the Python engine's _track_insert_inline exactly.\n const strip_tags = [\"w:vanish\", \"w:strike\", \"w:dstrike\", \"w:i\", \"w:iCs\"];\n if (suppress_emphasis) {\n strip_tags.push(\"w:b\", \"w:bCs\");\n }\n for (const tag of strip_tags) {\n const found = findChild(clone, tag);\n if (found) clone.removeChild(found);\n }\n r.appendChild(clone);\n }\n }\n this._apply_run_props(r, segProps, false);\n const t = xmlDoc.createElement(\"w:t\");\n this._set_text_content(t, segText);\n r.appendChild(t);\n ins.appendChild(r);\n }\n return ins;\n }\n\n private _parse_markdown_style(text: string): [string, string | null] {\n const stripped_text = text.trimStart();\n\n if (stripped_text.startsWith(\"#\")) {\n let level = 0;\n let temp = stripped_text;\n while (temp.startsWith(\"#\")) {\n level++;\n temp = temp.substring(1);\n }\n if (temp.startsWith(\" \")) return [temp.trim(), `Heading ${level}`];\n }\n\n if (stripped_text.startsWith(\"* \") || stripped_text.startsWith(\"- \")) {\n return [stripped_text.substring(2).trim(), \"List Paragraph\"];\n }\n\n // Numbered lists: the projection emits ordered items with a CONSTANT\n // \"1. \" marker (Markdown renumbers), so only that exact shape converts\n // back into a list style. Any other leading number (\"2024. Year in\n // review\", \"3. Clause text\") is literal document text. Continuation\n // items inside an existing list anchor keep full \"\\d+.\" handling via\n // the list-anchored insertion path.\n const match = stripped_text.match(/^1\\.\\s+/);\n if (match) {\n return [stripped_text.substring(match[0].length).trim(), \"List Number\"];\n }\n\n return [text, null];\n }\n\n /**\n * True when this edit's target or replacement text carries explicit\n * bold/italic markers, making the markers AUTHORITATIVE for the inserted\n * runs' formatting. Replacing `**X**` with `_X_` must yield italic-only\n * text, and replacing `**X**` with `X` must yield plain text — inheriting\n * the replaced span's run properties on top of (or instead of) the\n * requested markers silently produces the wrong document while the report\n * claims success (QA 2026-07-19 F-02). Plain-text edits (no markers on\n * either side) keep inheriting the context style so partial replacements\n * inside a styled span never lose formatting.\n */\n private _edit_declares_emphasis(edit: any): boolean {\n for (const text of [edit?.target_text, edit?.new_text]) {\n if (!text || (!text.includes(\"**\") && !text.includes(\"_\"))) continue;\n const segments = this._parse_inline_markdown(text);\n if (segments.some(([, props]: [string, any]) => props && Object.keys(props).length > 0)) {\n return true;\n }\n }\n return false;\n }\n\n private _parse_inline_markdown(\n text: string,\n baseStyle: any = {},\n ): [string, any][] {\n if (!text) return [];\n\n const tokenPattern = /(\\*\\*.*?\\*\\*)|(_.*?_)/;\n const match = text.match(tokenPattern);\n\n if (!match) return [[text, baseStyle]];\n\n const start = match.index!;\n const raw = match[0];\n const end = start + raw.length;\n\n const isBold = raw.startsWith(\"**\");\n const innerContent = isBold\n ? raw.substring(2, raw.length - 2)\n : raw.substring(1, raw.length - 1);\n\n const preText = text.substring(0, start);\n const postText = text.substring(end);\n\n const results: [string, any][] = [];\n if (preText) results.push([preText, baseStyle]);\n\n const newStyle = { ...baseStyle };\n if (isBold) newStyle.bold = true;\n else newStyle.italic = true;\n\n results.push(...this._parse_inline_markdown(innerContent, newStyle));\n results.push(...this._parse_inline_markdown(postText, baseStyle));\n\n return results;\n }\n\n private _apply_run_props(\n runElement: Element,\n props: any,\n suppressInherited: boolean = false,\n ) {\n if (!props) {\n if (!suppressInherited) return;\n props = {};\n }\n\n let rPr = findChild(runElement, \"w:rPr\");\n if (!rPr && (props.bold || props.italic || suppressInherited)) {\n const doc = runElement.ownerDocument!;\n rPr = doc.createElement(\"w:rPr\");\n runElement.appendChild(rPr);\n }\n\n if (rPr) {\n const doc = runElement.ownerDocument!;\n if (props.bold) {\n let b = findChild(rPr, \"w:b\");\n if (!b) {\n b = doc.createElement(\"w:b\");\n rPr.appendChild(b);\n }\n b.setAttribute(\"w:val\", \"1\");\n } else if (suppressInherited) {\n const b = findChild(rPr, \"w:b\");\n if (b) rPr.removeChild(b);\n }\n\n if (props.italic) {\n let i = findChild(rPr, \"w:i\");\n if (!i) {\n i = doc.createElement(\"w:i\");\n rPr.appendChild(i);\n }\n i.setAttribute(\"w:val\", \"1\");\n } else if (suppressInherited) {\n const i = findChild(rPr, \"w:i\");\n if (i) rPr.removeChild(i);\n }\n }\n }\n\n /**\n * Replaces (or creates) a paragraph's <w:pPr> with a single <w:pStyle> entry\n * pointing at `style_name`. Strips any existing pPr to avoid layering a new\n * heading style on top of a previous list/heading configuration.\n *\n * In Python, the style id is resolved via doc.styles[style_name].style_id and\n * falls back to stripping spaces. Node has no equivalent style cache exposed\n * on `doc`, so we always use the simple \"strip spaces\" fallback: \"Heading 1\"\n * becomes the style id \"Heading1\", \"List Number\" becomes \"ListNumber\", etc.\n * This matches python-docx's default style-id convention for the built-in\n * paragraph styles and is what Word writes by default.\n */\n private _set_paragraph_style(p_element: Element, style_name: string) {\n const xmlDoc = p_element.ownerDocument!;\n\n const existing_pPr = findChild(p_element, \"w:pPr\");\n if (existing_pPr) {\n p_element.removeChild(existing_pPr);\n }\n\n const pPr = xmlDoc.createElement(\"w:pPr\");\n const pStyle = xmlDoc.createElement(\"w:pStyle\");\n const style_id = style_name.replace(/\\s+/g, \"\");\n pStyle.setAttribute(\"w:val\", style_id);\n pPr.appendChild(pStyle);\n\n // pPr is the first child of <w:p> per OOXML schema.\n p_element.insertBefore(pPr, p_element.firstChild);\n }\n\n private _anchor_reply_comment(parent_id: string, new_id: string) {\n const docEl = this.doc.part._element.ownerDocument!;\n\n const starts = findAllDescendants(\n this.doc.element,\n \"w:commentRangeStart\",\n ).filter((n) => n.getAttribute(\"w:id\") === parent_id);\n if (starts.length === 0) return;\n const parent_start = starts[0];\n\n const new_start = docEl.createElement(\"w:commentRangeStart\");\n new_start.setAttribute(\"w:id\", new_id);\n insertAfter(new_start, parent_start);\n\n const ends = findAllDescendants(\n this.doc.element,\n \"w:commentRangeEnd\",\n ).filter((n) => n.getAttribute(\"w:id\") === parent_id);\n if (ends.length === 0) return;\n const parent_end = ends[0];\n\n const parent_refs = findAllDescendants(\n this.doc.element,\n \"w:commentReference\",\n ).filter((n) => n.getAttribute(\"w:id\") === parent_id);\n\n let insertion_point = parent_end;\n if (parent_refs.length > 0) {\n const ref_el = parent_refs[0];\n if (\n ref_el.parentNode &&\n (ref_el.parentNode as Element).tagName === \"w:r\"\n ) {\n insertion_point = ref_el.parentNode as Element;\n }\n }\n\n const new_end = docEl.createElement(\"w:commentRangeEnd\");\n new_end.setAttribute(\"w:id\", new_id);\n insertAfter(new_end, insertion_point);\n\n const ref_run = docEl.createElement(\"w:r\");\n const rPr = docEl.createElement(\"w:rPr\");\n const rStyle = docEl.createElement(\"w:rStyle\");\n rStyle.setAttribute(\"w:val\", \"CommentReference\");\n rPr.appendChild(rStyle);\n ref_run.appendChild(rPr);\n\n const ref = docEl.createElement(\"w:commentReference\");\n ref.setAttribute(\"w:id\", new_id);\n ref_run.appendChild(ref);\n\n insertAfter(ref_run, new_end);\n }\n /**\n * Read a comment's author directly from the comments part. Used by\n * _clean_wrapping_comments to decide whether a wrapping comment belongs to\n * another author (and must be preserved when its anchored change is\n * accepted/rejected) or to us (safe to delete). Reads the part rather than\n * the mapper because the mapper's comments_map is not rebuilt between review\n * actions, so it can be stale mid-batch. Returns null if not found.\n */\n private _get_comment_author(c_id: string): string | null {\n const part = this.doc.pkg.parts.find(\n (p) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\",\n );\n if (!part) return null;\n const comments = findAllDescendants(part._element, \"w:comment\");\n for (const c of comments) {\n if (c.getAttribute(\"w:id\") === c_id) {\n return c.getAttribute(\"w:author\");\n }\n }\n return null;\n }\n /** Returns how many comment BODIES were actually deleted (see below: only\n * our own are; foreign ones keep their body and lose only the anchor). */\n private _clean_wrapping_comments(element: Element): number {\n let deleted = 0;\n let first_node: Element = element;\n while (true) {\n const prev = getPreviousElement(first_node);\n if (prev && (prev.tagName === \"w:ins\" || prev.tagName === \"w:del\")) {\n first_node = prev;\n } else {\n break;\n }\n }\n\n let last_node: Element = element;\n while (true) {\n const nxt = getNextElement(last_node);\n if (nxt && (nxt.tagName === \"w:ins\" || nxt.tagName === \"w:del\")) {\n last_node = nxt;\n } else {\n break;\n }\n }\n\n const starts_to_remove: Element[] = [];\n let prev = getPreviousElement(first_node);\n while (prev) {\n if (prev.tagName === \"w:commentRangeStart\") {\n starts_to_remove.push(prev);\n prev = getPreviousElement(prev);\n } else if (prev.tagName === \"w:rPr\" || prev.tagName === \"w:pPr\") {\n prev = getPreviousElement(prev);\n } else {\n break;\n }\n }\n\n const ends_to_remove: Element[] = [];\n let nxt = getNextElement(last_node);\n while (nxt) {\n if (nxt.tagName === \"w:commentRangeEnd\") {\n ends_to_remove.push(nxt);\n nxt = getNextElement(nxt);\n } else if (\n nxt.tagName === \"w:r\" &&\n findAllDescendants(nxt, \"w:commentReference\").length > 0\n ) {\n ends_to_remove.push(nxt);\n nxt = getNextElement(nxt);\n } else if (nxt.tagName === \"w:commentReference\") {\n ends_to_remove.push(nxt);\n nxt = getNextElement(nxt);\n } else {\n break;\n }\n }\n\n const end_ids = new Set<string>();\n for (const e of ends_to_remove) {\n if (e.tagName === \"w:commentRangeEnd\") {\n const eid = e.getAttribute(\"w:id\");\n if (eid) end_ids.add(eid);\n } else {\n let ref = findAllDescendants(e, \"w:commentReference\")[0];\n if (!ref && e.tagName === \"w:commentReference\") ref = e;\n if (ref) {\n const eid = ref.getAttribute(\"w:id\");\n if (eid) end_ids.add(eid);\n }\n }\n }\n\n for (const s of starts_to_remove) {\n const c_id = s.getAttribute(\"w:id\");\n if (c_id && end_ids.has(c_id)) {\n // Author-aware preservation. A comment that merely WRAPS the change\n // being accepted/rejected is a separate annotation — often the\n // counterparty's note explaining the very edit we are resolving.\n // Deleting it silently destroys their provenance (and, e.g., fails a\n // \"keep the counterparty's comment\" review requirement). So: always\n // detach the range markers (leaving no orphaned anchor, which lets the\n // accept/reject proceed cleanly), but only delete the comment BODY when\n // it is ours. Foreign-authored comment bodies are kept in the comments\n // part. When the author can't be read we default to preserving, since\n // deletion is the irreversible, higher-cost mistake.\n const author = this._get_comment_author(c_id);\n const is_own = author !== null && author === this.author;\n if (is_own) {\n this.comments_manager.deleteComment(c_id);\n deleted++;\n }\n if (s.parentNode) s.parentNode.removeChild(s);\n for (const e of ends_to_remove) {\n let e_id: string | null = null;\n if (e.tagName === \"w:commentRangeEnd\") {\n e_id = e.getAttribute(\"w:id\");\n } else {\n let ref = findAllDescendants(e, \"w:commentReference\")[0];\n if (!ref && e.tagName === \"w:commentReference\") ref = e;\n if (ref) e_id = ref.getAttribute(\"w:id\");\n }\n if (e_id === c_id && e.parentNode) {\n e.parentNode.removeChild(e);\n }\n }\n }\n }\n return deleted;\n }\n\n /** Returns how many comment bodies were deleted. */\n private _delete_comments_in_element(element: Element): number {\n let deleted = 0;\n const refs = findAllDescendants(element, \"w:commentReference\");\n for (const ref of refs) {\n const c_id = ref.getAttribute(\"w:id\");\n if (c_id) {\n this.comments_manager.deleteComment(c_id);\n deleted++;\n for (const tag of [\"w:commentRangeStart\", \"w:commentRangeEnd\"]) {\n const nodes = findAllDescendants(this.doc.element, tag);\n for (const node of nodes) {\n if (node.getAttribute(\"w:id\") === c_id && node.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n }\n }\n }\n return deleted;\n }\n\n public validate_edits(edits: any[], index_offset: number = 0): string[] {\n const errors: string[] = [];\n if (!this.mapper.full_text) this.mapper[\"_build_map\"]();\n\n errors.push(...validate_edit_strings(edits, index_offset));\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n if (typeof edit !== \"object\" || edit === null) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Invalid change format. Expected a JSON object, but received a primitive ${typeof edit}. Do not pass raw strings.`,\n );\n continue;\n }\n if (!edit.target_text) continue;\n // Caller-pinned indexes (e.g. generate_edits_from_text output) resolve\n // by position, not content: ambiguity / not-found checks are meaningless\n // for them and false-positive whenever the target coincidentally matches\n // unrelated text (a comment timestamp, an earlier redline). The\n // string-shape checks above still apply.\n if (\n (edit._match_start_index !== undefined &&\n edit._match_start_index !== null) ||\n (edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null)\n )\n continue;\n\n const is_regex = (edit as any).regex || false;\n const match_mode = (edit as any).match_mode || \"strict\";\n\n if (is_regex) {\n // An unparsable pattern must be diagnosed as a regex problem. Without\n // this check it falls through the matcher's silent guard and surfaces\n // as \"target text not found\", sending the user hunting for a typo in\n // the document instead of in the pattern (QA 2026-07-19 F-13).\n try {\n new RegExp(edit.target_text);\n } catch (regex_err: any) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text is not a valid regular expression ` +\n `(${regex_err?.message ?? regex_err}). Fix the pattern, or set \"regex\": false to ` +\n \"match the text literally.\",\n );\n continue;\n }\n }\n\n // Matches covering ONLY virtual projection text (meta bubbles,\n // timestamps, style markers) are phantoms: they can neither be edited\n // nor legitimately ambiguate a real match — a target of \"4\" was\n // rejected as \"appears 8 times\" because comment-bubble timestamps\n // matched (QA 2026-07-19 ADEU-QA-002 C).\n let matches = this.mapper.drop_virtual_only_matches(\n this.mapper.find_all_match_indices(edit.target_text, is_regex),\n );\n let activeText = this.mapper.full_text;\n let target_mapper = this.mapper;\n\n if (matches.length === 0) {\n if (!this.clean_mapper)\n this.clean_mapper = new DocumentMapper(this.doc, true);\n matches = this.clean_mapper.drop_virtual_only_matches(\n this.clean_mapper.find_all_match_indices(edit.target_text, is_regex),\n );\n if (matches.length > 0) {\n activeText = this.clean_mapper.full_text;\n target_mapper = this.clean_mapper;\n }\n }\n\n // BUG-23-5: a copy of the target that lives entirely inside a tracked\n // deletion (<w:del>) is not a live, editable occurrence and must not\n // count toward ambiguity. Drop matches whose overlapping real text is\n // exclusively deleted. Only applies to the raw mapper (the clean mapper\n // already omits deleted text).\n if (activeText === this.mapper.full_text && matches.length > 0) {\n const liveMatches = matches.filter(([start, length]) => {\n const realSpans = this.mapper.spans.filter(\n (s) => s.run !== null && s.end > start && s.start < start + length,\n );\n // Virtual-only matches were already dropped above; here we only\n // skip matches buried entirely inside tracked deletions.\n if (realSpans.length === 0) return true;\n return realSpans.some((s) => !s.del_id);\n });\n matches = liveMatches;\n }\n\n let is_deleted_text = false;\n const deleted_authors = new Set<string>();\n\n if (matches.length === 0) {\n if (!this.original_mapper) {\n this.original_mapper = new DocumentMapper(this.doc, false, true);\n }\n const orig_matches = this.original_mapper.drop_virtual_only_matches(\n this.original_mapper.find_all_match_indices(\n edit.target_text,\n is_regex,\n ),\n );\n if (orig_matches.length > 0) {\n is_deleted_text = true;\n for (const [start, length] of orig_matches) {\n const spans = this.original_mapper.spans.filter(\n (s) => s.end > start && s.start < start + length,\n );\n for (const s of spans) {\n if (s.run !== null) {\n let parent = s.run._element as Node | null;\n while (parent) {\n if (\n parent.nodeType === 1 &&\n (parent as Element).tagName === \"w:del\"\n ) {\n const auth = (parent as Element).getAttribute(\"w:author\");\n if (auth) {\n deleted_authors.add(auth);\n }\n break;\n }\n parent = parent.parentNode;\n }\n }\n }\n }\n }\n }\n\n if (matches.length === 0) {\n if (is_deleted_text) {\n const author_phrase =\n deleted_authors.size > 0\n ? `by ${Array.from(deleted_authors).sort().join(\", \")}`\n : \"by an existing revision\";\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Target text matches text inside a tracked deletion ${author_phrase}. Reject/accept that change first or target the active replacement text instead.`,\n );\n } else {\n const hint = this._nearest_match_hint(edit.target_text, is_regex);\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Target text not found in document:\\n \"${truncate_middle(edit.target_text, REPORT_ECHO_CAP)}\"${hint}`,\n );\n }\n } else if (matches.length > 1 && match_mode === \"strict\") {\n if (edit.target_text.includes(\"|\")) {\n matches = matches.slice(0, 1);\n } else {\n const positions: [number, number][] = matches.map(\n ([start, length]) => [start, start + length],\n );\n errors.push(\n format_ambiguity_error(\n i + 1 + index_offset,\n edit.target_text,\n activeText,\n positions,\n ),\n );\n }\n }\n\n // BUG-23-4: when the effective (context-trimmed) target spans a\n // paragraph boundary with real body text on BOTH sides, we must reject\n // the modification to prevent silent corruption of the paragraph structure.\n if (matches.length === 1) {\n const [m_start, m_len] = matches[0];\n const matched = activeText.substring(m_start, m_start + m_len);\n const [pfx, sfx] = trim_common_context(matched, edit.new_text || \"\");\n const t_end = matched.length - sfx;\n const final_target = matched.substring(pfx, t_end);\n const final_new = (edit.new_text || \"\").substring(\n pfx,\n (edit.new_text || \"\").length - sfx,\n );\n\n // QA 2026-07-18 C1: the projection flattens headers, body, footers\n // and notes into one string, but a text edit whose matched span\n // covers real text from two different OPC parts cannot be applied\n // without putting content in the wrong part — including the\n // insertion shape, whose anchor point at the part gap is inherently\n // ambiguous. Refuse the RAW match range outright and ask for a\n // single-part anchor. (Single-part documents skip the scan.)\n const multi_part_doc =\n target_mapper.part_ranges.filter((r) => r[1] > r[0]).length > 1;\n const raw_span_parts = multi_part_doc\n ? Array.from(\n new Set(\n target_mapper.spans\n .filter(\n (s) =>\n s.run !== null &&\n s.end > m_start &&\n s.start < m_start + m_len,\n )\n .map((s) => s.part_index),\n ),\n ).sort((a, b) => a - b)\n : [];\n if (raw_span_parts.length > 1) {\n const kinds = raw_span_parts\n .map((pi) => target_mapper.part_kind_of(pi) || \"?\")\n .join(\" → \");\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text spans a structural document-part ` +\n `boundary (${kinds}). Headers, body, footers and footnotes are separate ` +\n \"Word parts — an edit cannot cross between them. Anchor the edit on text \" +\n \"within a single part (split it into one edit per part if both sides \" +\n \"must change).\",\n );\n }\n\n // QA 2026-07-18 M5: image markers are read-only projections. Only\n // the CHANGED span matters — markers sitting untouched in the\n // shared context are fine.\n const eff_start = m_start + pfx;\n const eff_end = m_start + m_len - sfx;\n if (eff_end > eff_start) {\n const overlapping = target_mapper.spans.filter(\n (s) =>\n s.end > eff_start &&\n s.start < eff_end &&\n (s.run !== null || s.text.trim() !== \"\"),\n );\n if (overlapping.some((s) => (s as any).is_image_marker)) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: the target overlaps a read-only image marker ` +\n \"(). Images cannot be edited or removed via text \" +\n \"replacement — target the text around the image instead.\",\n );\n }\n }\n\n // QA 2026-07-18 H4: comments can only be anchored in the main\n // document story. A comment-only edit (target == new) whose match\n // lives in a header/footer/footnote has no effect Word or\n // LibreOffice could render — refuse it clearly.\n if (edit.comment && (edit.new_text || \"\") === (edit.target_text || \"\")) {\n const kind_here = target_mapper.part_kind_at(m_start);\n if (kind_here !== null && kind_here !== \"body\") {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: comments cannot be anchored inside a ${kind_here} ` +\n \"part — Word only supports comments in the main document body. Comment on \" +\n \"the related body text instead.\",\n );\n }\n }\n\n // QA 2026-07-18 C2: a replacement may not smuggle new pipe-delimited\n // row lines into a table cell. Rows are structural; adding one\n // requires the insert_row operation.\n if (\n RedlineEngine._introduces_table_row_text(\n target_mapper,\n m_start,\n m_len,\n final_target,\n final_new,\n )\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: new_text introduces a pipe-delimited row line inside ` +\n \"a table. Text replacement cannot create table rows — use the structured \" +\n `'insert_row' operation instead (e.g. {\"type\": \"insert_row\", ` +\n `\"target_text\": \"<anchor row text>\", \"cells\": [\"...\", \"...\"]}).`,\n );\n }\n\n if (final_target.includes(\"\\n\\n\")) {\n // A *balanced* multi-paragraph modification (target and replacement\n // carry the same number of paragraph breaks) is safe: it is split\n // into one sub-edit per paragraph segment and applied, leaving the\n // structural \\n\\n breaks untouched. Only reject when the paragraph\n // structure would actually change (a merge or split), which cannot be\n // expressed as a per-paragraph text replacement. See\n // _pre_resolve_heuristic_edit.\n const balanced =\n matched.split(\"\\n\\n\").length ===\n (edit.new_text || \"\").split(\"\\n\\n\").length;\n if (!balanced) {\n if (final_new.includes(\"\\n\\n\")) {\n const parts = matched.split(\"\\n\\n\");\n if (\n parts.length >= 2 &&\n parts[0].trim() !== \"\" &&\n parts[parts.length - 1].trim() !== \"\"\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text spans a paragraph boundary with body text on both sides. The paragraph break is a structural element, not literal text, so it cannot be replaced as a single span without corrupting the document. Split this into one edit per paragraph.`,\n );\n }\n } else {\n const parts = final_target.split(\"\\n\\n\");\n if (\n parts.length >= 2 &&\n parts[0].trim() !== \"\" &&\n parts[parts.length - 1].trim() !== \"\"\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: target_text spans a paragraph boundary with body text on both sides. The paragraph break is a structural element, not literal text, so it cannot be replaced as a single span without corrupting the document. Split this into one edit per paragraph.`,\n );\n }\n }\n }\n }\n }\n\n for (const [start, length] of matches) {\n // Filter spans from the SAME mapper the match indices came from\n // (target_mapper may be the clean mapper); using this.mapper.spans here\n // would read a different coordinate space and miss the foreign <w:ins>\n // overlap for clean-mapper-resolved targets — silently letting a\n // partial straddle through. (Python filters target_mapper.spans too.)\n const spans = target_mapper.spans.filter(\n (s) => s.end > start && s.start < start + length,\n );\n const insAuthors = new Set<string>();\n const commentAuthors = new Set<string>();\n // Does any real (run-backed) text in the target lie OUTSIDE a foreign\n // insertion? If so the target only partially overlaps the insertion and\n // replacing it as one span would straddle the <w:ins> boundary — that\n // case must still be refused.\n let hasNonForeignRealText = false;\n for (const s of spans) {\n if (s.run === null) continue;\n let isForeignIns = false;\n if (s.ins_id) {\n const insNodes = findAllDescendants(\n this.doc.element,\n \"w:ins\",\n ).filter((n) => n.getAttribute(\"w:id\") === s.ins_id);\n if (insNodes.length > 0) {\n const auth = insNodes[0].getAttribute(\"w:author\");\n if (auth && auth !== this.author) {\n insAuthors.add(auth);\n isForeignIns = true;\n }\n }\n }\n if (!isForeignIns) hasNonForeignRealText = true;\n }\n for (const s of spans) {\n if (s.comment_ids) {\n for (const cid of s.comment_ids) {\n const c_data = this.mapper.comments_map[cid];\n if (c_data && c_data.author && c_data.author !== this.author) {\n commentAuthors.add(c_data.author);\n }\n }\n }\n }\n if (insAuthors.size > 0) {\n // A single (strict/first) modification whose target lies ENTIRELY\n // inside foreign-authored insertion(s) is allowed: track_delete_run\n // splits the enclosing <w:ins> and nests the change, producing valid\n // tracked-change XML. Refuse the remaining cases — match_mode \"all\"\n // fan-outs and partial overlaps that straddle the insertion\n // boundary.\n const fullyWithinForeignIns = !hasNonForeignRealText;\n if (\n !(\n (match_mode === \"strict\" || match_mode === \"first\") &&\n fullyWithinForeignIns\n )\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: Modification targets an active insertion from another author (${Array.from(insAuthors).join(\", \")}). Accept that change first or scope your edit outside of it.`,\n );\n continue;\n }\n }\n // Foreign comment ranges do NOT block deliberate single-occurrence\n // edits: amending body text under a colleague's comment is a normal\n // review workflow, and the comment anchor survives the tracked change.\n // Only blind match_mode=\"all\" fan-outs are refused, so a bulk\n // replacement cannot silently sweep through another author's\n // annotations (transactional rollback).\n if (commentAuthors.size > 0 && match_mode === \"all\") {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: match_mode=\"all\" would sweep through a comment range from another author (${Array.from(commentAuthors).join(\", \")}). Target the commented text deliberately with match_mode \"strict\" or \"first\", or scope your edit outside of it.`,\n );\n }\n }\n\n // Structural table edits: verify the anchor really is a table row, and\n // that insert_row does not provide more cells than the row has columns —\n // extra cells must never produce a structurally inconsistent row (QA M3).\n if (\n (edit.type === \"insert_row\" || edit.type === \"delete_row\") &&\n matches.length > 0\n ) {\n const [start, length] = matches[0];\n const n_cols = RedlineEngine._column_count_at(\n target_mapper,\n start,\n length,\n );\n if (n_cols === null) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: ${edit.type} target text was found, but it is not inside a table row. Anchor the operation on text that appears within the table.`,\n );\n } else if (\n edit.type === \"insert_row\" &&\n Array.isArray(edit.cells) &&\n edit.cells.length > n_cols\n ) {\n errors.push(\n `- Edit ${i + 1 + index_offset} Failed: insert_row provides ${edit.cells.length} cells but the target table has ${n_cols} column(s). The extra cell(s) would be dropped. Provide at most ${n_cols} cells — rows given fewer cells are padded with empty ones.`,\n );\n }\n }\n }\n return errors;\n }\n\n /**\n * Number of columns (w:tc elements) in the table row containing the text at\n * [start, start+length) in `mapper`, or null if that text is not inside a\n * table row.\n */\n /**\n * True when a replacement anchored in a table would ADD line-separated\n * pipe-delimited content — the text shape of a table row. Writing that\n * into a cell renders a fake row inside one cell while the real grid\n * stays unchanged (QA 2026-07-18 C2); such edits must use insert_row.\n */\n private static _introduces_table_row_text(\n mapper: DocumentMapper,\n start: number,\n length: number,\n final_target: string,\n final_new: string,\n ): boolean {\n if (!final_new.includes(\"\\n\") || !final_new.includes(\" | \")) return false;\n const new_pipe_lines = final_new\n .split(\"\\n\")\n .filter((line) => line.includes(\" | \")).length;\n const old_pipe_lines = final_target\n .split(\"\\n\")\n .filter((line) => line.includes(\" | \")).length;\n if (new_pipe_lines <= old_pipe_lines) return false;\n return (\n RedlineEngine._column_count_at(mapper, start, Math.max(length, 1)) !==\n null\n );\n }\n\n private static _column_count_at(\n mapper: DocumentMapper,\n start: number,\n length: number,\n ): number | null {\n for (const s of mapper.spans) {\n if (s.end <= start || s.start >= start + length) {\n continue;\n }\n let curr: Node | null = null;\n if (s.run !== null) {\n curr = s.run._element;\n } else if (s.paragraph !== null) {\n curr = s.paragraph._element;\n }\n while (curr) {\n if (curr.nodeType === 1 && (curr as Element).tagName === \"w:tr\") {\n return findAllDescendants(curr as Element, \"w:tc\").filter(\n (tc) => tc.parentNode === curr,\n ).length;\n }\n curr = curr.parentNode;\n }\n }\n return null;\n }\n\n public validate_review_actions(actions: any[]): string[] {\n const errors: string[] = [];\n\n // Document-context-free shape checks (QA 2026-07-19 v8 F-07), mirroring\n // Python's validate_review_action_batch: blank replies render as empty\n // Word comment bubbles; a duplicated or conflicting accept/reject on one\n // target_id either double-counts as \"applied\" or contradicts itself.\n // Distinct IDs one action resolves as a group (a modification's del+ins\n // pair) stay legitimate, as do DIFFERENT replies to the same comment.\n const seen_resolutions = new Map<string, [number, string]>();\n const seen_replies = new Set<string>();\n for (let i = 0; i < actions.length; i++) {\n const action = actions[i];\n const type = action.type;\n const target_id = action.target_id ?? \"\";\n if (type === \"reply\") {\n if (!String(action.text ?? \"\").trim()) {\n errors.push(\n `- Action ${i + 1} Failed: reply text for ${target_id} is empty or ` +\n `whitespace-only. Word would show a blank comment bubble — provide the ` +\n `reply content in 'text'.`,\n );\n continue;\n }\n const reply_key = `${target_id}\u0000${String(action.text).trim()}`;\n if (seen_replies.has(reply_key)) {\n errors.push(\n `- Action ${i + 1} Failed: duplicate reply — this batch already replies to ` +\n `${target_id} with the same text. Remove the duplicate action.`,\n );\n }\n seen_replies.add(reply_key);\n } else if (type === \"accept\" || type === \"reject\") {\n const prior = seen_resolutions.get(target_id);\n if (prior !== undefined) {\n const [first_idx, first_type] = prior;\n if (first_type === type) {\n errors.push(\n `- Action ${i + 1} Failed: duplicate action — Action ${first_idx + 1} in this ` +\n `batch already applies '${type}' to ${target_id}. A change can only be ` +\n `resolved once; remove the duplicate action.`,\n );\n } else {\n errors.push(\n `- Action ${i + 1} Failed: conflicting actions — Action ${first_idx + 1} in ` +\n `this batch applies '${first_type}' to ${target_id}, but this action applies ` +\n `'${type}'. Decide the outcome and keep exactly one of them.`,\n );\n }\n } else {\n seen_resolutions.set(target_id, [i, type]);\n }\n }\n }\n if (errors.length > 0) return errors;\n\n for (let i = 0; i < actions.length; i++) {\n const action = actions[i];\n const type = action.type;\n\n if (type === \"reply\") {\n const cid = action.target_id.replace(\"Com:\", \"\");\n let found = false;\n const part = this.doc.pkg.parts.find(\n (p) =>\n p.contentType ===\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml\",\n );\n if (part) {\n const comments = findAllDescendants(part._element, \"w:comment\");\n found = comments.some((c) => c.getAttribute(\"w:id\") === cid);\n }\n if (!found) {\n errors.push(\n `- Action ${i + 1} Failed: Target comment ID ${action.target_id} not found.`,\n );\n }\n } else if (type === \"accept\" || type === \"reject\") {\n const target_id = action.target_id.replace(\"Chg:\", \"\");\n const all_ins = findAllDescendants(this.doc.element, \"w:ins\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n const all_del = findAllDescendants(this.doc.element, \"w:del\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n if (all_ins.length === 0 && all_del.length === 0) {\n errors.push(\n `- Action ${i + 1} Failed: Target ID ${action.target_id} not found.`,\n );\n }\n }\n }\n return errors;\n }\n\n public process_batch(\n changes: DocumentChange[],\n dry_run: boolean = false,\n ): any {\n // Defensive sanitization: some LLM clients \"double-serialize\" nested\n // arrays, delivering each element of `changes` as a JSON string instead of\n // a parsed object. Downstream code mutates state trackers (e.g.\n // `edit._applied_status`) and reads `change.type` on these elements, which\n // throws a TypeError on string primitives. Parse stringified elements back\n // into objects here, leaving genuine objects (and unparseable strings)\n // untouched so validation can surface a clear error rather than crashing.\n if (Array.isArray(changes)) {\n changes = changes.map((item: any) => {\n if (typeof item === \"string\") {\n try {\n const parsed = JSON.parse(item);\n // Only swap in the parsed value if it is an object; a string that\n // parses to a scalar (e.g. \"42\") is not a valid change.\n if (parsed !== null && typeof parsed === \"object\") {\n return parsed;\n }\n return item;\n } catch {\n // Leave malformed strings as-is; the validation pass downstream\n // will report them rather than crashing on a raw TypeError.\n return item;\n }\n }\n return item;\n }) as DocumentChange[];\n }\n\n if (dry_run) {\n const snapshot = takeSnapshot(this.doc);\n const originalCurrentId = this.current_id;\n try {\n return this._process_batch_internal(changes, true);\n } finally {\n restoreSnapshot(this.doc, snapshot);\n this.current_id = originalCurrentId;\n this.mapper = new DocumentMapper(this.doc);\n this.comments_manager = new CommentsManager(this.doc);\n this.clean_mapper = null;\n }\n } else {\n return this._process_batch_internal(changes, false);\n }\n }\n\n private _process_batch_internal(\n changes: DocumentChange[],\n dry_run_mode: boolean = false,\n ): any {\n // Pre-process edits: strip identical leading heading hashes from target_text and new_text\n for (const c of changes) {\n if (\n c &&\n typeof c === \"object\" &&\n (c as any).type === \"modify\" &&\n (c as any).target_text &&\n (c as any).new_text\n ) {\n const [strippedTarget, strippedNew] = stripMatchingHeadingHashes(\n (c as any).target_text,\n (c as any).new_text,\n );\n (c as any).target_text = strippedTarget;\n (c as any).new_text = strippedNew;\n }\n }\n\n this.skipped_details = [];\n\n const actions = changes.filter(\n (c) =>\n c !== null &&\n typeof c === \"object\" &&\n [\"accept\", \"reject\", \"reply\"].includes(c.type),\n );\n const edits = changes.filter(\n (c) =>\n c === null ||\n typeof c !== \"object\" ||\n ![\"accept\", \"reject\", \"reply\"].includes(c.type),\n );\n\n // Never pre-unwrap a foreign author's <w:ins> to make a partially\n // straddling edit fit: that turns their tracked-inserted text into\n // untracked committed body text before the edit applies, destroying\n // their provenance. A partial straddle surfaces the standard validation\n // error (\"Modification targets an active insertion from another author\n // …\") via validate_edits, matching the Python engine. An edit fully\n // CONTAINED inside a foreign <w:ins> is allowed and handled by nesting\n // the <w:del> inside that <w:ins> (see _apply_single_edit_indexed /\n // _insert_and_split_ins).\n\n // BUG-7: Unified single-pass validation in wet-run / standard mode.\n // The document-aware pairing check runs BEFORE any action mutates the\n // DOM: accept + reject across one replacement's del+ins pair is a\n // contradiction, not two independent operations (ADEU-QA-004).\n if (!dry_run_mode) {\n let action_errors =\n actions.length > 0 ? this.validate_review_actions(actions) : [];\n if (actions.length > 0 && action_errors.length === 0) {\n action_errors = this.validate_action_pairing(actions);\n }\n const validate_edits_now = edits.length > 0 && action_errors.length > 0;\n const edit_errors = validate_edits_now ? this.validate_edits(edits) : [];\n const all_errors = [...action_errors, ...edit_errors];\n if (all_errors.length > 0) {\n throw new BatchValidationError(all_errors);\n }\n } else {\n if (actions.length > 0) {\n let action_errors = this.validate_review_actions(actions);\n if (action_errors.length === 0) {\n action_errors = this.validate_action_pairing(actions);\n }\n if (action_errors.length > 0) {\n throw new BatchValidationError(action_errors);\n }\n }\n }\n\n let applied_actions = 0;\n let skipped_actions = 0;\n let already_resolved_actions = 0;\n if (actions.length > 0) {\n const res = this.apply_review_actions(actions);\n applied_actions = res[0];\n skipped_actions = res[1];\n already_resolved_actions = res[2];\n if (skipped_actions > 0) {\n throw new BatchValidationError(this.skipped_details);\n }\n if (applied_actions > 0) {\n this.mapper[\"_build_map\"]();\n if (this.clean_mapper) this.clean_mapper[\"_build_map\"]();\n }\n }\n\n const [body_text] = split_structural_appendix(this.mapper.full_text);\n const pag_res = paginate(body_text, \"\");\n const page_offsets = pag_res.body_page_offsets;\n\n const edits_reports: any[] = [];\n let applied_edits = 0;\n let skipped_edits = 0;\n\n if (edits.length > 0) {\n // Sequential application rebuilds the mapper after every applied edit,\n // shifting every position at/after that edit. Caller-pinned indexes\n // (_match_start_index / _resolved_start_idx, e.g. generate_edits_from_text\n // output) are coordinates in the INITIAL document state, so apply indexed\n // edits bottom-up first — positions below an applied edit never move (the\n // same invariant apply_edits' reverse sweep relies on) — then let\n // text-anchored edits re-resolve against the mutated text as before.\n // Reports are keyed by `i` so they stay in batch order.\n const pinned_idx = (e: any): number | null => {\n if (\n e._resolved_start_idx !== undefined &&\n e._resolved_start_idx !== null\n )\n return e._resolved_start_idx;\n if (\n e._match_start_index !== undefined &&\n e._match_start_index !== null\n )\n return e._match_start_index;\n return null;\n };\n const ordered_edits = edits\n .map((edit, i) => ({ edit: edit as any, i }))\n .sort((a, b) => {\n const ka = pinned_idx(a.edit);\n const kb = pinned_idx(b.edit);\n if (ka === null && kb === null) return a.i - b.i;\n if (ka === null) return 1;\n if (kb === null) return -1;\n return kb - ka || a.i - b.i;\n });\n\n if (dry_run_mode) {\n const reports_by_input: any[] = new Array(edits.length);\n // Indexes that failed VALIDATION (not runtime skips): if any exist,\n // the real run rejects the whole batch, so the dry-run report must\n // not claim any edit \"applied\" (transactional parity with Python).\n const validation_failed_idx = new Set<number>();\n for (const { edit, i } of ordered_edits) {\n let single_errors: string[];\n try {\n single_errors = this.validate_edits([edit], i);\n } catch (e) {\n // A pathological user pattern must fail as a clean per-edit\n // validation error, never a hang or crash (QA 2026-07-17 F5).\n if (!(e instanceof RegexTimeoutError)) throw e;\n single_errors = [`- Edit ${i + 1} Failed: ${e.message}`];\n }\n if (single_errors.length > 0) {\n if (applied_edits > 0) {\n const hint = sequential_context_hint(applied_edits);\n single_errors = single_errors.map((err) => err + hint);\n }\n validation_failed_idx.add(i);\n skipped_edits++;\n // Only surface the punctuation-anchor warning when the edit actually\n // failed. A clean apply already returns the redline preview, so the\n // warning is pure noise on success — and it misleads agents into\n // hunting for a \"cleaner\" anchor that was never needed (e.g. on\n // placeholders/dates where the punctuation IS the literal target).\n const warning = this._check_punctuation_warning(\n (edit as any).target_text || \"\",\n );\n reports_by_input[i] = {\n status: \"failed\",\n type: (edit as any).type || \"modify\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: warning,\n error: single_errors.join(\"\\n\"),\n critic_markup: null,\n clean_text: null,\n };\n continue;\n }\n const res = this.apply_edits([edit], page_offsets);\n if ((edit as any)._applied_status) {\n applied_edits++;\n const previews = this._build_edit_context_previews(edit);\n reports_by_input[i] = {\n status: \"applied\",\n type: (edit as any).type || \"modify\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: null,\n error: null,\n critic_markup: previews[0],\n clean_text: previews[1],\n pages: (edit as any)._pages || [],\n heading_path: (edit as any)._heading_path || \"\",\n occurrences_modified: (edit as any)._occurrences_modified || 0,\n match_mode: (edit as any).match_mode || \"strict\",\n };\n this.mapper = new DocumentMapper(this.doc);\n this.clean_mapper = null;\n } else {\n skipped_edits++;\n const error_msg =\n this.skipped_details.length > 0\n ? this.skipped_details[this.skipped_details.length - 1]\n : \"Failed to apply edit\";\n const warning = this._check_punctuation_warning(\n (edit as any).target_text || \"\",\n );\n reports_by_input[i] = {\n status: \"failed\",\n type: (edit as any).type || \"modify\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: warning,\n error: error_msg,\n critic_markup: null,\n clean_text: null,\n };\n }\n }\n if (validation_failed_idx.size > 0) {\n // Dry-run mirrors the real run's transactional rejection: no edit\n // will be applied by the real run, so none may be reported as\n // applied here. Edits that only failed at runtime keep their own\n // error; edits that would have applied get the transactional note.\n applied_edits = 0;\n skipped_edits = edits.length;\n for (let i = 0; i < reports_by_input.length; i++) {\n const report = reports_by_input[i];\n if (!report || validation_failed_idx.has(i)) continue;\n if (report.status === \"applied\") {\n reports_by_input[i] = {\n status: \"failed\",\n type: report.type || \"modify\",\n target_text: report.target_text,\n new_text: report.new_text,\n warning: null,\n error: TRANSACTIONAL_NOT_APPLIED_ERROR,\n critic_markup: null,\n clean_text: null,\n };\n }\n }\n }\n edits_reports.push(...reports_by_input);\n } else {\n // Simulated dry-run sequentially for wet-run validation parity\n const snapshot = takeSnapshot(this.doc);\n const originalCurrentId = this.current_id;\n try {\n const sequential_errors: string[] = [];\n let applied_so_far = 0;\n for (const { edit, i } of ordered_edits) {\n let single_errors: string[];\n try {\n single_errors = this.validate_edits([edit], i);\n } catch (e) {\n // Clean per-edit failure for time-budget violations (QA F5).\n if (!(e instanceof RegexTimeoutError)) throw e;\n single_errors = [`- Edit ${i + 1} Failed: ${e.message}`];\n }\n if (single_errors.length > 0) {\n if (applied_so_far > 0) {\n const hint = sequential_context_hint(applied_so_far);\n single_errors = single_errors.map((err) => err + hint);\n }\n sequential_errors.push(...single_errors);\n } else {\n this.apply_edits([edit], page_offsets);\n if ((edit as any)._applied_status) {\n applied_so_far++;\n }\n this.mapper = new DocumentMapper(this.doc);\n this.clean_mapper = null;\n }\n }\n if (sequential_errors.length > 0) {\n throw new BatchValidationError(sequential_errors);\n }\n } catch (err) {\n restoreSnapshot(this.doc, snapshot);\n this.current_id = originalCurrentId;\n this.mapper = new DocumentMapper(this.doc);\n this.comments_manager = new CommentsManager(this.doc);\n this.clean_mapper = null;\n throw err;\n }\n\n applied_edits = edits.filter((e) => (e as any)._applied_status).length;\n skipped_edits = edits.length - applied_edits;\n\n for (const edit of edits) {\n const success = (edit as any)._applied_status || false;\n const error_msg = (edit as any)._error_msg || null;\n let critic_markup = null;\n let clean_text = null;\n // Punctuation-anchor warning is failure-context only: on success the\n // redline preview below already reports the change cleanly.\n let warning: string | null = null;\n if (success) {\n const previews = this._build_edit_context_previews(edit);\n critic_markup = previews[0];\n clean_text = previews[1];\n } else {\n warning = this._check_punctuation_warning(\n (edit as any).target_text || \"\",\n );\n }\n edits_reports.push({\n status: success ? \"applied\" : \"failed\",\n type: (edit as any).type || \"modify\",\n target_text: truncate_middle((edit as any).target_text || \"\", REPORT_ECHO_CAP),\n new_text: truncate_middle(RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),\n warning: warning,\n error: error_msg,\n critic_markup: critic_markup,\n clean_text: clean_text,\n pages: (edit as any)._pages || [],\n heading_path: (edit as any)._heading_path || \"\",\n occurrences_modified: (edit as any)._occurrences_modified || 0,\n match_mode: (edit as any).match_mode || \"strict\",\n });\n }\n }\n }\n return {\n actions_applied: applied_actions,\n actions_skipped: skipped_actions,\n // Actions whose target was already resolved by an earlier action of\n // this batch (via its replacement pair): consistent no-ops, never\n // counted as applied — every reported \"applied\" action causes an\n // observable state transition (ADEU-QA-004).\n actions_already_resolved: already_resolved_actions,\n edits_applied: applied_edits,\n edits_skipped: skipped_edits,\n // edits_applied counts change OBJECTS; this is the total number of\n // document occurrences they modified (match_mode=\"all\" fan-out), so\n // automation never has to guess which of the two a count means\n // (QA 2026-07-19 F-21).\n occurrences_modified: edits_reports.reduce(\n (sum: number, r: any) => sum + (r.occurrences_modified || 0),\n 0,\n ),\n skipped_details: this.skipped_details,\n edits: edits_reports,\n engine: \"node\",\n version: \"1.18.2\",\n };\n }\n\n public apply_edits(\n edits: any[],\n page_offsets: number[] = [],\n ): [number, number] {\n let applied = 0;\n let skipped = 0;\n\n if (!page_offsets || page_offsets.length === 0) {\n const [body_text] = split_structural_appendix(this.mapper.full_text);\n page_offsets = paginate(body_text, \"\").body_page_offsets;\n }\n const resolved_edits: [any, string | null][] = [];\n\n for (const edit of edits) {\n if (typeof edit !== \"object\" || edit === null) {\n skipped++;\n continue;\n }\n edit._applied_status = false;\n edit._error_msg = null;\n edit._any_sub_failure = false;\n }\n\n for (const edit of edits) {\n if (typeof edit !== \"object\" || edit === null) continue;\n\n if (\n edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null\n ) {\n resolved_edits.push([edit, edit.new_text || null]);\n } else if (\n edit._match_start_index !== undefined &&\n edit._match_start_index !== null\n ) {\n edit._resolved_start_idx = edit._match_start_index;\n resolved_edits.push([edit, edit.new_text || null]);\n } else if (edit.type === \"insert_row\" || edit.type === \"delete_row\") {\n let matches = this.mapper.drop_virtual_only_matches(\n this.mapper.find_all_match_indices(edit.target_text),\n );\n let resolved_mapper = this.mapper;\n if (matches.length === 0) {\n if (!this.clean_mapper) {\n this.clean_mapper = new DocumentMapper(this.doc, true);\n }\n matches = this.clean_mapper.drop_virtual_only_matches(\n this.clean_mapper.find_all_match_indices(edit.target_text),\n );\n resolved_mapper = this.clean_mapper;\n }\n\n if (matches.length > 0) {\n const match_mode = edit.match_mode || \"strict\";\n\n // We need to resolve matches to unique w:tr elements to deduplicate them.\n const unique_matches: [number, number][] = [];\n const seen_trs = new Set<any>();\n\n for (const match of matches) {\n const start_idx = match[0];\n const [anchor_run, anchor_para] = resolved_mapper.get_insertion_anchor(start_idx, false);\n let target_element: Element | null = null;\n if (anchor_run) target_element = anchor_run._element;\n else if (anchor_para) target_element = anchor_para._element;\n\n let tr: Element | null = target_element;\n while (tr && tr.tagName !== \"w:tr\") tr = tr.parentNode as Element;\n\n if (tr) {\n if (!seen_trs.has(tr)) {\n seen_trs.add(tr);\n unique_matches.push(match);\n }\n }\n }\n\n if (unique_matches.length > 0) {\n let matches_to_apply = unique_matches;\n if (match_mode === \"strict\" || match_mode === \"first\") {\n matches_to_apply = unique_matches.slice(0, 1);\n }\n\n if (match_mode === \"all\" || matches_to_apply.length > 1) {\n // Create sub-edits for each match so that they are processed as independent operations,\n // and the occurrences_modified and applied_status are tracked correctly on the parent.\n for (const m of matches_to_apply) {\n const sub_edit = {\n ...edit,\n _resolved_start_idx: m[0],\n _active_mapper_ref: resolved_mapper,\n _parent_edit_ref: edit,\n };\n resolved_edits.push([sub_edit, null]);\n }\n } else {\n // Single match case for non-\"all\" modes\n edit._resolved_start_idx = matches_to_apply[0][0];\n edit._active_mapper_ref = resolved_mapper;\n resolved_edits.push([edit, null]);\n }\n } else {\n skipped++;\n edit._applied_status = false;\n const target_snippet = (edit.target_text || \"\")\n .trim()\n .substring(0, 40);\n const msg = `- Failed to locate row target: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n }\n } else {\n skipped++;\n edit._applied_status = false;\n const target_snippet = (edit.target_text || \"\")\n .trim()\n .substring(0, 40);\n const msg = `- Failed to locate row target: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n }\n } else {\n let resolved: any;\n try {\n resolved = this._pre_resolve_heuristic_edit(edit);\n } catch (e) {\n // Direct apply_edits callers bypass validate_edits; the time\n // budget must still fail cleanly here (QA F5).\n if (!(e instanceof RegexTimeoutError)) throw e;\n skipped++;\n edit._applied_status = false;\n const msg = `- Failed to apply edit targeting: '${(edit.target_text || \"\").substring(0, 40)}...' (${e.message})`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n continue;\n }\n if (resolved) {\n if (Array.isArray(resolved)) {\n for (const r of resolved) {\n r._resolved_start_idx = r._match_start_index;\n r._parent_edit_ref = edit;\n if (\n edit._resolved_start_idx === undefined ||\n edit._resolved_start_idx === null\n ) {\n edit._resolved_start_idx = r._resolved_start_idx;\n }\n if (!edit._resolved_proxy_edit) {\n edit._resolved_proxy_edit = r;\n }\n resolved_edits.push([r, r.new_text]);\n }\n } else {\n resolved._resolved_start_idx = resolved._match_start_index;\n resolved._parent_edit_ref = edit;\n edit._resolved_start_idx = resolved._resolved_start_idx;\n edit._resolved_proxy_edit = resolved;\n resolved_edits.push([resolved, (resolved as any).new_text]);\n }\n } else {\n skipped++;\n edit._applied_status = false;\n const display_text = edit.target_text || \"insertion\";\n const target_snippet = display_text.trim().substring(0, 40);\n const msg = `- Failed to apply edit targeting: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._error_msg = msg;\n }\n }\n }\n\n resolved_edits.sort(\n (a, b) =>\n (b[0]._resolved_start_idx || 0) - (a[0]._resolved_start_idx || 0),\n );\n\n // Snapshot preview context now, while every resolved offset still refers\n // to the untouched document. The sweep below mutates the DOM and rebuilds\n // the map, shifting offsets and injecting tracked-change markup —\n // slicing full_text at report time garbles previews (QA H1).\n for (const [res_edit] of resolved_edits) {\n this._capture_preview_context(res_edit);\n if (res_edit._parent_edit_ref) {\n this._capture_parent_preview_context(res_edit._parent_edit_ref);\n }\n }\n\n const occupied_ranges: [number, number][] = [];\n // Sub-edits split from one balanced multi-paragraph modification share a\n // _split_group_id; count the group as a single applied edit (and a single\n // occurrence), even though it touches several paragraphs.\n const counted_split_groups = new Set<number>();\n\n for (const [edit, orig_new] of resolved_edits) {\n const start = edit._resolved_start_idx || 0;\n // An insert_row does not consume its anchor text — it adds an adjacent\n // row. Give it a zero-width range so several inserts sharing one\n // anchor (consecutive new rows) never flag each other as overlapping.\n const end =\n edit.type === \"insert_row\"\n ? start\n : start + (edit.target_text ? edit.target_text.length : 0);\n\n const overlaps = occupied_ranges.some(\n ([occ_start, occ_end]) => start < occ_end && end > occ_start,\n );\n if (overlaps) {\n skipped++;\n const display_text = edit.target_text || \"insertion\";\n const target_snippet = display_text.trim().substring(0, 40);\n const msg = `- Skipped overlapping edit targeting: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._applied_status = false;\n edit._error_msg = msg;\n edit._any_sub_failure = true;\n const parent = edit._parent_edit_ref;\n if (parent) {\n parent._applied_status = false;\n parent._error_msg = msg;\n parent._any_sub_failure = true;\n }\n continue;\n }\n\n let success = false;\n if (edit.type === \"modify\") {\n // Never rebuild the map inside the sweep: sub-edits apply in strictly\n // descending offset order, and every DOM mutation (run splits, w:del\n // wraps, w:ins insertions, bottom-up paragraph merges) happens at or\n // above the current offset, so spans below it stay valid in the stale\n // map. Rebuilding here made regex + match_mode=\"all\"\n // O(occurrences × document) (QA 2026-07-19 F-06).\n success = this._apply_single_edit_indexed(edit, orig_new, false);\n } else if (edit.type === \"insert_row\" || edit.type === \"delete_row\") {\n success = this._apply_table_edit(edit, false);\n }\n\n if (success) {\n // A balanced multi-paragraph split fans one logical edit into several\n // paragraph sub-edits sharing a _split_group_id; count it once. Edits\n // with no group id (the common case) always count.\n const group_id = edit._split_group_id;\n const first_in_group =\n group_id === undefined ||\n group_id === null ||\n !counted_split_groups.has(group_id);\n if (first_in_group && group_id !== undefined && group_id !== null) {\n counted_split_groups.add(group_id);\n }\n if (first_in_group) applied++;\n occupied_ranges.push([start, end]);\n edit._applied_status = true;\n const parent = edit._parent_edit_ref;\n if (parent) {\n parent._applied_status = true;\n if (first_in_group) {\n parent._occurrences_modified =\n (parent._occurrences_modified || 0) + 1;\n }\n const [path, page] = this._get_heading_path_and_page(\n start,\n this.mapper.full_text,\n page_offsets,\n );\n const pages: number[] = parent._pages || [];\n if (!pages.includes(page)) pages.unshift(page);\n parent._pages = pages;\n parent._heading_path = path;\n } else {\n if (first_in_group) {\n edit._occurrences_modified = (edit._occurrences_modified || 0) + 1;\n }\n const [path, page] = this._get_heading_path_and_page(\n start,\n this.mapper.full_text,\n page_offsets,\n );\n const pages: number[] = edit._pages || [];\n if (!pages.includes(page)) pages.unshift(page);\n edit._pages = pages;\n edit._heading_path = path;\n }\n } else {\n skipped++;\n const display_text = edit.target_text || \"insertion\";\n const target_snippet = display_text.trim().substring(0, 40);\n const msg = `- Failed to apply edit targeting: '${target_snippet}...'`;\n this.skipped_details.push(msg);\n edit._applied_status = false;\n edit._error_msg = msg;\n edit._any_sub_failure = true;\n const parent = edit._parent_edit_ref;\n if (parent) {\n parent._any_sub_failure = true;\n if (!parent._applied_status) {\n parent._applied_status = false;\n parent._error_msg = msg;\n }\n }\n }\n }\n\n // Return LOGICAL edit counts over the caller's input list: one\n // match_mode=\"all\" edit over N occurrences is one applied edit (its\n // occurrence count lives in _occurrences_modified / the report), never N\n // (QA 2026-07-19 F-21). An edit with any failed or skipped sub-edit\n // counts as skipped so the all-or-nothing batch contract is unchanged.\n let applied_logical = 0;\n let skipped_logical = 0;\n for (const input_edit of edits) {\n if (typeof input_edit !== \"object\" || input_edit === null) {\n skipped_logical++;\n continue;\n }\n if (input_edit._applied_status && !input_edit._any_sub_failure) {\n applied_logical++;\n } else {\n skipped_logical++;\n }\n }\n return [applied_logical, skipped_logical];\n }\n\n /**\n * True when the paragraph still carries visible content (w:t text, w:tab,\n * w:br) that is NOT wrapped in a tracked deletion — i.e. the paragraph\n * would render non-empty in the accepted document.\n */\n private _paragraph_has_visible_content(p_elem: Element): boolean {\n for (const tag of [\"w:t\", \"w:tab\", \"w:br\"]) {\n const nodes = findAllDescendants(p_elem, tag);\n for (const node of nodes) {\n let is_deleted = false;\n let curr = node.parentNode as Element | null;\n while (curr && curr !== p_elem.parentNode) {\n if (curr.tagName === \"w:del\") {\n is_deleted = true;\n break;\n }\n curr = curr.parentNode as Element | null;\n }\n if (!is_deleted) {\n if (tag === \"w:t\" && !node.textContent) continue;\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * All contiguous same-author w:ins/w:del siblings that form one logical\n * modification block with `node` (a replacement's del+ins pair). Mirrors\n * the Python engine's _get_paired_nodes: comment range markers and\n * rPr/pPr are transparent; a different author or any other element breaks\n * the group.\n */\n private _get_paired_nodes(node: Element): Element[] {\n const pairs: Element[] = [];\n const author = node.getAttribute(\"w:author\");\n const transparent = new Set([\n \"w:commentRangeStart\",\n \"w:commentRangeEnd\",\n \"w:commentReference\",\n \"w:rPr\",\n \"w:pPr\",\n ]);\n\n const walk = (start: Element, dir: \"next\" | \"prev\") => {\n let cur: Node | null =\n dir === \"next\" ? start.nextSibling : start.previousSibling;\n while (cur) {\n if (cur.nodeType !== 1) {\n cur = dir === \"next\" ? cur.nextSibling : cur.previousSibling;\n continue;\n }\n const el = cur as Element;\n if (transparent.has(el.tagName)) {\n cur = dir === \"next\" ? cur.nextSibling : cur.previousSibling;\n continue;\n }\n if (\n (el.tagName === \"w:ins\" || el.tagName === \"w:del\") &&\n el.getAttribute(\"w:author\") === author\n ) {\n pairs.push(el);\n cur = dir === \"next\" ? cur.nextSibling : cur.previousSibling;\n continue;\n }\n break;\n }\n };\n\n walk(node, \"next\");\n walk(node, \"prev\");\n return pairs;\n }\n\n /**\n * All revision ids that resolve as ONE unit with `target_id`: the ids of\n * every contiguous same-author w:ins/w:del sibling of its elements (a\n * replacement's del+ins pair), plus the id itself.\n */\n private _resolution_group_ids(target_id: string): Set<string> {\n const nodes = [\n ...findAllDescendants(this.doc.element, \"w:ins\"),\n ...findAllDescendants(this.doc.element, \"w:del\"),\n ].filter((n) => n.getAttribute(\"w:id\") === target_id);\n const group = new Set<string>();\n if (nodes.length === 0) return group;\n group.add(target_id);\n for (const node of nodes) {\n for (const paired of this._get_paired_nodes(node)) {\n const pid = paired.getAttribute(\"w:id\");\n if (pid) group.add(pid);\n }\n }\n return group;\n }\n\n /**\n * Document-aware validation (QA 2026-07-19 ADEU-QA-004): a replacement's\n * del+ins pair carries two distinct ids but resolves as one unit, so a\n * batch that accepts one side and rejects the other is contradictory.\n * Rejecting it up front — before any action mutates the document — keeps\n * the batch transactional.\n */\n public validate_action_pairing(actions: any[]): string[] {\n const errors: string[] = [];\n const group_first = new Map<string, [number, string, string]>();\n for (let pos = 0; pos < actions.length; pos++) {\n const act = actions[pos];\n if (act.type !== \"accept\" && act.type !== \"reject\") continue;\n const raw_id = String(act.target_id ?? \"\");\n if (raw_id.startsWith(\"Com:\")) continue;\n const target_id = raw_id.startsWith(\"Chg:\") ? raw_id.slice(4) : raw_id;\n const group = this._resolution_group_ids(target_id);\n if (group.size === 0) continue; // unknown ids fail with their own not-found error\n let conflict: [number, string, string] | null = null;\n for (const gid of group) {\n const prior = group_first.get(gid);\n if (prior !== undefined && prior[1] !== act.type) {\n conflict = prior;\n break;\n }\n }\n if (conflict !== null) {\n const [first_pos, first_type, first_id] = conflict;\n errors.push(\n `- Action ${pos + 1} Failed: conflicting actions on one replacement — Action ` +\n `${first_pos + 1} applies '${first_type}' to Chg:${first_id}, and Chg:${target_id} is ` +\n `part of the same change (a replacement's contiguous del+ins pair resolves as one ` +\n `unit, so '${first_type}' already decides both sides). Accepting one side and ` +\n `rejecting the other is contradictory — decide the outcome and submit exactly one ` +\n `action for the pair.`,\n );\n continue;\n }\n for (const gid of group) {\n if (!group_first.has(gid)) {\n group_first.set(gid, [pos, act.type, target_id]);\n }\n }\n }\n return errors;\n }\n\n /**\n * Returns [applied, skipped, already_resolved]. `applied` counts actions\n * that caused an observable state transition; an action naming an id an\n * earlier action of this batch already resolved (via its replacement pair)\n * is counted in `already_resolved` instead — never as applied\n * (QA 2026-07-19 ADEU-QA-004).\n */\n public apply_review_actions(actions: any[]): [number, number, number] {\n let applied = 0;\n let skipped = 0;\n let already_resolved = 0;\n const resolved_history = new Map<string, string>(); // id -> resolving action type\n\n // Sort actions internally: non-destructive metadata operations (ReplyComment) first,\n // followed by destructive structural operations (AcceptChange, RejectChange).\n // Stable sort preserves the original relative ordering, and we preserve `pos`\n // so diagnostic messages refer to the original array indexes.\n const sortedActions = actions\n .map((action, pos) => ({ action, pos }))\n .sort((a, b) => {\n const aPri = a.action.type === \"reply\" ? 0 : 1;\n const bPri = b.action.type === \"reply\" ? 0 : 1;\n if (aPri !== bPri) {\n return aPri - bPri;\n }\n return a.pos - b.pos;\n });\n\n for (const { action, pos } of sortedActions) {\n const type = action.type;\n if (type === \"reply\") {\n const cid = action.target_id.replace(\"Com:\", \"\");\n const new_id = this.comments_manager.addComment(\n this.author,\n action.text,\n cid,\n );\n this._anchor_reply_comment(cid, new_id);\n applied++;\n continue;\n }\n\n const target_id = action.target_id.replace(\"Chg:\", \"\");\n\n const prior_type = resolved_history.get(target_id);\n if (prior_type !== undefined) {\n if (prior_type === type) {\n // Consistent follow-up on the pair: legitimate agent workflow\n // (\"accept both ids of the replacement\"), but no state transition\n // happens — report it accurately (ADEU-QA-004).\n already_resolved++;\n this.skipped_details.push(\n `- Note: Action ${pos + 1} ('${type}' on ${action.target_id}) had no additional effect — ` +\n `the change was already resolved together with its replacement pair by an earlier ` +\n `action in this batch. Counted as already_resolved, not applied.`,\n );\n continue;\n }\n // Contradiction. validate_action_pairing rejects this shape before\n // anything mutates; this guard covers direct callers.\n this.skipped_details.push(\n `- Action ${pos + 1} Failed: contradictory action — '${type}' on ${action.target_id}, but ` +\n `the change was already resolved as '${prior_type}' together with its replacement ` +\n `pair by an earlier action in this batch.`,\n );\n skipped++;\n continue;\n }\n\n const all_ins = findAllDescendants(this.doc.element, \"w:ins\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n const all_del = findAllDescendants(this.doc.element, \"w:del\").filter(\n (n) => n.getAttribute(\"w:id\") === target_id,\n );\n const all_nodes = [...all_ins, ...all_del];\n\n if (all_nodes.length === 0) {\n skipped++;\n this.skipped_details.push(\n `- Failed to apply action: Target ID ${action.target_id} not found.`,\n );\n continue;\n }\n\n // Refuse accept/reject on a w:id shared by revisions from DIFFERENT\n // authors. Uniqueness of w:id is assumed but not guaranteed for\n // externally produced documents (merges, cross-document copy-paste),\n // where one action would silently resolve several unrelated changes\n // (QA 2026-07-17 F9). Same-author reuse is legitimate — this engine\n // itself mints one id across every element of a single logical edit —\n // so authorship is the discriminator.\n const dup_authors = Array.from(\n new Set(all_nodes.map((n) => n.getAttribute(\"w:author\") || \"Unknown\")),\n ).sort();\n if (dup_authors.length > 1) {\n skipped++;\n this.skipped_details.push(\n `- Failed to apply action: ${type} on Chg:${target_id} is ambiguous. The document ` +\n `contains ${all_nodes.length} tracked-change elements sharing w:id=${target_id} from ` +\n `different authors (${dup_authors.join(\", \")}) — duplicate revision IDs produced ` +\n `outside this engine (e.g. by a document merge or copy-paste). Acting on this ID ` +\n `would resolve all of them at once. Resolve these changes individually in Word, or ` +\n `apply the intended outcome as an explicit text edit instead.`,\n );\n continue;\n }\n\n // A modification is one logical unit stored as a contiguous\n // same-author del+ins pair: resolving either side resolves BOTH —\n // Word's atomic replacement handling, and the Python engine's\n // long-standing behavior. Without this, accepting the deletion side\n // left the paired insertion pending (engine divergence,\n // QA 2026-07-19 ADEU-QA-004).\n const group_nodes = new Set<Element>(all_nodes);\n for (const node of all_nodes) {\n for (const paired of this._get_paired_nodes(node)) {\n group_nodes.add(paired);\n }\n }\n const resolved_now = new Set<string>();\n for (const node of group_nodes) {\n const rid = node.getAttribute(\"w:id\");\n if (rid) resolved_now.add(rid);\n }\n\n for (const node of group_nodes) {\n const is_ins = node.tagName === \"w:ins\";\n const parent_tag = node.parentNode\n ? (node.parentNode as Element).tagName\n : \"\";\n const is_trPr = parent_tag === \"w:trPr\";\n\n if (type === \"accept\") {\n if (is_ins) {\n this._clean_wrapping_comments(node);\n if (is_trPr) node.parentNode?.removeChild(node);\n else {\n while (node.firstChild)\n node.parentNode?.insertBefore(node.firstChild, node);\n node.parentNode?.removeChild(node);\n }\n } else {\n this._clean_wrapping_comments(node);\n this._delete_comments_in_element(node);\n if (is_trPr) {\n const tr = node.parentNode?.parentNode;\n tr?.parentNode?.removeChild(tr);\n } else {\n node.parentNode?.removeChild(node);\n }\n }\n } else if (type === \"reject\") {\n if (is_ins) {\n this._clean_wrapping_comments(node);\n this._delete_comments_in_element(node);\n if (is_trPr) {\n const tr = node.parentNode?.parentNode;\n tr?.parentNode?.removeChild(tr);\n } else node.parentNode?.removeChild(node);\n } else {\n this._clean_wrapping_comments(node);\n if (is_trPr) node.parentNode?.removeChild(node);\n else {\n const delTexts = Array.from(\n node.getElementsByTagName(\"w:delText\"),\n );\n for (const dt of delTexts) {\n const t = dt.ownerDocument!.createElement(\"w:t\");\n t.textContent = dt.textContent;\n if (dt.hasAttribute(\"xml:space\"))\n t.setAttribute(\"xml:space\", \"preserve\");\n dt.parentNode?.replaceChild(t, dt);\n }\n while (node.firstChild)\n node.parentNode?.insertBefore(node.firstChild, node);\n node.parentNode?.removeChild(node);\n }\n }\n }\n }\n for (const rid of resolved_now) {\n resolved_history.set(rid, type);\n }\n applied++;\n }\n return [applied, skipped, already_resolved];\n }\n\n private _apply_table_edit(edit: any, rebuild_map: boolean): boolean {\n const start_idx =\n edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null\n ? edit._resolved_start_idx\n : edit._match_start_index || 0;\n // The offset must be looked up in the coordinate space it was resolved\n // in: a clean-view offset applied to the raw\n // mapper points at earlier text once tracked changes exist.\n const active_mapper: DocumentMapper = edit._active_mapper_ref || this.mapper;\n const [anchor_run, anchor_para] = active_mapper.get_insertion_anchor(\n start_idx,\n rebuild_map,\n );\n\n let target_element: Element | null = null;\n if (anchor_run) target_element = anchor_run._element;\n else if (anchor_para) target_element = anchor_para._element;\n\n if (!target_element) return false;\n\n let tr: Element | null = target_element;\n while (tr && tr.tagName !== \"w:tr\") tr = tr.parentNode as Element;\n if (!tr) return false;\n\n if (edit.type === \"delete_row\") {\n let trPr = findChild(tr, \"w:trPr\");\n if (!trPr) {\n trPr = tr.ownerDocument!.createElement(\"w:trPr\");\n tr.insertBefore(trPr, tr.firstChild);\n }\n trPr.appendChild(this._create_track_change_tag(\"w:del\"));\n return true;\n } else if (edit.type === \"insert_row\") {\n const new_tr = tr.ownerDocument!.createElement(\"w:tr\");\n const trPr = tr.ownerDocument!.createElement(\"w:trPr\");\n new_tr.appendChild(trPr);\n trPr.appendChild(this._create_track_change_tag(\"w:ins\"));\n // The new row must carry exactly as many cells as the anchor row has\n // columns: pad missing cells with empty strings and drop extras\n // (validation already rejects overfilled batches upfront, QA M3) so a\n // mismatched `cells` list can never produce a structurally\n // inconsistent table row.\n const anchor_cols = findAllDescendants(tr, \"w:tc\").filter(\n (tc) => tc.parentNode === tr,\n ).length;\n let cell_values: string[] = Array.isArray(edit.cells)\n ? [...edit.cells]\n : [];\n if (anchor_cols > 0) {\n while (cell_values.length < anchor_cols) cell_values.push(\"\");\n cell_values = cell_values.slice(0, anchor_cols);\n }\n for (const cellText of cell_values) {\n const tc = tr.ownerDocument!.createElement(\"w:tc\");\n const p = tr.ownerDocument!.createElement(\"w:p\");\n const r = tr.ownerDocument!.createElement(\"w:r\");\n const t = tr.ownerDocument!.createElement(\"w:t\");\n t.textContent = cellText;\n if (cellText.trim() !== cellText)\n t.setAttribute(\"xml:space\", \"preserve\");\n r.appendChild(t);\n p.appendChild(r);\n tc.appendChild(p);\n new_tr.appendChild(tc);\n }\n if (edit.position === \"above\") tr.parentNode?.insertBefore(new_tr, tr);\n else insertAfter(new_tr, tr);\n return true;\n }\n return false;\n }\n\n private _pre_resolve_heuristic_edit(edit: any): any {\n if (!edit.target_text) return null;\n\n const is_regex = edit.regex || false;\n const match_mode = edit.match_mode || \"strict\";\n\n let matches = this.mapper.drop_virtual_only_matches(\n this.mapper.find_all_match_indices(edit.target_text, is_regex),\n );\n let use_clean_map = false;\n\n if (matches.length === 0) {\n if (!this.clean_mapper)\n this.clean_mapper = new DocumentMapper(this.doc, true);\n matches = this.clean_mapper.drop_virtual_only_matches(\n this.clean_mapper.find_all_match_indices(edit.target_text, is_regex),\n );\n if (matches.length > 0) use_clean_map = true;\n else return null;\n }\n\n const active_mapper = use_clean_map ? this.clean_mapper! : this.mapper;\n\n let live_matches: [number, number][] = [];\n for (const [s, match_len] of matches) {\n const realSpans = active_mapper.spans.filter(\n (span) =>\n span.run !== null && span.end > s && span.start < s + match_len,\n );\n // Virtual-only matches were already dropped above; here we only skip\n // matches buried entirely inside tracked deletions.\n if (realSpans.length === 0 || realSpans.some((span) => !span.del_id)) {\n live_matches.push([s, match_len]);\n }\n }\n\n if (live_matches.length === 0) return null;\n\n if (match_mode === \"strict\" || match_mode === \"first\") {\n live_matches = live_matches.slice(0, 1);\n }\n\n const all_sub_edits: any[] = [];\n\n for (const [start_idx, match_len] of live_matches) {\n const actual_doc_text = active_mapper.full_text.substring(\n start_idx,\n start_idx + match_len,\n );\n let current_effective_new_text = edit.new_text || \"\";\n\n // Cell anchors ({#cell:<paraId>}) are pure position markers with no real\n // content — they let the model address an empty (or any) table cell that\n // has no run to diff against. Treat such a target as a clean INSERTION at\n // the anchor's paragraph: never delete the marker, never run trim_common_context\n // (which refuses to split inside {#...} markup and yields a no-op MODIFICATION).\n // Strip any echoed anchor from new_text so the model can send either\n // \"June 22, 2026\" or \"June 22, 2026{#cell:...}\" and get the same result.\n if (/^\\{#cell:[^}]+\\}$/.test(actual_doc_text.trim())) {\n let ins_text = current_effective_new_text;\n // Drop a leading/trailing copy of the same anchor token if echoed.\n ins_text = ins_text.split(actual_doc_text.trim()).join(\"\");\n if (ins_text) {\n all_sub_edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: ins_text,\n comment: edit.comment,\n // Insert at the anchor token's start so the new run lands inside\n // the cell paragraph that get_insertion_anchor resolves there.\n _match_start_index: start_idx,\n _internal_op: \"INSERTION\",\n _active_mapper_ref: active_mapper,\n });\n } else if (edit.comment) {\n // Anchor target with empty effective new_text but a comment: attach\n // the comment to the cell paragraph.\n all_sub_edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: \"\",\n comment: edit.comment,\n _match_start_index: start_idx,\n _internal_op: \"COMMENT_ONLY\",\n _active_mapper_ref: active_mapper,\n });\n }\n continue;\n }\n\n if (is_regex && current_effective_new_text) {\n try {\n current_effective_new_text = actual_doc_text.replace(\n new RegExp(edit.target_text),\n current_effective_new_text,\n );\n } catch (e) {}\n }\n\n // Stash the first occurrence's full match for the report preview, so it\n // can show the complete logical change rather than only the first\n // word-diff sub-edit (e.g. \"{--two--}{++five++} (2) years\" for a\n // \"two (2) years\" -> \"five (5) years\" edit). Mirrors Python (QA H1).\n if (!edit._preview_span) {\n edit._preview_span = [start_idx, match_len];\n edit._preview_matched_text = actual_doc_text;\n edit._preview_new_text = current_effective_new_text;\n edit._preview_mapper_ref = active_mapper;\n }\n\n const [edit_target_clean, edit_target_style] = this._parse_markdown_style(\n edit.target_text,\n );\n const [edit_new_clean, edit_new_style] = this._parse_markdown_style(\n current_effective_new_text,\n );\n\n if (edit_target_style !== edit_new_style) {\n const [actual_clean] = this._parse_markdown_style(actual_doc_text);\n const final_target = actual_clean;\n const final_new = edit_new_clean;\n const style_op =\n final_target === final_new ? \"STYLE_ONLY\" : \"STYLE_AND_TEXT\";\n const prefix_offset = actual_doc_text.indexOf(actual_clean);\n const effective_start_idx =\n start_idx + (prefix_offset !== -1 ? prefix_offset : 0);\n const resolved_style =\n edit_new_style !== null ? edit_new_style : \"Normal\";\n\n all_sub_edits.push({\n type: \"modify\",\n target_text: final_target,\n new_text: final_new,\n comment: edit.comment,\n _match_start_index: effective_start_idx,\n _internal_op: style_op,\n _new_style: resolved_style,\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n if (\n actual_doc_text === current_effective_new_text ||\n edit.target_text === current_effective_new_text\n ) {\n all_sub_edits.push({\n type: \"modify\",\n target_text: actual_doc_text,\n new_text: actual_doc_text,\n comment: edit.comment,\n _match_start_index: start_idx,\n _internal_op: \"COMMENT_ONLY\",\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n let overlaps_virtual_pipe = false;\n if (active_mapper) {\n overlaps_virtual_pipe = active_mapper.spans.some(\n (s: any) =>\n s.text === \" | \" &&\n (s.run === null || s.run === undefined) &&\n s.start < start_idx + match_len &&\n s.end > start_idx,\n );\n }\n\n if (overlaps_virtual_pipe) {\n const actual_cells = actual_doc_text.split(\"|\");\n const new_cells = current_effective_new_text.split(\"|\");\n\n if (actual_cells.length !== new_cells.length) {\n throw new BatchValidationError([\n `Target text spans ${actual_cells.length} table cells, but replacement provides ${new_cells.length}. To modify text without altering table structure (rows or columns), ensure the replacement contains the exact same number of '|' separators (e.g., replace with 'CellC | ' to empty the second cell).`\n ]);\n }\n\n if (actual_cells.length > 1) {\n const sub_edits: any[] = [];\n\n // actual_doc_text IS the document slice at\n // [start_idx, start_idx + len): per-cell offsets are exact\n // arithmetic over that slice — never a search of mapper.full_text,\n // which cannot distinguish repeated cell text and lands in the\n // wrong cell when the matched range starts inside a \" | \"\n // separator.\n let cell_start_in_target = 0;\n\n // Determine which cell receives the comment\n let target_comment_idx = 0;\n for (let idx = 0; idx < actual_cells.length; idx++) {\n if (actual_cells[idx].trim() !== new_cells[idx].trim()) {\n target_comment_idx = idx;\n break;\n }\n }\n\n for (let cell_idx = 0; cell_idx < actual_cells.length; cell_idx++) {\n const a_cell = actual_cells[cell_idx];\n const n_cell = new_cells[cell_idx];\n const a_clean = a_cell.trim();\n const n_clean = n_cell.trim();\n const actual_start =\n start_idx +\n cell_start_in_target +\n (a_clean ? a_cell.indexOf(a_clean) : 0);\n\n const should_attach_comment = (edit.comment !== null && edit.comment !== undefined) && (cell_idx === target_comment_idx);\n\n if (a_clean !== n_clean || should_attach_comment) {\n const cell_sub_edits = this._word_diff_sub_edits(\n a_clean,\n n_clean,\n actual_start,\n should_attach_comment ? edit.comment : null,\n true,\n active_mapper,\n );\n for (const se of cell_sub_edits) {\n se._original_target_text = edit.target_text;\n se._split_group_id = start_idx;\n sub_edits.push(se);\n }\n }\n\n cell_start_in_target += a_cell.length + 1; // +1 for the '|'\n }\n\n for (const sub of sub_edits) {\n all_sub_edits.push(sub);\n }\n continue;\n }\n // Exactly one \"cell\": the target merely brushes a separator (its\n // match range starts or ends inside \" | \") without crossing into\n // another cell's text. That is an ordinary in-cell edit — fall\n // through to the standard resolution.\n }\n\n let has_markdown = false;\n if (edit.target_text && (edit.target_text.includes(\"**\") || edit.target_text.includes(\"_\"))) {\n has_markdown = true;\n }\n if (current_effective_new_text && (current_effective_new_text.includes(\"**\") || current_effective_new_text.includes(\"_\"))) {\n has_markdown = true;\n }\n\n let effective_op = \"\";\n let final_target = \"\";\n let final_new = \"\";\n let effective_start_idx = start_idx;\n\n if (current_effective_new_text.startsWith(actual_doc_text)) {\n effective_op = \"INSERTION\";\n final_new = current_effective_new_text.substring(actual_doc_text.length);\n effective_start_idx = start_idx + match_len;\n } else {\n const [prefix_len, suffix_len] = trim_common_context(\n actual_doc_text,\n current_effective_new_text,\n );\n const t_end = actual_doc_text.length - suffix_len;\n const n_end = current_effective_new_text.length - suffix_len;\n\n final_target = actual_doc_text.substring(prefix_len, t_end);\n final_new = current_effective_new_text.substring(prefix_len, n_end);\n effective_start_idx = start_idx + prefix_len;\n }\n\n if (has_markdown) {\n if (!final_target && final_new) {\n effective_op = \"INSERTION\";\n } else if (final_target && !final_new) {\n effective_op = \"DELETION\";\n } else if (final_target && final_new) {\n effective_op = \"MODIFICATION\";\n } else {\n all_sub_edits.push({\n type: \"modify\",\n target_text: final_target,\n new_text: final_new,\n comment: edit.comment,\n _match_start_index: effective_start_idx,\n _internal_op: \"COMMENT_ONLY\",\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n all_sub_edits.push({\n type: \"modify\",\n target_text: final_target,\n new_text: final_new,\n comment: edit.comment,\n _resolved_start_idx: effective_start_idx,\n _match_start_index: effective_start_idx,\n _internal_op: effective_op,\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n // Balanced multi-paragraph modification: the matched span crosses one or\n // more paragraph breaks and the replacement preserves the same number of\n // breaks. Apply it as one independent sub-edit per paragraph segment so\n // the structural \\n\\n breaks are left intact. Each sub-edit shares a\n // _split_group_id (the occurrence's start index) so the batch report\n // counts it as a single applied edit. Unbalanced cases (a genuine\n // paragraph merge or split) fall through to the single-span path and are\n // rejected by validate_edits.\n const target_segs = actual_doc_text.split(\"\\n\\n\");\n const new_segs = current_effective_new_text.split(\"\\n\\n\");\n if (\n actual_doc_text.includes(\"\\n\\n\") &&\n target_segs.length === new_segs.length\n ) {\n const split_sub_edits: any[] = [];\n let seg_offset = start_idx;\n let comment_assigned = false;\n for (let k = 0; k < target_segs.length; k++) {\n const t_seg = target_segs[k];\n const n_seg = new_segs[k];\n if (t_seg !== n_seg) {\n const seg_comment =\n edit.comment && !comment_assigned ? edit.comment : null;\n const seg_sub_edits = this._word_diff_sub_edits(\n t_seg,\n n_seg,\n seg_offset,\n seg_comment,\n false,\n active_mapper,\n );\n if (seg_sub_edits.some((se) => se.comment !== null && se.comment !== undefined)) {\n comment_assigned = true;\n }\n for (const se of seg_sub_edits) {\n se._split_group_id = start_idx;\n split_sub_edits.push(se);\n }\n }\n // Advance past this segment plus its \"\\n\\n\" separator span.\n seg_offset += t_seg.length + 2;\n }\n if (split_sub_edits.length > 0) {\n for (const sub of split_sub_edits) all_sub_edits.push(sub);\n continue;\n }\n }\n\n // After trimming shared context, an edit whose target remainder is\n // EMPTY is a pure insertion with exactly one hunk. Resolve it\n // directly at the effective offset instead of word-diffing the full\n // strings: dmp's alignment can cross-match punctuation between the\n // shared context and the inserted text (pairing the period of \"two.\"\n // with \"marker.\") and split the insertion apart.\n if (!final_target && final_new) {\n all_sub_edits.push({\n type: \"modify\",\n target_text: \"\",\n new_text: final_new,\n comment: edit.comment,\n _resolved_start_idx: effective_start_idx,\n _match_start_index: effective_start_idx,\n _internal_op: \"INSERTION\",\n _active_mapper_ref: active_mapper,\n });\n continue;\n }\n\n const sub_edits = this._word_diff_sub_edits(\n actual_doc_text,\n current_effective_new_text,\n start_idx,\n edit.comment,\n false,\n active_mapper,\n );\n for (const se of sub_edits) {\n se._split_group_id = start_idx;\n all_sub_edits.push(se);\n }\n }\n\n if (all_sub_edits.length === 0) return null;\n if (match_mode === \"all\" || all_sub_edits.length > 1) return all_sub_edits;\n return all_sub_edits[0];\n }\n\n /**\n * Split a <w:ins> so that everything up to and INCLUDING split_after stays in\n * a left <w:ins>, new_elem is placed between, and the remainder moves to a\n * right <w:ins> — all at the grandparent level. Used when revising another\n * author's pending insertion: the <w:del> stays nested in their <w:ins> while\n * our replacement <w:ins> lands as a sibling, so we never nest <w:ins> in\n * <w:ins>.\n */\n private _insert_and_split_ins(\n parent_ins: Element,\n anchor: Element,\n new_elem: Element,\n split_before: boolean = false,\n ) {\n const grandparent = parent_ins.parentNode as Element | null;\n if (!grandparent) return;\n // cloneNode(false) copies the attributes (author/id/date) onto both halves.\n // The split lands after `anchor` by default; with split_before the anchor\n // itself goes to the right half so new_elem ends up in front of it.\n const left = parent_ins.cloneNode(false) as Element;\n const right = parent_ins.cloneNode(false) as Element;\n let toRight = false;\n for (const kid of Array.from(parent_ins.childNodes)) {\n parent_ins.removeChild(kid);\n if (split_before && kid === anchor) toRight = true;\n if (!toRight) {\n left.appendChild(kid);\n if (kid === anchor) toRight = true;\n } else {\n right.appendChild(kid);\n }\n }\n if (left.childNodes.length > 0) grandparent.insertBefore(left, parent_ins);\n grandparent.insertBefore(new_elem, parent_ins);\n if (right.childNodes.length > 0)\n grandparent.insertBefore(right, parent_ins);\n grandparent.removeChild(parent_ins);\n }\n\n private _apply_single_edit_indexed(\n edit: any,\n orig_new: string | null,\n rebuild_map: boolean,\n ): boolean {\n let op = edit._internal_op;\n const active_mapper = edit._active_mapper_ref || this.mapper;\n const start_idx =\n edit._resolved_start_idx !== undefined &&\n edit._resolved_start_idx !== null\n ? edit._resolved_start_idx\n : edit._match_start_index || 0;\n const length = edit.target_text ? edit.target_text.length : 0;\n\n // Indexed edits (caller-supplied _match_start_index, e.g. straight from\n // generate_edits_from_text) bypass _pre_resolve_heuristic_edit — the only\n // place _internal_op is normally assigned. Without this fallback the\n // deletion sweep below still runs but no insertion branch does: a\n // replacement silently degrades to a pure tracked deletion and a pure\n // insertion fails. Mirrors the Python engine.\n if (op === undefined || op === null) {\n if (!edit.target_text && edit.new_text) {\n op = \"INSERTION\";\n } else if (edit.target_text && !edit.new_text) {\n op = \"DELETION\";\n } else {\n op = \"MODIFICATION\";\n }\n }\n\n // Explicit bold/italic markers in the edit make the markers\n // authoritative: inserted runs must not additionally inherit the replaced\n // span's emphasis (QA 2026-07-19 F-02). Keys on THIS resolved edit's\n // post-trim fields: identical markers on both sides were absorbed into\n // context (formatting unchanged — keep inheriting), and plain edits\n // fuzzy-matched onto styled text never receive marker hunks at all.\n const suppress_emphasis = this._edit_declares_emphasis(edit);\n\n if (op === \"STYLE_ONLY\" || op === \"STYLE_AND_TEXT\") {\n const [anchor_run, anchor_para] = active_mapper.get_insertion_anchor(\n start_idx,\n rebuild_map,\n );\n let target_para_el: Element | null = null;\n if (anchor_para) {\n target_para_el = anchor_para._element;\n } else if (anchor_run) {\n let walker: Element | null = anchor_run._element;\n while (walker && walker.tagName !== \"w:p\") {\n walker = walker.parentNode as Element | null;\n }\n target_para_el = walker;\n }\n\n if (target_para_el && edit._new_style) {\n this._set_paragraph_style(target_para_el, edit._new_style);\n }\n\n if (op === \"STYLE_ONLY\") {\n if (edit.comment) {\n const target_runs = active_mapper.find_target_runs_by_index(\n start_idx,\n length,\n rebuild_map,\n );\n if (target_runs.length > 0) {\n const first_el = target_runs[0]._element;\n const last_el = target_runs[target_runs.length - 1]._element;\n let start_p: Element | null = first_el;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element;\n let end_p: Element | null = last_el;\n while (end_p && end_p.tagName !== \"w:p\")\n end_p = end_p.parentNode as Element;\n if (start_p && end_p) {\n const ascend_to_paragraph_child = (\n el: Element,\n p: Element,\n ): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n const first_anchor = ascend_to_paragraph_child(first_el, start_p);\n const last_anchor = ascend_to_paragraph_child(last_el, end_p);\n if (start_p === end_p) {\n this._attach_comment(\n start_p,\n first_anchor,\n last_anchor,\n edit.comment,\n );\n } else {\n this._attach_comment_spanning(\n start_p,\n first_anchor,\n end_p,\n last_anchor,\n edit.comment,\n );\n }\n }\n }\n }\n return true;\n }\n\n if (edit.target_text && edit.new_text) {\n op = \"MODIFICATION\";\n } else if (!edit.target_text && edit.new_text) {\n op = \"INSERTION\";\n } else if (edit.target_text && !edit.new_text) {\n op = \"DELETION\";\n } else {\n op = \"COMMENT_ONLY\";\n }\n }\n\n const del_id = [\"DELETION\", \"MODIFICATION\"].includes(op)\n ? this._getNextId()\n : null;\n const ins_id = [\"INSERTION\", \"MODIFICATION\"].includes(op)\n ? this._getNextId()\n : null;\n\n if (op === \"COMMENT_ONLY\") {\n // Resolve the runs covering [start_idx, start_idx+length) and attach a\n // comment around them. No tracked-change is produced.\n const target_runs = active_mapper.find_target_runs_by_index(\n start_idx,\n length,\n rebuild_map,\n );\n if (target_runs.length === 0) return false;\n if (!edit.comment) return true;\n\n const first_el = target_runs[0]._element;\n const last_el = target_runs[target_runs.length - 1]._element;\n\n // Walk up from the first/last run to their containing <w:p>.\n let start_p: Element | null = first_el;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element;\n let end_p: Element | null = last_el;\n while (end_p && end_p.tagName !== \"w:p\")\n end_p = end_p.parentNode as Element;\n if (!start_p || !end_p) return false;\n\n // first_el / last_el may live inside a <w:ins> or <w:del>. We need their\n // top-level child-of-paragraph ancestor so the comment markers become\n // siblings of those wrappers, not children.\n const ascend_to_paragraph_child = (el: Element, p: Element): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n const first_anchor = ascend_to_paragraph_child(first_el, start_p);\n const last_anchor = ascend_to_paragraph_child(last_el, end_p);\n\n if (start_p === end_p) {\n this._attach_comment(start_p, first_anchor, last_anchor, edit.comment);\n } else {\n this._attach_comment_spanning(\n start_p,\n first_anchor,\n end_p,\n last_anchor,\n edit.comment,\n );\n }\n return true;\n }\n if (op === \"INSERTION\") {\n let final_new_text = edit.new_text || \"\";\n\n // A MACHINE-PINNED pure insertion (diff/text round-trip output:\n // authored with an empty target and no parent edit) positioned in the\n // separator gap between the body and a following part anchors to the\n // end of the BODY with forced new-paragraph semantics — anchoring on\n // the next part's first paragraph writes the new final body paragraph\n // into word/footer1.xml. Insertions DERIVED from a target-anchored\n // edit (parent ref set — e.g. prepending \"DRAFT \" to \"FOOTER MARKER\")\n // keep the user's chosen anchor: their context names the part they\n // meant.\n let boundary_anchor: TextSpan | null = null;\n const boundary =\n typeof (active_mapper as any).part_boundary_at === \"function\"\n ? active_mapper.part_boundary_at(start_idx)\n : null;\n const is_machine_pure_insertion =\n !edit.target_text &&\n (edit._parent_edit_ref === undefined || edit._parent_edit_ref === null);\n if (boundary !== null && is_machine_pure_insertion) {\n const [prev_i, next_i] = boundary;\n const prev_kind = active_mapper.part_kind_of(prev_i);\n const next_kind = active_mapper.part_kind_of(next_i);\n if (prev_kind === \"body\" && next_kind !== \"body\") {\n const real_before = active_mapper.spans.filter(\n (s: TextSpan) => s.run !== null && s.part_index === prev_i,\n );\n if (real_before.length > 0) {\n boundary_anchor = real_before[real_before.length - 1];\n }\n }\n }\n\n let anchor_run: Run | null;\n let anchor_para: Paragraph | null;\n if (boundary_anchor !== null) {\n anchor_run = boundary_anchor.run;\n anchor_para = boundary_anchor.paragraph;\n if (!final_new_text.startsWith(\"\\n\")) {\n final_new_text = \"\\n\\n\" + final_new_text;\n }\n } else {\n [anchor_run, anchor_para] = active_mapper.get_insertion_anchor(\n start_idx,\n rebuild_map,\n );\n }\n if (!anchor_run && !anchor_para) return false;\n\n // QA 2026-07-18 C2 (apply-level backstop, pinned edits bypass\n // validate_edits): refuse insertions that would write row-shaped pipe\n // text into a table cell.\n if (\n RedlineEngine._introduces_table_row_text(\n active_mapper,\n start_idx,\n 1,\n \"\",\n final_new_text,\n )\n ) {\n return false;\n }\n\n // BUG-23-3: a prefix insertion whose new_text ends in a paragraph break\n // (e.g. \"Summary\\n\\n\" inserted before \"Conclusion\") must become a NEW\n // paragraph placed BEFORE the anchor paragraph, not inline text merged\n // into a neighbouring paragraph. _track_insert_multiline drops the\n // trailing break and inlines the remainder, which both loses the\n // paragraph boundary and mis-orders the content. Handle this case here.\n // (Skipped when the C1 boundary re-anchor above took over the anchor.)\n const _bug233_new = final_new_text;\n const _bug233_trailing_break =\n boundary_anchor === null && /\\n\\s*$/.test(_bug233_new);\n let _bug233_target_para: Element | null = null;\n {\n const startingSpans = active_mapper.spans.filter(\n (s: TextSpan) => s.paragraph !== null && s.start === start_idx,\n );\n if (startingSpans.length > 0 && startingSpans[0].paragraph) {\n _bug233_target_para = startingSpans[0].paragraph._element;\n }\n }\n if (\n _bug233_trailing_break &&\n _bug233_target_para &&\n _bug233_target_para.parentNode\n ) {\n const body = _bug233_target_para.parentNode as Element;\n const xmlDoc = this.doc.part._element.ownerDocument!;\n const lines = _bug233_new\n .split(/[\\r\\n]+/)\n .filter((l: string) => l !== \"\");\n let firstNew: Element | null = null;\n let lastNew: Element | null = null;\n let lastIns: Element | null = null;\n for (const raw_line of lines) {\n const [clean_text, style_name] = this._parse_markdown_style(raw_line);\n const new_p = xmlDoc.createElement(\"w:p\");\n if (style_name) {\n this._set_paragraph_style(new_p, style_name);\n } else {\n const existing_pPr = findChild(_bug233_target_para, \"w:pPr\");\n if (existing_pPr) {\n new_p.appendChild(this._clone_pPr_scrubbing_headings(existing_pPr));\n }\n }\n let pPr = findChild(new_p, \"w:pPr\");\n if (!pPr) {\n pPr = xmlDoc.createElement(\"w:pPr\");\n new_p.insertBefore(pPr, new_p.firstChild);\n }\n let rPr = findChild(pPr, \"w:rPr\");\n if (!rPr) {\n rPr = xmlDoc.createElement(\"w:rPr\");\n pPr.appendChild(rPr);\n }\n rPr.appendChild(this._create_track_change_tag(\"w:ins\", \"\", ins_id!));\n const content_ins = this._build_tracked_ins_for_line(\n clean_text,\n anchor_run,\n ins_id!,\n xmlDoc,\n suppress_emphasis,\n );\n if (content_ins) new_p.appendChild(content_ins);\n body.insertBefore(new_p, _bug233_target_para);\n if (!firstNew) firstNew = new_p;\n lastNew = new_p;\n lastIns = content_ins;\n }\n if (firstNew) {\n if (edit.comment && lastNew && lastIns) {\n const ascend = (el: Element, p: Element): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p)\n cur = cur.parentNode as Element;\n return cur;\n };\n const startIns =\n findAllDescendants(firstNew, \"w:ins\")[0] || firstNew;\n this._attach_comment_spanning(\n firstNew,\n ascend(startIns, firstNew),\n lastNew,\n ascend(lastIns, lastNew),\n edit.comment,\n );\n }\n return true;\n }\n }\n\n const result = this._track_insert_multiline(\n final_new_text,\n anchor_run,\n anchor_para,\n ins_id!,\n null,\n suppress_emphasis,\n // Paragraph-start insertions attach BEFORE the anchor (see\n // before_anchor below): the suffix relocation must know.\n start_idx === 0,\n );\n\n if (!result.first_node) return false;\n\n // Place the inline <w:ins> (or block-mode first paragraph) into the DOM.\n // Block-mode first_node is already a freshly-inserted <w:p>; only the\n // inline case needs DOM splicing here.\n const is_inline_first = result.first_node.tagName === \"w:ins\";\n if (is_inline_first) {\n if (anchor_run) {\n let anchor_el: Element = anchor_run._element;\n let anchor_parent = anchor_el.parentNode as Element | null;\n // A tracked-deleted anchor (run inside <w:del>) cannot host the\n // new <w:ins> as a child — an insertion nested inside a deletion\n // is invalid revision XML. Lift the anchor to the <w:del> wrapper\n // so the insert lands beside the whole block (mirrors the Python\n // engine).\n if (anchor_parent && anchor_parent.tagName === \"w:del\") {\n anchor_el = anchor_parent;\n anchor_parent = anchor_el.parentNode as Element | null;\n }\n // get_insertion_anchor(0) resolves to the document's FIRST run: the\n // insertion point precedes it, so the new <w:ins> must land before\n // the anchor, not after (mirrors the Python engine's insert_before\n // path).\n const before_anchor = start_idx === 0;\n if (anchor_parent && anchor_parent.tagName === \"w:ins\") {\n // Inserting inside another author's pending <w:ins>: split it so our\n // new <w:ins> lands as a sibling right next to the anchor run, never\n // <w:ins> nested in <w:ins> (mirrors the MODIFICATION path and the\n // Python engine).\n this._insert_and_split_ins(\n anchor_parent,\n anchor_el,\n result.first_node,\n before_anchor,\n );\n } else if (before_anchor && anchor_parent) {\n anchor_parent.insertBefore(result.first_node, anchor_el);\n } else {\n insertAfter(result.first_node, anchor_el);\n }\n } else if (anchor_para) {\n // Paragraph-anchored insertion: the anchor resolves to a paragraph\n // (not a run) for zero-width paragraph-start spans — e.g. index 0 of\n // the document. The insertion point is the START of the paragraph\n // content, so land right after pPr, mirroring the Python engine;\n // appendChild would drop the text at the paragraph's END.\n const para_el = anchor_para._element;\n let ref: Node | null = para_el.firstChild;\n while (ref && (ref as Element).tagName === \"w:pPr\") {\n ref = ref.nextSibling;\n }\n para_el.insertBefore(result.first_node, ref);\n }\n }\n\n // Attach the comment if requested. Anchor depends on whether we created\n // additional paragraphs.\n if (edit.comment) {\n const ascend_to_paragraph_child = (\n el: Element,\n p: Element,\n ): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n\n if (result.last_p && result.last_ins) {\n // Multi-paragraph: anchor from first_node (in its host paragraph)\n // through last_ins (inside last_p).\n let start_p: Element | null = result.first_node;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element;\n if (start_p) {\n let first_anchor_target = result.first_node;\n if (result.first_node.tagName === \"w:p\") {\n first_anchor_target =\n findAllDescendants(result.first_node, \"w:ins\")[0] ||\n result.first_node;\n }\n const start_anchor = ascend_to_paragraph_child(\n first_anchor_target,\n start_p,\n );\n const end_anchor = ascend_to_paragraph_child(\n result.last_ins,\n result.last_p,\n );\n this._attach_comment_spanning(\n start_p,\n start_anchor,\n result.last_p,\n end_anchor,\n edit.comment,\n );\n }\n } else {\n // Inline only: anchor around first_node in its host paragraph.\n let host_p: Element | null = result.first_node;\n while (host_p && host_p.tagName !== \"w:p\")\n host_p = host_p.parentNode as Element;\n if (host_p) {\n let first_anchor_target = result.first_node;\n if (result.first_node.tagName === \"w:p\") {\n first_anchor_target =\n findAllDescendants(result.first_node, \"w:ins\")[0] ||\n result.first_node;\n }\n const anchor = ascend_to_paragraph_child(\n first_anchor_target,\n host_p,\n );\n this._attach_comment(host_p, anchor, anchor, edit.comment);\n }\n }\n }\n return true;\n }\n\n // QA 2026-07-18 C1 (apply-level backstop, pinned edits bypass\n // validate_edits): a modification/deletion may never mutate real text\n // from two different OPC parts in one span. Single-part documents skip\n // the scan.\n if (\n (op === \"DELETION\" || op === \"MODIFICATION\") &&\n length &&\n active_mapper.part_ranges.filter((r: [number, number, string]) => r[1] > r[0]).length > 1\n ) {\n const crossed_parts = new Set<number>();\n for (const s of active_mapper.spans) {\n if (s.run !== null && s.end > start_idx && s.start < start_idx + length) {\n crossed_parts.add(s.part_index);\n }\n }\n if (crossed_parts.size > 1) {\n console.error(\n `Refusing edit that spans OPC part boundary (start=${start_idx}, parts=${Array.from(crossed_parts).sort().join(\",\")})`,\n );\n return false;\n }\n }\n\n // DELETION / MODIFICATION\n const target_runs = active_mapper.find_target_runs_by_index(\n start_idx,\n length,\n rebuild_map,\n );\n const virtual_spans = active_mapper.get_virtual_spans_in_range(\n start_idx,\n length,\n );\n\n if (target_runs.length === 0 && virtual_spans.length === 0) return false;\n\n const affected_ps = new Set<Element>();\n for (const run of target_runs) {\n let p: Element | null = run._element.parentNode as Element;\n while (p && p.tagName !== \"w:p\") p = p.parentNode as Element;\n if (p) affected_ps.add(p);\n }\n\n let first_del: Element | null = null;\n let last_del: Element | null = null;\n for (const run of target_runs) {\n const del_tag = this._create_track_change_tag(\"w:del\", \"\", del_id);\n const new_run = run._element.cloneNode(true) as Element;\n\n const tNodes = Array.from(new_run.getElementsByTagName(\"w:t\"));\n tNodes.forEach((t) => {\n const delText = new_run.ownerDocument!.createElement(\"w:delText\");\n delText.textContent = t.textContent;\n if (t.hasAttribute(\"xml:space\"))\n delText.setAttribute(\"xml:space\", \"preserve\");\n new_run.replaceChild(delText, t);\n });\n\n del_tag.appendChild(new_run);\n run._element.parentNode?.replaceChild(del_tag, run._element);\n if (first_del === null) first_del = del_tag;\n last_del = del_tag;\n }\n\n let ins_elem: Element | null = null;\n let mod_last_p: Element | null = null;\n let mod_last_ins: Element | null = null;\n\n if (op === \"MODIFICATION\" && edit.new_text && last_del) {\n // Resolve a paragraph anchor: the <w:p> hosting last_del.\n let mod_anchor_para_el: Element | null = last_del;\n while (mod_anchor_para_el && mod_anchor_para_el.tagName !== \"w:p\") {\n mod_anchor_para_el = mod_anchor_para_el.parentNode as Element | null;\n }\n const mod_anchor_para: Paragraph | null = mod_anchor_para_el\n ? new Paragraph(mod_anchor_para_el, null)\n : null;\n\n // The \"anchor run\" for style inheritance is the run we just deleted; reuse\n // the deleted run's rPr by sourcing the original target run if available.\n const style_source_run: Run | null =\n target_runs.length > 0 ? target_runs[target_runs.length - 1] : null;\n\n const result = this._track_insert_multiline(\n edit.new_text,\n style_source_run,\n mod_anchor_para,\n ins_id!,\n // The insertion physically follows the deletion block; the style\n // run was detached when the deletion cloned it into <w:del>.\n last_del,\n suppress_emphasis,\n );\n\n if (result.first_node) {\n const is_inline_first = result.first_node.tagName === \"w:ins\";\n if (is_inline_first) {\n const del_parent = last_del!.parentNode as Element | null;\n if (del_parent && del_parent.tagName === \"w:ins\") {\n // Revising another author's pending insertion: keep the <w:del>\n // nested in their <w:ins> and splice our new <w:ins> in right after\n // it by splitting their <w:ins>, so we never nest <w:ins> in\n // <w:ins>.\n this._insert_and_split_ins(\n del_parent,\n last_del!,\n result.first_node,\n );\n } else {\n // Inline: place the first <w:ins> immediately after last_del.\n insertAfter(result.first_node, last_del!);\n }\n ins_elem = result.first_node;\n } else {\n // Block-mode first paragraph was already inserted after the anchor\n // paragraph by the helper. We still need ins_elem for comment fallback.\n ins_elem = result.last_ins;\n }\n mod_last_p = result.last_p;\n mod_last_ins = result.last_ins;\n }\n }\n\n // PHASE 2: OOXML Paragraph Merge Protocol\n if (op === \"DELETION\" || op === \"MODIFICATION\") {\n if (\n op === \"MODIFICATION\" &&\n target_runs.length === 0 &&\n virtual_spans.length > 0 &&\n edit.new_text\n ) {\n const first_span = virtual_spans[0];\n if (first_span.paragraph) {\n const p1_el = first_span.paragraph._element;\n const last_runs = findAllDescendants(p1_el, \"w:r\");\n const anchor =\n last_runs.length > 0\n ? new Run(last_runs[last_runs.length - 1], first_span.paragraph)\n : null;\n\n const result = this._track_insert_multiline(\n edit.new_text,\n anchor,\n first_span.paragraph,\n ins_id!,\n null,\n suppress_emphasis,\n );\n if (result.first_node) {\n p1_el.appendChild(result.first_node);\n }\n }\n }\n\n for (const span of [...virtual_spans].reverse()) {\n if (span.paragraph) {\n const p1_element = span.paragraph._element;\n let p2_element = getNextElement(p1_element);\n while (p2_element && p2_element.tagName !== \"w:p\") {\n p2_element = getNextElement(p2_element);\n }\n\n if (p2_element && p2_element.tagName === \"w:p\") {\n // Decide the merged container's properties BEFORE p2's children\n // move in: when p1 keeps no visible content (a FULL paragraph\n // deletion), the only surviving text is p2's — the merged\n // paragraph must carry p2's properties (style, numbering).\n // Keeping p1's restyled the following paragraph: deleting a\n // heading turned the next body paragraph into a heading,\n // deleting a plain paragraph before a list item stripped the\n // item's numbering (QA 2026-07-19 ADEU-QA-002 B).\n const p1_fully_deleted =\n !this._paragraph_has_visible_content(p1_element);\n\n let pPr = findChild(p1_element, \"w:pPr\");\n if (p1_fully_deleted) {\n const p2_pPr = findChild(p2_element, \"w:pPr\");\n const adopted = (\n p2_pPr\n ? p2_pPr.cloneNode(true)\n : p1_element.ownerDocument!.createElement(\"w:pPr\")\n ) as Element;\n // Section properties belong to p1's position in the document\n // flow, never to p2's styling — carry them over so a section\n // boundary is not destroyed.\n if (pPr) {\n const sect = findChild(pPr, \"w:sectPr\");\n if (sect && !findChild(adopted, \"w:sectPr\")) {\n adopted.appendChild(sect.cloneNode(true));\n }\n p1_element.removeChild(pPr);\n }\n p1_element.insertBefore(\n adopted,\n p1_element.firstChild as Node | null,\n );\n pPr = adopted;\n }\n if (!pPr) {\n pPr = p1_element.ownerDocument!.createElement(\"w:pPr\") as Element;\n p1_element.insertBefore(\n pPr,\n p1_element.firstChild as Node | null,\n );\n }\n let rPr = findChild(pPr!, \"w:rPr\");\n if (!rPr) {\n rPr = p1_element.ownerDocument!.createElement(\"w:rPr\") as Element;\n pPr!.appendChild(rPr);\n }\n if (!findChild(rPr!, \"w:del\")) {\n const del_mark = this._create_track_change_tag(\"w:del\");\n rPr!.appendChild(del_mark);\n }\n\n const children = Array.from(p2_element.childNodes);\n for (const child of children) {\n if (\n child.nodeType === 1 &&\n (child as Element).tagName === \"w:pPr\"\n ) {\n continue;\n }\n p1_element.appendChild(child);\n }\n\n if (p2_element.parentNode) {\n p2_element.parentNode.removeChild(p2_element);\n }\n }\n }\n }\n }\n\n // Attach comment around the modification or deletion if requested.\n if (edit.comment && first_del !== null) {\n // Resolve the comment END anchor. For multi-paragraph modifications,\n // the end anchor lives in the LAST inserted paragraph (mod_last_p);\n // otherwise it's the inline ins/del in the source paragraph.\n let end_anchor_el: Element;\n let end_p: Element | null;\n\n if (mod_last_p && mod_last_ins) {\n end_anchor_el = mod_last_ins;\n end_p = mod_last_p;\n } else {\n const final_anchor: Element = ins_elem !== null ? ins_elem : last_del!;\n end_anchor_el = final_anchor;\n end_p = final_anchor;\n while (end_p && end_p.tagName !== \"w:p\")\n end_p = end_p.parentNode as Element | null;\n }\n\n let start_p: Element | null = first_del;\n while (start_p && start_p.tagName !== \"w:p\")\n start_p = start_p.parentNode as Element | null;\n if (!start_p || !end_p) return true;\n\n const ascend_to_paragraph_child = (el: Element, p: Element): Element => {\n let cur: Element = el;\n while (cur.parentNode && cur.parentNode !== p) {\n cur = cur.parentNode as Element;\n }\n return cur;\n };\n const start_anchor = ascend_to_paragraph_child(first_del, start_p);\n const end_anchor = ascend_to_paragraph_child(end_anchor_el, end_p);\n\n if (start_p === end_p) {\n this._attach_comment(start_p, start_anchor, end_anchor, edit.comment);\n } else {\n this._attach_comment_spanning(\n start_p,\n start_anchor,\n end_p,\n end_anchor,\n edit.comment,\n );\n }\n }\n\n // PHASE 2: Check for orphaned paragraphs with zero visible content remaining\n for (const p_elem of affected_ps) {\n const has_visible = this._paragraph_has_visible_content(p_elem);\n\n if (!has_visible) {\n let pPr = findChild(p_elem, \"w:pPr\");\n if (!pPr) {\n pPr = p_elem.ownerDocument!.createElement(\"w:pPr\") as Element;\n p_elem.insertBefore(pPr, p_elem.firstChild as Node | null);\n }\n let rPr = findChild(pPr!, \"w:rPr\");\n if (!rPr) {\n rPr = p_elem.ownerDocument!.createElement(\"w:rPr\") as Element;\n pPr!.appendChild(rPr);\n }\n if (!findChild(rPr!, \"w:del\")) {\n const del_mark = this._create_track_change_tag(\"w:del\");\n rPr!.appendChild(del_mark);\n }\n }\n }\n\n return true;\n }\n}\n","import { DocumentObject, Part } from '../docx/bridge.js';\nimport { findAllDescendants, findChild, findChildren } from '../docx/dom.js';\nimport { extract_comments_data, CommentsManager } from '../comments.js';\nimport { RedlineEngine } from '../engine.js';\n\nexport function findDescendantsByLocalName(element: Element, localName: string): Element[] {\n const result: Element[] = [];\n const all = element.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n const tag = all[i].tagName;\n if (tag === localName || tag.endsWith(':' + localName)) {\n result.push(all[i]);\n }\n }\n return result;\n}\n\nexport function coalesce_runs(doc: DocumentObject): string[] {\n let count = 0;\n\n function areRunsIdentical(rPr1: Element | null, rPr2: Element | null): boolean {\n const xml1 = rPr1 ? rPr1.toString() : '';\n const xml2 = rPr2 ? rPr2.toString() : '';\n return xml1 === xml2;\n }\n\n function hasSpecialContent(run: Element): boolean {\n const safeTags = ['w:t', 'w:tab', 'w:br', 'w:cr', 'w:delText', 'w:rPr'];\n for (let i = 0; i < run.childNodes.length; i++) {\n const child = run.childNodes[i];\n if (child.nodeType === 1) {\n const tag = (child as Element).tagName;\n if (!safeTags.includes(tag)) return true;\n }\n }\n return false;\n }\n\n function coalesceContainer(container: Element) {\n const children = Array.from(container.childNodes).filter(n => n.nodeType === 1) as Element[];\n let i = 0;\n while (i < children.length - 1) {\n const curr = children[i];\n const nxt = children[i + 1];\n\n if (curr.tagName === 'w:r' && nxt.tagName === 'w:r') {\n if (!hasSpecialContent(curr) && !hasSpecialContent(nxt)) {\n const rPr1 = findChild(curr, 'w:rPr');\n const rPr2 = findChild(nxt, 'w:rPr');\n if (areRunsIdentical(rPr1, rPr2)) {\n let last_t: Element | null = null;\n for (let c = 0; c < curr.childNodes.length; c++) {\n const child = curr.childNodes[c];\n if (child.nodeType === 1 && ((child as Element).tagName === 'w:t' || (child as Element).tagName === 'w:delText')) {\n last_t = child as Element;\n }\n }\n\n const nxtChildren = Array.from(nxt.childNodes).filter(n => n.nodeType === 1) as Element[];\n for (const child of nxtChildren) {\n if (child.tagName === 'w:rPr') continue;\n if ((child.tagName === 'w:t' || child.tagName === 'w:delText') && last_t && last_t.tagName === child.tagName) {\n const t1 = last_t.textContent || '';\n const t2 = child.textContent || '';\n const combined = t1 + t2;\n last_t.textContent = combined;\n if (combined.trim() !== combined) {\n last_t.setAttribute('xml:space', 'preserve');\n }\n } else {\n curr.appendChild(child);\n if (child.tagName === 'w:t' || child.tagName === 'w:delText') {\n last_t = child;\n }\n }\n }\n container.removeChild(nxt);\n children.splice(i + 1, 1);\n count++;\n continue; \n }\n }\n }\n\n if (['w:ins', 'w:del', 'w:hyperlink', 'w:sdt', 'w:smartTag', 'w:fldSimple', 'w:sdtContent'].includes(curr.tagName)) {\n coalesceContainer(curr);\n }\n i++;\n }\n \n if (children.length > 0) {\n const last = children[children.length - 1];\n if (['w:ins', 'w:del', 'w:hyperlink', 'w:sdt', 'w:smartTag', 'w:fldSimple', 'w:sdtContent'].includes(last.tagName)) {\n coalesceContainer(last);\n }\n }\n }\n\n const paragraphs = findAllDescendants(doc.element, 'w:p');\n for (const p of paragraphs) coalesceContainer(p);\n\n return count ? [`Adjacent identical runs coalesced: ${count}`] : [];\n}\n\nexport function strip_rsid(doc: DocumentObject): string[] {\n let count = 0;\n const rsidAttrs = ['w:rsidR', 'w:rsidRPr', 'w:rsidRDefault', 'w:rsidP', 'w:rsidDel', 'w:rsidSect', 'w:rsidTr'];\n \n const all = doc.element.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n for (const attr of rsidAttrs) {\n if (all[i].hasAttribute(attr)) {\n all[i].removeAttribute(attr);\n count++;\n }\n }\n }\n \n const rsidsElements = findAllDescendants(doc.element, 'w:rsids');\n for (const el of rsidsElements) {\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n count++;\n }\n }\n \n return count ? [`rsid attributes: ${count} removed`] : [];\n}\n\nexport function strip_para_ids(doc: DocumentObject): string[] {\n let count = 0;\n const attrs = ['w14:paraId', 'w14:textId'];\n const all = doc.element.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n for (const attr of attrs) {\n if (all[i].hasAttribute(attr)) {\n all[i].removeAttribute(attr);\n count++;\n }\n }\n }\n return count ? [`Paragraph/text IDs: ${count} removed`] : [];\n}\n\nexport function strip_proof_errors(doc: DocumentObject): string[] {\n const elements = findAllDescendants(doc.element, 'w:proofErr');\n elements.forEach(el => el.parentNode?.removeChild(el));\n return elements.length ? [`Spell check markers: ${elements.length} removed`] : [];\n}\n\nexport function strip_empty_properties(doc: DocumentObject): string[] {\n let count = 0;\n for (const tag of ['w:rPr', 'w:pPr']) {\n const elements = findAllDescendants(doc.element, tag);\n for (const el of elements) {\n if (el.childNodes.length === 0 || (el.childNodes.length === 1 && el.childNodes[0].nodeType === 3 && !el.childNodes[0].textContent?.trim())) {\n el.parentNode?.removeChild(el);\n count++;\n }\n }\n }\n return count ? [`Empty property elements: ${count} removed`] : [];\n}\n\nexport function strip_hidden_text(doc: DocumentObject): string[] {\n let count = 0;\n const elements = findAllDescendants(doc.element, 'w:rPr');\n for (const rPr of elements) {\n if (findChild(rPr, 'w:vanish') || findChild(rPr, 'w:webHidden')) {\n const run = rPr.parentNode as Element;\n if (run && run.tagName === 'w:r' && run.parentNode) {\n run.parentNode.removeChild(run);\n count++;\n }\n }\n }\n return count ? [`Hidden text runs: ${count} removed`] : [];\n}\n\nexport function count_tracked_changes(doc: DocumentObject): [number, number, number] {\n const ins = findAllDescendants(doc.element, 'w:ins').length;\n const del = findAllDescendants(doc.element, 'w:del').length;\n const fmt = findAllDescendants(doc.element, 'w:rPrChange').length +\n findAllDescendants(doc.element, 'w:pPrChange').length +\n findAllDescendants(doc.element, 'w:sectPrChange').length;\n return [ins, del, fmt];\n}\n\nexport function get_track_change_authors(doc: DocumentObject): Set<string> {\n const authors = new Set<string>();\n for (const tag of ['w:ins', 'w:del', 'w:rPrChange', 'w:pPrChange', 'w:sectPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n const author = el.getAttribute('w:author');\n if (author) authors.add(author);\n }\n }\n return authors;\n}\n\nfunction _getElementText(el: Element): string {\n const texts: string[] = [];\n const ts = findAllDescendants(el, 'w:t');\n for (const t of ts) if (t.textContent) texts.push(t.textContent);\n const dts = findAllDescendants(el, 'w:delText');\n for (const dt of dts) if (dt.textContent) texts.push(dt.textContent);\n return texts.join('');\n}\n\nexport function _truncate(text: string, maxLen: number = 60): string {\n const clean = text.replace(/\\n/g, ' ').trim();\n if (clean.length <= maxLen) return clean;\n return clean.substring(0, maxLen - 3) + \"...\";\n}\n\nexport function accept_all_tracked_changes(doc: DocumentObject): string[] {\n const lines: string[] = [];\n const insEls = findAllDescendants(doc.element, 'w:ins');\n const delEls = findAllDescendants(doc.element, 'w:del');\n \n for (const ins of insEls) {\n const text = _getElementText(ins).trim();\n if (text) lines.push(` Accepted insertion: \"${_truncate(text, 60)}\"`);\n }\n for (const del of delEls) {\n const text = _getElementText(del).trim();\n if (text) lines.push(` Accepted deletion of: \"${_truncate(text, 60)}\"`);\n }\n\n const engine = new RedlineEngine(doc);\n engine.accept_all_revisions();\n\n for (const tag of ['w:rPrChange', 'w:pPrChange', 'w:sectPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n el.parentNode?.removeChild(el);\n }\n }\n\n const total = insEls.length + delEls.length;\n if (total) {\n return [`Tracked changes auto-accepted: ${total}`].concat(lines);\n }\n return [];\n}\n\nexport function get_comments_summary(doc: DocumentObject): any {\n const data = extract_comments_data(doc.pkg);\n const comments = [];\n let openCount = 0;\n let resolvedCount = 0;\n\n for (const [cId, info] of Object.entries(data)) {\n if (info.resolved) resolvedCount++;\n else openCount++;\n comments.push({ id: cId, ...info });\n }\n\n return { total: comments.length, open: openCount, resolved: resolvedCount, comments };\n}\n\nexport function remove_all_comments(doc: DocumentObject): string[] {\n const data = extract_comments_data(doc.pkg);\n const keys = Object.keys(data);\n if (keys.length === 0) return [];\n\n const lines: string[] = [];\n const cm = new CommentsManager(doc);\n\n for (const [cId, info] of Object.entries(data)) {\n const status = info.resolved ? \"[Resolved]\" : \"[Open]\";\n lines.push(` ${status} \"${_truncate(info.text || '', 60)}\" (${info.author || 'Unknown'})`);\n cm.deleteComment(cId);\n }\n\n for (const tag of ['w:commentRangeStart', 'w:commentRangeEnd']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n el.parentNode?.removeChild(el);\n }\n }\n\n const refs = findAllDescendants(doc.element, 'w:commentReference');\n for (const ref of refs) {\n const parent = ref.parentNode as Element | null;\n if (parent) {\n if (parent.tagName === 'w:r' || parent.tagName.endsWith(':r')) {\n const nonRprChildren = Array.from(parent.childNodes).filter(\n (c) => c.nodeType === 1 && (c as Element).tagName !== 'w:rPr' && (c as Element).tagName !== 'rPr'\n );\n if (nonRprChildren.length <= 1) {\n parent.parentNode?.removeChild(parent);\n } else {\n parent.removeChild(ref);\n }\n } else {\n parent.removeChild(ref);\n }\n }\n }\n\n const resolvedCount = Object.values(data).filter(c => c.resolved).length;\n const openCount = Object.values(data).filter(c => !c.resolved).length;\n return [`Comments removed: ${keys.length} (${resolvedCount} resolved, ${openCount} open)`].concat(lines);\n}\n\nexport function eject_comment_parts(doc: DocumentObject) {\n const pkg = doc.pkg;\n \n // 1. Find all comment-related partnames\n const comment_partnames = new Set<string>();\n for (const part of pkg.parts) {\n if (part.partname.toLowerCase().includes(\"comments\")) {\n comment_partnames.add(part.partname);\n const withSlash = part.partname.startsWith(\"/\") ? part.partname : \"/\" + part.partname;\n const withoutSlash = part.partname.startsWith(\"/\") ? part.partname.substring(1) : part.partname;\n comment_partnames.add(withSlash);\n comment_partnames.add(withoutSlash);\n }\n }\n\n if (comment_partnames.size === 0) return;\n\n // 2. Sever relationships referencing these parts from all parts in the package\n for (const part of pkg.parts) {\n if (part.partname.endsWith(\".rels\")) {\n const rels = findAllDescendants(part._element, \"Relationship\");\n const toRemove: Element[] = [];\n for (const rel of rels) {\n const target = rel.getAttribute(\"Target\") || \"\";\n if (target.toLowerCase().includes(\"comments\")) {\n toRemove.push(rel);\n \n const sourcePath = part.partname.replace(\"/_rels/\", \"/\").replace(\".rels\", \"\");\n const sourcePart = pkg.getPartByPath(sourcePath);\n if (sourcePart) {\n const relId = rel.getAttribute(\"Id\");\n if (relId) sourcePart.rels.delete(relId);\n }\n }\n }\n for (const relEl of toRemove) {\n relEl.parentNode?.removeChild(relEl);\n }\n }\n }\n\n // 3. Remove overrides from [Content_Types].xml\n const ctPart = pkg.getPartByPath(\"[Content_Types].xml\");\n if (ctPart) {\n const overrides = findAllDescendants(ctPart._element, \"Override\");\n const toRemove: Element[] = [];\n for (const override of overrides) {\n const partName = override.getAttribute(\"PartName\") || \"\";\n if (comment_partnames.has(partName) || partName.toLowerCase().includes(\"comments\")) {\n toRemove.push(override);\n }\n }\n for (const overrideEl of toRemove) {\n overrideEl.parentNode?.removeChild(overrideEl);\n }\n }\n\n // 4. Remove comment parts from pkg.parts\n pkg.parts = pkg.parts.filter(p => !p.partname.toLowerCase().includes(\"comments\"));\n\n // 5. Remove comment files from pkg.unzipped as well\n for (const key of Object.keys(pkg.unzipped)) {\n if (key.toLowerCase().includes(\"comments\")) {\n delete pkg.unzipped[key];\n }\n }\n}\n\nexport function replace_comment_authors(doc: DocumentObject, newAuthor: string): string[] {\n const cm = new CommentsManager(doc);\n if (!cm.commentsPart) return [];\n\n const original = new Set<string>();\n const comments = findAllDescendants(cm.commentsPart._element, 'w:comment');\n for (const c of comments) {\n const author = c.getAttribute('w:author');\n if (author) {\n original.add(author);\n c.setAttribute('w:author', newAuthor);\n }\n if (c.hasAttribute('w:initials')) {\n const initials = newAuthor.split(' ').filter(Boolean).map(p => p[0]).join('').toUpperCase();\n c.setAttribute('w:initials', initials);\n }\n }\n return original.size ? [`Comment authors replaced: ${Array.from(original).sort().join(', ')} → \"${newAuthor}\"`] : [];\n}\n\nexport function replace_change_authors(doc: DocumentObject, newAuthor: string): string[] {\n const original = new Set<string>();\n for (const tag of ['w:ins', 'w:del', 'w:rPrChange', 'w:pPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n const author = el.getAttribute('w:author');\n if (author) {\n original.add(author);\n el.setAttribute('w:author', newAuthor);\n }\n }\n }\n return original.size ? [`Track change authors replaced: ${Array.from(original).sort().join(', ')} → \"${newAuthor}\"`] : [];\n}\n\nexport function normalize_change_dates(doc: DocumentObject): string[] {\n let count = 0;\n const fixed = \"2025-01-01T00:00:00Z\";\n for (const tag of ['w:ins', 'w:del', 'w:rPrChange', 'w:pPrChange']) {\n for (const el of findAllDescendants(doc.element, tag)) {\n if (el.hasAttribute('w:date')) {\n el.setAttribute('w:date', fixed);\n count++;\n }\n }\n }\n return count ? [`Track change timestamps: ${count} normalized`] : [];\n}\n\n/**\n * Normalize timestamps on RETAINED comments to the fixed sanitize date.\n * Keep-markup sanitize normalized core and tracked-change timestamps but\n * left the original comment timestamps in word/comments.xml (w:date) and\n * word/commentsExtensible.xml (w16cex:dateUtc) — visible through any\n * extraction and carrying exactly the when-did-they-work signal the other\n * normalizations remove (QA 2026-07-19 F-09).\n */\nexport function normalize_comment_dates(doc: DocumentObject): string[] {\n let count = 0;\n const fixed = \"2025-01-01T00:00:00Z\";\n for (const part of doc.pkg.parts) {\n if (!part.contentType.includes('comments')) continue;\n for (const el of findAllDescendants(part._element, 'w:comment')) {\n if (el.hasAttribute('w:date')) {\n el.setAttribute('w:date', fixed);\n count++;\n }\n }\n for (const el of findAllDescendants(part._element, 'w16cex:commentExtensible')) {\n if (el.hasAttribute('w16cex:dateUtc')) {\n el.setAttribute('w16cex:dateUtc', fixed);\n count++;\n }\n }\n }\n return count ? [`Comment timestamps: ${count} normalized`] : [];\n}\n\nexport function scrub_doc_properties(doc: DocumentObject): string[] {\n const lines: string[] = [];\n const corePart = doc.pkg.getPartByPath('docProps/core.xml');\n if (corePart) {\n const creators = findDescendantsByLocalName(corePart._element, 'creator');\n creators.forEach(c => { if (c.textContent) { lines.push(`Author: ${c.textContent}`); c.textContent = \"\"; }});\n\n const modifiers = findDescendantsByLocalName(corePart._element, 'lastModifiedBy');\n modifiers.forEach(c => { if (c.textContent) { lines.push(`Last modified by: ${c.textContent}`); c.textContent = \"\"; }});\n\n // Title is often intentional, but can leak. Report it, don't strip\n // (QA 2026-07-17 F4; mirrors Python).\n const titles = findDescendantsByLocalName(corePart._element, 'title');\n titles.forEach(c => { if (c.textContent) { lines.push(`Title kept (review manually): \"${c.textContent}\"`); }});\n\n // Classification-style properties are textbook leak vectors (\"Project\n // Falcon\", \"confidential,merger,...\"). Unlike title they carry no\n // legitimate outbound formatting value, so strip them and say so.\n // dc:identifier, dc:language and cp:version are scrubbed with them:\n // identifiers are DMS/matter-ID carriers.\n const leakFields: Array<[string, string]> = [\n ['category', 'Category'],\n ['keywords', 'Keywords'],\n ['subject', 'Subject'],\n ['contentStatus', 'Content status'],\n ['description', 'Description/comments'],\n ['identifier', 'Identifier'],\n ['language', 'Language'],\n ['version', 'Version'],\n ];\n for (const [local, label] of leakFields) {\n findDescendantsByLocalName(corePart._element, local).forEach(c => {\n if (c.textContent) {\n lines.push(`${label}: ${c.textContent}`);\n c.textContent = \"\";\n }\n });\n }\n\n const revisions = findDescendantsByLocalName(corePart._element, 'revision');\n revisions.forEach(c => { if (c.textContent && parseInt(c.textContent) > 1) { lines.push(`Revision count: ${c.textContent} → 1`); c.textContent = \"1\"; }});\n }\n\n const appPart = doc.pkg.getPartByPath('docProps/app.xml');\n if (appPart) {\n const docEl = appPart._element;\n const intFields = [\"TotalTime\", \"Words\", \"Characters\", \"Paragraphs\", \"Lines\", \"CharactersWithSpaces\"];\n for (const f of intFields) {\n findDescendantsByLocalName(docEl, f).forEach(el => {\n if (el.textContent && el.textContent !== \"0\") {\n if (f === \"TotalTime\") lines.push(`Total editing time: ${el.textContent} minutes`);\n el.textContent = \"0\";\n }\n });\n }\n const strFields = [\"Template\", \"Manager\", \"Company\"];\n for (const f of strFields) {\n findDescendantsByLocalName(docEl, f).forEach(el => {\n if (el.textContent) {\n lines.push(`${f}: ${el.textContent}`);\n el.textContent = \"\";\n }\n });\n }\n }\n\n return lines.length ? [\"Metadata scrubbed:\", ...lines.map(l => ` ${l}`)] : [];\n}\n\nexport function scrub_timestamps(doc: DocumentObject): string[] {\n let modified = false;\n const epoch = \"1970-01-01T00:00:00Z\";\n const corePart = doc.pkg.getPartByPath('docProps/core.xml');\n if (corePart) {\n for (const tag of ['created', 'modified', 'lastPrinted']) {\n findDescendantsByLocalName(corePart._element, tag).forEach(el => {\n if (el.textContent && el.textContent !== epoch) {\n el.textContent = epoch;\n modified = true;\n }\n });\n }\n }\n return modified ? [\"Timestamps normalized to epoch\"] : [];\n}\n\n/**\n * Fully ejects package members whose path matches `matcher`: the parsed part\n * list, the raw `pkg.unzipped` bytes (save() re-zips EVERY unzipped\n * member, so skipping this ships the original bytes in the output), the\n * [Content_Types].xml overrides, and every .rels Relationship whose\n * target matches `relTargetMatcher`.\n */\nfunction ejectPackageMembers(\n doc: DocumentObject,\n matcher: (path: string) => boolean,\n relTargetMatcher: (target: string) => boolean,\n) {\n const pkg = doc.pkg;\n const normalized = (p: string) => (p.startsWith('/') ? p.substring(1) : p);\n\n // 1. Sever relationships from every .rels part (and the in-memory rels maps)\n for (const part of pkg.parts) {\n if (!part.partname.endsWith('.rels')) continue;\n const toRemove: Element[] = [];\n for (const rel of findAllDescendants(part._element, 'Relationship')) {\n const target = rel.getAttribute('Target') || '';\n if (relTargetMatcher(target)) {\n toRemove.push(rel);\n const sourcePath = part.partname.replace('/_rels/', '/').replace('.rels', '');\n const sourcePart = pkg.getPartByPath(sourcePath);\n if (sourcePart) {\n const relId = rel.getAttribute('Id');\n if (relId) sourcePart.rels.delete(relId);\n }\n }\n }\n toRemove.forEach(r => r.parentNode?.removeChild(r));\n }\n\n // 2. Remove [Content_Types].xml overrides\n const ctPart = pkg.getPartByPath('[Content_Types].xml');\n if (ctPart) {\n const toRemove: Element[] = [];\n for (const override of findAllDescendants(ctPart._element, 'Override')) {\n const partName = override.getAttribute('PartName') || '';\n if (matcher(normalized(partName))) toRemove.push(override);\n }\n toRemove.forEach(o => o.parentNode?.removeChild(o));\n }\n\n // 3. Drop the parts from the serialization list AND the raw zip map\n pkg.parts = pkg.parts.filter(p => !matcher(normalized(p.partname)));\n for (const key of Object.keys(pkg.unzipped)) {\n if (matcher(normalized(key))) delete pkg.unzipped[key];\n }\n}\n\nexport function strip_custom_xml(doc: DocumentObject): string[] {\n const isCustomXml = (path: string) => path.startsWith('customXml/');\n const customParts = doc.pkg.parts.filter(p =>\n isCustomXml(p.partname.startsWith('/') ? p.partname.substring(1) : p.partname),\n );\n const leakedMembers = Object.keys(doc.pkg.unzipped).filter(isCustomXml);\n if (customParts.length === 0 && leakedMembers.length === 0) return [];\n\n ejectPackageMembers(doc, isCustomXml, target => target.includes('customXml'));\n\n for (const sdtPr of findAllDescendants(doc.element, 'w:sdtPr')) {\n findChildren(sdtPr, 'w:dataBinding').forEach(b => sdtPr.removeChild(b));\n }\n\n return [`Custom XML parts: ${Math.max(customParts.length, leakedMembers.length)} removed`];\n}\n\nconst CUSTOM_PROPS_PATH = 'docProps/custom.xml';\n\n/**\n * Remove the custom document properties part (docProps/custom.xml) and its\n * package relationship. Custom properties are a standard home for matter\n * numbers, client names, DMS identifiers and workflow secrets; a package\n * that keeps them can never be reported CLEAN.\n */\nexport function strip_custom_properties(doc: DocumentObject): string[] {\n const part = doc.pkg.getPartByPath(CUSTOM_PROPS_PATH);\n const leaked = Object.keys(doc.pkg.unzipped).includes(CUSTOM_PROPS_PATH);\n if (!part && !leaked) return [];\n\n // Enumerate what is being removed so the report discloses it.\n const lines: string[] = [];\n if (part) {\n for (const prop of findDescendantsByLocalName(part._element, 'property')) {\n const name = prop.getAttribute('name') || '(unnamed)';\n const value = (prop.textContent || '').trim();\n lines.push(` Custom property removed: ${name} = \"${_truncate(value, 60)}\"`);\n }\n }\n\n ejectPackageMembers(\n doc,\n path => path === CUSTOM_PROPS_PATH,\n target => target.includes('docProps/custom.xml'),\n );\n\n const count = Math.max(lines.length, 1);\n return [`Custom document properties: ${count} removed (docProps/custom.xml)`].concat(lines);\n}\n\n/**\n * Remove Word document variables (<w:docVars>/<w:docVar>) from\n * word/settings.xml. Document variables are invisible in Word's UI but are a\n * standard carrier for matter references, DMS identifiers, template state and\n * integration tokens — a package that keeps them can never be reported CLEAN\n * (QA 2026-07-19 ADEU-QA-001). Variables are disclosed by NAME only: their\n * values are exactly the secrets a sanitize report must not echo.\n */\nexport function strip_document_variables(doc: DocumentObject): string[] {\n const settingsPart = doc.pkg.getPartByPath('word/settings.xml');\n if (!settingsPart) return [];\n\n const names: string[] = [];\n let removedAny = false;\n\n for (const container of findDescendantsByLocalName(settingsPart._element, 'docVars')) {\n for (const child of Array.from(container.childNodes)) {\n const el = child as Element;\n const tag = el.tagName || '';\n if (tag === 'docVar' || tag.endsWith(':docVar')) {\n names.push(el.getAttribute('w:name') || el.getAttribute('name') || '(unnamed)');\n }\n }\n container.parentNode?.removeChild(container);\n removedAny = true;\n }\n\n // Defensive: stray <w:docVar> elements outside a <w:docVars> container.\n for (const stray of findDescendantsByLocalName(settingsPart._element, 'docVar')) {\n names.push(stray.getAttribute('w:name') || stray.getAttribute('name') || '(unnamed)');\n stray.parentNode?.removeChild(stray);\n removedAny = true;\n }\n\n if (!removedAny) return [];\n const shown = Array.from(new Set(names)).sort().join(', ') || '(unnamed)';\n return [`Document variables: ${names.length} removed (${shown})`];\n}\n\nexport function strip_image_alt_text(doc: DocumentObject): string[] {\n let count = 0;\n for (const docPr of findDescendantsByLocalName(doc.element, 'docPr')) {\n const descr = docPr.getAttribute('descr');\n if (descr) {\n const isShort = descr.length < 10;\n const isFile = descr.includes('.') && descr.length < 60;\n if (isShort || isFile) {\n docPr.removeAttribute('descr');\n count++;\n }\n }\n }\n return count ? [`Image alt text: ${count} auto-generated descriptions removed`] : [];\n}\n\n/**\n * Detect watermark-like embedded text objects (VML shapes with a textpath,\n * Word's native watermark mechanism) in headers, footers and the body.\n * Non-destructive: returns warnings so the report never declares a document\n * fully clean while such an object silently remains (QA 2026-07-18 M3).\n */\nexport function detect_watermarks(doc: DocumentObject): string[] {\n const warnings: string[] = [];\n const seen = new Set<string>();\n\n for (const part of doc.pkg.parts) {\n const name = String(part.partname);\n let location: string;\n if (name.startsWith(\"/word/header\")) location = \"header\";\n else if (name.startsWith(\"/word/footer\")) location = \"footer\";\n else if (name === \"/word/document.xml\") location = \"body\";\n else continue;\n\n let textpaths: Element[];\n try {\n textpaths = findDescendantsByLocalName(part._element, \"textpath\");\n } catch {\n continue;\n }\n for (const tp of textpaths) {\n const text = (tp.getAttribute(\"string\") || \"\").trim();\n const key = `${location}\\x1f${text}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const label = text ? `\"${_truncate(text, 60)}\"` : \"(no text)\";\n warnings.push(\n `Watermark-like text object in ${location}: ${label} — NOT removed. ` +\n \"It remains in the document package and may render in other applications; \" +\n \"review and remove it in Word if it must not reach the counterparty.\",\n );\n }\n }\n return warnings;\n}\n\nexport function audit_hyperlinks(doc: DocumentObject): string[] {\n const internal = [\"sharepoint.com\", \"onedrive.com\", \".internal\", \"intranet\", \"localhost\", \"10.\", \"192.168.\", \"172.16.\"];\n const warnings: string[] = [];\n \n const docRels = doc.pkg.getOrCreateRelsPart(doc.part.partname);\n for (const rel of findAllDescendants(docRels._element, 'Relationship')) {\n if (rel.getAttribute('TargetMode') === 'External') {\n const url = rel.getAttribute('Target') || '';\n for (const pattern of internal) {\n if (url.toLowerCase().includes(pattern.toLowerCase())) {\n warnings.push(`Hyperlink targets internal URL: ${_truncate(url, 80)}`);\n break;\n }\n }\n }\n }\n return warnings;\n}","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Run } from \"./docx/primitives.js\";\nimport { iter_block_items, get_run_text } from \"./utils/docx.js\";\nimport { findAllDescendants } from \"./docx/dom.js\";\nimport { findDescendantsByLocalName } from \"./sanitize/transforms.js\";\n\nfunction boundedLevenshtein(a: string, b: string, maxDist: number = 2): number {\n if (a === b) return 0;\n if (Math.abs(a.length - b.length) > maxDist) return maxDist + 1;\n if (a.length === 0) return b.length <= maxDist ? b.length : maxDist + 1;\n if (b.length === 0) return a.length <= maxDist ? a.length : maxDist + 1;\n\n if (a.length > b.length) {\n const temp = a;\n a = b;\n b = temp;\n }\n\n let row = Array.from({ length: a.length + 1 }, (_, i) => i);\n\n for (let i = 1; i <= b.length; i++) {\n const newRow = [i];\n let minInRow = i;\n for (let j = 1; j <= a.length; j++) {\n const cost = a[j - 1] === b[i - 1] ? 0 : 1;\n const val = Math.min(row[j] + 1, newRow[j - 1] + 1, row[j - 1] + cost);\n newRow.push(val);\n if (val < minInRow) minInRow = val;\n }\n if (minInRow > maxDist) return maxDist + 1;\n row = newRow;\n }\n return row[a.length] <= maxDist ? row[a.length] : maxDist + 1;\n}\n\nfunction _get_paragraph_text(p: Paragraph): string {\n let text = \"\";\n const runs = findAllDescendants(p._element, \"w:r\");\n for (const r of runs) {\n text += get_run_text(new Run(r, p));\n }\n return text;\n}\n\nconst _TERM_BODY = \"[A-Z][A-Za-z0-9\\\\s\\\\-&'’]{1,60}\";\n// Definition typography, matched repeatedly within a paragraph (QA 2026-07-18\n// M7 — a paragraph defining Alpha, Beta AND Gamma must yield all three):\n// 1. paragraph-leading quoted term (optionally after a numbering token)\n// 2. sentence-leading quoted term (after . ; : ! ?)\n// 3. parenthesized inline definition — (the \"Term\")\n// The 'd' flag (ES2022 match indices) recovers each term's exact position for\n// position-keyed dedupe, mirroring Python's m.start(1).\nconst _LEADING_TERM_RE = new RegExp(\n `^(?:[\\\\d.\\\\-()a-zA-Z]+\\\\s*)?[\"“](${_TERM_BODY})[\"”]`,\n \"d\",\n);\n// Like the leading pattern, a sentence-start definition may carry a numbering\n// token ('… the product. 2.2 \"Beta\" means …').\nconst _SENTENCE_TERM_RE = new RegExp(\n `(?<=[.;:!?])\\\\s+(?:[\\\\d.\\\\-()a-zA-Z]+\\\\s+)?[\"“](${_TERM_BODY})[\"”]`,\n \"dg\",\n);\nconst _INLINE_TERM_RE = new RegExp(\n `\\\\([^)]*?[\"“](${_TERM_BODY})[\"”][^)]*?\\\\)`,\n \"dg\",\n);\n\n/**\n * All defined terms declared in one paragraph, in appearance order,\n * deduplicated. Language-agnostic: keyed on quoting typography, never on\n * English phrases like \"means\".\n */\nexport function extract_terms_from_paragraph(text: string): string[] {\n const found: [number, string][] = [];\n const leading = _LEADING_TERM_RE.exec(text) as RegExpExecArray & {\n indices?: Array<[number, number]>;\n };\n if (leading && leading.indices && leading.indices[1]) {\n found.push([leading.indices[1][0], leading[1].trim()]);\n }\n for (const m of text.matchAll(_SENTENCE_TERM_RE)) {\n const indices = (m as any).indices as Array<[number, number]> | undefined;\n if (indices && indices[1]) found.push([indices[1][0], m[1].trim()]);\n }\n for (const m of text.matchAll(_INLINE_TERM_RE)) {\n const indices = (m as any).indices as Array<[number, number]> | undefined;\n if (indices && indices[1]) found.push([indices[1][0], m[1].trim()]);\n }\n\n const terms: string[] = [];\n const seen_positions = new Set<number>();\n found.sort((a, b) => a[0] - b[0]);\n for (const [pos, term] of found) {\n if (seen_positions.has(pos)) continue;\n seen_positions.add(pos);\n terms.push(term);\n }\n return terms;\n}\n\nexport function extract_all_domain_metadata(\n doc: DocumentObject,\n base_text: string,\n): [\n Record<string, { count: number }>,\n string[],\n Record<string, { anchored_to: string; referenced_from: string[] }>,\n] {\n const definitions: Record<string, { count: number }> = {};\n const duplicates = new Set<string>();\n const raw_anchors: Record<\n string,\n { anchored_to: string; referenced_from: string[] }\n > = {};\n const raw_references: [string, string][] = [];\n\n for (const item of iter_block_items(doc)) {\n if (!(item instanceof Paragraph)) continue;\n\n const text = _get_paragraph_text(item).trim();\n if (!text) continue;\n\n // 1. Extract Definitions (every declaration in the paragraph — QA M7)\n for (const term of extract_terms_from_paragraph(text)) {\n if (definitions[term]) duplicates.add(term);\n else definitions[term] = { count: 0 };\n }\n\n const short_text = text.length > 60 ? text.substring(0, 60) + \"...\" : text;\n\n const nodes = findAllDescendants(item._element, \"*\");\n for (const node of nodes) {\n if (node.tagName === \"w:bookmarkStart\") {\n const b_name = node.getAttribute(\"w:name\");\n if (b_name && (!b_name.startsWith(\"_\") || b_name.startsWith(\"_Ref\"))) {\n if (!raw_anchors[b_name]) {\n raw_anchors[b_name] = {\n anchored_to: short_text,\n referenced_from: [],\n };\n }\n }\n }\n\n let target: string | null = null;\n if (node.tagName === \"w:fldSimple\") {\n const instr = node.getAttribute(\"w:instr\") || \"\";\n const parts = instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\") target = parts[1];\n } else if (node.tagName === \"w:instrText\") {\n const instr = node.textContent || \"\";\n const parts = instr.trim().split(/\\s+/);\n if (parts.length > 1 && parts[0] === \"REF\") target = parts[1];\n }\n\n if (target) raw_references.push([target, short_text]);\n }\n }\n\n for (const [target, ref_text] of raw_references) {\n if (raw_anchors[target]) {\n raw_anchors[target].referenced_from.push(ref_text);\n }\n }\n\n const diagnostics: string[] = [];\n\n const def_keys = Object.keys(definitions);\n if (def_keys.length > 0) {\n const sorted_terms = def_keys.sort((a, b) => b.length - a.length);\n const escapeRegExp = (str: string) =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const alt = sorted_terms.map(escapeRegExp).join(\"|\");\n const usage_pattern = new RegExp(`(?<![\"“])\\\\b(${alt})\\\\b(?![”\"])`, \"g\");\n\n for (const m of base_text.matchAll(usage_pattern)) {\n const matched_term = m[1];\n if (definitions[matched_term]) definitions[matched_term].count++;\n }\n\n // Drop unused terms from the SYMBOL TABLE only — the filter is noise\n // reduction for the Defined Terms listing, and must not gate the\n // Semantic Diagnostics: a term defined twice and never used is two\n // drafting errors, not zero (QA 2026-07-17 F6; mirrors Python). Surface\n // the orphan definition itself as a diagnostic instead.\n for (const term of def_keys) {\n if (definitions[term].count === 0) {\n delete definitions[term];\n if (!duplicates.has(term)) {\n diagnostics.push(\n `[Warning] Unused Definition: '${term}' is defined but never used.`,\n );\n }\n }\n }\n }\n\n for (const term of duplicates) {\n diagnostics.push(\n `[Error] Duplicate Definition: '${term}' is defined multiple times.`,\n );\n }\n\n const stop_words = new Set([\n \"The\",\n \"This\",\n \"That\",\n \"Such\",\n \"A\",\n \"An\",\n \"Any\",\n \"All\",\n \"Some\",\n \"No\",\n \"Every\",\n \"Each\",\n \"As\",\n \"In\",\n \"Of\",\n \"For\",\n \"To\",\n \"On\",\n \"By\",\n \"With\",\n ]);\n\n const all_cap_pattern = /\\b[A-Z][a-zA-Z]*(?:\\s+[A-Z][a-zA-Z]*)*\\b/g;\n const all_caps = new Set(base_text.match(all_cap_pattern) || []);\n\n const valid_terms = new Set(Object.keys(definitions));\n const terms_by_first_letter: Record<string, string[]> = {};\n for (const term of valid_terms) {\n const fl = term[0].toLowerCase();\n if (!terms_by_first_letter[fl]) terms_by_first_letter[fl] = [];\n terms_by_first_letter[fl].push(term);\n }\n\n const candidates_by_term: Record<string, string[]> = {};\n\n for (const raw_candidate of all_caps) {\n let candidate = raw_candidate.trim();\n const words = candidate.split(/\\s+/);\n while (words.length > 0) {\n const first = words[0];\n const title =\n first.charAt(0).toUpperCase() + first.slice(1).toLowerCase();\n if (stop_words.has(title)) words.shift();\n else break;\n }\n candidate = words.join(\" \");\n\n if (candidate.length < 4) continue;\n if (valid_terms.has(candidate)) continue;\n\n const first_letter = candidate[0].toLowerCase();\n let candidate_terms = terms_by_first_letter[first_letter] || [];\n\n if (candidate.length > 5) {\n for (const [k, v] of Object.entries(terms_by_first_letter)) {\n if (k !== first_letter) candidate_terms = candidate_terms.concat(v);\n }\n }\n\n for (const term of candidate_terms) {\n if (Math.abs(candidate.length - term.length) > 2) continue;\n if (candidate === term + \"s\" || candidate === term + \"es\") continue;\n if (term === candidate + \"s\" || term === candidate + \"es\") continue;\n\n const dist = boundedLevenshtein(candidate, term, 2);\n if (dist === 0 || dist > 2) continue;\n\n if (term.length <= 5) {\n if (dist > 1) continue;\n if (candidate[0].toLowerCase() !== term[0].toLowerCase()) continue;\n }\n\n if (!candidates_by_term[term]) candidates_by_term[term] = [];\n if (!candidates_by_term[term].includes(candidate))\n candidates_by_term[term].push(candidate);\n }\n }\n\n for (const [term, candidates] of Object.entries(candidates_by_term)) {\n candidates.sort();\n const c_str = candidates.map((c) => `'${c}'`).join(\", \");\n diagnostics.push(`[Info] Possible Typos for '${term}': Found ${c_str}`);\n }\n\n function diag_sort_key(msg: string) {\n if (msg.startsWith(\"[Error]\")) return 0;\n if (msg.startsWith(\"[Warning]\")) return 1;\n return 2;\n }\n\n diagnostics.sort((a, b) => {\n const keyA = diag_sort_key(a);\n const keyB = diag_sort_key(b);\n if (keyA !== keyB) return keyA - keyB;\n return a.localeCompare(b);\n });\n\n return [definitions, diagnostics, raw_anchors];\n}\n\n/**\n * Inspects word/settings.xml for privacy flags that cause Microsoft Word to\n * silently strip authorship metadata (w:author, w:date, w:initials) from\n * tracked changes and comments on the next save. These flags do not affect\n * what this engine writes — but they will scrub the engine's attribution the\n * next time Word opens and saves the file, breaking auditability and\n * multi-turn agent state tracking.\n *\n * Returns a list of human-readable warning lines (without leading bullets);\n * empty when no relevant flag is present or all flags are explicitly disabled.\n */\nexport function extract_document_settings_warnings(\n doc: DocumentObject,\n): string[] {\n const warnings: string[] = [];\n const settingsPart = doc.pkg.getPartByPath(\"word/settings.xml\");\n if (!settingsPart) return warnings;\n\n const isTruthy = (el: Element): boolean => {\n // OOXML boolean rule: element present with no w:val attribute defaults to true.\n // w:val of \"0\", \"false\", or \"off\" means disabled. Anything else (including\n // \"1\", \"true\", \"on\") is enabled.\n if (!el.hasAttribute(\"w:val\")) return true;\n const val = (el.getAttribute(\"w:val\") || \"\").toLowerCase();\n return val !== \"0\" && val !== \"false\" && val !== \"off\";\n };\n\n const removePersonal = findDescendantsByLocalName(\n settingsPart._element,\n \"removePersonalInformation\",\n );\n if (removePersonal.length > 0 && isTruthy(removePersonal[0])) {\n warnings.push(\n \"[Warning] Privacy flag `removePersonalInformation` is enabled in word/settings.xml. \" +\n \"Microsoft Word will strip the `w:author`, `w:initials`, and `w:date` attributes from every tracked change and comment the next time this document is opened and saved. \" +\n \"Edits made by this agent will lose attribution, breaking audit trails and any multi-turn workflow that relies on identifying prior edits.\",\n );\n }\n\n const removeDateTime = findDescendantsByLocalName(\n settingsPart._element,\n \"removeDateAndTime\",\n );\n if (removeDateTime.length > 0 && isTruthy(removeDateTime[0])) {\n warnings.push(\n \"[Warning] Privacy flag `removeDateAndTime` is enabled in word/settings.xml. \" +\n \"Microsoft Word will strip the `w:date` attribute from every tracked change and comment the next time this document is opened and saved. \" +\n \"Timestamps on this agent's edits will be lost on the next Word save.\",\n );\n }\n\n return warnings;\n}\n\nexport function build_structural_appendix(\n doc: DocumentObject,\n base_text: string,\n): string {\n const [defs, diagnostics, anchors] = extract_all_domain_metadata(\n doc,\n base_text,\n );\n const settings_warnings = extract_document_settings_warnings(doc);\n\n const lines: string[] = [\n \"\\n\\n---\",\n \"\",\n \"<!-- READONLY_BOUNDARY_START -->\",\n \"# Document Structure (Read-Only)\",\n \"The content below is metadata describing the document's reference structure. Do not include this section in any tracked changes or edits \\u2014 it is for your context only and will be discarded on write.\",\n ];\n\n let has_content = false;\n\n if (settings_warnings.length > 0) {\n has_content = true;\n lines.push(\"\\n## Document Settings\");\n for (const warning of settings_warnings) {\n lines.push(`- ${warning}`);\n }\n }\n\n if (Object.keys(defs).length > 0) {\n has_content = true;\n lines.push(\"\\n## Defined Terms\");\n for (const [term, data] of Object.entries(defs)) {\n lines.push(`- \"${term}\" \\u2014 used ${data.count} times.`);\n }\n }\n\n if (diagnostics.length > 0) {\n has_content = true;\n lines.push(\"\\n## Semantic Diagnostics\");\n for (const diag of diagnostics) {\n lines.push(`- ${diag}`);\n }\n }\n\n if (Object.keys(anchors).length > 0) {\n has_content = true;\n lines.push(\"\\n## Named Anchors\");\n for (const [b_name, data] of Object.entries(anchors)) {\n lines.push(`- ${b_name} \\u2192 Anchored to: \"${data.anchored_to}\"`);\n for (const ref of data.referenced_from) {\n lines.push(` - Referenced from: \"${ref}\"`);\n }\n }\n }\n\n if (has_content) {\n return lines.join(\"\\n\");\n }\n return \"\";\n}\n","import { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, Run, DocxEvent } from \"./docx/primitives.js\";\nimport {\n _get_style_cache,\n compute_change_pair_map,\n get_paragraph_prefix,\n is_heading_paragraph,\n is_native_heading,\n get_run_style_markers,\n get_run_text,\n apply_formatting_to_segments,\n iter_block_items,\n iter_document_parts_with_kind,\n iter_paragraph_content,\n} from \"./utils/docx.js\";\nimport { findChild } from \"./docx/dom.js\";\nimport { build_structural_appendix } from \"./domain.js\";\nimport { extract_comments_data } from \"./comments.js\";\n\n/** Text-space extent of one projected table row plus its cell texts. */\nexport interface RowGeometry {\n start: number;\n end: number;\n cells: string[];\n}\n\n/** Text-space extent of one projected top-level table. */\nexport interface TableGeometry {\n start: number;\n end: number;\n rows: RowGeometry[];\n}\n\n/**\n * Structural map of a projection: which offset ranges belong to which OPC\n * part, and where top-level table rows live. Produced in the SAME pass as\n * the text, so offsets always agree with it. Consumed by the diff pipeline\n * to keep generated edits from crossing part boundaries (QA 2026-07-18 C1)\n * and to emit structured row operations for table changes (QA C2).\n */\nexport interface ExtractStructure {\n part_ranges: [number, number, string][]; // [start, end, kind]\n tables: TableGeometry[];\n}\n\nexport async function extractTextFromBuffer(\n buffer: Buffer,\n cleanView = false,\n includeAppendix = true,\n): Promise<string> {\n const doc = await DocumentObject.load(buffer);\n return _extractTextFromDoc(doc, cleanView, includeAppendix) as string;\n}\n\nexport function _extractTextFromDoc(\n doc: DocumentObject,\n cleanView = false,\n includeAppendix = true,\n return_paragraph_offsets = false,\n return_structure = false,\n):\n | string\n | { text: string; paragraph_offsets: Map<any, [number, number]> }\n | { text: string; structure: ExtractStructure } {\n const comments_map = extract_comments_data(doc.pkg);\n\n const full_text: string[] = [];\n const paragraph_offsets = new Map<any, [number, number]>();\n const structure: ExtractStructure | null = return_structure\n ? { part_ranges: [], tables: [] }\n : null;\n let cursor = 0;\n\n for (const [part, part_kind] of iter_document_parts_with_kind(doc)) {\n const part_cursor = full_text.length > 0 ? cursor + 2 : cursor;\n const part_text = _extract_blocks(\n part,\n comments_map,\n cleanView,\n part_cursor,\n return_paragraph_offsets ? paragraph_offsets : undefined,\n structure ? structure.tables : undefined,\n );\n if (part_text) {\n if (full_text.length > 0) cursor += 2;\n full_text.push(part_text);\n if (structure) {\n structure.part_ranges.push([cursor, cursor + part_text.length, part_kind]);\n }\n cursor += part_text.length;\n }\n }\n\n let base_text = full_text.join(\"\\n\\n\");\n\n if (includeAppendix) {\n const appendix = build_structural_appendix(doc, base_text);\n if (appendix) base_text += appendix;\n }\n\n if (return_paragraph_offsets) {\n return { text: base_text, paragraph_offsets };\n }\n if (structure) {\n return { text: base_text, structure };\n }\n return base_text;\n}\n\n/**\n * table_acc: optional list collecting TableGeometry for TOP-LEVEL tables.\n * Deliberately not forwarded into cells — nested tables stay invisible to\n * the structured row-op diff, whose row pairing assumes one flat grid.\n */\nfunction _extract_blocks(\n container: any,\n comments_map: any,\n cleanView: boolean,\n cursor: number,\n paragraph_offsets?: Map<any, [number, number]>,\n table_acc?: TableGeometry[],\n): string {\n const part = container.part || container;\n const [style_cache, default_pstyle] = _get_style_cache(part);\n\n const blocks: string[] = [];\n let local_cursor = cursor;\n let is_first_block = true;\n let is_first_para = true;\n\n if (container.constructor && container.constructor.name === \"NotesPart\") {\n const header =\n container.note_type === \"fn\" ? \"## Footnotes\" : \"## Endnotes\";\n const sep = `---\\n${header}`;\n blocks.push(sep);\n local_cursor += sep.length;\n is_first_block = false;\n }\n\n for (const item of iter_block_items(container)) {\n if (!is_first_block) local_cursor += 2;\n const block_start = local_cursor;\n\n if (item.constructor.name === \"FootnoteItem\") {\n const fn_text = _extract_blocks(\n item,\n comments_map,\n cleanView,\n block_start,\n paragraph_offsets,\n );\n if (fn_text) {\n blocks.push(fn_text);\n local_cursor = block_start + fn_text.length;\n is_first_block = false;\n } else if (!is_first_block) {\n local_cursor -= 2;\n }\n } else if (item instanceof Paragraph) {\n let prefix = get_paragraph_prefix(item, style_cache, default_pstyle);\n if (is_first_para && container.constructor.name === \"FootnoteItem\") {\n prefix = `[^${container.note_type}-${container.id}]: ` + prefix;\n }\n const p_text = build_paragraph_text(\n item,\n comments_map,\n cleanView,\n style_cache,\n default_pstyle,\n );\n const full_block = prefix + p_text;\n blocks.push(full_block);\n if (paragraph_offsets) {\n paragraph_offsets.set(item._element, [block_start, full_block.length]);\n }\n local_cursor = block_start + full_block.length;\n is_first_para = false;\n is_first_block = false;\n } else if (item instanceof Table) {\n const geometry: TableGeometry | null = table_acc\n ? { start: block_start, end: block_start, rows: [] }\n : null;\n const table_text = extract_table(\n item,\n comments_map,\n cleanView,\n block_start,\n paragraph_offsets,\n geometry,\n );\n if (table_text) {\n blocks.push(table_text);\n local_cursor = block_start + table_text.length;\n is_first_block = false;\n if (geometry && table_acc) {\n geometry.end = block_start + table_text.length;\n table_acc.push(geometry);\n }\n } else if (!is_first_block) {\n local_cursor -= 2;\n }\n is_first_para = false;\n }\n }\n\n return blocks.join(\"\\n\\n\");\n}\n\nexport function extract_table(\n table: Table,\n comments_map: any,\n cleanView: boolean,\n cursor: number,\n paragraph_offsets?: Map<any, [number, number]>,\n geometry?: TableGeometry | null,\n): string {\n const rows_text: string[] = [];\n let rows_processed = 0;\n let local_cursor = cursor;\n\n for (const row of table.rows) {\n const cell_texts: string[] = [];\n const seen_cells = new Set();\n\n const trPr = findChild(row._element, \"w:trPr\");\n const ins = trPr ? findChild(trPr, \"w:ins\") : null;\n const del_node = trPr ? findChild(trPr, \"w:del\") : null;\n\n if (cleanView && del_node) continue;\n\n const row_start = local_cursor + (rows_processed > 0 ? 1 : 0);\n const wrapper_prefix_len =\n !cleanView && ins ? 4 : !cleanView && del_node ? 4 : 0;\n\n let cell_cursor = row_start + wrapper_prefix_len;\n let first_cell = true;\n\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n if (!first_cell) cell_cursor += 3;\n\n let cell_content = _extract_blocks(\n cell,\n comments_map,\n cleanView,\n cell_cursor,\n paragraph_offsets,\n );\n // Emit a stable, document-native anchor for this cell so empty/short\n // value cells are addressable by the engine. Reuses the {#...} bookmark\n // projection (already protected by validate_edit_strings and resolvable\n // via the mapper). We key on the cell's first paragraph w14:paraId, which\n // Word assigns and keeps stable across reads.\n if (!cleanView) {\n let firstP = cell._element.getElementsByTagName(\"w:p\")[0] as\n | Element\n | undefined;\n let paraId = firstP ? firstP.getAttribute(\"w14:paraId\") : null;\n if (!paraId && (!cell_content || cell_content.trim() === \"\")) {\n if (!firstP) {\n const xmlDoc = cell._element.ownerDocument!;\n firstP = xmlDoc.createElement(\"w:p\");\n cell._element.appendChild(firstP);\n }\n const allPs = Array.from(cell._element.ownerDocument!.getElementsByTagName(\"w:p\"));\n const index = allPs.indexOf(firstP);\n let hash = 2166136261;\n const str = `fallback-paraId-${index}`;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);\n }\n paraId = (hash >>> 0).toString(16).toUpperCase().padStart(8, '0');\n firstP.setAttribute(\"w14:paraId\", paraId);\n }\n if (paraId) {\n const space_pad = cell_content ? \" \" : \"\";\n const anchor = `${space_pad}{#cell:${paraId}}`;\n cell_content = cell_content + anchor;\n }\n }\n cell_texts.push(cell_content);\n cell_cursor += cell_content.length;\n first_cell = false;\n }\n\n let row_str = cell_texts.join(\" | \");\n\n if (!cleanView) {\n if (ins) row_str = `{++ ${row_str} |Chg:${ins.getAttribute(\"w:id\")}++}`;\n else if (del_node)\n row_str = `{-- ${row_str} |Chg:${del_node.getAttribute(\"w:id\")}--}`;\n }\n\n rows_text.push(row_str);\n local_cursor = row_start + row_str.length;\n if (geometry) {\n geometry.rows.push({\n start: row_start,\n end: local_cursor,\n cells: [...cell_texts],\n });\n }\n rows_processed++;\n }\n\n return rows_text.join(\"\\n\");\n}\n\nexport function build_paragraph_text(\n paragraph: Paragraph,\n comments_map: any,\n cleanView: boolean,\n style_cache?: any,\n default_pstyle?: string | null,\n): string {\n const parts: string[] = [];\n const active_ins: Record<string, DocxEvent> = {};\n const active_del: Record<string, DocxEvent> = {};\n const active_comments: Set<string> = new Set();\n const active_fmt: Record<string, DocxEvent> = {};\n const deferred_meta_states: any[] = [];\n\n let pending_text = \"\";\n let current_wrappers: [string, string] = [\"\", \"\"];\n let current_style: [string, string] = [\"\", \"\"];\n\n const items = Array.from(iter_paragraph_content(paragraph));\n const is_heading = is_heading_paragraph(\n paragraph,\n style_cache,\n default_pstyle,\n );\n const native_heading = is_native_heading(\n paragraph,\n style_cache,\n default_pstyle,\n );\n let leading_strip_active = is_heading;\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n\n if (item instanceof Run) {\n const [prefix, suffix] = get_run_style_markers(item, native_heading);\n const text = get_run_text(item);\n\n if (cleanView && Object.keys(active_del).length > 0) continue;\n\n if (leading_strip_active) {\n if (!text || !text.trim()) continue;\n leading_strip_active = false;\n }\n\n const seg = apply_formatting_to_segments(text, prefix, suffix);\n if (seg) {\n const new_wrappers = cleanView\n ? ([\"\", \"\"] as [string, string])\n : _get_wrappers(active_ins, active_del, active_comments, active_fmt);\n const new_style: [string, string] = [prefix, suffix];\n\n if (\n pending_text &&\n new_wrappers[0] === current_wrappers[0] &&\n new_wrappers[1] === current_wrappers[1]\n ) {\n // Hoisted leading whitespace may sit before the incoming segment's\n // opening marker (\"**A**\" + \" **B**\" -> \"**A B**\"), mirroring the\n // mapper's part-level elision exactly (QA 2026-07-19 F-03).\n const escaped_prefix = new_style[0].replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const lead_match =\n new_style[0] !== \"\" || new_style[1] !== \"\"\n ? seg.match(new RegExp(\"^(\\\\s*)\" + escaped_prefix))\n : null;\n if (\n new_style[0] === current_style[0] &&\n new_style[1] === current_style[1] &&\n current_style[0] !== \"\" &&\n pending_text.endsWith(current_style[1]) &&\n lead_match !== null\n ) {\n pending_text =\n pending_text.slice(0, -current_style[1].length) +\n lead_match[1] +\n seg.slice(lead_match[0].length);\n } else {\n pending_text += seg;\n }\n current_style = new_style;\n } else {\n if (pending_text)\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = seg;\n current_wrappers = new_wrappers;\n current_style = new_style;\n }\n\n if (!cleanView) {\n const has_meta =\n Object.keys(active_ins).length > 0 ||\n Object.keys(active_del).length > 0 ||\n active_comments.size > 0 ||\n Object.keys(active_fmt).length > 0;\n if (has_meta) {\n deferred_meta_states.push([\n { ...active_ins },\n { ...active_del },\n new Set(active_comments),\n { ...active_fmt },\n ]);\n }\n\n let should_defer = false;\n const has_any_meta =\n Object.keys(active_ins).length > 0 ||\n Object.keys(active_del).length > 0 ||\n Object.keys(active_fmt).length > 0 ||\n active_comments.size > 0;\n\n if (has_any_meta) {\n let j = i + 1;\n let next_has_meta = false;\n let temp_ins = Object.keys(active_ins).length;\n let temp_del = Object.keys(active_del).length;\n let temp_fmt = Object.keys(active_fmt).length;\n const temp_comments = new Set(active_comments);\n\n while (j < items.length) {\n const next_item = items[j];\n if (next_item instanceof Run) {\n if (!get_run_text(next_item)) {\n j++;\n continue;\n }\n if (\n temp_ins > 0 ||\n temp_del > 0 ||\n temp_fmt > 0 ||\n temp_comments.size > 0\n )\n next_has_meta = true;\n break;\n } else {\n const ev = next_item as DocxEvent;\n if (ev.type === \"ins_start\") temp_ins++;\n else if (ev.type === \"ins_end\")\n temp_ins = Math.max(0, temp_ins - 1);\n else if (ev.type === \"del_start\") temp_del++;\n else if (ev.type === \"del_end\")\n temp_del = Math.max(0, temp_del - 1);\n else if (ev.type === \"fmt_start\") temp_fmt++;\n else if (ev.type === \"fmt_end\")\n temp_fmt = Math.max(0, temp_fmt - 1);\n else if (ev.type === \"start\") temp_comments.add(ev.id);\n else if (ev.type === \"end\") temp_comments.delete(ev.id);\n }\n j++;\n }\n if (next_has_meta) should_defer = true;\n }\n\n if (!should_defer && deferred_meta_states.length > 0) {\n const meta_block = _build_merged_meta_block(\n deferred_meta_states,\n comments_map,\n );\n if (meta_block) {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`{>>${meta_block}<<}`);\n }\n deferred_meta_states.length = 0; // clear\n }\n }\n }\n } else {\n const ev = item as DocxEvent;\n leading_strip_active = false;\n\n if (\n ![\n \"ins_start\",\n \"ins_end\",\n \"del_start\",\n \"del_end\",\n \"fmt_start\",\n \"fmt_end\",\n ].includes(ev.type)\n ) {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n }\n\n if (ev.type === \"start\") active_comments.add(ev.id);\n else if (ev.type === \"end\") active_comments.delete(ev.id);\n else if (ev.type === \"ins_start\") active_ins[ev.id] = ev;\n else if (ev.type === \"ins_end\") delete active_ins[ev.id];\n else if (ev.type === \"del_start\") active_del[ev.id] = ev;\n else if (ev.type === \"del_end\") delete active_del[ev.id];\n else if (ev.type === \"fmt_start\") active_fmt[ev.id] = ev;\n else if (ev.type === \"fmt_end\") delete active_fmt[ev.id];\n else if (ev.type === \"image\") {\n // Read-only image marker (QA 2026-07-18 M5); hidden with its run in\n // clean view when it sits inside an active tracked deletion.\n if (!(cleanView && Object.keys(active_del).length > 0)) {\n const alt = (ev.date || \"image\")\n .replace(/\\]/g, \")\")\n .replace(/\\n/g, \" \");\n parts.push(``);\n }\n } else if (ev.type === \"footnote\" || ev.type === \"endnote\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`[^${ev.type === \"footnote\" ? \"fn\" : \"en\"}-${ev.id}]`);\n } else if (ev.type === \"hyperlink_start\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(\"[\");\n } else if (ev.type === \"hyperlink_end\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`](${ev.date})`);\n } else if (ev.type === \"xref_start\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(\"[~\");\n } else if (ev.type === \"xref_end\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`~](#${ev.id})`);\n } else if (ev.type === \"bookmark\") {\n if (pending_text) {\n parts.push(\n `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,\n );\n pending_text = \"\";\n current_wrappers = [\"\", \"\"];\n current_style = [\"\", \"\"];\n }\n parts.push(`{#${ev.id}}`);\n }\n }\n }\n\n if (pending_text)\n parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);\n\n if (deferred_meta_states.length > 0) {\n const meta_block = _build_merged_meta_block(\n deferred_meta_states,\n comments_map,\n );\n if (meta_block) parts.push(`{>>${meta_block}<<}`);\n }\n\n return parts.join(\"\");\n}\n\nfunction _get_wrappers(\n ins: any,\n del: any,\n comments: Set<string>,\n fmt: any,\n): [string, string] {\n if (Object.keys(del).length > 0) return [\"{--\", \"--}\"];\n if (Object.keys(ins).length > 0) return [\"{++\", \"++}\"];\n if (comments.size > 0 || Object.keys(fmt).length > 0) return [\"{==\", \"==}\"];\n return [\"\", \"\"];\n}\n\nfunction _build_merged_meta_block(\n states_list: any[],\n comments_map: any,\n): string {\n const change_lines: string[] = [];\n const comment_lines: string[] = [];\n const seen_sigs = new Set<string>();\n\n // Ids of one resolution group (a replacement's contiguous same-author\n // del+ins pair) must not read as independently resolvable — either side\n // resolves the whole group (QA 2026-07-19 ADEU-QA-004).\n const pair_map = compute_change_pair_map(states_list);\n const pairSuffix = (uid: string): string =>\n pair_map[uid] ? ` (pairs with ${pair_map[uid]})` : \"\";\n\n for (const [ins_map, del_map, comments_set, fmt_map] of states_list) {\n for (const [uid, meta] of Object.entries(\n ins_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n change_lines.push(\n `[${sig} insert] ${meta.author || \"Unknown\"}${pairSuffix(uid)}`,\n );\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n del_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n change_lines.push(\n `[${sig} delete] ${meta.author || \"Unknown\"}${pairSuffix(uid)}`,\n );\n seen_sigs.add(sig);\n }\n }\n for (const [uid, meta] of Object.entries(\n fmt_map as Record<string, DocxEvent>,\n )) {\n const sig = `Chg:${uid}`;\n if (!seen_sigs.has(sig)) {\n change_lines.push(`[${sig} format] ${meta.author || \"Unknown\"}`);\n seen_sigs.add(sig);\n }\n }\n\n // Threaded Comment Resolution Tree\n const children_map: Record<string, string[]> = {};\n for (const [c_id, data] of Object.entries(\n comments_map as Record<string, any>,\n )) {\n const p_id = data.parent_id;\n if (p_id) {\n if (!children_map[p_id]) children_map[p_id] = [];\n children_map[p_id].push(c_id);\n }\n }\n\n function render_comment(cid: string) {\n if (!comments_map[cid]) return;\n const sig = `Com:${cid}`;\n if (seen_sigs.has(sig)) return;\n\n const data = comments_map[cid];\n let header = `[${sig}] ${data.author}`;\n if (data.date) header += ` @ ${data.date}`;\n if (data.resolved) header += `(RESOLVED)`;\n comment_lines.push(`${header}: ${data.text}`);\n seen_sigs.add(sig);\n\n if (children_map[cid]) {\n const children = children_map[cid].sort((a, b) =>\n (comments_map[a]?.date || \"\").localeCompare(\n comments_map[b]?.date || \"\",\n ),\n );\n for (const child_id of children) {\n render_comment(child_id);\n }\n }\n }\n\n const sorted_ids = Array.from(comments_set as Set<string>).sort();\n for (const c_id of sorted_ids) {\n render_comment(c_id);\n }\n }\n\n return [...change_lines, ...comment_lines].join(\"\\n\");\n}\n","/**\n * Structural outline extractor.\n */\n\nimport { DocumentObject } from \"./docx/bridge.js\";\nimport { Paragraph, Table, DocxEvent } from \"./docx/primitives.js\";\nimport { build_paragraph_text, extract_table } from \"./ingest.js\";\nimport { extract_comments_data } from \"./comments.js\";\nimport { findChild } from \"./docx/dom.js\";\nimport {\n _get_style_cache,\n get_paragraph_prefix,\n iter_block_items,\n iter_document_parts,\n iter_paragraph_content,\n} from \"./utils/docx.js\";\n\nconst _HEADING_PREFIX_RE = /^(#{1,6}) /;\nconst _HEURISTIC_MIN_WORDS = 3;\n\nexport interface OutlineNode {\n level: number;\n text: string;\n page: number;\n style: string;\n has_table: boolean;\n footnote_ids: string[];\n}\n\ninterface _BlockRecord {\n item: any;\n is_paragraph: boolean;\n is_table: boolean;\n start_offset: number;\n projected_length: number;\n}\n\nexport function extract_outline(\n doc: DocumentObject,\n projected_body: string,\n body_pages: string[],\n body_page_offsets: number[],\n paragraph_offsets: Record<string, [number, number]> | Map<any, [number, number]> | null = null,\n): OutlineNode[] {\n if (body_pages.length !== body_page_offsets.length) {\n throw new Error(\"body_pages and body_page_offsets length mismatch\");\n }\n\n if (paragraph_offsets) {\n return _extract_outline_fast(doc, projected_body, body_page_offsets, paragraph_offsets);\n }\n\n const comments_map = extract_comments_data(doc.pkg);\n const block_records = _walk_doc_body(doc, comments_map);\n\n const heading_indices: number[] = [];\n for (let idx = 0; idx < block_records.length; idx++) {\n const rec = block_records[idx];\n if (!(rec.is_paragraph && _is_heading(rec.item))) continue;\n if (!_heading_passes_quality_filter(rec.item, comments_map)) continue;\n heading_indices.push(idx);\n }\n\n if (heading_indices.length === 0) return [];\n\n const nodes: OutlineNode[] = [];\n for (let h_pos = 0; h_pos < heading_indices.length; h_pos++) {\n const rec_idx = heading_indices[h_pos];\n const rec = block_records[rec_idx];\n const paragraph = rec.item as Paragraph;\n\n const level = _heading_level(paragraph);\n const text = _heading_text(paragraph, comments_map);\n const style = _determine_heading_style(paragraph);\n\n const owned_end = _find_owned_end(\n block_records,\n heading_indices,\n h_pos,\n level,\n );\n const owned_blocks = block_records.slice(rec_idx + 1, owned_end);\n\n const has_table = _direct_has_table(block_records, rec_idx + 1, owned_end);\n const footnote_ids = _collect_footnote_ids(owned_blocks);\n\n const page_num = _offset_to_page(rec.start_offset, body_page_offsets);\n\n nodes.push({ level, text, page: page_num, style, has_table, footnote_ids });\n }\n\n return nodes;\n}\n\nfunction _direct_has_table(\n block_records: _BlockRecord[],\n range_start: number,\n range_end: number,\n): boolean {\n for (let idx = range_start; idx < range_end; idx++) {\n const rec = block_records[idx];\n if (rec.is_paragraph && _is_heading(rec.item)) return false;\n if (rec.is_table) return true;\n }\n return false;\n}\n\nfunction _walk_doc_body(\n doc: DocumentObject,\n comments_map: any,\n): _BlockRecord[] {\n const parts = Array.from(iter_document_parts(doc));\n let body_start_offset = 0;\n let body_part: any = null;\n\n for (const part of parts) {\n if (part === doc) {\n body_part = part;\n break;\n }\n const part_text = _project_part(part, comments_map);\n if (part_text) {\n if (body_start_offset > 0) body_start_offset += 2;\n body_start_offset += part_text.length;\n }\n }\n\n if (!body_part) {\n body_part = doc;\n body_start_offset = 0;\n } else {\n if (body_start_offset > 0) body_start_offset += 2;\n }\n\n const records: _BlockRecord[] = [];\n let cursor = body_start_offset;\n let is_first_block = true;\n\n for (const item of iter_block_items(body_part)) {\n if (item instanceof Paragraph) {\n const prefix = get_paragraph_prefix(item);\n const p_text = build_paragraph_text(item, comments_map, false);\n const block_len = (prefix + p_text).length;\n\n if (!is_first_block) cursor += 2;\n\n records.push({\n item,\n is_paragraph: true,\n is_table: false,\n start_offset: cursor,\n projected_length: block_len,\n });\n cursor += block_len;\n is_first_block = false;\n } else if (item instanceof Table) {\n const table_text = extract_table(item, comments_map, false, 0);\n const block_len = table_text ? table_text.length : 0;\n\n if (!is_first_block) cursor += 2;\n\n const table_start = cursor;\n records.push({\n item,\n is_paragraph: false,\n is_table: true,\n start_offset: table_start,\n projected_length: block_len,\n });\n _record_table_inner_blocks_lite(item, table_start, records, comments_map);\n cursor += block_len;\n is_first_block = false;\n }\n }\n\n return records;\n}\n\nfunction _compute_inner_block_offset(\n table: Table,\n target_paragraph: Paragraph,\n table_start_offset: number,\n comments_map: any,\n): number {\n const target_el = target_paragraph._element;\n let cursor = table_start_offset;\n let rows_processed = 0;\n\n for (const row of table.rows) {\n if (rows_processed > 0) cursor += 1;\n\n const seen_cells = new Set();\n let cells_in_row = 0;\n\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n if (cells_in_row > 0) cursor += 3;\n\n const [new_cursor, found] = _walk_cell_for_offset(\n cell,\n target_el,\n cursor,\n comments_map,\n );\n if (found) return new_cursor;\n cursor = new_cursor;\n\n cells_in_row++;\n }\n rows_processed++;\n }\n\n return table_start_offset;\n}\n\nfunction _walk_cell_for_offset(\n cell: any,\n target_el: any,\n cell_start_cursor: number,\n comments_map: any,\n): [number, boolean] {\n let cursor = cell_start_cursor;\n let is_first_block = true;\n\n for (const inner_item of iter_block_items(cell)) {\n if (!is_first_block) cursor += 2;\n\n if (inner_item instanceof Paragraph) {\n if (inner_item._element === target_el) return [cursor, true];\n const prefix = get_paragraph_prefix(inner_item);\n const p_text = build_paragraph_text(inner_item, comments_map, false);\n cursor += (prefix + p_text).length;\n } else if (inner_item instanceof Table) {\n const nested_offset = _compute_inner_block_offset(\n inner_item,\n new Paragraph(target_el, null),\n cursor,\n comments_map,\n );\n if (nested_offset !== cursor) {\n if (_element_is_descendant(target_el, inner_item._element))\n return [nested_offset, true];\n }\n const table_text = extract_table(inner_item, comments_map, false, 0);\n cursor += table_text ? table_text.length : 0;\n }\n is_first_block = false;\n }\n return [cursor, false];\n}\n\nfunction _element_is_descendant(\n target_el: Element,\n ancestor_el: Element,\n): boolean {\n let cur: Node | null = target_el.parentNode;\n while (cur) {\n if (cur === ancestor_el) return true;\n cur = cur.parentNode;\n }\n return false;\n}\n\nfunction _record_table_inner_blocks_lite(\n table: Table,\n inherited_offset: number,\n records: _BlockRecord[],\n comments_map: any,\n) {\n const seen_cells = new Set();\n for (const row of table.rows) {\n for (const cell of row.cells) {\n if (seen_cells.has(cell)) continue;\n seen_cells.add(cell);\n\n for (const inner_item of iter_block_items(cell)) {\n if (inner_item instanceof Paragraph) {\n const true_offset = _is_heading(inner_item)\n ? _compute_inner_block_offset(\n table,\n inner_item,\n inherited_offset,\n comments_map,\n )\n : inherited_offset;\n records.push({\n item: inner_item,\n is_paragraph: true,\n is_table: false,\n start_offset: true_offset,\n projected_length: 0,\n });\n } else if (inner_item instanceof Table) {\n records.push({\n item: inner_item,\n is_paragraph: false,\n is_table: true,\n start_offset: inherited_offset,\n projected_length: 0,\n });\n _record_table_inner_blocks_lite(\n inner_item,\n inherited_offset,\n records,\n comments_map,\n );\n }\n }\n }\n }\n}\n\nfunction _project_part(part: any, comments_map: any): string {\n const blocks: string[] = [];\n const c_type = part.constructor.name;\n\n if (c_type === \"NotesPart\") {\n const header = part.note_type === \"fn\" ? \"## Footnotes\" : \"## Endnotes\";\n blocks.push(`---\\n${header}`);\n }\n\n let is_first_para = true;\n for (const item of iter_block_items(part)) {\n if (item.constructor.name === \"FootnoteItem\") {\n const fn_text = _project_part(item, comments_map);\n if (fn_text) blocks.push(fn_text);\n } else if (item instanceof Paragraph) {\n let prefix = get_paragraph_prefix(item);\n if (is_first_para && c_type === \"FootnoteItem\")\n prefix = `[^${part.note_type}-${part.id}]: ${prefix}`;\n const p_text = build_paragraph_text(item, comments_map, false);\n blocks.push(prefix + p_text);\n is_first_para = false;\n } else if (item instanceof Table) {\n const table_text = extract_table(item, comments_map, false, 0);\n if (table_text) blocks.push(table_text);\n is_first_para = false;\n }\n }\n\n return blocks.join(\"\\n\\n\");\n}\n\nfunction _is_heading(paragraph: Paragraph): boolean {\n return _HEADING_PREFIX_RE.test(get_paragraph_prefix(paragraph));\n}\n\nfunction _heading_passes_quality_filter(\n paragraph: Paragraph,\n comments_map: any,\n): boolean {\n const style = _determine_heading_style(paragraph);\n if (style !== \"(heuristic)\") return true;\n const text = _heading_text(paragraph, comments_map);\n if (!text) return false;\n const word_count = (text.match(/\\w+/g) || []).length;\n return word_count >= _HEURISTIC_MIN_WORDS;\n}\n\nfunction _heading_level(paragraph: Paragraph): number {\n const match = _HEADING_PREFIX_RE.exec(get_paragraph_prefix(paragraph));\n return match ? Math.min(match[1].length, 6) : 1;\n}\n\nfunction _heading_text(paragraph: Paragraph, comments_map: any): string {\n const p_text = build_paragraph_text(paragraph, comments_map, false);\n let cleaned = _strip_critic_markup(p_text);\n cleaned = _strip_inline_formatting(cleaned);\n return cleaned.trim();\n}\n\nfunction _strip_critic_markup(text: string): string {\n if (!text) return \"\";\n text = text.replace(/\\{--[\\s\\S]*?--\\}/g, \"\");\n text = text.replace(/\\{>>[\\s\\S]*?<<\\}/g, \"\");\n text = text.replace(/\\{\\+\\+([\\s\\S]*?)\\+\\+\\}/g, \"$1\");\n text = text.replace(/\\{==([\\s\\S]*?)==\\}/g, \"$1\");\n return text;\n}\n\nfunction _strip_inline_formatting(text: string): string {\n if (!text) return \"\";\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, \"$1\");\n text = text.replace(/__(.+?)__/g, \"$1\");\n text = text.replace(/(?<!\\w)_(\\S(?:.*?\\S)?)_(?!\\w)/g, \"$1\");\n return text;\n}\n\nfunction _determine_heading_style(paragraph: Paragraph): string {\n const [style_cache, default_pstyle] = _get_style_cache(\n paragraph._parent.part || paragraph._parent,\n );\n const pPr = findChild(paragraph._element, \"w:pPr\");\n let style_id = default_pstyle;\n\n if (pPr) {\n const pStyle = findChild(pPr, \"w:pStyle\");\n if (pStyle) style_id = pStyle.getAttribute(\"w:val\") || default_pstyle;\n }\n\n let outline_level: number | null = null;\n let outline_level_from_style = false;\n if (pPr) {\n const oLvl = findChild(pPr, \"w:outlineLvl\");\n if (oLvl && /^\\d+$/.test(oLvl.getAttribute(\"w:val\") || \"\")) {\n outline_level = parseInt(oLvl.getAttribute(\"w:val\") as string, 10);\n }\n }\n \n if (outline_level === null && style_id && style_cache && style_cache[style_id]) {\n outline_level = style_cache[style_id].outline_level;\n outline_level_from_style = true;\n }\n\n const style_name =\n style_id && style_cache && style_cache[style_id]\n ? style_cache[style_id].name\n : style_id;\n\n let normalized_style_name = style_name;\n if (normalized_style_name && typeof normalized_style_name === \"string\") {\n if (normalized_style_name.toLowerCase().startsWith(\"heading\")) {\n normalized_style_name = normalized_style_name.replace(/^heading/i, \"Heading\");\n } else if (normalized_style_name.toLowerCase() === \"title\") {\n normalized_style_name = \"Title\";\n }\n }\n\n if (outline_level_from_style && outline_level !== null) {\n const is_heading_or_title =\n normalized_style_name &&\n (normalized_style_name.startsWith(\"Heading\") || normalized_style_name === \"Title\");\n if (!is_heading_or_title) {\n outline_level = null;\n }\n }\n\n if (outline_level !== null && outline_level >= 0 && outline_level <= 8) {\n if (normalized_style_name && (normalized_style_name.startsWith(\"Heading\") || normalized_style_name === \"Title\")) {\n return normalized_style_name;\n }\n return \"(outline_level)\";\n }\n\n if (\n normalized_style_name &&\n (normalized_style_name.startsWith(\"Heading\") || normalized_style_name === \"Title\")\n )\n return normalized_style_name;\n\n if (normalized_style_name && /Heading[ ]?([1-6])(?![0-9])/.test(normalized_style_name))\n return normalized_style_name;\n\n return \"(heuristic)\";\n}\n\nfunction _safe_style_name(\n paragraph: Paragraph,\n style_cache: any,\n default_pstyle: any,\n): string | null {\n const pPr = findChild(paragraph._element, \"w:pPr\");\n let style_id = default_pstyle;\n if (pPr) {\n const pStyle = findChild(pPr, \"w:pStyle\");\n if (pStyle) style_id = pStyle.getAttribute(\"w:val\") || default_pstyle;\n }\n return style_id && style_cache && style_cache[style_id]\n ? style_cache[style_id].name\n : style_id;\n}\n\nfunction _find_owned_end(\n block_records: _BlockRecord[],\n heading_indices: number[],\n current_h_pos: number,\n current_level: number,\n): number {\n for (\n let next_h_pos = current_h_pos + 1;\n next_h_pos < heading_indices.length;\n next_h_pos++\n ) {\n const next_idx = heading_indices[next_h_pos];\n if (_heading_level(block_records[next_idx].item) <= current_level)\n return next_idx;\n }\n return block_records.length;\n}\n\nfunction _collect_footnote_ids(owned_blocks: _BlockRecord[]): string[] {\n const seen = new Set<string>();\n const ordered: string[] = [];\n for (const rec of owned_blocks) {\n if (!rec.is_paragraph) continue;\n for (const event of iter_paragraph_content(rec.item)) {\n if (!(\"type\" in event)) continue;\n let fn_id = \"\";\n if (event.type === \"footnote\") fn_id = `fn-${event.id}`;\n else if (event.type === \"endnote\") fn_id = `en-${event.id}`;\n else continue;\n\n if (!seen.has(fn_id)) {\n seen.add(fn_id);\n ordered.push(fn_id);\n }\n }\n }\n return ordered;\n}\n\nfunction _offset_to_page(offset: number, body_page_offsets: number[]): number {\n if (!body_page_offsets || body_page_offsets.length === 0) return 1;\n let page = 1;\n for (let i = 0; i < body_page_offsets.length; i++) {\n if (offset >= body_page_offsets[i]) page = i + 1;\n else break;\n }\n return page;\n}\n\nfunction _extract_outline_fast(\n doc: DocumentObject,\n projected_body: string,\n body_page_offsets: number[],\n paragraph_offsets: Map<any, [number, number]> | Record<string, [number, number]>,\n): OutlineNode[] {\n const paragraphs_and_tables: [\"p\" | \"t\", any][] = [];\n const seen_cells = new Set<any>();\n\n function walk(container: any) {\n for (const item of iter_block_items(container)) {\n const i_type = item.constructor.name;\n if (i_type === \"FootnoteItem\") {\n walk(item);\n } else if (item instanceof Paragraph) {\n paragraphs_and_tables.push([\"p\", item]);\n } else if (item instanceof Table) {\n paragraphs_and_tables.push([\"t\", item]);\n for (const row of item.rows) {\n for (const cell of row.cells) {\n if (seen_cells.has(cell._element)) {\n continue;\n }\n seen_cells.add(cell._element);\n walk(cell);\n }\n }\n }\n }\n }\n\n walk(doc);\n\n const heading_indices: number[] = [];\n for (let idx = 0; idx < paragraphs_and_tables.length; idx++) {\n const [kind, item] = paragraphs_and_tables[idx];\n if (kind !== \"p\") continue;\n\n let hasOffset = false;\n if (paragraph_offsets instanceof Map) {\n hasOffset = paragraph_offsets.has(item._element);\n } else {\n hasOffset = item._element in (paragraph_offsets as any);\n }\n if (!hasOffset) {\n continue;\n }\n\n if (!_is_heading(item)) continue;\n if (!_heading_passes_quality_filter_fast(item, projected_body, paragraph_offsets)) continue;\n\n heading_indices.push(idx);\n }\n\n if (heading_indices.length === 0) return [];\n\n const nodes: OutlineNode[] = [];\n for (let h_pos = 0; h_pos < heading_indices.length; h_pos++) {\n const item_idx = heading_indices[h_pos];\n const paragraph = paragraphs_and_tables[item_idx][1] as Paragraph;\n const level = _heading_level(paragraph);\n const text = _heading_text_fast(paragraph, projected_body, paragraph_offsets);\n const style = _determine_heading_style(paragraph);\n\n // Owned range: items strictly between this heading and the next equal-or-higher heading.\n let owned_end = item_idx;\n for (let next_h_pos = h_pos + 1; next_h_pos < heading_indices.length; next_h_pos++) {\n const next_idx = heading_indices[next_h_pos];\n const next_paragraph = paragraphs_and_tables[next_idx][1] as Paragraph;\n if (_heading_level(next_paragraph) <= level) {\n owned_end = next_idx;\n break;\n }\n }\n if (owned_end === item_idx) {\n owned_end = paragraphs_and_tables.length;\n }\n\n const owned = paragraphs_and_tables.slice(item_idx + 1, owned_end);\n\n // has_table: nearest-claim semantics (no bubbling to ancestors).\n let has_table = false;\n for (const [kind2, item2] of owned) {\n if (kind2 === \"p\" && _is_heading(item2)) {\n break;\n }\n if (kind2 === \"t\") {\n has_table = true;\n break;\n }\n }\n\n // Footnote IDs in document order, deduped.\n const footnote_ids = _collect_footnote_ids_fast(owned);\n\n // Page resolution from the paragraph's known offset.\n let para_offset: [number, number] | undefined;\n if (paragraph_offsets instanceof Map) {\n para_offset = paragraph_offsets.get(paragraph._element);\n } else {\n para_offset = paragraph_offsets[paragraph._element as any];\n }\n\n let page_num = 1;\n if (para_offset !== undefined) {\n const [start_offset] = para_offset;\n page_num = _offset_to_page(start_offset, body_page_offsets);\n }\n\n nodes.push({\n level,\n text,\n page: page_num,\n style,\n has_table,\n footnote_ids,\n });\n }\n\n return nodes;\n}\n\nfunction _heading_passes_quality_filter_fast(\n paragraph: Paragraph,\n projected_body: string,\n paragraph_offsets: Map<any, [number, number]> | Record<string, [number, number]>,\n): boolean {\n const style = _determine_heading_style(paragraph);\n if (style !== \"(heuristic)\") return true;\n\n const text = _heading_text_fast(paragraph, projected_body, paragraph_offsets);\n if (!text) return false;\n const words = text.match(/\\w+/g) || [];\n return words.length >= _HEURISTIC_MIN_WORDS;\n}\n\nfunction _heading_text_fast(\n paragraph: Paragraph,\n projected_body: string,\n paragraph_offsets: Map<any, [number, number]> | Record<string, [number, number]>,\n): string {\n let offset: [number, number] | undefined;\n if (paragraph_offsets instanceof Map) {\n offset = paragraph_offsets.get(paragraph._element);\n } else {\n offset = paragraph_offsets[paragraph._element as any];\n }\n\n if (offset === undefined) {\n return \"\";\n }\n const [start, length] = offset;\n const raw = projected_body.substring(start, start + length);\n let cleaned = _strip_critic_markup(raw);\n cleaned = _strip_inline_formatting(cleaned);\n cleaned = cleaned.replace(/^#+\\s+/, \"\");\n return cleaned.trim();\n}\n\nfunction _collect_footnote_ids_fast(owned_items: [\"p\" | \"t\", any][]): string[] {\n const seen = new Set<string>();\n const ordered: string[] = [];\n for (const [kind, item] of owned_items) {\n if (kind !== \"p\") continue;\n for (const event of iter_paragraph_content(item)) {\n if (!(\"type\" in event)) continue;\n let fn_id = \"\";\n if (event.type === \"footnote\") fn_id = `fn-${event.id}`;\n else if (event.type === \"endnote\") fn_id = `en-${event.id}`;\n else continue;\n\n if (!seen.has(fn_id)) {\n seen.add(fn_id);\n ordered.push(fn_id);\n }\n }\n }\n return ordered;\n}\n","import { strFromU8, unzipSync } from 'fflate';\nimport { DocumentObject } from '../docx/bridge.js';\nimport { SanitizeReport } from './report.js';\nimport * as transforms from './transforms.js';\nimport { findAllDescendants, parseXml } from '../docx/dom.js';\n\nexport interface FinalizeOptions {\n filename: string;\n sanitize_mode?: 'full' | 'keep-markup' | 'baseline';\n accept_all?: boolean;\n protection_mode?: 'read_only' | 'encrypt' | null;\n password?: string | null;\n author?: string | null;\n export_pdf?: boolean;\n}\n\nexport interface FinalizeResult {\n reportText: string;\n outBuffer?: Buffer;\n}\n\nexport async function finalize_document(doc: DocumentObject, options: FinalizeOptions): Promise<FinalizeResult> {\n const report = new SanitizeReport(options.filename, options.sanitize_mode || 'full', options.author || null);\n\n if (options.sanitize_mode === 'full') {\n const counts = transforms.count_tracked_changes(doc);\n const total = counts[0] + counts[1] + counts[2];\n report.tracked_changes_found = total;\n\n if (total > 0 && !options.accept_all) {\n report.status = 'blocked';\n report.blocked_reason = `Document contains ${total} unresolved tracked changes (${counts[0]} insertions, ${counts[1]} deletions, ${counts[2]} formatting). Review in Word first, set accept_all=true, or set sanitize_mode='keep-markup'.`;\n return { reportText: report.render() };\n }\n\n if (total > 0) {\n const authors = transforms.get_track_change_authors(doc);\n if (authors.size > 1) {\n report.warnings.push(`Multiple authors detected in tracked changes: ${Array.from(authors).sort().join(', ')}. Review per-change list before sending.`);\n }\n report.add_transform_lines(transforms.accept_all_tracked_changes(doc));\n report.tracked_changes_accepted = total;\n }\n\n const commentsSummary = transforms.get_comments_summary(doc);\n report.comments_removed = commentsSummary.total;\n report.add_transform_lines(transforms.remove_all_comments(doc));\n transforms.eject_comment_parts(doc);\n } else if (options.sanitize_mode === 'keep-markup') {\n // Basic support for keep-markup in TS\n const counts = transforms.count_tracked_changes(doc);\n report.tracked_changes_found = counts[0] + counts[1] + counts[2];\n report.tracked_changes_kept = report.tracked_changes_found;\n\n if (options.author) {\n report.add_transform_lines(transforms.replace_comment_authors(doc, options.author));\n report.add_transform_lines(transforms.replace_change_authors(doc, options.author));\n }\n }\n\n // Common transforms\n report.add_transform_lines(transforms.strip_rsid(doc));\n report.add_transform_lines(transforms.strip_para_ids(doc));\n report.add_transform_lines(transforms.strip_proof_errors(doc));\n report.add_transform_lines(transforms.strip_empty_properties(doc));\n report.add_transform_lines(transforms.strip_hidden_text(doc));\n report.add_transform_lines(transforms.coalesce_runs(doc));\n report.add_transform_lines(transforms.scrub_doc_properties(doc));\n report.add_transform_lines(transforms.scrub_timestamps(doc));\n report.add_transform_lines(transforms.strip_custom_xml(doc));\n report.add_transform_lines(transforms.strip_custom_properties(doc));\n report.add_transform_lines(transforms.strip_document_variables(doc));\n report.add_transform_lines(transforms.strip_image_alt_text(doc));\n \n const warnings = transforms.audit_hyperlinks(doc);\n for (const w of warnings) report.warnings.push(w);\n // Audit (non-destructive — just warnings): watermark-like VML text objects\n // must never let the report declare the document clean (QA 2026-07-18 M3).\n for (const w of transforms.detect_watermarks(doc)) report.warnings.push(w);\n\n report.add_transform_lines(transforms.normalize_change_dates(doc));\n // Retained comments carry the same when-did-they-work signal in\n // word/comments.xml as tracked changes do in the body (QA 2026-07-19 F-09).\n report.add_transform_lines(transforms.normalize_comment_dates(doc));\n\n // Protection (Settings injection)\n if (options.protection_mode === 'read_only' || options.protection_mode === 'encrypt') {\n if (options.protection_mode === 'encrypt') {\n report.warnings.push(\"Encryption mode (AES compound wrappers) is strictly unsupported in the zero-dependency Node engine. Falling back to native Word Read-Only lock.\");\n }\n \n const settingsPart = doc.pkg.getPartByPath('word/settings.xml');\n if (settingsPart) {\n const docEl = settingsPart._element.ownerDocument!;\n let prot = transforms.findDescendantsByLocalName(settingsPart._element, 'documentProtection')[0];\n if (!prot) {\n prot = docEl.createElement('w:documentProtection');\n // Word expects documentProtection to be inserted before elements like w:autoFormatOverride, w:styleLockTheme, etc.\n // For standard robustness without complex XSD enforcement, appendChild generally works.\n settingsPart._element.appendChild(prot);\n }\n prot.setAttribute('w:edit', 'readOnly');\n prot.setAttribute('w:enforcement', '1');\n report.structural_lines.push(\"Document locked (Read-Only enforcement injected into settings.xml)\");\n }\n }\n\n if (options.export_pdf) {\n report.warnings.push(\"PDF export requires the Python/Word COM environment and is skipped in this zero-dependency Node agent.\");\n }\n\n // Clean up leaked Microsoft namespaces\n for (const part of doc.pkg.parts) {\n // Match the exact injection condition from RedlineEngine constructor\n if (part === doc.part || (part.contentType.includes('wordprocessingml') && part.contentType.endsWith('+xml'))) {\n if (part._element.hasAttribute('xmlns:w16du')) {\n let hasW16du = false;\n // Check root element attributes (excluding the xmlns declaration itself)\n if (Array.from(part._element.attributes || []).some(a => a.name.startsWith('w16du:') && a.name !== 'xmlns:w16du')) {\n hasW16du = true;\n }\n if (!hasW16du) {\n const allNodes = findAllDescendants(part._element, '*');\n for (const n of allNodes) {\n if (n.tagName.startsWith('w16du:') || Array.from(n.attributes || []).some(a => a.name.startsWith('w16du:'))) {\n hasW16du = true;\n break;\n }\n }\n }\n if (!hasW16du) part._element.removeAttribute('xmlns:w16du');\n }\n }\n }\n\n if (report.warnings.length > 0) report.status = 'clean_with_warnings';\n\n const outBuffer = await doc.save();\n verifySanitizedPackage(outBuffer);\n return { reportText: report.render(), outBuffer };\n}\n\n// Core-property elements the pipeline claims to scrub; the post-sanitize\n// verification re-checks each one in the SAVED bytes.\nconst VERIFIED_CORE_FIELDS: Array<[string, string]> = [\n ['creator', 'author (dc:creator)'],\n ['lastModifiedBy', 'last modified by (cp:lastModifiedBy)'],\n ['identifier', 'identifier (dc:identifier)'],\n ['description', 'description (dc:description)'],\n ['keywords', 'keywords (cp:keywords)'],\n ['category', 'category (cp:category)'],\n ['subject', 'subject (dc:subject)'],\n ['contentStatus', 'content status (cp:contentStatus)'],\n ['language', 'language (dc:language)'],\n ['version', 'version (cp:version)'],\n];\n\n/**\n * Post-sanitize package scan: re-open the SAVED bytes —\n * bypassing every in-memory caching layer — and verify the claims the report\n * is about to make. A \"Result: CLEAN\" verdict over a package that still\n * carries custom properties or an identifier is worse than no sanitizer.\n */\nexport function verifySanitizedPackage(outBuffer: Buffer): void {\n const unzipped = unzipSync(new Uint8Array(outBuffer));\n const names = Object.keys(unzipped);\n const problems: string[] = [];\n\n if (names.includes('docProps/custom.xml')) {\n problems.push('docProps/custom.xml (custom document properties) is still in the package');\n }\n if (names.some(n => n.startsWith('customXml/'))) {\n problems.push('customXml/* parts are still in the package');\n }\n if (names.includes('docProps/core.xml')) {\n const core = parseXml(strFromU8(unzipped['docProps/core.xml']));\n for (const [local, label] of VERIFIED_CORE_FIELDS) {\n for (const el of transforms.findDescendantsByLocalName(core.documentElement! as unknown as Element, local)) {\n if ((el.textContent || '').trim()) {\n problems.push(`core property ${label} still contains a value`);\n }\n }\n }\n }\n if (names.includes('word/settings.xml')) {\n // Document variables are invisible metadata (QA ADEU-QA-001): a surviving\n // w:docVar means the strip transform silently failed.\n const settings = parseXml(strFromU8(unzipped['word/settings.xml']));\n if (\n transforms.findDescendantsByLocalName(settings.documentElement! as unknown as Element, 'docVar').length > 0\n ) {\n problems.push('word/settings.xml still contains document variables (w:docVar)');\n }\n }\n\n if (problems.length > 0) {\n throw new Error(\n 'Sanitize integrity check failed — the saved package still contains metadata this run ' +\n 'claims to remove:\\n - ' +\n problems.join('\\n - ') +\n '\\nRefusing to report a clean document.',\n );\n }\n}","export class SanitizeReport {\n public filename: string;\n public mode: string;\n public author: string | null;\n\n public tracked_changes_found: number = 0;\n public tracked_changes_accepted: number = 0;\n public tracked_changes_kept: number = 0;\n public change_lines: string[] = [];\n\n public comments_removed: number = 0;\n public comments_kept: number = 0;\n public removed_comment_lines: string[] = [];\n public kept_comment_lines: string[] = [];\n\n public metadata_lines: string[] = [];\n public structural_lines: string[] = [];\n public warnings: string[] = [];\n\n public status: string = \"clean\";\n public blocked_reason: string | null = null;\n\n constructor(filename: string, mode: string = \"full\", author: string | null = null) {\n this.filename = filename;\n this.mode = mode;\n this.author = author;\n }\n\n public add_transform_lines(lines: string[]) {\n for (const line of lines) {\n const lower = line.toLowerCase();\n if (lower.includes(\"tracked change\") || lower.includes(\"insertion\") || lower.includes(\"deletion\") || lower.includes(\"accepted\")) {\n this.change_lines.push(line);\n } else if (\n lower.includes(\"author\") || lower.includes(\"template\") || lower.includes(\"company\") ||\n lower.includes(\"manager\") || lower.includes(\"metadata\") || lower.includes(\"timestamp\") ||\n lower.includes(\"custom xml\") || lower.includes(\"custom propert\") || lower.includes(\"identifier\") ||\n lower.includes(\"document variable\") ||\n lower.includes(\"language\") || lower.includes(\"version\") ||\n lower.includes(\"last modified by\") || lower.includes(\"revision count\") || lower.includes(\"last printed\") ||\n lower.includes(\"description/comments\")\n ) {\n this.metadata_lines.push(line);\n } else if (lower.includes(\"comment\") || lower.includes(\"[open]\") || lower.includes(\"[resolved]\")) {\n if (lower.includes(\"kept\") || lower.includes(\"visible\")) {\n this.kept_comment_lines.push(line);\n } else {\n this.removed_comment_lines.push(line);\n }\n } else if (lower.includes(\"hyperlink\") || lower.includes(\"warning\")) {\n this.warnings.push(line);\n } else {\n this.structural_lines.push(line);\n }\n }\n }\n\n public render(): string {\n const sep = \"═\".repeat(50);\n const lines: string[] = [sep, `Finalization Report: ${this.filename}`];\n\n const flags: string[] = [];\n if (this.mode === \"keep-markup\") flags.push(\"--keep-markup\");\n if (this.author) flags.push(`--author \"${this.author}\"`);\n if (this.tracked_changes_accepted > 0) flags.push(\"--accept-all\");\n\n if (flags.length > 0) lines.push(flags.join(\" \"));\n lines.push(sep);\n\n if (this.status === \"blocked\") {\n lines.push(\"\");\n lines.push(`BLOCKED: ${this.blocked_reason}`);\n lines.push(sep);\n return lines.join(\"\\n\");\n }\n\n if (this.mode === \"keep-markup\" && (this.tracked_changes_kept > 0 || this.comments_kept > 0)) {\n lines.push(\"\");\n lines.push(\"VISIBLE TO COUNTERPARTY\");\n if (this.tracked_changes_kept > 0) lines.push(` Tracked changes: ${this.tracked_changes_kept}`);\n if (this.comments_kept > 0) {\n lines.push(` Open comments: ${this.comments_kept}`);\n for (const cl of this.kept_comment_lines) lines.push(` ${cl}`);\n }\n if (this.author) lines.push(` Author on all markup: \"${this.author}\"`);\n }\n\n if (this.change_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"TRACKED CHANGES\");\n for (const cl of this.change_lines) lines.push(` ${cl}`);\n }\n\n if (this.removed_comment_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"COMMENTS (stripped)\");\n for (const cl of this.removed_comment_lines) lines.push(` ${cl}`);\n }\n\n if (this.metadata_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"METADATA\");\n for (const ml of this.metadata_lines) lines.push(` ${ml}`);\n }\n\n if (this.structural_lines.length > 0) {\n lines.push(\"\");\n lines.push(\"STRUCTURAL & PROTECTION\");\n for (const sl of this.structural_lines) lines.push(` ${sl}`);\n }\n\n if (this.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"WARNINGS\");\n for (const w of this.warnings) lines.push(` ⚠ ${w}`);\n }\n\n lines.push(\"\");\n lines.push(sep);\n if (this.warnings.length > 0) {\n lines.push(`Result: CLEAN WITH WARNINGS (${this.warnings.length} warning${this.warnings.length > 1 ? 's' : ''})`);\n } else {\n lines.push(`Result: CLEAN (${this.tracked_changes_found} changes resolved, ${this.comments_removed} comments removed)`);\n }\n lines.push(sep);\n\n return lines.join(\"\\n\");\n }\n}","export function identifyEngine() {\n return 'adeu-core-node';\n}\n\nexport { DocumentObject } from './docx/bridge.js';\nexport { DocumentMapper, TextSpan } from './mapper.js';\nexport { RedlineEngine, BatchValidationError, validate_edit_strings, describe_illegal_control_chars } from './engine.js';\nexport { generate_edits_from_text, generate_structured_edits, trim_common_context, create_unified_diff, create_word_patch_diff, collect_media_difference_warnings, DiffEdit } from './diff.js';\nexport { apply_edits_to_markdown, MarkupEditReport } from './markup.js';\nexport { paginate, split_structural_appendix, PaginationResult, PageInfo } from './pagination.js';\nexport { extract_outline, OutlineNode } from './outline.js';\nexport { extractTextFromBuffer, _extractTextFromDoc, ExtractStructure, TableGeometry, RowGeometry } from './ingest.js';\nexport { finalize_document, FinalizeOptions, FinalizeResult } from './sanitize/core.js';\nexport { RegexTimeoutError, userFindAllMatches, userSearch, USER_PATTERN_TIMEOUT_MS } from './utils/safe-regex.js';"],"mappings":"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","names":["result","matches","unzipSync","i","j","ops","prev","nxt","final_target","final_new","effective_start_idx","sub_edits","target_runs","render_comment","strFromU8","unzipSync","unzipSync","strFromU8"]}
|