Skip to content

feat(validate): report cross-part comment inconsistencies - #36

Merged
kklimuk merged 1 commit into
mainfrom
claude/triage-issue-34-validate-consistency
Nov 6, 2026
Merged

kklimuk merged 1 commit into
mainfrom
claude/triage-issue-34-validate-consistency

Conversation

@kklimuk

@kklimuk kklimuk commented Nov 5, 2026

Copy link
Copy Markdown
Owner

🤖 docx-cli triage

What was wrong

docx validate only schema-checks each part, so cross-part comment breakage went unreported. Repro: cp tests/fixtures/academic-paper.docx a.docx && docx comments add a.docx --at p1 --text "new note" && docx validate a.docx printed valid — 11 parts checked, exit 0. The new comment has no entry in commentsIds.xml or commentsExtended.xml, which is the Word repair trigger reported in #33.

What changed

  • New pure audit src/core/raw/package-consistency.ts (checkPackageConsistency). validate runs it alongside the schema pass, over the same parsed parts. It checks:
    • every comment has an entry, keyed by its last paragraph's w14:paraId, in each side part that is present (commentsExtended.xml, commentsIds.xml). A side part that is missing entirely is legal and not reported.
    • comment markers balance across the body, headers/footers and footnotes/endnotes: each range start has a range end, each range has a commentReference, and each reference names a comment that exists.
  • Each finding is listed under the part it concerns, tagged (consistency) in text output and kind: "consistency" in --json, and it makes validate exit 1. Not reported on purpose, to avoid noise: orphan side-part entries, comments with no markers in the document, ids that appear more than once because of mc:AlternateContent (compared as sets), and the glossary document.
  • The raw gate is unchanged: it still judges a raw edit on schema errors only.
  • Docs: --help, REFERENCE.md, the skill's commands.md, src/cli/CLAUDE.md, src/core/raw/CLAUDE.md.

Verification

  • Same repro after the change: exit 1 with
    word/commentsExtended.xml: 1 error
      comment c44 (paraId 25858A85) has no entry in word/commentsExtended.xml (consistency)
    word/commentsIds.xml: 1 error
      comment c44 (paraId 25858A85) has no entry in word/commentsIds.xml (consistency)
    
  • Every shipped fixture still validates clean (the existing "every fixture validates clean" test guards against false positives). That includes the Word-authored academic-paper.docx, which has all three comment parts.
  • 6 new tests in tests/cli/validate.test.ts built from hand-made inconsistent packages: missing commentsIds entry, a consistent commentsIds, a range whose reference was deleted, an unpaired range start, a dangling reference (--json), and a clean commented doc.
  • bun run check ✅ bun run test:unit ✅ (1915 tests)
  • /simplify (one pass, no Agent tool): dropped one redundant filter. /code-review xhigh: the forked run reviewed the wrong checkout (see the triage report), so I reviewed this diff by hand instead. That review added the glossary exclusion; nothing else changed.

Decisions for you

Action needed: approve/merge — review the decisions above, ideally merging after #33's fix lands.

Fixes #34


Generated by Claude Code

`docx validate` checked each WML part against the schema only, so a package
whose comments were missing from commentsIds.xml / commentsExtended.xml (a
Word repair trigger, #33) reported "valid". Add a pure package-consistency
audit beside the schema pass:

- every comment keyed by its last paragraph's w14:paraId in each PRESENT
  side-part (commentsExtended.xml, commentsIds.xml)
- comment marker balance across story parts: range start/end pairing,
  range -> commentReference, commentReference -> existing comment

Findings file under the part they concern, tagged "(consistency)" in text
and `kind: "consistency"` in --json, and count toward exit 1. Every shipped
fixture (including Word-authored academic-paper.docx with commentsIds.xml)
still validates clean.

Fixes #34

Triage-Routine: true
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LkctEMYpX1DxpKLGCMzZxp
@kklimuk
kklimuk merged commit 9d16eed into main Nov 6, 2026
10 checks passed
kklimuk added a commit that referenced this pull request Nov 6, 2026
…rst minted

A create'd doc has no commentsExtended.xml until the first reply or resolve
materializes it, and that path registered only the touched thread. So
add -> add -> reply c0 left c1 with no <w15:commentEx>, which the new
validate consistency check (#36) reports. Materializing the part now writes
a done="0" entry for every comment already there (Word's shape), and
reply ensures the part before appending its own body so the reply is not
registered twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kklimuk added a commit that referenced this pull request Nov 6, 2026
…/footer parts

Word lets a reviewer comment inside a footnote or endnote, so the comment's
range markers and reference run live in footnotes.xml/endnotes.xml. comments
delete pruned word/document.xml only, leaving a commentReference that names
no comment, which validate's new consistency check (#36) reports. It now
prunes every story part the consistency check scans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kklimuk added a commit that referenced this pull request Nov 6, 2026
…t removes a revision

Rejecting an insertion or accepting a deletion spliced the wrapper out with
every comment marker inside it. A comment's markers often straddle a
revision: edit --text on a commented paragraph under tracking re-anchors
the range ends after the new words (inside the <w:ins>) while the starts
stay ahead of the <w:del>, and a tracked delete wraps the reference runs.
So reject --all after a tracked rewrite left range starts with no end, and
accept --all after a tracked delete left ranges with no reference; validate
(#36) reports both and Word drops such comments. Markers whose comment also
has a marker outside the revision now stay where the wrapper stood; a
comment wholly inside the revision still goes with its text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kklimuk added a commit that referenced this pull request Nov 6, 2026
… its paragraphs goes

An untracked delete --at pN / edit --at pN --text "" on the paragraph
holding one half of a cross-paragraph comment removed that half with it:
deleting the start paragraph left a commentRangeEnd with no start, deleting
the end paragraph left a start with no end or reference. edit --runs '[]'
(an emptied paragraph) dropped the half the same way. validate (#36)
reports all three, and Word drops the comment. The straddling markers now
move onto the neighboring paragraph (previous, else next — the text-box
rule), and an emptied paragraph keeps its half at offset 0. A comment
wholly on the removed paragraph still goes with it. The 'which markers
straddle' check is shared with accept/reject via
core/comments/straddling-markers.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

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

2 participants