Conversation
DocxSnapshotStore.CompareAsync and DocxVersionHistory.CompareVersionsAsync read the caller's DocxDiffSettings only after awaiting host blob reads, and the returned lazy DocxDiffComparison kept reading that same object. A caller that reused its settings mid-flight got a comparison stamped with the changed values (e.g. the wrong revision author). Clone at entry, matching how CaptureAsync already owns its bytes before yielding. Also clarifies that CompareAsync is raw-engine semantics (not the DocxCompare pre-accept front door), null-checks its snapshot arguments up front, and drops the redundant #nullable enable directives from the files added in #708. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EuVfv22yFAxchW5H2F7Sk9
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up review of #708 (DOCX snapshot store), which is already merged. CI was green on #708 and is green on
main, so there was no pipeline failure to fix. This PR fixes the one real defect found in review, plus two small cleanups.The bug
DocxSnapshotStore.CompareAsynctakes aDocxDiffSettingsobject, then awaits two reads from host blob storage before it passes that object toDocxDiff.CreateComparison.DocxVersionHistory.CompareVersionsAsyncadds two more awaits (the version-record reads) in front of that. The returnedDocxDiffComparisonalso keeps the same object by reference and reads it lazily when a product is requested.So a caller that reuses its settings object and changes it while storage is slow gets a comparison built from the changed values. The tests change
AuthorForRevisions, and the redline comes back stamped with the wrong author. #708 already guards against this for the document bytes (CaptureAsynccopies them before yielding "to an asynchronous host adapter"). Settings were missed, and the downstreamDocxHistoryReader.CompareVersionsToDocxAsyncalready clones its settings for the same reason.Fix: clone the settings on entry to both methods, before the first await.
DocxDiffSettings.Clone()is the existing shallow copy theDocxComparefront door already uses.Other changes
CompareAsync"retains"DocxDiff's compatibility policy. That reads as if it behaves like the product comparison. In fact it runs the raw engine with its opt-in input-revision defaults and does not apply theDocxComparepre-accept step. That split is intentional, since the client-facing path goes throughDocxCompare. The behavior is unchanged; only the wording now matches it.CompareAsyncnow null-checks both snapshot references up front instead of failing insideExportAsync.#nullable enablefrom the two files feat(history): capture exact DOCX snapshots and reuse lazy comparisons #708 added. The project enables nullable reference types globally, and repo rules forbid per-file directives.Review notes on the rest of #708
The rest of #708 holds up on review:
The copyright header #708 originally shipped was already corrected on
main.One pre-existing issue is outside this PR's scope:
DocxDiffComparisonholds caller settings by reference in every entry point, not just history. The history API no longer exposes it, but a constructor-level clone in the engine would close it everywhere. That's worth a separate change.Validation (TDD)
DocxSnapshotStoreTests.ComparisonOwnsSettingsBeforeAwaitingHostStorageandDocxVersionHistoryTests.VersionComparisonOwnsSettingsBeforeAwaitingHostStoragefirst. Each uses a blob store that pauses reads, changes the settings mid-read, then checks the revision author. Both failed before the fix (Actual: "Changed during storage read") and pass after it.DocxCompareand copyright-guard tests pass locally.--no-incrementalare unchanged at the documented baseline (library 175, tests 788).🤖 Generated with Claude Code
https://claude.ai/code/session_01EuVfv22yFAxchW5H2F7Sk9
Generated by Claude Code