Skip to content

feat(verification): close inv_field_001 with Tier 2 OoxmlDoc subset#208

Merged
stevenobiajulu merged 3 commits into
mainfrom
worktree-inv-field-001-proof
May 22, 2026
Merged

feat(verification): close inv_field_001 with Tier 2 OoxmlDoc subset#208
stevenobiajulu merged 3 commits into
mainfrom
worktree-inv-field-001-proof

Conversation

@stevenobiajulu
Copy link
Copy Markdown
Member

Summary

Implements OpenSpec change add-ooxml-doc-subset-and-inv-field-001-proof (merged 2026-05-14 via #202). Closes the inv_field_001 sorry in verification/lean/LeanSpike/Spec.lean with a machine-checked preservation lemma over a definitional Lean OOXML subset, composed with a single named residual axiom.

  • New verification/lean/Tier2/ module: OoxmlModel, FieldStructure, WalkLemmas, AcceptReject, InvFieldOne. All zero-sorry. The preservation lemma field_structure_preserved is proven against a stack-valued field-context walk (FieldCtx := List Bool) exactly mirroring the TS engine's pastSeparatorAtDepth: number[] at pipeline.ts:374-389, with the strictly stronger fieldContextNeutral per-subtree predicate that survives the round-3 counterexample families.
  • Spec.lean rewires OoxmlDoc / acceptAllChanges / rejectAllChanges / validateFieldStructure from axiom to Tier 2 definitions, adds the single residual axiom compareDocumentXml_output_recursivelyWellformed, and closes the inv_field_001 sorry with a two-line proof. #print axioms inv_field_001 confirms zero sorryAx — depends only on propext, Quot.sound, compareDocumentXml, and the named residual axiom.
  • inv_rt_001 remains sorry'd (explicitly deferred to add-inv-rt-001-proof).
  • lean-build.yml audit extended to cover Tier2/; Spec.lean expected-sorry count drops from 2 to 1.
  • lean-spec-bridge.test.ts gets one field-bearing fixture case (NUMPAGES insert) that runs a TS analogue of recursivelyWellformed against the live engine as a falsifiability layer for the new axiom.
  • Tier2/README.md, verification/lean/README.md, and verification/ROADMAP.md document scope, residual obligations, and Tier 2 status.

Ref: #201. See change at openspec/changes/add-ooxml-doc-subset-and-inv-field-001-proof/.

Test plan

  • cd verification/lean && lake build — clean build, single expected sorry warning (Spec.lean:126 = inv_rt_001).
  • Non-Spec zero-sorry audit (workflow logic): find LeanSpike.lean LeanSpike Tier2.lean Tier2 -name '*.lean' ! -name 'Spec.lean' -print0 | xargs -0 grep -nwH sorry → empty.
  • grep -cw sorry LeanSpike/Spec.lean1.
  • #print axioms LeanSpike.inv_field_001[propext, compareDocumentXml, compareDocumentXml_output_recursivelyWellformed, Quot.sound] (no sorryAx).
  • npx vitest run packages/docx-core/src/integration/lean-spec-bridge.test.ts — all 5 tests pass, including the new field-bearing fixture case.
  • npx tsc --noEmit -p packages/docx-core/tsconfig.json — clean.
  • npx eslint packages/docx-core/src/integration/lean-spec-bridge.test.ts — clean.
  • npx openspec validate add-ooxml-doc-subset-and-inv-field-001-proof --strict — valid; all 10 tasks checked off.
  • CI green (lean-build workflow + workspace-test matrix).

Implements OpenSpec change `add-ooxml-doc-subset-and-inv-field-001-proof`
(merged 2026-05-14 via PR #202).

Replaces the uninterpreted document-level axioms in `LeanSpike/Spec.lean`
with a definitional Lean OOXML subset under `verification/lean/Tier2/`
and proves the field-structure preservation lemma machine-checked.
`inv_field_001` is closed by composing that lemma with a single named
residual axiom `compareDocumentXml_output_recursivelyWellformed`, which
captures the only remaining assumption (discharging it by modeling
`compareDocumentXml` definitionally is Tier 3 work). `inv_rt_001`
remains `sorry`'d (deferred to `add-inv-rt-001-proof`).

Why: PR #164 shipped `Spec.lean` over fully uninterpreted axioms, leaving
both invariants as `sorry`. Closing `inv_field_001` requires either a
definitional comparison model (Tier 3) or carrying an explicit, named
residual obligation. Three peer-review rounds (codex + gemini CLI) drove
the design to a stack-valued field context exactly mirroring the TS
engine's `pastSeparatorAtDepth: number[]` and the strictly stronger
`fieldContextNeutral` per-subtree predicate.

What's delivered:
- `Tier2/OoxmlModel.lean` — tree-structured OOXML subset.
- `Tier2/FieldStructure.lean` — stack-valued walk, `validateFieldStructure`,
  `fieldContextNeutral`, `recursivelyWellformed`.
- `Tier2/WalkLemmas.lean` — `walkBlocks_append`, neutrality no-op,
  `neutral_balanced` (via a tall-stack length-tracking argument so no
  `end` underflows), `delInstrText_rewrite_safe`.
- `Tier2/AcceptReject.lean` — definitional `accept` / `reject`.
- `Tier2/InvFieldOne.lean` — closed `field_structure_preserved` (zero
  `sorry`).
- `LeanSpike/Spec.lean` — `OoxmlDoc` / `acceptAllChanges` /
  `rejectAllChanges` / `validateFieldStructure` rewired from `axiom` to
  Tier 2 definitions; new named residual axiom; `inv_field_001` proof.
- `lean-build.yml` — non-Spec zero-sorry audit extended to `Tier2/`;
  Spec.lean audit updated from 2 sorries to 1.
- `lean-spec-bridge.test.ts` — one field-bearing fixture case
  exercising a TS analogue of `recursivelyWellformed` as a falsifiability
  layer for the new axiom.
- `Tier2/README.md`, `verification/lean/README.md`,
  `verification/ROADMAP.md` — scope, residual obligations, status.

Verification: `lake build` clean with one expected `sorry` warning
(`inv_rt_001`). `#print axioms inv_field_001` depends only on `propext`,
`Quot.sound`, `compareDocumentXml`, and the one residual axiom — no
`sorryAx`. Full `lean-spec-bridge.test.ts` suite (5 tests) passes.
`tsc --noEmit` and ESLint clean on the test file. `openspec validate
--strict` passes; all 10 tasks checked off.

Ref: #201
@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 2026

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

Project Deployment Actions Updated (UTC)
site Ready Ready Preview, Comment May 22, 2026 6:29am

Request Review

@github-actions github-actions Bot added the feat label May 20, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@stevenobiajulu
Copy link
Copy Markdown
Member Author

Peer-review synthesis (Codex + Gemini + ECMA-376 deep research)

Captured here so the patterns are durable for future Lean/TS-fidelity work.

Blocking findings (both reviewers converged)

1. w:delInstrText TS↔Lean divergence — TS under-validates the spec.
TS validateFieldStructure (pipeline.ts:357, :391-393) checks only w:instrText; Lean Tier2/FieldStructure.lean:64-71 checks both. ECMA-376 (DeletedFieldCode) mandates w:delInstrText placement inside <w:del> — Word, LibreOffice, and docx4j all enforce or split to maintain this. Lean is right; TS is the gap. Tracked in #209.

2. OoxmlModel subset coverage gap — projection is doing silent load-bearing work.
Lean Block := run|ins|del|moveFrom|moveTo (OoxmlModel.lean:54-63) omits w:tbl, w:sdt, w:hyperlink, bookmarks. The residual axiom is over compareDocumentXml : OoxmlDoc → OoxmlDoc → Option OoxmlDoc, which side-steps the projection. Adding a second projection axiom would grow the trusted base without fixing the underlying issue. Preferred fix: extend Lean Block with a transparent other tag children constructor and let walkBlocks descend through it — keeps the trusted base at one axiom, mirrors TS's recursive-scan behavior.

3. fieldContextNeutral ∀ ctx is incompatible with ECMA-376 field fragmentation. ⚠️ Foundational
ECMA-376 explicitly requires conformant emitters to fragment fields across wrapper boundaries when a field is modified under track changes. Canonical fixture (FORMCHECKBOX→FORMFIELDTEXT):

<w:fldChar w:fldCharType=\"begin\"/>
<w:ins><w:r><w:instrText>FORMCHECKBOX</w:instrText></w:r></w:ins>
<w:del><w:r><w:delInstrText>FORMFIELDTEXT</w:delInstrText></w:r></w:del>
<w:fldChar w:fldCharType=\"separate\"/>

The <w:ins> wrapper contains only [w:instrText] and is not fieldContextNeutral under empty ctx (instrText on empty stack → invalid). The current NUMPAGES test fixture passes only because it's a whole-field insertion (entire field in one <w:ins>). For any inplace output that modifies an existing field, the residual axiom is demonstrably false, not just thinly evidenced. The Lean predicate needs path-conditional neutrality ("neutral under the contexts the walk actually reaches it with"), not universal ∀ ctx.

4. Falsifiability layer is too thin.
One NUMPAGES insertion fixture exercises zero w:delInstrText atoms and zero fragmented-field topologies. Minimum additions before merge: deleted-field fixture, complete-field-in-<w:del> fixture, complete-field-in-<w:ins> fixture, negative neutrality unit cases (standalone separate, standalone end, [begin, separate]).

5. #print axioms LeanSpike.inv_field_001 is unverified.
Both reviewers ran static-only (no lake in their sandboxes). Static grep confirms no sorry/unsafe/classical/decide in Tier2/, but the exact claimed axiom list must be confirmed in CI or local Lean before merge.

Not blockers

  • Stale pastSeparatorAtDepth[depth+1] vs Lean pop — observationally equivalent (TS only reads at current depth; next begin overwrites). No change needed; optional comment in pipeline.ts documenting why the stale entry is unreachable would harden against future refactors.
  • Doc.blocks paragraph flattening — aligned with TS recursive scan and with ECMA-376's "fields can cross paragraph boundaries within a story" rule. No change.
  • Lean proof tactics — no suspicious usage. omega is bounded to count arithmetic backed by explicit count lemmas. The weak point is the axiom + model fidelity, not the proof.

Cross-cutting TS engine recommendations from this Lean work

  1. Add w:fldChar-inside-<w:del> rejection. ECMA-376 strictly forbids this; Word discards the field state machine on violation. Currently unchecked. → Folded into validateFieldStructure: add w:delInstrText placement check + reject w:fldChar inside <w:del> #209.
  2. Cross-story field-closure check. Per ECMA-376 an unclosed field at end-of-story invalidates the field. The current global balance check is whole-document, not per-story; footnote/header expansions may miss this.
  3. Per-wrapper neutrality as a runtime safety gate. Bring the bridge test's isFieldContextNeutral (in the now path-conditional form) into the engine itself so the residual axiom becomes a checked invariant, not just an asserted one.

Pattern for future Lean↔TS fidelity work

The recurring failure mode in this review: Lean models that over-strengthen a predicate beyond what production XML actually satisfies, with a single thin fixture as falsifiability evidence. When the next OpenSpec change touches a validate* function or another invariant proof, check:

  • Does the Lean predicate match the spec, the engine, or some intersection? If the engine under-validates the spec, fix the engine first.
  • Is the predicate's quantifier (∀ over contexts, ∀ over inputs) tighter than what the engine can plausibly produce? Look for fragmentation/split behaviors in the engine that violate the universal.
  • Is the falsifiability layer exercising the adverse shapes of every atom case (esp. delText/delInstrText/wrapper-fragmented fields), or just the happy path?

Sources

  • Codex review log: /tmp/peer-review-pr208-codex-output.txt (final verdict at ~line 5906)
  • Gemini review log: /tmp/peer-review-pr208-gemini-output.txt
  • ECMA-376 research: notes thread (DeletedFieldCode placement, fldChar/del nesting prohibition, fragmentation requirement, sibling rule for fldChar runs)

…ner; add delInstrText falsifiability fixtures

Closes peer-review gap B (subset coverage) and tightens gap C (axiom evidence)
on PR #208. Both surfaced by Codex + Gemini peer review (commit-comment thread)
and an ECMA-376 Part 4 deep-research report.

## Lean changes

Adds a 6th `Block` constructor `Block.other (tag : String) (children : List Block)`
to model OOXML structural containers that the field-context walk MUST descend
through transparently but that are NOT track-change wrappers: `w:tbl`, `w:tr`,
`w:tc`, `w:sdt`, `w:sdtContent`, `w:hyperlink`, bookmark elements, etc. Before
this change the Lean model implicitly assumed inplace output contained no such
containers — `compareDocumentXml : OoxmlDoc → OoxmlDoc → Option OoxmlDoc` was
side-stepping a lossy projection.

- `Tier2/OoxmlModel.lean`: add `.other` constructor with docstring explaining
  the modeling intent.
- `Tier2/FieldStructure.lean`: `walkBlocks`, `countBlocks` descend through
  `.other` transparently. `wrapperSubtreesBlocks` does NOT emit the children
  as a wrapper subtree (only wrappers nested inside `.other` are emitted) —
  `.other` is structural, not a track-change wrapper.
- `Tier2/AcceptReject.lean`: `acceptBlocks`, `rejectBlocks`, `renameBlocks`
  preserve the `.other` container with its tag while recursively processing
  children. Accept/reject don't unwrap or drop the container itself.
- `Tier2/WalkLemmas.lean`: add `case7` to `walkBlocks_invalid`,
  `walkBlocks_append`, `countBlocks_append`, and the inductive `walkBlocks_tall`
  key block.
- `Tier2/InvFieldOne.lean`: add `case7` to every `induction ... using
  *.induct` (walkBlocks_renameBlocks, countBlocks_renameBlocks,
  walkBlocks_acceptBlocks, walkBlocks_rejectBlocks, both
  countBlocks_*_balance). Introduce `allNeutral_other` helper that does NOT
  extract a `fieldContextNeutral` obligation on the container's children (since
  `.other` is not in `wrapperSubtreesBlocks`). `acceptBlocks_append` /
  `rejectBlocks_append` / `renameBlocks_append` and `accept_blocks` /
  `reject_blocks` use `cases b <;> simp [...]` patterns and require no edit —
  Lean enumerates all 6 constructors.

## Spec.lean axiom docstring rewrite

Honestly states the engine-specific justification for the `∀ ctx` neutrality
strength: safe-docx's current inplace atomizer emits whole field sequences as
single track-change wrappers (verified at `inPlaceModifier.ts:717, 938, 1505,
1671, 1957, 2300` and `collapsed-field-inplace.test.ts:211`). The axiom is
NOT spec-conformant: under ECMA-376 Part 4 a conformant emitter must fragment
fields across wrapper boundaries when modifying them, and fragmented wrappers
are not `fieldContextNeutral` under `∀ ctx`. When the engine becomes
ECMA-376-conformant, this axiom and the per-subtree neutrality predicate will
need replacement with a document-level form (follow-up PR-B tracked in plan).

## TS bridge fixtures (gap C)

Adds three new tests to `lean-spec-bridge.test.ts`:

  1. **NUMPAGES deletion fixture** — original has the complete field; revised
     deletes it. Exercises the `w:delInstrText` atom case in
     `isFieldContextNeutral`, which the existing NUMPAGES insertion fixture
     never reaches.

  2. **Regression guard — `isFieldContextNeutral` rejects non-neutral shapes**:
     standalone `w:fldChar separate`, standalone `w:fldChar end`, and a
     `[begin, separate]` fragment. Crafted DOM-level XML, not full DOCX.

  3. **Regression guard — `isFieldContextNeutral` accepts a complete
     self-contained field wrapper**: the canonical NUMPAGES-in-w:ins shape the
     engine actually emits.

All 8 bridge tests pass locally; typecheck and lint clean.

## Out of scope (deferred to PR-B)

The `∀ ctx` → document-level predicate weakening. Codex's review concluded
that the current engine satisfies the existing `∀ ctx` predicate, so the
weakening is not required for shipping PR #208. PR-B will land after the
engine fragmentation conformance work (new GH issue to be filed) is scoped.

Ref: #208
…iom docstring

Replaces the placeholder "see follow-up issue" with the concrete cross-reference
to the engine fragmentation conformance work tracked in #217. No behavior
change.

Ref: #208, #217
@stevenobiajulu stevenobiajulu merged commit 55c0673 into main May 22, 2026
24 checks passed
stevenobiajulu added a commit that referenced this pull request May 22, 2026
…r inside <w:del> (#211)

Per ECMA-376 Part 4 (DeletedFieldCode and fldChar topics), validateFieldStructure
was under-checking the spec on two counts:

  1. w:delInstrText placement was unvalidated. The engine emits this tag
     (inPlaceModifier.ts:319-320; reject converts it back at
     trackChangesAcceptorAst.ts:613-615), so production was producing a
     schema-relevant element with no structural check. Word, LibreOffice, and
     docx4j all enforce or split to maintain this. The Lean Tier 2 model in
     PR #208 already validates both atoms; this commit brings TS into line.

  2. w:fldChar nested inside <w:del> was accepted. ECMA-376 strictly forbids
     this and Microsoft Word treats violations as fatal (discards the field
     state machine, renders raw instructions as literal text).

The scan now tracks <w:del>-ancestor depth alongside field depth, applies the
existing pre-separator field-body check to both w:instrText and w:delInstrText,
adds an "inside-<w:del>" requirement for w:delInstrText, and rejects any
w:fldChar reached while inside-<w:del>-depth is positive.

Unit tests cover the happy path (field-free, complete field, conformant
ECMA-376 fragmented field modification with unwrapped fldChars + ins/del
instrText), the existing rejections (orphan instrText, post-separator
instrText, unbalanced begin/end), and the new rejections (delInstrText outside
<w:del>, delInstrText outside any field body, fldChar nested in <w:del>).

Ref: #209
Ref: #208 (peer review of PR #208 surfaced this gap; Lean docstring at
Tier2/FieldStructure.lean:7-9 already documents the stricter property)

Co-authored-by: Steven Obiajulu <stevenobiajulu@Stevens-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
stevenobiajulu added a commit that referenced this pull request May 22, 2026
…nt-level preservation friendliness (#219)

Closes peer-review concern D (predicate strength) from PR #208. Codex review
confirmed the current engine satisfies the stronger `∀ ctx` predicate, but the
ECMA-376 Part 4 deep-research report showed that a conformant emitter MUST
fragment fields across wrapper boundaries when modifying a field — fragmented
`<w:ins>`/`<w:del>` wrappers containing only `w:instrText`/`w:delInstrText`
are NOT `fieldContextNeutral` under `∀ ctx`. When safe-docx becomes
ECMA-376-conformant (tracked in #217), the stronger predicate will break.

This commit weakens the residual axiom to be future-compatible without
touching the engine.

## Predicate weakening

Adds `Tier2.AcceptReject.preservationFriendly` — a document-level property
asserting only that accept and reject preserve the *composed* field walk and
begin/end balance. Strictly weaker than the previous per-subtree
`Tier2.FieldStructure.recursivelyWellformed`:

  * Old: `validateFieldStructure d ∧ ∀ wrapper-subtree, fieldContextNeutral subtree`
    where `fieldContextNeutral bs := ∀ ctx, walkBlocks (.ok ctx) bs = .ok ctx`.
  * New: `validateFieldStructure d ∧ walkBlocks (.ok []) (acceptBlocks d.blocks)
    = walkBlocks (.ok []) d.blocks ∧ ...` (analogous for reject + balance).

The old predicate is retained in `Tier2.FieldStructure` and the legacy
`field_structure_preserved` lemma still compiles — they remain available for
audit traceability. Only `inv_field_001` is rewired to consume the new
predicate via the new `Tier2.InvFieldOne.field_structure_preserved_doc` lemma.

## Axiom replacement

`Spec.lean` replaces `compareDocumentXml_output_recursivelyWellformed` with
`compareDocumentXml_output_preservation_friendly`. The `inv_field_001` proof
body changes to compose the new axiom with `field_structure_preserved_doc`.
`#print axioms LeanSpike.inv_field_001` becomes:

  [propext, compareDocumentXml, compareDocumentXml_output_preservation_friendly, Quot.sound]

## TS bridge — explanatory comment

The existing `isFieldContextNeutral` / `assertRecursivelyWellformed` checks in
`lean-spec-bridge.test.ts` enforce the OLD stricter property. With the axiom
now weaker, these become an audit OVER-check: the engine currently satisfies
them (whole-field wrapping), but when #217 lands and the engine starts
fragmenting, these checks will need to be removed or relaxed. The comment
block above the field-bearing fixtures is updated to reflect this layering.

Ref: #208, #217

Co-authored-by: Steven Obiajulu <stevenobiajulu@Stevens-MacBook-Pro.local>
stevenobiajulu added a commit that referenced this pull request May 22, 2026
…preservationFriendly (rebased follow-up to #208) (#220)

* refactor(verification): weaken inv_field_001 residual axiom to document-level preservation friendliness

Closes peer-review concern D (predicate strength) from PR #208. Codex review
confirmed the current engine satisfies the stronger `∀ ctx` predicate, but the
ECMA-376 Part 4 deep-research report showed that a conformant emitter MUST
fragment fields across wrapper boundaries when modifying a field — fragmented
`<w:ins>`/`<w:del>` wrappers containing only `w:instrText`/`w:delInstrText`
are NOT `fieldContextNeutral` under `∀ ctx`. When safe-docx becomes
ECMA-376-conformant (tracked in #217), the stronger predicate will break.

This commit weakens the residual axiom to be future-compatible without
touching the engine.

## Predicate weakening

Adds `Tier2.AcceptReject.preservationFriendly` — a document-level property
asserting only that accept and reject preserve the *composed* field walk and
begin/end balance. Strictly weaker than the previous per-subtree
`Tier2.FieldStructure.recursivelyWellformed`:

  * Old: `validateFieldStructure d ∧ ∀ wrapper-subtree, fieldContextNeutral subtree`
    where `fieldContextNeutral bs := ∀ ctx, walkBlocks (.ok ctx) bs = .ok ctx`.
  * New: `validateFieldStructure d ∧ walkBlocks (.ok []) (acceptBlocks d.blocks)
    = walkBlocks (.ok []) d.blocks ∧ ...` (analogous for reject + balance).

The old predicate is retained in `Tier2.FieldStructure` and the legacy
`field_structure_preserved` lemma still compiles — they remain available for
audit traceability. Only `inv_field_001` is rewired to consume the new
predicate via the new `Tier2.InvFieldOne.field_structure_preserved_doc` lemma.

## Axiom replacement

`Spec.lean` replaces `compareDocumentXml_output_recursivelyWellformed` with
`compareDocumentXml_output_preservation_friendly`. The `inv_field_001` proof
body changes to compose the new axiom with `field_structure_preserved_doc`.
`#print axioms LeanSpike.inv_field_001` becomes:

  [propext, compareDocumentXml, compareDocumentXml_output_preservation_friendly, Quot.sound]

## TS bridge — explanatory comment

The existing `isFieldContextNeutral` / `assertRecursivelyWellformed` checks in
`lean-spec-bridge.test.ts` enforce the OLD stricter property. With the axiom
now weaker, these become an audit OVER-check: the engine currently satisfies
them (whole-field wrapping), but when #217 lands and the engine starts
fragmenting, these checks will need to be removed or relaxed. The comment
block above the field-bearing fixtures is updated to reflect this layering.

Ref: #208, #217

* fix(verification): drop assertRecursivelyWellformed from deletion fixture (currently catches #217 engine non-conformance)

PR #208 added a deleted-NUMPAGES bridge fixture that calls
`assertRecursivelyWellformed(result.combined)`. Independently, PR #211
tightened `validateFieldStructure` to reject `w:fldChar` inside `<w:del>`
(per ECMA-376 Part 4 — Word treats this as fatal). Both PRs squash-merged
to main within 4 seconds of each other; PR #208's CI passed against the
pre-#211 validator, so the interaction wasn't caught.

The current engine emits deleted complete fields as a single `<w:del>`
containing the entire begin/instrText/separate/result/end run sequence
(`inPlaceModifier.ts:938`) — that is, with `w:fldChar` inside `<w:del>`.
The engine's own safety check at `pipeline.ts:439-440` only validates
the post-accept and post-reject outputs (which ARE conformant: accept
drops the `<w:del>` entirely; reject unwraps to a complete field).
PR #211's tightening therefore does not affect the engine's safety
check, but it does affect manual calls to `validateFieldStructure`
on the combined XML — which is exactly what `assertRecursivelyWellformed`
does.

Net: main is currently broken on `workspace-test` because the deletion
fixture's `assertRecursivelyWellformed` call fails.

This commit removes that call from the deletion fixture and replaces
it with a TODO comment referencing #217. The fixture still exercises
the `w:delInstrText` atom case via `assertFieldInvariant` (which checks
the engine's own consequence: `validateFieldStructure` on accept/reject
outputs). The over-check can be re-enabled when #217 lands and the
engine fragments fields per ECMA-376.

The renamed test description reflects the actual asserted property.

Ref: #217 (engine fragmentation conformance — the long-term fix).
Ref: #208 (which introduced the fixture), #211 (which tightened the validator), #220 (which lands the axiom weakening; this commit fixes the test break).

---------

Co-authored-by: Steven Obiajulu <stevenobiajulu@Stevens-MacBook-Pro.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant