Skip to content

feat(docx-markdoc): validate structural insertions - #970

Open
stevenobiajulu wants to merge 2 commits into
add-brownfield-markdoc-authoring-20260812from
tweak-markdoc-structural-validation
Open

feat(docx-markdoc): validate structural insertions#970
stevenobiajulu wants to merge 2 commits into
add-brownfield-markdoc-authoring-20260812from
tweak-markdoc-structural-validation

Conversation

@stevenobiajulu

Copy link
Copy Markdown
Member

Summary

  • add shared structural diagnostics for parent-child slicing, list-level mismatch, and mid-list renumbering
  • validate Markdoc insertions transactionally and surface matching MCP warnings with corrective anchors
  • detect source-proven bonded run-in heading/body pairs, including NVCA Heading2 + HeadingPara2 structures
  • support atomic bonded pairs in batch_edit without allowing unrelated same-slot collisions

Verification

  • Claude Opus 4.6 dynamic peer review: approved; all advisories addressed in bd45f93
  • docx-core structural validation: 11 passed
  • docx-markdoc: 21 passed
  • docx-mcp structural + batch tests: 18 passed
  • strict OpenSpec validation and MCP spec coverage passed

Notes

This PR is stacked on add-brownfield-markdoc-authoring-20260812 because the validation preflight integrates with that new Markdoc compilation surface.

Safe DOCX already preserves formatting when callers choose the right peer, but structurally valid edits can still split parents from descendants, import the wrong list topology, or collapse a two-paragraph run-in provision into one formatted paragraph. Add one deterministic validator registry at the document-view boundary so Markdoc preflight and MCP insertion responses share stable, actionable diagnostics before output is written.\n\nThe bonded-pair rule relies on repeated adjacent style and indent transitions, not legal-text heuristics, so the NVCA Heading2/HeadingPara2 pattern remains two paragraphs with distinct formatting sources. Junior Harness retry state and product-specific classifiers remain intentionally outside this package.\n\nRef: add-markdoc-structural-validation
Dynamic peer review identified that positional matching could reuse one body operation, silently choose among multiple follower styles, and leave BEFORE ordering unspecified. Make pairing one-to-one, direction-aware, and explicitly fail ambiguous source patterns.\n\nAllow batch_edit to express the validated two-paragraph construction atomically through an explicit bonded_pair_id. The collision exception applies only to exactly two source-proven, correctly ordered steps with distinct style peers; unrelated and three-step same-slot insertions remain hard conflicts.\n\nRef: add-markdoc-structural-validation
@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
site Ready Ready Preview Sep 3, 2026 12:06pm UTC

Request Review

@usejunior-llm-gate

Copy link
Copy Markdown

LLM gate (advisory)

1 finding to review (advisory, does not block) - 7 pass, 1 warn, 0 error, 9 skipped, 17 total

Findings (1)

Rule Verdict Detail
.openspec tag ↔ test-assertion drift WARN Several .openspec tags in packages/docx-mcp/src/structural_validation_openspec.test.ts (lines 23, 37, 44, and 57) exhibit tag-assertion drift, as they are placed on low-level unit tests that do not exercise the full compiler, preflight, or batch execution flows defined in the specs. The actual end-to-end behaviors are tested elsewhere (e.g., docx-markdoc.test.ts:88 and replace_plan_tools_with_batch_edit.test.ts:188) but remain untagged.
All 17 rules (8 evaluated, 9 skipped)
Rule Verdict Detail
read_file response metadata parity SKIPPED paths not touched by this PR
Live DOM namespace-safe OOXML writes SKIPPED paths not touched by this PR
Deleted field markup keeps w:fldChar outside w:del PASS The PR implements paragraph structural validation and does not touch field atomization, validateFieldStructure, hasFldCharInsideDel, w:fldChar, w:instrText, w:delInstrText, or collapsed field comparison logic.
Field validation per story, not global SKIPPED paths not touched by this PR
Revision IDs seeded from all revision-bearing side parts SKIPPED paths not touched by this PR
Accept/reject sweep side parts and caches PASS The PR does not touch DocxDocument.acceptChanges, DocxDocument.rejectChanges, REVISION_STORY_PART_PATHS, accept_changes, reject_changes, or side-part revision markup, as its scope is restricted to implementing Markdoc structural validation.
DocumentViewNode.heading stays canonical SKIPPED paths not touched by this PR
AI-author parity across entry points SKIPPED paths not touched by this PR
Property-change wrapper discipline SKIPPED paths not touched by this PR
SUPPORT.md Table A drift vs. implementation PASS The PR only adds a structural insertion validator in packages/docx-core/src/primitives/structural_validation.ts and does not modify OOXML revision emission behavior or touch packages/docx-core/SUPPORT.md.
Table A / Table B boundary on side-part revisions SKIPPED paths not touched by this PR
Canonical-emission surface completeness PASS The PR only introduces structural insertion validation in packages/docx-core/src/primitives/structural_validation.ts and does not add or change any tracked-edit or revisionable emission surface. Therefore, the precondition is not met.
Lean predicate drift against engine semantics (asymmetric) SKIPPED paths not touched by this PR
Unit-test quality (avoid tautological / change-detector tests) PASS The tests added and modified across packages/docx-core/src/primitives/structural_validation.test.ts, packages/docx-markdoc/src/docx-markdoc.test.ts, and packages/docx-mcp/src/structural_validation_openspec.test.ts are highly robust and independent of the SUT. They construct inputs and expected values from first principles (using explicit XML snippets or node objects), make concrete semantic assertions on warning codes and layout views, and completely avoid SUT mocking and tautologies.
Re-derived facts vs canonical sources PASS The PR consumes the canonical DocumentViewNode list derived from DocxDocument.buildDocumentView across all validation layers, correctly exporting the new checkers from packages/docx-core/src/primitives/index.ts:3 without any duplicate fldChar walks, footnote-reference passes, or other re-derived document facts.
.openspec tag ↔ test-assertion drift WARN Several .openspec tags in packages/docx-mcp/src/structural_validation_openspec.test.ts (lines 23, 37, 44, and 57) exhibit tag-assertion drift, as they are placed on low-level unit tests that do not exercise the full compiler, preflight, or batch execution flows defined in the specs. The actual end-to-end behaviors are tested elsewhere (e.g., docx-markdoc.test.ts:88 and replace_plan_tools_with_batch_edit.test.ts:188) but remain untagged.
Library stays general (no downstream-domain leakage) PASS The PR introduces structural validation APIs and types in packages/docx-core/src/primitives/structural_validation.ts that focus entirely on general Word/OOXML hierarchical structures (such as lists, headings, and bonded paragraph pairs) without leaking any downstream domain-specific concepts.

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.

1 participant