Skip to content

fix: the same document always saves to the same bytes - #33

Merged
baseballyama merged 1 commit into
mainfrom
fix/deterministic-zip-mtime
Oct 9, 2026
Merged

baseballyama merged 1 commit into
mainfrom
fix/deterministic-zip-mtime

Conversation

@baseballyama

Copy link
Copy Markdown
Member

Summary

Saving the same document now always produces the same bytes. Until now, the ZIP entries carried the time of saving. That made the output differ between saves and made idempotent-resave.test.ts fail intermittently.

Motivation

CI on main failed after #32. idempotent-resave.test.ts › a single mutation produces exactly one new byte stream then stabilises failed on Node 24 and passed on Node 22, on the same commit (run 37884074956).

The cause is in writeZip. It gives fflate no mtime, so fflate stamps each entry with new Date(). ZIP's DOS timestamps have a 2-second resolution. When two saves of an unchanged document fall on either side of a 2-second boundary, their bytes differ.

This affects users too, not only the test: templating pipelines, caches and diff tools rely on re-saving an unchanged document being byte-stable. The test file describes that property.

Changes

  • writeZip dates every entry 1980-01-01 00:00, the earliest DOS date. The Date is built from local-time fields, which is what fflate encodes, so the bytes do not depend on the time zone. Word and other readers ignore entry dates.
  • New test: saving the same document at two different (faked) times gives identical bytes. It fails without the fix.
  • Changeset: @office-kit/docx patch.

Testing

  • The new test fails before the fix (1 failed) and passes after it.
  • pnpm test: 1294 passed, 8 skipped. pnpm typecheck passes. oxlint reports the 2 known warnings. check:tree-shake passes.
  • unzip -l on a saved file shows 01-01-1980 00:00 for every entry.

Breaking changes

None. The bytes of saved files change (the entry dates), but their contents do not.

Checklist

  • I have read CLAUDE.md and followed the project's conventions.
  • I have added or updated tests for the change.
  • I have added or updated documentation where user-visible behavior changed.
  • If this is a breaking change, I have added a changeset / CHANGELOG entry and flagged it above.
  • I have re-read my own diff and removed dead code, debug prints, and stale comments.
  • If I used an LLM to draft this PR, I have verified each change myself, the PR represents real work that warrants a maintainer's review, and I am willing to defend each line in review.

🤖 Generated with Claude Code

fflate stamps each ZIP entry with the current time when none is given, so
two saves of an unchanged document differed whenever they straddled a
two-second boundary of the DOS timestamp. That made idempotent-resave.test.ts
fail now and then (CI on main after #32). Every entry now carries a fixed
date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 9, 2026 04:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@baseballyama
baseballyama merged commit a5fe1b8 into main Oct 9, 2026
5 checks passed
@baseballyama
baseballyama deleted the fix/deterministic-zip-mtime branch October 9, 2026 04:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants