Release note · August 3, 2026

A Word document can change its XML-save transform without changing its text

By SybilGambleyyu · Document Change Assurance Benchmark 0.18.0

Not every consequential WordprocessingML change is part of the visible document body. A document can retain every stored text node and its complete Settings markup while changing the external transform configured for a single-XML save. A normal text diff has little reason to surface that boundary; a package-review tool should be able to.

Document Change Assurance Benchmark (DCAB) 0.18.0 adds its twenty-ninth deterministic pair: external.save_through_xslt_target_retargeted. Both sides preserve the package-member set, every stored w:t value, the explicit enabled setting, the transform anchor, the relationship ID, and all Settings XML. Only word/_rels/settings.xml.rels changes, where the synthetic external transform target is retargeted.

A complete stored topology, not a loose flag

Microsoft’s SaveThroughXslt documentation identifies a custom XSL transform used when a document is saved as a single XML file. Its UseXsltWhenSaving companion controls whether that transform is applied. The OOXML Document Settings relationship contract defines the associated transform relationship as external.

word/settings.xml                         fixed on both sides
  w:useXSLTWhenSaving true               fixed enabled state
  w:saveThroughXslt r:id                 fixed transform anchor

word/_rels/settings.xml.rels             only changed package member
  transform relationship / target         synthetic target retargeted

The fixture therefore isolates the static review fact rather than inventing a target in an unrelated part. It does not provide an XSLT payload, execute a transformation, save a document through one, open Word, or claim emitted XML or client behavior.

A public fact without publishing the target

The target-free oracle reports only save_through_xslt_target_changed, its external binding class, the generic XML-transform relationship category, and the Word Settings source. It excludes both targets, the relationship ID, the relationship path, and any local solution identifier. All URI-like fixture targets use the reserved example.invalid domain.

Structural validation checks the package topology independently: exact settings elements and order, explicit enabled value, transform anchor, standard external relationship type and mode, stable member set, declared one-member boundary, unchanged stored text, reproducible generation, and absence of sensitive fixture material from public truth.

One released consumer, still a tool-neutral benchmark

The optional DocFence 0.28.0 adapter reaches a strict 29/29 score from aggregate evidence: external_relationships_changed, save_through_xslt_inventory_changed, one enabled setting, one transform anchor, one external transform relationship, and no local solution identifier. It does not consume a target, relationship ID, part path, or private fingerprint.

Hosted CI passed on Python 3.11, 3.12, and 3.13 for the main commit and release tag. The standard python-docx reader opens all 56 .docx fixtures, while its lower-level OPC reader opens all 58 packages. Clean wheel and source-distribution installs validate the bundled 29-case corpus, and the public Hugging Face dataset mirror was byte-verified against the generated tree.

Use the release

python -m pip install https://github.com/SybilGambleyyu/document-change-benchmark/releases/download/v0.18.0/document_change_benchmark-0.18.0-py3-none-any.whl
dcab validate
dcab docfence-observations --executable docfence --output observations.json
dcab score --observations observations.json --strict

DCAB 0.18.0 retains fixture schema version 1 because its public truth and observation envelopes are unchanged. It adds one narrowly defined stored configuration boundary—not a transform engine, client emulator, renderer, or universal security-policy claim.

The MIT-licensed builder, generated fixtures, verifier, release artifacts, and research notes are available on GitHub. The corpus is also mirrored as a public Hugging Face dataset.