Skip to content

test(diff): pin gridSpan/vMerge property-only table change scope (#230)#257

Merged
JSv4 merged 1 commit into
mainfrom
claude/issue-230-review-x5tubs
Jul 4, 2026
Merged

test(diff): pin gridSpan/vMerge property-only table change scope (#230)#257
JSv4 merged 1 commit into
mainfrom
claude/issue-230-review-x5tubs

Conversation

@JSv4

@JSv4 JSv4 commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Closes #230.

What #230 asked

The IR did not model property-only table/cell changes (w:tcPr / w:tblPr / gridSpan / vMerge): a reviewer who changed only cell shading/borders/width, table properties, or cell spanning produced an IR whose content/format fingerprints were identical to the base, so both 2-way DocxDiff.Compare and consolidate treated the table as EqualBlock — the change was silently invisible (no revision, no markup, no conflict).

Acceptance criteria: (1) a tcPr-only cell change is detected as a format change in 2-way Compare and composes/conflicts in consolidate; (2) document the chosen scope for gridSpan/vMerge (detect vs. compose); (3) base 2-way parity floor holds, full suite green.

What I found (proved with a fixture)

I first wrote a throwaway probe that ran DocxDiff.Compare / Consolidate over programmatic tables and inspected the IR hashes + emitted markup. Ground truth:

The genuinely-unmet parts were criterion (2) — the gridSpan/vMerge scope was never explicitly documented — and the absence of direct regression fixtures for that corner. So this PR closes the proof + documentation gap rather than touching the (already-correct) engine.

Changes

  • BlockFormatChangeTests.{GridSpanOnly,VMergeOnly}_cell_change_is_tracked_with_native_tcPrChange — 2-way pins: a gridSpan- / vMerge-only change (cell count stable, text unchanged) → native w:tcPrChange, TableCell FormatChanged revision, clean round-trip, schema-valid, no spurious ins/del.
  • IrCompositeTableTests.VMerge_only_cell_edit_composes (3 conflict policies) — consolidate pin: the reviewer's vMerge lands on accept, reject ≡ base, no conflict.
  • docs/architecture/ir_diff_engine.md — the explicit gridSpan/vMerge scope decision: detect (2-way) / compose (consolidate) / column-structure fallback / ["shell"] changed-name granularity rationale.
  • CHANGELOG.md[Unreleased] entry.

No production code changed — the behavior already held; this makes it auditable and regression-proof.

Verification

  • Full test suite: 2607 passed, 3 skipped, 0 real failures (the one flaky failure was IrAlignerAdversarialTests.Scale_guard_..., a wall-clock micro-benchmark that failed only under full-suite CPU contention and passes 3/3 in isolation — unrelated to these test/doc-only changes).
  • Both parity scoreboards (IrParityScoreboardTests, ConsolidateParityScoreboardTests) green — the 2-way parity floor holds.

Generated by Claude Code

Issue #230 flagged that the IR did not model property-only table/cell
changes (w:tcPr / w:tblPr / gridSpan / vMerge), so a reviewer's
formatting-only table edit read as unchanged. The cell-shell case was
resolved by the block-format-change family (native w:tcPrChange;
IrCell.ShellDigest folded into the cell ContentHash) and by consolidate
cell-shell composition.

This closes the issue's remaining acceptance criterion -- documenting the
chosen gridSpan/vMerge scope -- and adds the direct regression proof that
was missing:

- BlockFormatChangeTests.{GridSpanOnly,VMergeOnly}_cell_change_is_tracked_with_native_tcPrChange:
  a gridSpan- or vMerge-only change (cell count stable, text unchanged) is
  detected in 2-way Compare, renders native w:tcPrChange with a TableCell
  FormatChanged revision, and round-trips (accept == right, reject == left)
  at the tcPr-byte level; schema-valid.
- IrCompositeTableTests.VMerge_only_cell_edit_composes: the same edit
  composes in Consolidate like a width/shading edit (lands on accept,
  reject == base, no conflict) under all three conflict policies.
- docs/architecture/ir_diff_engine.md: the gridSpan/vMerge scope decision
  (detect / compose / column-structure fallback / changed-name granularity).

No engine change -- the behavior already held; this makes it auditable and
regression-proof. Full suite green (2607 passed, 3 skipped).
@JSv4 JSv4 merged commit 33ca90c into main Jul 4, 2026
12 checks passed
@JSv4 JSv4 deleted the claude/issue-230-review-x5tubs branch July 4, 2026 23:53
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(diff): IR doesn't model property-only table changes (w:tcPr / w:tblPr / gridSpan / vMerge) — read as unchanged

2 participants