Skip to content

fix(core): coalesce deleted runs without duplicate revision IDs - #142

Open
6uimorais wants to merge 1 commit into
dealfluence:mainfrom
6uimorais:fix-multirun-revision-ids
Open

fix(core): coalesce deleted runs without duplicate revision IDs#142
6uimorais wants to merge 1 commit into
dealfluence:mainfrom
6uimorais:fix-multirun-revision-ids

Conversation

@6uimorais

Copy link
Copy Markdown

Summary

Fixes #141.

Keep adjacent runs deleted by one resolved text edit inside a single w:del wrapper, rather than writing sibling deletion wrappers with duplicate IDs. This is mirrored in the Node and Python engines, as required by the contribution guidelines.

Thank you for the earlier work on logical-change grouping. This proposal preserves the compact two-entry delete/insert bubble for the ordinary adjacent multi-run case in #16 while making that output pass independent OpenXML validation.

Implementation and scope

  • Preserve each deleted run and its properties; coalesce only immediately adjacent runs from the current edit.
  • Leave intervening nodes in their original position. Separate deletion wrappers get fresh IDs instead of reusing the reserved first ID.
  • Preserve Python's insertion-style inheritance from the last deleted run after coalescing.
  • Include additional deletion IDs in Python's post-apply preview bookkeeping.
  • Update the existing coalescing regression assertions to require one deletion wrapper containing both runs, rather than two wrappers sharing an ID. The existing two-entry projection and accept/reject tests remain in place.
  • Add mirrored synthetic regression tests and document the invariant in AI_CONTEXT.md.

No new dependencies, tool schema changes, version bumps, global XML normalization, or renumbering of existing revisions. This is scoped to the regular text deletion/replacement path, not a redesign of insertion IDs, paragraph-mark IDs, or revision grouping.

Regression coverage

The initial four cases in each engine failed on duplicate deletion IDs before the fix. They now verify:

  • replacement and deletion across three differently formatted runs;
  • one wrapper for adjacent runs and distinct IDs across intervening proofing markers;
  • run formatting and insertion-style inheritance;
  • proofing markers remain paragraph children, outside deletion wrappers;
  • save/reload followed by accept/reject produces the expected text;
  • another author's revisions in an unrelated paragraph remain unchanged.

Validation

On Linux, Node 24.13.0 and Python 3.13.7:

  • npm ci, then npm run build: passed for all Node workspaces, including MCP bundle verification.
  • npm test: core 1,067 passed / 32 skipped, MCP server 327 passed, n8n 51 passed.
  • npm run lint: passed.
  • uv run ruff check . and uv run ruff format --check .: passed.
  • uv run mypy src: passed (42 source files).
  • uv run pytest: 1,998 passed / 128 skipped; system LibreOffice 7.3.7.2 selected on PATH.
  • Independent @ooxml-tools/validate@0.4.6, Microsoft365 target, on the synthetic example from Multi-run replacements emit duplicate w:del IDs rejected by OpenXML validation #141: input 0 errors, unpatched Node output Sem_UniqueAttributeValue, patched Node output 0 errors, patched Python output 0 errors.

An initial Python run selected an incompatible bundled LibreOffice executable and failed three probe tests. The same three failed on an unmodified main checkout. Selecting the working system LibreOffice resolved them without changing or skipping tests. Likewise, installation used Node 24 after the machine's default Node 25 failed compiling the existing isolated-vm dependency.

Limitations / review points

  • Desktop Microsoft Word / Windows COM validation was not run on this Linux host. Existing platform-conditional skips remain; validator success is not claimed as proof of every Word rendering behavior.
  • When structural markers separate deleted runs, the output exposes distinct revision IDs. Callers should use the current revision listing rather than assume every logical edit has only one deletion ID. Adjacent runs retain compact grouping.
  • I would appreciate review of that boundary behavior and the Python preview/style preservation in particular. No customer documents or customer content are included in this contribution.

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.

Multi-run replacements emit duplicate w:del IDs rejected by OpenXML validation

1 participant