Skip to content

feat(validate): report cross-part comment inconsistencies, not only per-part schema errors #34

Closed

Description

@michaelgasser

Version: docx-cli 0.28.0, release binary (Windows x64), Windows 11, Word 16.

What happens

docx validate reports a package as clean while Word refuses to open it without repair:

$ docx validate fixture-comments-base.docx     # after one comments add, 3 comments / 2 ids / 2 ext
valid — 6 parts checked

By design validate is a per-part ECMA-376 check (src/cli/validate/, a thin shell over
@core/raw/validate), so package-level invariants are outside what it can see. This asks for those
invariants somewhere explicit — not for the schemas to change.

Invariants worth reporting

warn  comments  comment c23 (p79) has no entry in commentsIds.xml        (22 of 25 affected)
warn  comments  comment c24 (p51) has no entry in commentsExtended.xml
warn  comments  commentRangeStart 41 has no matching commentReference

The first two are the measured failure (companion issue, filed separately, has the full numbers and a
7.6 KB fixture, #33). The third is the neighbouring class — a range whose start and end survive but whose
reference run was deleted — not observed in the document that surfaced this.

What it should not report

Measured against an 18.5 MB report, so the check does not become noise:

construct verdict
duplicate w14:paraId 25 present in the untouched source document too; they are mc:AlternateContent choice/fallback pairs, which CLAUDE.md covers via alternateContentBranch. Legal.
a comment id equal to a revision w:id separate id spaces, present in Word's own files. Legal.
<w:del> nested inside <w:ins> legal revision-of-a-revision, and what #20 deliberately produces for a different author. Legitimate.

Where it likely lives

src/core/raw/ already runs a "reference audit" stage in the fragment gate; this is the
package-level analogue. A separate verb (docx check FILE) may fit the architecture better than
extending validate, since validate's contract is "does this part match the schema" — #31 is a good
precedent for keeping that contract narrow (there the fix preprocesses Word's shape instead of
loosening the schema).

Why it matters

The failure surfaced on the recipient's screen, not in the agent's terminal: read, diff, wc,
comments list and validate all report a healthy document. A pre-delivery check is the only step
in the loop that would have caught it.

Possible shape

  • docx check FILE → exit 0 when all invariants hold, non-zero with one line per violation.
  • Start with the comment-part set (highest value: it is a Word-repair trigger), then relationships
    pointing at absent parts, then commentRange* balance.
  • --json for the same ack shape as the rest of the CLI.

Activity

  1. changed the title [-]`feat(validate): report cross-part comment inconsistencies, not only per-part schema errors`[/-] [+]feat(validate): report cross-part comment inconsistencies, not only per-part schema errors[/+] on Nov 5, 2026
  2. kklimuk commented on Nov 6, 2026

    @kklimuk
    Owner

    Shipped in v0.29.0 (#36 plus follow-ups on main).

    docx validate now checks comment consistency across parts as well as the schema. Severity follows what Word for Mac actually did with each state (tested live on 2026-11-05):

    Finding Severity --fix
    commentReference names no comment (Word refuses to open) error, exit 1 removes it
    comment missing a commentsExtended/commentsIds entry or paraId (Word opens, but replies and resolved state can be lost) warning adds the entry
    range with no end or no reference (Word collapses or drops it) warning closes it the way Word does
    orphan comment with no markers (Word deletes it on open) warning reported only
    reply pointing at a missing parent (thread lost) warning reported only
    stale or duplicate sidecar entries (harmless) not reported cleaned
    • Fixable findings end with run `docx validate FILE --fix` .
    • Warnings exit 0 and errors exit 1, so commented files saved by LibreOffice (sparse commentsExtended) aren't reported as broken.
    • The relationship-target check from this issue's second priority isn't in this release.
  3. kklimuk commented on Nov 6, 2026

    @kklimuk
    Owner

    @michaelgasser thanks for the report! this should work nicely now =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions