anthropics / anthropics/skills

DOCX skill: tracked change w:id values collide with existing bookmark IDs, corrupting files

Open
#489 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
176k
Forks
20.8k
Avg merge
7h 21m
Merged PRs (30d)
5

Description

When the DOCX skill adds tracked changes to an existing document, it introduces two types of corruption:

## Issue 1: Duplicate w:id values

When the DOCX skill adds tracked changes (`w:ins`, `w:del`, etc.) to an existing document, it assigns `w:id` attributes starting from low numbers (0, 1, 2...).

If the original document already has bookmarks (`w:bookmarkStart`/`w:bookmarkEnd`) using those same IDs, Microsoft Word rejects the file as corrupt.

macOS Preview opens the file fine because it's more lenient about ID uniqueness.

### Root Cause

In the OOXML spec, `w:id` is a shared ID space across all of:
- Bookmarks (`w:bookmarkStart` / `w:bookmarkEnd`)
- Tracked changes (`w:ins`, `w:del`, `w:rPrChange`, etc.)
- Comments (`w:commentRangeStart` / `w:commentRangeEnd`)
- Move ranges (`w:moveFromRangeStart` / `w:moveToRangeStart`, etc.)

The SKILL.md examples use hardcoded low IDs:
```xml

```

Claude follows this pattern and starts numbering from 0/1/2. Documents with existing bookmarks in that range (common — many documents have hundreds of bookmarks) end up with duplicate IDs.

## Issue 2: Structural nesting violations

The skill sometimes places tracked change elements (`w:ins`, `w:del`) inside `w:t` (text) or `w:r` (run) elements. The OOXML spec requires these at the `w:p` (paragraph) level.

### Example of corrupt structure

```xml

some text
deleted text
more text

```

### What the spec requires

```xml

some text

deleted text

more text
```

Word is strict about this and refuses to open files with these nesting violations. This appears to happen non-deterministically — in our testing it occurred in 3 out of 10 attempts on the same document.

## Reproduction

1. Take a DOCX with many bookmarks (e.g., one with 100+ bookmarks using IDs 0–100)
2. Use the DOCX skill to add tracked changes (markup/redline)
3. The resulting file may have:
- Duplicate `w:id` values between bookmarks and tracked changes
- `w:ins`/`w:del` elements nested inside `w:t` or `w:r` instead of at `w:p` level
4. Word refuses to open the file

In our testing, 3 out of 10 attempts produced corrupted files when marking up the same document.

## Validator Gap

The `validate_unique_ids()` method in `scripts/office/validators/base.py` checks uniqueness within element types (bookmark vs bookmark) via `UNIQUE_ID_REQUIREMENTS`, but does not include tracked change elements (`ins`, `del`, `rPrChange`, etc.) in the uniqueness check. So the ID collision goes undetected by `validate.py`.

There also appears to be no structural validation checking that tracked change elements are placed at the correct nesting level (paragraph, not inside runs or text elements).

## Suggested Fix

1. **ID uniqueness**: Before assigning `w:id` to tracked changes, scan for the max existing `w:id` across ALL element types in the document and start from `max + 1`
2. **Nesting**: Ensure tracked change elements (`w:ins`, `w:del`) are emitted at the `w:p` (paragraph) level, never inside `w:r` (run) or `w:t` (text) elements
3. **Validator**: Add `ins`, `del`, `rPrChange`, `pPrChange`, `sectPrChange`, `tblPrChange`, `tcPrChange`, `trPrChange`, `cellIns`, `cellDel`, `cellMerge`, `numberingChange` to `UNIQUE_ID_REQUIREMENTS` in `base.py`, and add a nesting-level check for tracked change elements

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.