Validate mixed-section PDF geometry (#440) - #503
Closed
JSv4 wants to merge 15 commits into
Closed
Conversation
The verification suite built every fixture in-process, so the generator had never met a Word-authored file. Sweeping the committed corpus finds five it calls invalid and one class of false equality. Directory-only ZIP entries failed the OPC segment grammar (the trailing slash splits into an empty final segment), so each one raised unsafe_entry_path as well as the directory_entry warning written for exactly this case — making that warning's lenient severity unreachable, and marking Fax.docx, Letter.docx and DB014-WebExtensions.docx invalid. They are now inventoried with a trailing-slash URI that cannot collide with a part, kept out of content-type resolution, and excluded from both content digests, because adding or dropping folder entries is repackaging. Breaching MaxEntryCount truncated the entry list but still emitted both content digests over the surviving prefix, so two packages differing only past the cut compared equal — the doc's "repacked ZIP only" reading of a comparison that is in fact between different documents. Truncation now suppresses both digests, and declared expansion is summed over the whole central directory so the two limits cannot be played against each other. Three findings blamed every part for one unreadable file: an unusable [Content_Types].xml produced missing_content_type per entry, an unparsed .rels part produced dangling_relationship per reference it owned, and an oversize [Content_Types].xml reported its limit twice. Each is now reported once against the file that caused it, via content_types_unreadable and relationship_part_unreadable. A part declaring an XML content type that does not parse nulled the whole package's normalizedSemanticDigest. It now contributes its exact bytes under a distinct 'U' tag, costing that part its serialization independence rather than the package its identity. PM038 sweeps every committed .docx and allowlists only CA009-altChunk.docx, whose Override genuinely lies about a ZIP payload. PM037 asserts a blank session manifest is valid — the surface that reported isValid: false for every document until the preceding commit, while PM015 asserted everything about it except that. Also: MaxCharactersFromEntities was 0, which XmlReaderSettings reads as "no limit"; IsRelationshipPart was duplicated in two files and its StartsWith subsumed by its Contains; XDocument.Descendants() already yields the root, so the Prepend visited it twice (PM039 guards the removal).
The raw-byte fallback added in the previous commit was reached by any XML part without a normalized digest, including one skipped by MaxXmlPartBytes. That made normalizedSemanticDigest a function of the options object: the same bytes hashed as 'X' plus a normalized digest at the default limit and as 'U' plus raw bytes at a lower one. The mirror image of the truncation bug it was committed alongside — false difference instead of false equality. The fallback is now reserved for bytes that no budget would parse, recorded where the parse actually fails. A part skipped by a limit leaves the package digest null, as before: unavailable, not different. relationship_part_unreadable had reintroduced a smaller version of the cascade this work removed. When a package-wide budget stops every payload read, one systemic breach is already reported, so the per-part finding is omitted; the owner is still recorded so dangling_relationship stays suppressed. Content-type Default declarations keep the extension spelling the package wrote instead of a lower-cased copy — matching the documented promise to preserve every declaration, with matching still case-insensitive through the lookup dictionaries. The attribute sort drops its unreachable value tiebreak: an element cannot carry two attributes with the same expanded name.
JSv4
force-pushed
the
agent/issue-439-pdf-export
branch
from
August 17, 2026 21:01
e8f061d to
be8eee4
Compare
JSv4
force-pushed
the
agent/issue-440-mixed-page-geometry
branch
from
August 17, 2026 21:35
14765be to
452d3ec
Compare
JSv4
force-pushed
the
agent/issue-439-pdf-export
branch
from
August 20, 2026 18:22
be8eee4 to
e6a9df7
Compare
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.
Closes #440.
Stacked on #502 (
agent/issue-439-pdf-export). This PR remains draft until its dependencies land.Summary
Validation
npm-export: 7 passedArtifacts
The Actions
playwright-reportartifact is uploaded withif: always(). Download it and opennpm-export/test-artifacts/view-artifacts.htmlto inspect the generated DOCX, standalone HTML, normal/scaled PDFs, screenshot, PageMap, render report, and PDF inspection JSON.